Considerazioni speciali sull'uso di Python nello script init.d?
Domanda
Esistono considerazioni speciali sull'uso di Python in uno script 'init.d'
che viene eseguito tramite init
? (es. avvio di Ubuntu)
Da quello che ho capito tramite google / test su Ubuntu, le variabili di ambiente fornite a uno script 'init.d'
sono scarse e quindi usando " #! / usr / bin / env python "
potrebbe non funzionare.
Qualcos'altro?
Soluzione
Ciò evidenzia solo il problema più grande con Python in uno script init.d - ha aggiunto complessità.
Python non ha specifiche e l'env non deve nemmeno puntare a cpython. Se esegui l'upgrade e le pause di Python, dovrai morderti la lingua. E c'è una possibilità molto più grande che Python si rompa rispetto a sh (la scommessa sicura per gli script init.d). Essendo la ragione, semplice utility:
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 si sta collegando in libpthread, libdl, libutil, libz, libm tra le altre cose che possono eventualmente rompersi. Python sta semplicemente facendo di più.
-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
Puoi leggere di più su ciò di cui stai specificamente parlando con le variabili env qui: http://www.debian.org/doc/ debian-policy / ch-opersys.html # s9.9 Il problema principale è che i valori predefiniti per env possono essere impostati in / etc / profile che verrebbe eseguito solo se lo script viene eseguito in una shell che supporta la lettura.
Altri suggerimenti
Suppongo che stia eseguendo una specie di demone scritto in Python, altrimenti potrebbe non essere applicabile.
Probabilmente vorrai fare il doppio fork standard di Unix e reindirizzare i descrittori di file. Questo è quello che uso (adattato da una ricezione di codice ActiveState il cui url mi sfugge al momento).
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())
Eseguilo prima di avviare il tuo daemon loop e probabilmente farà la cosa giusta.
Come nota a margine, sto usando #! / usr / bin / env python come linea shebang in uno script su Ubuntu e funziona bene per me.
Probabilmente vorrai comunque reindirizzare stdout / stderr su un file anche se non stai eseguendo un demone per fornire informazioni di debug.