J’ai un processus qui fonctionne déjà depuis longtemps et ne veut pas y mettre fin.
Comment puis-je le mettre sous nohup (c’est-à-dire comment le faire continuer à fonctionner même si je ferme le terminal?)
Utilisation du contrôle des tâches de bash pour envoyer le processus en arrière-plan:
bg
pour l’exécuter en arrière-plan. disown -h [job-spec]
où [spec-job] est le numéro de job (comme %1
pour le premier job en cours d’exécution; recherchez votre numéro avec la commande jobs
) pour que le job ne soit pas supprimé à la fermeture du terminal. Supposons que pour une raison quelconque, Ctrl + Z ne fonctionne pas non plus, accédez à un autre terminal, trouvez l’identifiant du processus (en utilisant ps
) et lancez:
kill -20 PID kill -18 PID
kill -20
( SIGTSTP
) suspendra le processus et kill -18
( SIGCONT
) reprendra le processus en arrière-plan. Alors maintenant, la fermeture de vos deux terminaux n’arrête pas votre processus.
La commande pour séparer un travail en cours d’exécution du shell (= le rend inutile) est disown
et une commande shell de base.
De bash-manpage (man bash):
désavouer [-ar] [-h] [jobspec …]
Sans options, chaque jobpec est supprimé de la table des jobs actifs. Si l’option -h est donnée, chaque jobpec n’est pas supprimé de la table, mais est marqué de manière à ce que SIGHUP ne soit pas envoyé au travail si le shell reçoit un SIGHUP. Si aucun jobpec n’est présent et que l’option -a ou -r n’est fournie, le travail en cours est utilisé. Si aucun jobpec n’est fourni, l’option -a signifie supprimer ou marquer tous les travaux; l’option -r sans argument jobspec limite le fonctionnement aux travaux en cours. La valeur de retour est 0 sauf si un jobpec ne spécifie pas un travail valide.
Cela signifie qu’un simple
disown -a
va supprimer tous les emplois de la table de travail et les rend nohup
Ce sont de bonnes réponses ci-dessus, je voulais juste append une précision:
Vous ne pouvez pas disown
un pid ou un processus, vous disown
un travail, et c’est une distinction importante.
Un travail est une notion de processus attaché à un shell. Par conséquent, vous devez lancer le travail en arrière-plan (sans le suspendre), puis le supprimer.
Problème:
% jobs [1] running java [2] suspended vi % disown %1
Voir http://www.quantprinciple.com/invest/index.php/docs/tipsandsortingcks/unix/jobcontrol/ pour une discussion plus détaillée du contrôle des tâches sous Unix.
Malheureusement, le rejet 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
qui peut être appliquée à un processus en cours d’exécution:
nohup -p pid
La réponse de Node est vraiment géniale, mais la question est de savoir comment redirect stdout et stderr. J’ai trouvé une solution sous Unix et Linux , mais ce n’est pas complet. Je voudrais fusionner ces deux solutions. C’est ici:
Pour mon test, j’ai réalisé un petit script bash appelé loop.sh, qui imprime le pid de lui-même avec une minute de sumil dans une boucle infinie.
$./loop.sh
Obtenez maintenant le PID de ce processus en quelque sorte. Habituellement, ps -C loop.sh
est suffisant, mais il est imprimé dans mon cas.
Maintenant, nous pouvons passer à un autre terminal (ou appuyer sur ^ Z et dans le même terminal). Maintenant, gdb
devrait être attaché à ce processus.
$ gdb -p
Cela arrête le script (s’il est en cours d’exécution). Son état peut être vérifié par ps -f
, où le champ STAT
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.
Cet open est égal à 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
indique “u” pour tous les gestionnaires de fichiers std * (colonne FD
), ce qui correspond à 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 le ferait nohup
, mais cela n’est pas suggéré par man open(2)
, à cause de problèmes NFS possibles.
Si nous obtenons -1 comme valeur de retour, call perror("")
imprime le message d’erreur. Si nous avons besoin de l’errno, utilisez p errno
gdb comand.
Maintenant, nous pouvons vérifier le fichier nouvellement redirigé. /usr/sbin/lsof -p
imprime:
loop.sh truey 1u REG 0,26 0 15008411 /home/truey/loop.out
Si nous le voulons, nous pouvons redirect stderr vers un autre fichier, si nous voulons utiliser call close(2)
et call open(...)
en utilisant un nom de fichier différent.
Maintenant, le bash
attaché doit être libéré et nous pouvons quitter gdb
:
(gdb) detach Detaching from program: /bin/bash, process (gdb) q
Si le script a été arrêté par gdb
depuis un autre terminal, il continue de fonctionner. Nous pouvons revenir au terminal loop.sh. Maintenant, il n’écrit 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 sums dans le même état que si ^Z
était pressé au début.)
Maintenant, nous pouvons vérifier l’état du travail:
$ ps -f 24522 UID PID PPID C STIME TTY STAT TIME CMD 0 11:16 pts/36 S 0:00 /bin/bash ./loop.sh $ jobs [1]+ Stopped ./loop.sh
Donc, le processus devrait être exécuté en arrière-plan et détaché du terminal. Le nombre entre crochets dans la commande des jobs
identifie le travail dans bash
. Nous pouvons utiliser les commandes bash
intégrées suivantes en appliquant un signe ‘%’ avant le numéro de travail:
$ bg %1 [1]+ ./loop.sh & $ disown -h %1 $ ps -f UID PID PPID C STIME TTY STAT TIME CMD 0 11:16 pts/36 S 0:00 /bin/bash ./loop.sh
Et maintenant, nous pouvons quitter le bash appelant. Le processus continue de fonctionner 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 UID PID PPID C STIME TTY STAT TIME CMD 1 0 11:16 ? S 0:00 /bin/bash ./loop.sh $ /usr/bin/lsof -p ... loop.sh truey 0u CHR 136,36 38 /dev/pts/36 (deleted) loop.sh truey 1u REG 0,26 1127 15008411 /home/truey/loop.out loop.sh truey 2u CHR 136,36 38 /dev/pts/36 (deleted)
COMMENTAIRE
Les fichiers gdb peuvent être automatisés en créant un fichier (par exemple loop.gdb) contenant les commandes et exécutez gdb -q -x loop.gdb -p
. 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 ligne suivante:
gdb -q -ex 'call close(1)' -ex 'call open("loop.out", 01102, 0600)' -ex detach -ex quit -p
J’espère que c’est une description assez complète de la solution.
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 fonctionné très bien
Exécutez SOMECOMMAND, par exemple /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
pour que le processus ne soit pas tué lorsque le terminal se ferme.
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, 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 de terminal. Nous avons ksh comme shell par défaut, donc les commandes bg
et disown
n’ont pas fonctionné.
bg
– cela va mettre le travail en arrière-plan et revenir en cours d’exécution disown -a
– cela va couper toute la pièce jointe avec le job (donc vous pouvez 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 à jour (selon ma compréhension de votre question, vous n’en avez pas besoin ici).
Cela a fonctionné pour moi sur Ubuntu Linux en tcshell.
Ctrl Z pour le mettre en pause
bg
pour courir en arrière-plan
jobs
pour obtenir son numéro de travail
nohup %n
où n est le numéro de job