Parfois, je veux démarrer un processus et l'oublier. Si je le démarre à partir de la ligne de commande, comme ceci:
redshift
Je ne peux pas fermer le terminal, sinon cela tuera le processus. Puis-je exécuter une commande de manière à pouvoir fermer le terminal sans tuer le processus?
L'un des 2 suivants devrait fonctionner:
$ Nohup redshift &
ou
$ redshift &
$ disown
Voir ce qui suit pour un peu plus d'informations sur la façon dont cela fonctionne:
man Nohup
help disown
Différence entre Nohup, disown et & (assurez-vous de lire également les commentaires)
Si votre programme est déjà en cours d'exécution vous pouvez le mettre en pause avec Ctrl-Z
, tirez-le en arrière-plan avec bg
puis disown
, comme ceci:
$ sleep 1000
^Z
[1]+ Stopped sleep 1000
$ bg
$ disown
$ exit
ne bonne réponse est déjà publiée par @StevenD, mais je pense que cela pourrait clarifier un peu plus.
La raison pour laquelle le processus est tué à la fin du terminal est que le processus que vous démarrez est un processus enfant du terminal. Une fois le terminal fermé, cela supprimera également ces processus enfants. Vous pouvez voir l'arborescence des processus avec pstree
, par exemple lorsque vous exécutez kate &
à Konsole:
init-+
├─konsole─┬─bash─┬─kate───2*[{kate}]
│ │ └─pstree
│ └─2*[{konsole}]
Pour séparer le processus kate
de konsole
lorsque vous terminez konsole
, utilisez Nohup
avec la commande, comme ceci:
Nohup kate &
Après la fermeture de konsole
, pstree
ressemblera à ceci:
init-+
|-kate---2*[{kate}]
et kate
survivra. :)
Une alternative utilise screen
/tmux
/byobu
, qui maintiendra le shell en cours d'exécution, indépendamment du terminal.
Vous pouvez exécuter le processus comme ceci dans le terminal
setsid process
Cela exécutera le programme dans une nouvelle session. Comme expliqué http://hanoo.org/index.php?article=run-program-in-new-session-linux
Bien que toutes les suggestions fonctionnent bien, j'ai trouvé que mon alternative est d'utiliser screen
, un programme qui configure un terminal virtuel sur votre écran.
Vous pourriez envisager de le démarrer avec screen -S session_name
. Screen peut être installé sur pratiquement tous les dérivés Linux et Unix. Frappe Ctrl+A et (minuscule) C va commencer une deuxième session. Cela vous permettrait de basculer entre la session initiale en appuyant sur Ctrl+A et ou la session la plus récente en appuyant sur Ctrl+A et 1. Vous pouvez avoir jusqu'à dix sessions dans un même terminal. J'avais l'habitude de démarrer une session au travail, de rentrer à la maison, de lancer ssh sur ma machine de travail, puis d'appeler screen -d -R session_name
. Cela vous reconnectera à cette session distante.
Je préfère:
(Nom de l'application et)
par exemple: linux@linux-desktop:~$ (chromium-browser &)
Assurez-vous d'utiliser des parenthèses lorsque vous tapez la commande!
J'ai un script pour:
Je l'utilise principalement pour gedit
, evince
, inkscape
etc qui ont tous beaucoup de sorties de terminaux ennuyeuses. Si la commande se termine avant TIMEOUT
, l'état de sortie de Nohup est renvoyé au lieu de zéro.
#!/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
exemples...
>>> 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
La manière Shell uniquement de faire tout cela est de fermer stdin et d'arrière-plan la commande:
command <&- &
Ensuite, il ne se fermera pas lorsque vous quitterez le shell. Rediriger stdout est une option facultative intéressante.
L'inconvénient est que vous ne pouvez pas le faire après coup.
Vous pouvez définir un processus (PID) pour ne pas recevoir de signal HUP lors de la déconnexion et de la fermeture de la session de terminal. Utilisez la commande suivante:
Nohup -p PID
Sans doute similaire à la réponse offerte par apolinsky , j'utilise une variante sur screen
. La commande Vanilla est comme ça
screen bash -c 'long_running_command_here; echo; read -p "ALL DONE:"'
La session peut être déconnectée avec Ctrl ACtrl D et reconnecté dans le cas simple avec screen -r
. Je l'ai enveloppé dans un script appelé session
qui vit dans mon PATH
prêt pour un accès pratique:
#!/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 "$@; echo; echo '--------------------'; read -p 'ALL DONE (Enter to exit):'"
echo "ERROR: 'screen' is not installed on this system" >&2
fi
exit 1
Cela ne fonctionne que si vous savez à l'avance que vous souhaitez déconnecter un programme. Il ne prévoit pas qu'un programme déjà en cours d'exécution soit déconnecté.
Comme pour les autres réponses publiées précédemment, on peut transférer un processus en cours pour utiliser "screen" rétrospectivement grâce à reptyr puis fermer le terminal. Les étapes sont décrites dans ce post . Les étapes à suivre sont les suivantes: