web-dev-qa-db-fra.com

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

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 (comment le faire continuer même si je ferme le terminal?)

878
flybywire

Utiliser le Job Control 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ù [job-spec] est le numéro du travail (comme %1 pour le premier travail en cours; recherchez votre numéro à l'aide de la commande jobs, de sorte que le travail ne soit pas supprimé lorsque le terminal ferme.
1297
Node

Supposons pour une raison quelconque Ctrl+Z ne fonctionne pas non plus, accédez à un autre terminal, recherchez l'ID du processus (à l'aide de 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ête pas votre processus.

166
Pungs

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ésavouer [-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 tâche spécifiée n'est pas supprimée de la table, mais est marquée de sorte que SIGHUP ne soit pas envoyé à la tâche si le shell reçoit un SIGHUP. Si aucune tâche n'est présente et que ni l'option -a ni l'option -r ne sont fournies, le travail en cours est utilisé. Si aucune tâche n'est fournie, l'option -a signifie supprimer ou marquer toutes les tâches. l'option -r sans l'argument jobspec limite l'opération à l'exécution des travaux. La valeur de retour est 0 sauf si jobspec ne spécifie pas de travail valide.

Cela signifie qu'un simple

disown -a

supprime tous les travaux de la table des travaux et les rend Nohup

85
serioys sam

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 une notion de processus associé à un shell. Vous devez donc le jeter en arrière-plan (et non 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.

70
Q Boiler

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 qui peut être appliquée à un processus en cours d'exécution:

Nohup -p pid

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

44
Dale

La réponse de Node 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 nix et Linux , mais elle n'est pas complète non plus. Je voudrais fusionner ces deux solutions. C'est ici:

Pour mon test, j'ai créé un petit script bash appelé loop.sh, qui affiche le pid de lui-même avec une minute de sommeil dans une boucle infinie.

$./loop.sh

Maintenant, obtenez le PID de ce processus en quelque sorte. Habituellement, ps -C loop.sh suffit, 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 devrait être associé à 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 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

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_RDWRO_WRONLY pourrait être appliqué, mais /usr/sbin/lsof dit 'u' pour tous les gestionnaires de fichiers std * (FD colonne), 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 peut être ouvert avec O_APPEND, comme le ferait Nohup, mais cela n’est pas suggéré par man open(2), en raison de problèmes possibles avec NFS.

Si nous obtenons -1 comme valeur de retour, alors call perror("") imprime le message d'erreur. Si nous avons besoin du code d'erreur, utilisez p errno gdb.

Nous pouvons maintenant vérifier le fichier récemment redirigé. /usr/sbin/lsof -p <PID> imprime:

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(...) encore en utilisant un nom de fichier différent.

Maintenant la bash attachée 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 à 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. Appuyez donc sur ^Z.

^Z
[1]+  Stopped                 ./loop.sh

(Nous sommes maintenant dans le même état que si ^Z avait été pressé 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 jobs identifie le travail à l'intérieur de bash. Nous pouvons utiliser dans les commandes intégrées suivantes bash appliquant 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)

COMMENT

Le fichier gdb peut être automatisé en créant un fichier (par exemple, loop.gdb) contenant les commandes et en exécutant 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 le liner suivant à 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 ceci est une description assez complète de la solution.

24
TrueY

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é

  1. Exécutez un certain SOMECOMMAND, dites /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 afin que le processus ne soit pas tué à la fermeture du terminal.

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

7
minhas23

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.

2
guest
  1. ctrl + z - cela mettra le travail en pause (ne pas annuler!)
  2. bg - cela mettra le travail en arrière-plan et retournera au processus en cours
  3. disown -a - cela 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).

1
hi-zir

Cela a fonctionné pour moi sur Ubuntu Linux tout en tcshell.

  1. CtrlZ faire une pause

  2. bg pour s'exécuter en arrière-plan

  3. jobs pour obtenir son numéro de travail

  4. Nohup %n où n est le numéro de travail

0
eshaya