it-swarm.it

Come posso eseguire un comando che sopravviverà alla chiusura del terminale?

A volte voglio iniziare un processo e non pensarci più. Se lo avvio dalla riga di comando, in questo modo:

redshift

Non riesco a chiudere il terminale, o ucciderà il processo. Posso eseguire un comando in modo tale da poter chiudere il terminale senza interrompere il processo?

339
Matthew

Uno dei seguenti 2 dovrebbe funzionare:

$ Nohup redshift &

o

$ redshift &
$ disown

Vedere di seguito per ulteriori informazioni su come funziona:

342
Steven D

Se il tuo programma è già in esecuzione puoi metterlo in pausa con Ctrl-Z, trascinalo sullo sfondo con bg e poi disown, in questo modo:

$ sleep 1000
^Z
[1]+  Stopped                 sleep 1000
$ bg
$ disown
$ exit
147
Stefan

na buona risposta è già pubblicata da @StevenD, ma penso che questo potrebbe chiarire un po 'di più.

Il motivo per cui il processo viene interrotto al termine del terminale è che il processo avviato è un processo figlio del terminale. Una volta chiuso il terminale, questo ucciderà anche questi processi figlio. Puoi vedere l'albero dei processi con pstree, ad esempio quando esegui kate & a Konsole:

init-+
     ├─konsole─┬─bash─┬─kate───2*[{kate}]
     │         │      └─pstree
     │         └─2*[{konsole}]

Per rendere il processo kate staccato da konsole quando si termina konsole, utilizzare Nohup con il comando, in questo modo:

Nohup kate &

Dopo aver chiuso konsole, pstree sarà simile al seguente:

init-+
     |-kate---2*[{kate}]

e kate sopravviveranno. :)

Un'alternativa sta usando screen/tmux/byobu, che manterrà Shell in esecuzione, indipendentemente dal terminale.

50
gertvdijk

È possibile eseguire il processo in questo modo nel terminale

setsid process

Questo eseguirà il programma in una nuova sessione. Come spiegato http://hanoo.org/index.php?article=run-program-in-new-session-linux

31
hanoo

Sebbene tutti i suggerimenti funzionino bene, ho scoperto che la mia alternativa è usare screen, un programma che imposta un terminale virtuale sullo schermo.

Potresti considerare di avviarlo con screen -S session_name. Lo schermo può essere installato praticamente su tutti i derivati ​​Linux e Unix. colpire Ctrl+A e (lettere minuscole) C inizierà una seconda sessione. Ciò ti consentirebbe di alternare tra la sessione iniziale e l'altra Ctrl+A e  o la sessione più recente colpendo Ctrl+A e 1. Puoi avere fino a dieci sessioni in un terminale. Avviavo una sessione di lavoro, tornavo a casa, ssh nella mia macchina di lavoro, quindi invocavo screen -d -R session_name. Questo ti riconnetterà a quella sessione remota.

10
apolinsky

Preferisco:

(nome dell'applicazione e)

ad esempio: [email protected]:~$ (chromium-browser &)

Assicurati di usare le parentesi quando digita il comando!

8
daGo

Ho una sceneggiatura per:

  • Esegui comandi arbitrari in background

  • Impedisci loro di essere uccisi con la finestra del terminale

  • Sopprime il loro output

  • Gestisce lo stato di uscita

Lo uso principalmente per gedit, evince, inkscape etc che hanno tutti un output terminale fastidioso. Se il comando termina prima di TIMEOUT, lo stato di uscita di Nohup viene restituito anziché zero.

#!/bin/bash

TIMEOUT=0.1

#use Nohup to run the command, suppressing its output and allowing the terminal to be closed
#also send Nohup's output to /dev/null, supressing Nohup.out
#run Nohup in the background so this script doesn't block
Nohup "${@}" >/dev/null 2>&1 &
Nohup_PID=$!

#kill this script after a short time, exiting with success status - command is still running
#this is needed as there is no timeout argument for `wait` below
MY_PID=$$
trap "exit 0" SIGINT SIGTERM
sleep $TIMEOUT && kill $MY_PID 2>/dev/null & #ignore "No such process" error if this exits normally

#if the command finishes before the above timeout, everything may be just fine or there could have been an error
wait $Nohup_PID
Nohup_STATUS=$?
#print an error if there was any. most commonly, there was a typo in the command
[ $Nohup_STATUS != 0 ] && echo "Error ${@}"
#return the exit status of Nohup, whatever it was
exit $Nohup_STATUS

esempi ...

>>> run true && echo success || echo fail
success
>>> run false && echo success || echo fail
Error false
fail
>>> run sleep 1000 && echo success || echo fail
success
>>> run notfound && echo success || echo fail
Error notfound
fail
7
jozxyqk

Il solo modo di Shell per fare tutto ciò è chiudere stdin e mettere in background il comando:

command <&- & 

Quindi non si chiuderà quando si chiude Shell. Il reindirizzamento di stdout è una cosa facoltativa da fare.

Lo svantaggio è che non puoi farlo dopo il fatto.

7
w00t

È possibile impostare un processo (PID) per non ricevere un segnale HUP al momento della disconnessione e della chiusura della sessione del terminale. Utilizzare il comando seguente:

Nohup -p PID
4
tony

Probabilmente simile al risposta offerta da apolinsky , utilizzo una variante su screen. Il comando Vanilla è così

screen bash -c 'long_running_command_here; echo; read -p "ALL DONE:"'

La sessione può essere disconnessa con Ctrl ACtrl D e ricollegato nel caso semplice con screen -r. L'ho racchiuso in uno script chiamato session che vive nel mio PATH pronto per un comodo accesso:

#!/bin/bash
#
if screen -ls | awk '$1 ~ /^[1-9][0-9]*\.'"$1"'/' >/dev/null
then
    echo "WARNING: session is already running (reattach with 'screen -r $1')" >&2
else
    exec screen -S "$1" bash -c "[email protected]; echo; echo '--------------------'; read -p 'ALL DONE (Enter to exit):'"
    echo "ERROR: 'screen' is not installed on this system" >&2
fi
exit 1

Funziona solo quando sai in anticipo che vuoi disconnettere un programma. Non prevede la disconnessione di un programma già in esecuzione .

3
roaima

Analogamente ad altre risposte precedentemente pubblicate, è possibile trasferire un processo in esecuzione per utilizzare retrospettivamente lo "schermo" grazie a reptyr e quindi chiudere il terminale. I passaggi sono descritti in questo post . I passi da compiere sono:

  1. Sospendi il processo
  2. Riprendi il processo in background
  3. Nega il processo
  4. Avvia una sessione schermo
  5. Trova il PID del processo
  6. Utilizzare reptyr per assumere il controllo del processo
2
user308879