Comment puis-je mettre un processus déjà en cours sous nohup?

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:

  1. Ctrl + Z pour arrêter (mettre en pause) le programme et revenir au shell.
  2. bg pour l’exécuter en arrière-plan.
  3. 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 

Voir http://en.wikipedia.org/wiki/Nohup

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

  1. Exécutez SOMECOMMAND, par exemple /usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1 .

  2. Ctrl + Z pour arrêter (mettre en pause) le programme et revenir au shell.

  3. bg pour l’exécuter en arrière-plan.

  4. disown -h pour que le processus ne soit pas tué lorsque le terminal se ferme.

  5. 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é.

  1. ctrl + z – cela mettra le travail en pause (ne pas annuler!)
  2. bg – cela va mettre le travail en arrière-plan et revenir en cours d’exécution
  3. 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.

  1. Ctrl Z pour le mettre en pause

  2. bg pour courir en arrière-plan

  3. jobs pour obtenir son numéro de travail

  4. nohup %n où n est le numéro de job