2012-04-20 6 views
9

Sto cercando di scrivere uno script shell di Linux (preferibilmente bash), presumibilmente chiamato detach.sh, per staccare in modo sicuro i programmi da un terminale, tale che:Su scrivere uno script shell di Linux per staccare in modo sicuro i programmi da un terminale

  1. Invocazione: ./detach.sh prog [arg1 arg2 ...].

  2. È exec -abile, ad es. eseguendo questo nella shell:

    exec ./detach.sh prog [arg1 arg2 ...] 
    
  3. Con una corretta citando (manipolazione principalmente di argomenti contenenti spazi bianchi).

  4. Scarta le uscite (poiché non sono necessarie).

  5. Vuol Non utilizzare screen, tmux, ecc (stessa ragione con 4, più alcuna necessità di un processo di babysitting extra).

  6. Utilizza (ragionevolmente) comandi e programmi portatili, e non cose come start-stop-daemon che è piuttosto distro-specifico.

ho pensato a diversi modi (linee Shebang #!/bin/bash trascurati per il bene di brevità):

  1. nohup:

    nohup "[email protected]" >& /dev/null & 
    
  2. disown:

    "[email protected]" >& /dev/null & 
    disown 
    
  3. setsid:

    setsid "[email protected]" >& /dev/null & 
    
  4. Utilizzando una subshell:

    ("[email protected]" >& /dev/null &) 
    
  5. nohup/setsid combinato con subshell:

    # Or alternatively: 
    # (nohup "[email protected]" >& /dev/null &) 
    (setsid "[email protected]" >& /dev/null &) 
    

Quando si utilizza gedit come il programma di test (sostituendo la parte "[email protected]"), condizione 1 può essere soddisfatto con tutti i metodi sopra, ma la condizione 2 può essere soddisfatta con nessuno.

Tuttavia, se un programma arbitrario (ma non una shell incorporata) viene aggiunto allo script 5, , tutte le condizioni sembrano essere soddisfatte (almeno per me nel caso gedit). Per esempio:

(setsid "[email protected]" >& /dev/null &) 
# Not just `true' because it is also a shell builtin. 
/bin/true 

Chiunque abbia un'idea su una spiegazione dei fenomeni di cui sopra e come implementare correttamente i requisiti?

EDIT:

Con condizione 2, intendo il programma deve essere staccato dal terminale, ma funziona come al solito altrimenti. Ad esempio, con il caso gedit, la condizione non riesce se si chiude immediatamente subito dopo che il processo dello script è terminato.

+2

In che modo la soluzione 5 non soddisfa il requisito 2, a patto di avere la baracca ? O, all'incirca in modo equivalente, che cosa significa il requisito 2 che non è soddisfatto dalla soluzione 5? –

+0

Cosa ti aspetti che succeda quando 'gedit' viene eseguito in background? Poiché 'gedit' è un editor che funziona in modo interattivo, ma un processo in background è, più o meno per definizione, qualcosa che funziona senza interazione dell'utente, forse il problema è la scelta del programma di test. La gestione dei programmi basati su X11 è piuttosto diversa dalla gestione di compilatori e simili. Cosa vedi quando esegui 'gedit' in background? –

+0

Ci scusiamo per la spiegazione errata della mia idea. Intendevo "staccare" quando dicevo "sfondo". Si prega di consultare la versione aggiornata di questa domanda. Grazie per il tuo aiuto :) –

risposta

3

Dopo alcune indagini più da vicino, questi fatti precedentemente inosservata sono state rivelate:

  1. Entrambi gli script 3 e 5 (la variante setsid unico) saranno soddisfare tutte le condizioni se un /bin/true viene aggiunto lo script.

  2. Questi script, come modificato di fatto 1, funzioneranno anche se /bin/true viene sostituito con for i in {0..9999}; do :; done.

Pertanto possiamo concludere che:

  • (Dal fatto 1)

    Più livelli di distacco (come nello script 5) è inutile, e la chiave è quello di utilizzare il corretta utilità (setsid).

  • (da fatto 2)

    è necessario per il successo di script Un ritardo adeguato prima uscita bash. (Calling programma esterno /bin/true consuma un po 'di tempo, proprio come il puro-bash tempo consumer for i in {0..9999}; do :; done.)

    non ho guardato il codice sorgente, ma credo che una possibile spiegazione è che bash possibile uscire prima setsid finiture configurazione dell'esecuzione dell'ambiente del programma da eseguire, se non viene applicato un ritardo appropriato.

Infine, una soluzione ottimale deve essere

#!/bin/bash 
setsid "[email protected]" >& /dev/null & 
sleep 0.01 

EDIT 1:

La necessità di un ritardo è stato spiegato here. Mille grazie a @wilx!

EDIT 2:

(Grazie a @MateiDavid) ci sembra di aver dimenticato di reindirizzare l'input standard, e un modo migliore sarebbe:

#!/bin/bash 
setsid "[email protected]" >& /dev/null < /dev/null & 
+0

Prova a lasciare lo sfondo e il ritardo: 'setsid" $ @ "> & - 2> & - <& -'. –

+0

@MateiDavid: Mille grazie! Ho aggiornato la mia risposta, ma lo sfondo sembra ancora necessario per bash. –

0

Si sta tentando di creare un processo daemon UNIX (ovvero un processo che non ha un terminale di controllo e che è il proprio terminale session). Il comando setsid dovrebbe farlo per te, ma sei responsabile della chiusura di tutti i descrittori di file che sono aperti sul terminale che stai abbandonando. Questo può essere fatto reindirizzandoli a /dev/null o usando la sintassi della shell per la chiusura dei descrittori di file (ad es., 2>&- e 0<&- in Bash).

+0

Grazie, ma penso che gli script 3 e 5 (vedi la mia domanda) li abbiano fatti entrambi, mentre ancora non risolvono il problema. Inoltre, la causa del fenomeno secondo cui una chiamata a '/ bin/true' o così risolve il problema è ancora inspiegabile. –

1

penso che devi fare setsid "[email protected]" >& /dev/null & wait in modo che il terminale di controllo non scompaia prima che setsid riesca a biforcare il bambino.

UPDATE

Mi sembra che questo funziona sia sulla riga di comando e come argomento di -c:

(setsid tail -F /var/log/messages >& /dev/null) & disown 
+0

Molte grazie :) Ho aggiornato la mia risposta per riflettere il tuo suggerimento. –

+1

La spiegazione è molto ragionevole.Ma bash -c 'setsid sleep 1> &/dev/null & wait'' in qualche modo blocca (mentre non blocca in interattivo 'bash'), quindi per il momento non risolve il problema. –

+0

@ CasperTi.Vector: ho aggiornato la mia risposta. – wilx

Problemi correlati