在init.d脚本中使用Python的特殊注意事项?

时间:2009-09-10 14:17:42

标签: python linux ubuntu init.d

在通过'init.d'运行的init脚本中使用Python是否有任何特殊注意事项? (即启动Ubuntu)

根据我的理解,通过在Ubuntu上进行Google搜索/测试,提供给'init.d'脚本的环境变量很少,因此使用"#!/usr/bin/env python"可能无效。

还有别的吗?

2 个答案:

答案 0 :(得分:4)

这只是突出了init.d脚本中python的最大问题 - 增加了复杂性。

Python没有规范,env甚至不必指向cpython。如果你升级和python休息,你将不得不咬你的舌头。并且python打破的可能性大于sh(init.d脚本的安全赌注)。原因是,简单实用:

ecarroll@x60s:/etc/init.d$ ldd /usr/bin/python
    linux-gate.so.1 =>  (0xb7ff7000)
    libpthread.so.0 => /lib/tls/i686/cmov/libpthread.so.0 (0xb7fc9000)
    libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (0xb7fc5000)
    libutil.so.1 => /lib/tls/i686/cmov/libutil.so.1 (0xb7fc0000)
    libz.so.1 => /lib/libz.so.1 (0xb7faa000)
    libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0xb7f84000)
    libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7e21000)
    /lib/ld-linux.so.2 (0xb7ff8000)
ecarroll@x60s:/etc/init.d$ ldd /bin/sh
    linux-gate.so.1 =>  (0xb803f000)
    libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7ec7000)
    /lib/ld-linux.so.2 (0xb8040000)

Python链接到libpthread,libdl,libutil,libz,libm等可能会破坏的东西。 Python只是做得更多。

-rwxr-xr-x 1 root root  86K 2008-11-05 01:51 /bin/dash
-rwxr-xr-x 1 root root 2.2M 2009-04-18 21:53 /usr/bin/python2.6

您可以在这里阅读更多关于您与env变量的具体讨论内容: http://www.debian.org/doc/debian-policy/ch-opersys.html#s9.9 主要问题是env的默认值可以在/ etc / profile中设置,只有当脚本在支持读取它的shell下运行时才会运行。

答案 1 :(得分:1)

我假设这是运行某种用python编写的守护进程,如果没有,那么这可能不适用。

你(可能)想要做标准的unix双叉和重定向文件描述符的事情。这是我使用的(改编自ActiveState代码接收,其目前的网址不在我这里)。

def daemonize(stdin, stdout, stderr, pidfile):
    if os.path.isfile(pidfile):
        p = open(pidfile, "r")
        oldpid = p.read().strip()
        p.close()
        if os.path.isdir("/proc/%s"%oldpid):
            log.err("Server already running with pid %s"%oldpid)
            sys.exit(1)
    try:
        pid = os.fork()
        if pid > 0:
            sys.exit(0)
    except OSError, e:
        log.err("Fork #1 failed: (%d) %s"%(e.errno, e.strerror))
        sys.exit(1)
    os.chdir("/")
    os.umask(0)
    os.setsid()
    try:
        pid = os.fork()
        if pid > 0:
            if os.getuid() == 0:
                pidfile = open(pidfile, "w+")
                pidfile.write(str(pid))
                pidfile.close()
            sys.exit(0)
    except OSError, e:
        log.err("Fork #2 failed: (%d) %s"%(e.errno, e.strerror))
        sys.exit(1)
    try:
        os.setgid(grp.getgrnam("nogroup").gr_gid)
    except KeyError, e:
        log.err("Failed to get GID: %s"%e)
        sys.exit(1)
    except OSError, e:
        log.err("Failed to set GID: (%s) %s"%(e.errno, e.strerror))
        sys.exit(1)
    try:
        os.setuid(pwd.getpwnam("oracle").pw_uid)
    except KeyError, e:
        log.err("Failed to get UID: %s"%e)
        sys.exit(1)
    except OSError, e:
        log.err("Failed to set UID: (%s) %s"%(e.errno, e.strerror))
        sys.exit(1)
    for f in sys.stdout, sys.stderr:
        f.flush()
    si = open(stdin, "r")
    so = open(stdout, "a+")
    se = open(stderr, "a+", 0)
    os.dup2(si.fileno(), sys.stdin.fileno())
    os.dup2(so.fileno(), sys.stdout.fileno())
    os.dup2(se.fileno(), sys.stderr.fileno())

在启动守护程序循环之前运行它,它可能会做正确的事情。

作为旁注,我使用#!/ usr / bin / env python作为ubuntu脚本中的shebang行,它对我来说很好。

即使您没有运行守护程序来提供调试信息,您可能仍希望将stdout / stderr重定向到文件。