Domanda

Ho un processo che è già in esecuzione da molto tempo e non voglio interromperlo.

Come lo inserisco in nohup (ovvero, come faccio a farlo continuare anche se chiudo il terminale?)

È stato utile?

Soluzione

Utilizzo del Controllo lavoro di bash per inviare il processo nel sfondo:

  1. Ctrl + Z per interrompere (mettere in pausa) il programma e tornare alla shell.
  2. bg per eseguirlo in background.
  3. disown -h [job-spec] dove [specifica lavoro] è il numero del lavoro (come %1 per il primo lavoro in esecuzione; trova il tuo numero con il comando jobs) in modo che il lavoro non venga interrotto alla chiusura del terminale .

Altri suggerimenti

Supponiamo che per qualche motivo Ctrl + Z non funzioni, vai su un altro terminale, trova l'id del processo (usando ps) ed esegui:

kill -SIGSTOP PID 
kill -SIGCONT PID

SIGSTOP sospenderà il processo e SIGCONT riprenderà il processo, in background. Quindi ora chiudere entrambi i terminali non interromperà il processo.

Il comando per separare un processo in esecuzione dalla shell (= lo rende nohup) è disown e un comando shell di base.

Da bash-manpage (man bash):

  

disown [-ar] [-h] [jobspec ...]

     

Senza opzioni, ogni jobspec viene rimosso dalla tabella dei lavori attivi. Se viene fornita l'opzione -h, ogni jobspec non lo è   rimosso dalla tabella, ma è contrassegnato in modo che SIGHUP non venga inviato al lavoro se la shell riceve un SIGHUP. Se non c'è jobspec   presente e non viene fornita né l'opzione -a né -r, viene utilizzato il lavoro corrente. Se non viene fornito jobspec, l'opzione -a   significa rimuovere o contrassegnare tutti i lavori; l'opzione -r senza argomento jobspec limita l'operazione ai lavori in esecuzione. Il ritorno   il valore è 0 a meno che un jobspec non specifichi un lavoro valido.

Ciò significa che è un semplice

disown -a

rimuoverà tutti i lavori dalla tabella dei lavori e li renderà nohup

Queste sono buone risposte sopra, volevo solo aggiungere un chiarimento:

Non puoi disown un pid o processo, tu <=> un lavoro, e questa è una distinzione importante.

Un lavoro è qualcosa che è una nozione di un processo che è collegato a una shell, quindi è necessario gettare il lavoro in background (non sospenderlo) e quindi rinnegarlo.

Edizione:

%  jobs
[1]  running java 
[2]  suspended vi
%  disown %1

Vedi http://www.quantprinciple.com/ investire / index.php / docs / TipsAndTricks / unix / JobControl / per una discussione più dettagliata di Unix Job Control.

Purtroppo disown è specifico per bash e non disponibile in tutte le shell.

Alcune versioni di Unix (ad esempio AIX e Solaris) hanno un'opzione sul comando nohup stesso che può essere applicato a un processo in esecuzione:

nohup -p pid

Vedi http://en.wikipedia.org/wiki/Nohup

La risposta del nodo è davvero eccezionale, ma ha lasciato aperta la domanda su come ottenere reindirizzamento di stdout e stderr. Ho trovato una soluzione su Unix & Amp; Linux , ma non è completo. Vorrei unire queste due soluzioni. Eccolo:

Per il mio test ho realizzato un piccolo script bash chiamato loop.sh, che stampa il pid di se stesso con un minuto di sonno in un ciclo infinito.

$./loop.sh

Ora ottieni il PID di questo processo in qualche modo. Di solito ps -C loop.sh è abbastanza buono, ma è stampato nel mio caso.

Ora possiamo passare a un altro terminale (o premere ^ Z e nello stesso terminale). Ora gdb dovrebbe essere allegato a questo processo.

$ gdb -p <PID>

Questo interrompe lo script (se in esecuzione). Il suo stato può essere verificato da ps -f <PID>, dove il campo STAT è 'T +' (o nel caso di ^ Z 'T'), che significa (man ps (1))

    T Stopped, either by a job control signal or because it is being traced
    + is in the foreground process group

(gdb) call close(1)
$1 = 0

Chiudi (1) restituisce zero in caso di successo.

(gdb) call open("loop.out", 01102, 0600)
$6 = 1

Apri (1) restituisce il nuovo descrittore di file in caso di successo.

Questa apertura è uguale a open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR). Invece di O_RDWR O_WRONLY potrebbe essere applicato, ma /usr/sbin/lsof dice 'u' per tutti i gestori di file std * (FD colonna), che è O_APPEND.

Ho controllato i valori nel file di intestazione /usr/include/bits/fcntl.h.

Il file di output potrebbe essere aperto con nohup, come farebbe man open(2), ma ciò non è suggerito da call perror(""), a causa di possibili problemi di NFS.

Se otteniamo -1 come valore di ritorno, p errno stampa il messaggio di errore. Se abbiamo bisogno dell'errno, usa /usr/sbin/lsof -p <PID> comando gdb.

Ora possiamo controllare il file appena reindirizzato. call close(2) stampe:

loop.sh <PID> truey    1u   REG   0,26        0 15008411 /home/truey/loop.out

Se vogliamo, possiamo reindirizzare stderr a un altro file, se vogliamo usare nuovamente call open(...) e bash usando un altro nome file.

Ora il ^Z allegato deve essere rilasciato e possiamo uscire da jobs:

(gdb) detach
Detaching from program: /bin/bash, process <PID>
(gdb) q

Se lo script è stato interrotto da gdb -q -x loop.gdb -p <PID> da un altro terminale, continua a essere eseguito. Possiamo tornare al terminale di loop.sh. Ora non scrive nulla sullo schermo, ma esegue e scrive nel file. Dobbiamo metterlo in secondo piano. Quindi premere <=>.

^Z
[1]+  Stopped                 ./loop.sh

(Ora siamo nello stesso stato come se <=> fosse premuto all'inizio.)

Ora possiamo controllare lo stato del lavoro:

$ ps -f 24522
UID        PID  PPID  C STIME TTY      STAT   TIME CMD
<UID>    <PID><PPID>  0 11:16 pts/36   S      0:00 /bin/bash ./loop.sh
$ jobs
[1]+  Stopped                 ./loop.sh

Quindi il processo dovrebbe essere in esecuzione in background e staccato dal terminale. Il numero nell'output del comando <=> tra parentesi quadre identifica il lavoro all'interno di <=>. Possiamo usare i seguenti comandi <=> integrati che applicano un segno '%' prima del numero del lavoro:

$ bg %1
[1]+ ./loop.sh &
$ disown -h %1
$ ps -f <PID>
UID        PID  PPID  C STIME TTY      STAT   TIME CMD
<UID>    <PID><PPID>  0 11:16 pts/36   S      0:00 /bin/bash ./loop.sh

E ora possiamo uscire dalla bash chiamante. Il processo continua in esecuzione in background. Se abbandoniamo il suo PPID diventiamo 1 (processo init (1)) e il terminale di controllo diventa sconosciuto.

$ ps -f <PID>
UID        PID  PPID  C STIME TTY      STAT   TIME CMD
<UID>    <PID>     1  0 11:16 ?        S      0:00 /bin/bash ./loop.sh
$ /usr/bin/lsof -p <PID>
...
loop.sh <PID> truey    0u   CHR 136,36                38 /dev/pts/36 (deleted)
loop.sh <PID> truey    1u   REG   0,26     1127 15008411 /home/truey/loop.out
loop.sh <PID> truey    2u   CHR 136,36                38 /dev/pts/36 (deleted)

COMMENTO

Le cose di gdb possono essere automatizzate creando un file (ad esempio loop.gdb) contenente i comandi ed eseguendo <=>. Il mio loop.gdb è simile al seguente:

call close(1)
call open("loop.out", 01102, 0600)
# call close(2)
# call open("loop.err", 01102, 0600)
detach
quit

Oppure si può usare invece il seguente liner:

gdb -q -ex 'call close(1)' -ex 'call open("loop.out", 01102, 0600)' -ex detach -ex quit -p <PID>

Spero che questa sia una descrizione abbastanza completa della soluzione.

Per inviare il processo in esecuzione a nohup ( http://en.wikipedia.org/wiki/Nohup)

nohup -p pid, non ha funzionato per me

Quindi ho provato i seguenti comandi e ha funzionato molto bene

  1. Esegui SOMECOMMAND, dì /usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1.

  2. Ctrl + Z per interrompere (mettere in pausa) il programma e tornare alla shell.

  3. bg per eseguirlo in background.

  4. disown -h in modo che il processo non venga interrotto alla chiusura del terminale.

  5. Digita exit per uscire dalla shell perché ora sei a posto perché l'operazione verrà eseguita in background nel suo stesso processo, quindi non è legata a una shell.

Questo processo equivale all'esecuzione di nohup SOMECOMMAND.

Sul mio sistema AIX, ho provato

nohup -p  processid>

Questo ha funzionato bene. Ha continuato a eseguire il mio processo anche dopo aver chiuso le finestre del terminale. Abbiamo ksh come shell di default, quindi i comandi bg e disown non hanno funzionato.

  1. ctrl + z - questo interromperà il lavoro (non verrà annullato!)
  2. bg - questo metterà il lavoro in background e ritornerà nel processo in esecuzione
  3. disown -a - questo taglierà tutti gli allegati con il lavoro (in modo da poter chiudere il terminale e continuerà a funzionare)

Questi semplici passaggi ti permetteranno di chiudere il terminale mantenendo il processo in esecuzione.

Non inserirà nohup (in base alla mia comprensione della tua domanda, non ne hai bisogno qui).

Questo ha funzionato per me su Ubuntu Linux mentre era in tcshell.

  1. Ctrl Z per metterlo in pausa

  2. bg per l'esecuzione in background

  3. jobs per ottenere il numero di lavoro

  4. nohup %n dove n è il numero del lavoro

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top