init.dスクリプトでPythonを使用する際の特別な考慮事項は?
質問
init
で実行される 'init.d'
スクリプトでPythonを使用する際に特別な考慮事項はありますか? (つまり、Ubuntuの起動)
Ubuntuでのグーグル/テストを通じて理解したことから、 'init.d'
スクリプトに提供される環境変数は不足しているため、"#!/ usr / bin /を使用してenv python"
は機能しない可能性があります。
他に何かありますか?
解決
これは、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で設定できることです。これは、スクリプトの読み取りをサポートするシェルでスクリプトが実行されている場合にのみ実行されます。
他のヒント
これはpythonで書かれた何らかのデーモンを実行していると仮定していますが、そうでない場合は適用されない可能性があります。
(おそらく)標準のUNIXダブルフォークを行い、ファイル記述子のリダイレクトを行います。これは私が使用しているものです(現時点ではURLがわからない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のスクリプトのシバン行として使用していますが、うまく機能しています。
デバッグ情報を提供するデーモンを実行していない場合でも、おそらくstdout / stderrをファイルにリダイレクトする必要があります。