J'ai un processus qui fonctionne déjà depuis longtemps et je ne veux pas y mettre fin.
Comment le placer sous nohup (c'est-à-dire comment le faire continuer à fonctionner même si je ferme le terminal?)
J'ai un processus qui fonctionne déjà depuis longtemps et je ne veux pas y mettre fin.
Comment le placer sous nohup (c'est-à-dire comment le faire continuer à fonctionner même si je ferme le terminal?)
Réponses:
Utilisation du Job Control de bash pour envoyer le processus en arrière-plan:
bg
pour l'exécuter en arrière-plan.disown -h [job-spec]
où [job-spec] est le numéro de la tâche (comme %1
pour la première tâche en cours d'exécution; recherchez votre numéro avec la jobs
commande) afin que la tâche ne soit pas supprimée à la fermeture du terminal.disown -h
peut-être la réponse la plus exacte: "faire en sorte que désavoué se comporte plus comme nohup (c'est-à-dire que les travaux resteront dans l'arbre de processus de votre shell actuel jusqu'à ce que vous quittiez votre shell). Cela vous permet de voir tous les travaux que cet obus a commencé. " (depuis [ quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/… )
disown
, disown fait d'un processus un démon, ce qui signifie que les entrées / sorties standard sont redirigées vers / dev / null. Donc, si vous envisagez de renoncer à un travail, il vaut mieux le démarrer en vous connectant à un fichier, par exemplemy_job_command | tee my_job.log
Supposons que pour une raison quelconque Ctrl+ Zne fonctionne pas non plus, allez sur un autre terminal, trouvez l'identifiant du processus (en utilisant ps
) et exécutez:
kill -SIGSTOP PID
kill -SIGCONT PID
SIGSTOP
suspendra le processus et SIGCONT
reprendra le processus en arrière-plan. Alors maintenant, la fermeture de vos deux terminaux n'arrêtera pas votre processus.
disown %1
dans le premier terminal avant de le fermer.
kwin
après un crash sans penser aux conséquences). Donc, si j'avais arrêté kwin, tout aurait gelé et je n'avais aucune possibilité de courir bg
!
La commande pour séparer un travail en cours d'exécution du shell (= ne le fait pas) est disown
une commande shell de base.
Depuis bash-manpage (man bash):
renoncer [-ar] [-h] [jobspec ...]
Sans option, chaque spécification de tâche est supprimée de la table des tâches actives. Si l'option -h est donnée, chaque spécification de travail n'est pas supprimée de la table, mais est marquée de sorte que SIGHUP ne soit pas envoyé au travail si le shell reçoit un SIGHUP. Si aucune spécification de tâche n'est présente et que ni l'option -a ni l'option -r n'est fournie, la tâche actuelle est utilisée. Si aucune spécification de tâche n'est fournie, l'option -a signifie supprimer ou marquer toutes les tâches; l'option -r sans argument jobspec limite l'opération aux travaux en cours d'exécution. La valeur de retour est 0, sauf si une spécification de travail ne spécifie pas de travail valide.
Cela signifie qu'un simple
disown -a
supprimera tous les travaux de la table des travaux et les rendra nohup
disown -a
supprime tous les travaux. Un simple disown
supprime uniquement le travail en cours. Comme le dit la page de manuel de la réponse.
Ce sont de bonnes réponses ci-dessus, je voulais juste ajouter une clarification:
Vous ne pouvez pas disown
un pid ou un processus, vous disown
un travail, et c'est une distinction importante.
Un travail est quelque chose qui est une notion d'un processus qui est attaché à un shell, donc vous devez jeter le travail en arrière-plan (pas le suspendre), puis le renier.
Problème:
% jobs
[1] running java
[2] suspended vi
% disown %1
Voir http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/ pour une discussion plus détaillée sur Unix Job Control.
Malheureusement, disown
est spécifique à bash et n'est pas disponible dans tous les shells.
Certaines versions d'Unix (par exemple AIX et Solaris) ont une option sur la nohup
commande elle-même qui peut être appliquée à un processus en cours d'exécution:
nohup -p pid
AIX
et Solaris
. "Les versions AIX et Solaris de nohup ont une option -p qui modifie un processus en cours pour ignorer les futurs signaux SIGHUP. Contrairement à la fonction de désabonnement de bash décrite ci-dessus, nohup -p accepte les ID de processus.". Source
La réponse de Node est vraiment excellente, mais elle a laissé ouverte la question de savoir comment obtenir stdout et stderr redirigés. J'ai trouvé une solution sur Unix et Linux , mais elle n'est pas non plus complète. Je voudrais fusionner ces deux solutions. C'est ici:
Pour mon test, j'ai fait un petit script bash appelé loop.sh, qui imprime le pid de lui-même avec une minute de sommeil dans une boucle infinie.
$./loop.sh
Maintenant, obtenez le PID de ce processus d'une manière ou d'une autre. ps -C loop.sh
Est généralement assez bon, mais il est imprimé dans mon cas.
Maintenant, nous pouvons passer à un autre terminal (ou appuyez sur ^ Z et dans le même terminal). Maintenant gdb
devrait être attaché à ce processus.
$ gdb -p <PID>
Cela arrête le script (s'il est en cours d'exécution). Son état peut être vérifié par ps -f <PID>
, où le STAT
champ est 'T +' (ou en cas de ^ Z 'T'), ce qui signifie (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
Close (1) renvoie zéro en cas de succès.
(gdb) call open("loop.out", 01102, 0600)
$6 = 1
Open (1) renvoie le nouveau descripteur de fichier en cas de succès.
Cette ouverture est égale à open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)
. Au lieu de O_RDWR
O_WRONLY
pourrait être appliqué, mais /usr/sbin/lsof
dit «u» pour tous les gestionnaires de fichiers std * ( FD
colonne), ce qui est O_RDWR
.
J'ai vérifié les valeurs dans le fichier d'en-tête /usr/include/bits/fcntl.h.
Le fichier de sortie pourrait être ouvert avec O_APPEND
, comme ce nohup
serait le cas, mais cela n'est pas suggéré par man open(2)
, en raison de problèmes NFS possibles.
Si nous obtenons -1 comme valeur de retour, call perror("")
imprime alors le message d'erreur. Si nous avons besoin de l'errno, utilisez la commande p errno
gdb.
Nous pouvons maintenant vérifier le fichier nouvellement redirigé. /usr/sbin/lsof -p <PID>
impressions:
loop.sh <PID> truey 1u REG 0,26 0 15008411 /home/truey/loop.out
Si nous voulons, nous pouvons rediriger stderr vers un autre fichier, si nous voulons utiliser call close(2)
et à call open(...)
nouveau en utilisant un nom de fichier différent.
Maintenant, la pièce jointe bash
doit être libérée et nous pouvons quitter gdb
:
(gdb) detach
Detaching from program: /bin/bash, process <PID>
(gdb) q
Si le script a été arrêté par gdb
un autre terminal, il continue de s'exécuter. Nous pouvons revenir au terminal de loop.sh. Maintenant, il n'écrit plus rien à l'écran, mais s'exécute et écrit dans le fichier. Nous devons le mettre en arrière-plan. Alors appuyez sur ^Z
.
^Z
[1]+ Stopped ./loop.sh
(Maintenant, nous sommes dans le même état que si on ^Z
avait appuyé au début.)
Nous pouvons maintenant vérifier l'état de la tâche:
$ 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
Le processus doit donc être exécuté en arrière-plan et détaché du terminal. Le nombre dans la jobs
sortie de la commande entre crochets identifie le travail à l'intérieur bash
. Nous pouvons utiliser les bash
commandes intégrées suivantes en appliquant un signe «%» avant le numéro de travail:
$ 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
Et maintenant, nous pouvons quitter le bash appelant. Le processus continue de s'exécuter en arrière-plan. Si nous quittons son PPID, il devient 1 (processus init (1)) et le terminal de commande devient inconnu.
$ 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)
COMMENTAIRE
Le truc gdb peut être automatisé en créant un fichier (par exemple loop.gdb) contenant les commandes et exécuter gdb -q -x loop.gdb -p <PID>
. Mon loop.gdb ressemble à ceci:
call close(1)
call open("loop.out", 01102, 0600)
# call close(2)
# call open("loop.err", 01102, 0600)
detach
quit
Ou on peut utiliser la doublure suivante à la place:
gdb -q -ex 'call close(1)' -ex 'call open("loop.out", 01102, 0600)' -ex detach -ex quit -p <PID>
J'espère que c'est une description assez complète de la solution.
lsof
(le nom du descripteur de fichier est pipe
, pas comme /dev/pts/1
) ou ls -l /proc/<PID>/fd/<fd>
(cela montre le lien symbolique de la poignée). De même, les sous-processus peuvent toujours ne pas avoir redirigé les sorties, qui doivent être redirigées vers un fichier.
Pour envoyer le processus en cours à nohup ( http://en.wikipedia.org/wiki/Nohup )
nohup -p pid
, ça n'a pas marché pour moi
Ensuite, j'ai essayé les commandes suivantes et cela a très bien fonctionné
Exécutez SOMECOMMAND, par exemple /usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1
.
Ctrl+ Zpour arrêter (mettre en pause) le programme et revenir au shell.
bg
pour l'exécuter en arrière-plan.
disown -h
afin que le processus ne soit pas interrompu à la fermeture du terminal.
Tapez exit
pour sortir du shell car maintenant vous êtes prêt à partir car l'opération s'exécutera en arrière-plan dans son propre processus, donc elle n'est pas liée à un shell.
Ce processus est équivalent à l'exécution nohup SOMECOMMAND
.
bg
- cela mettra le travail en arrière-plan et reviendra dans le processus en coursdisown -a
- cela coupera toute la pièce jointe avec le travail (vous pouvez donc fermer le terminal et il fonctionnera toujours)Ces étapes simples vous permettront de fermer le terminal tout en maintenant le processus en cours.
Il ne sera pas mis nohup
(selon ma compréhension de votre question, vous n'en avez pas besoin ici).
Cela a fonctionné pour moi sur Ubuntu linux en tcshell.
CtrlZ pour le mettre en pause
bg
courir en arrière-plan
jobs
pour obtenir son numéro de travail
nohup %n
où n est le numéro de tâche
nohup: failed to run command '%1': No such file or directory
yourExecutable &
et que les sorties continuent à apparaître sur l'écran etCtrl+C
ne semblent rien arrêter, tapez simplement aveuglémentdisown;
et appuyezEnter
même si l'écran défile avec les sorties et que vous ne pouvez pas voir ce que vous tapez. Le processus sera désavoué et vous pourrez fermer le terminal sans que le processus ne meure.