Comment puis-je mettre un processus déjà en cours sous nohup?
Question
J'ai un processus en cours d'exécution depuis longtemps et je ne veux pas y mettre fin.
Comment puis-je le mettre sous nohup (c’est-à-dire, comment puis-je le faire fonctionner même si je ferme le terminal?)
La solution
Utilisation du Contrôle des travaux de bash pour envoyer le processus dans le fond:
- Ctrl + Z pour arrêter (mettre en pause) le programme et revenir au shell.
-
bg
pour l'exécuter en arrière-plan. -
disown -h [job-spec]
où [spéc-type de travail] est le numéro du travail (comme%1
pour le premier travail en cours d'exécution; recherchez votre numéro à l'aide de la commandejobs
) afin que le travail ne soit pas supprimé à la fermeture du terminal .
Autres conseils
Supposons que, pour une raison quelconque, Ctrl + Z ne fonctionne pas non plus, accédez à un autre terminal, recherchez l'identifiant du processus (avec ps
) et exécutez:
kill -SIGSTOP PID
kill -SIGCONT PID
SIGSTOP
suspend le processus et SIGCONT
le reprend en arrière-plan. Alors maintenant, la fermeture de vos deux terminaux n’arrête pas votre processus.
La commande permettant de séparer un travail en cours d'exécution du shell (= = nohup) est disown
et une commande shell de base.
De bash-manpage (man bash):
désavoué [-ar] [-h] [jobspec ...]
Sans options, chaque tâche spécifiée est supprimée du tableau des tâches actives. Si l'option -h est donnée, chaque jobpec n'est pas supprimé de la table, mais est marqué de sorte que SIGHUP ne soit pas envoyé au travail si le shell reçoit un message SIGHUP. Si aucun jobpec n'est Si l'option -a ou l'option -r n'est pas fournie, le travail en cours est utilisé. Si aucun jobpec n’est fourni, l’option -a moyen de supprimer ou de marquer tous les travaux; l'option -r sans l'argument jobspec limite l'opération à l'exécution des travaux. Le retour la valeur est 0 sauf si un jobpec ne spécifie pas de travail valide.
Cela signifie qu’un simple
disown -a
supprimera toutes les tâches de la table des tâches et les rendra nulles
Ce sont de bonnes réponses ci-dessus, je voulais juste ajouter une clarification:
Vous ne pouvez pas disown
créer un pid ou un processus, vous <=> un travail, et c'est une distinction importante.
Un travail est une notion de processus attaché à un shell. Vous devez donc le jeter 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 du contrôle des tâches Unix.
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 commande nohup
elle-même qui peut être appliquée à un processus en cours d'exécution:
nohup -p pid
La réponse du nœud est vraiment géniale, mais elle laisse ouverte la question de savoir comment obtenir stdout et stderr redirigés. J'ai trouvé une solution sur Unix & Amp; Linux , mais ce n’est pas non plus complet. Je voudrais fusionner ces deux solutions. La voici:
Pour mon test, j'ai créé un petit script bash appelé loop.sh, qui affiche son pid avec une minute de sommeil dans une boucle infinie.
$./loop.sh
Maintenant, récupérez le PID de ce processus d’une manière ou d’une autre. Habituellement, ps -C loop.sh
est suffisant, mais il est imprimé dans mon cas.
Nous pouvons maintenant passer à un autre terminal (ou appuyer sur ^ Z et dans le même terminal). Maintenant, gdb
doit être associé à ce processus.
$ gdb -p <PID>
Ceci arrête le script (s'il est en cours d'exécution). Son état peut être vérifié par ps -f <PID>
, où le champ STAT
est 'T +' (ou dans le 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
Fermer (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), qui est O_APPEND
.
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 nohup
, comme le ferait man open(2)
, mais cela n'est pas suggéré par call perror("")
, en raison de problèmes NFS possibles.
Si nous obtenons -1 comme valeur de retour, alors p errno
affiche le message d'erreur. Si nous avons besoin du code d'erreur, utilisez /usr/sbin/lsof -p <PID>
la commande gdb.
Nous pouvons maintenant vérifier le fichier récemment redirigé. call close(2)
impressions:
loop.sh <PID> truey 1u REG 0,26 0 15008411 /home/truey/loop.out
Si nous le voulons, nous pouvons rediriger stderr vers un autre fichier, si nous voulons utiliser call open(...)
et bash
à nouveau en utilisant un nom de fichier différent.
Il faut maintenant libérer le fichier attaché ^Z
et nous pouvons quitter jobs
:
(gdb) detach
Detaching from program: /bin/bash, process <PID>
(gdb) q
Si le script a été arrêté par gdb -q -x loop.gdb -p <PID>
à partir d'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’écrit et s’écrit dans le fichier. Nous devons le mettre en arrière-plan. Alors appuyez sur <=>.
^Z
[1]+ Stopped ./loop.sh
(Nous sommes maintenant dans le même état que si <=> avait été enfoncé au début.)
Nous pouvons maintenant vérifier l'état du travail:
$ 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 entre crochets dans la sortie de la commande <=> identifie le travail contenu dans <=>. Nous pouvons utiliser dans les suivantes <=> commandes intégrées portant le 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 la bash d’appel. 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 contrôle 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 contenu de gdb peut être automatisé en créant un fichier (par exemple, loop.gdb) contenant les commandes, puis en exécutant <=>. 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
Vous pouvez également utiliser le liner suivant:
gdb -q -ex 'call close(1)' -ex 'call open("loop.out", 01102, 0600)' -ex detach -ex quit -p <PID>
J'espère qu'il s'agit d'une description assez complète de la solution.
Pour envoyer le processus en cours à nohup ( http://fr.wikipedia.org/wiki/Nohup)
nohup -p pid
, cela n'a pas fonctionné pour moi
Ensuite, j'ai essayé les commandes suivantes et cela a très bien fonctionné
-
Lancez un certain SOMECOMMAND, dire
/usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1
. -
Ctrl + Z pour 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 tué à la fermeture du terminal. -
Tapez
exit
pour sortir du shell, car vous pouvez maintenant y aller car l'opération s'exécute en arrière-plan dans son propre processus, elle n'est donc pas liée à un shell.
Ce processus équivaut à exécuter nohup SOMECOMMAND
.
Sur mon système AIX, j'ai essayé
.nohup -p processid>
Cela a bien fonctionné. Il a continué à exécuter mon processus même après la fermeture des fenêtres du terminal. Nous avons ksh comme shell par défaut pour que les commandes bg
et disown
ne fonctionnent pas.
- ctrl + z - le travail sera mis en pause (ne sera pas annulé!)
-
bg
- cela mettra le travail en arrière-plan et reviendra dans le processus en cours -
disown -a
- Ceci coupera toute la pièce jointe avec le travail (vous pourrez donc fermer le terminal et le lancer encore)
Ces étapes simples vous permettront de fermer le terminal tout en maintenant le processus en cours.
Il ne sera pas mis sur nohup
(d'après ce que j'ai compris de votre question, vous n'en avez pas besoin ici).
Cela a fonctionné pour moi sur Ubuntu Linux tout en tcshell.
-
Ctrl Z pour le suspendre
-
bg
à exécuter en arrière-plan -
jobs
pour obtenir son numéro de travail -
nohup %n
où n est le numéro de travail