2009-09-10 3 views
9

Esistono considerazioni speciali sull'uso di Python in uno script 'init.d' eseguito tramite init? (avviando Ubuntu)Considerazioni speciali sull'uso di Python nello script init.d?

Da quanto ho capito tramite googling/testing su Ubuntu, le variabili di ambiente fornite da uno script 'init.d' sono scarse e quindi l'utilizzo di "#!/usr/bin/env python" potrebbe non funzionare.

C'è altro?

risposta

4

Questo evidenzia solo il problema più grande con python in uno script init.d - complessità aggiunta.

Python non ha specifiche e l'env non deve nemmeno puntare a cpython. Se esegui l'aggiornamento e le interruzioni di python, dovrai morderti la lingua. E c'è una possibilità molto più grande che Python rompa di sh (la scommessa sicura per gli script init.d). Ragione di essere, semplice utility:

 
[email protected]:/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) 
[email protected]:/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 è il collegamento in libpthread, libdl, libutil, libz, libm tra le altre cose che possono funzionare più correttamente. 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 

Si può leggere di più su cosa si sta parlando specificamente con le variabili env qui: http://www.debian.org/doc/debian-policy/ch-opersys.html#s9.9 Il problema principale è che le impostazioni predefinite per ENV può essere impostato in/etc/profile che avrebbe eseguito solo se lo script viene eseguito sotto una shell che supporta la lettura.

1

Suppongo che stia eseguendo una sorta di demone scritto in python, in caso contrario questo potrebbe non essere applicabile.

Si vorrà (probabilmente) voler eseguire il doppio fork standard unix e reindirizzare i descrittori di file. Questo è quello che uso (adattato da una recepie in 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()) 

Basta eseguirlo prima di avviare il ciclo daemon e probabilmente farà la cosa giusta.

Come nota a margine, sto usando #!/Usr/bin/env python come linea di shebang in uno script su ubuntu e sta funzionando bene per me.

Probabilmente si vorrà comunque reindirizzare stdout/stderr in un file anche se non si sta eseguendo un daemon per fornire informazioni di debug.

+0

Gli script di init non sono daemon. –

+0

Peter - Mi riferisco a uno script nella directory /etc/init.d/ (eseguito all'avvio); il suddetto script è scritto in Python (perché non posso sopportare bash). – jldupont