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

j'ai un processus qui est déjà en cours 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 continuer à fonctionner même si je ferme le terminal?)

789
demandé sur Peter Mortensen 2009-03-09 11:33:37

10 réponses

utilisant le Job Control de bash pour envoyer le processus dans l'arrière-plan:

  1. Ctrl + Z pour arrêter (pause) le programme et revenir à l'interpréteur de commandes.
  2. bg pour l'exécuter en arrière-plan.
  3. disown -h [job-spec] où [job-spec] est le numéro d'emploi (comme %1 pour le premier emploi en cours d'exécution; trouver à propos de votre numéro avec le jobs ) afin que le travail ne soit pas tué lorsque le terminal ferme.
1177
répondu Node 2014-05-21 00:19:14

Suppose pour une raison quelconque Ctrl + Z ne fonctionne pas non plus, aller à un autre terminal, trouver le numéro du processus (en utilisant ps ) et exécuter:

kill -20 PID 
kill -18 PID

kill -20 ( SIGTSTP ) va suspendre le processus et kill -18 ( SIGCONT ) va reprendre le processus, en arrière-plan. Donc maintenant, fermer vos deux terminaux n'arrêtera pas votre processus.

146
répondu Pungs 2015-11-01 00:27:00

la commande pour séparer un travail en cours d'exécution du shell ( = le rend nohup) est disown et une commande-shell de base.

De bash-page de manuel (man bash):

désavouer [ar] [-h] [jobspec ...]

sans options, chaque jobspec est retiré du tableau des emplois actifs. Si l'option-h est donnée, chaque jobspec n'est pas retiré de la table, mais est marqué de sorte que SIGHUP ne soit pas envoyé à la tâche si le shell reçoit un soupir. Si aucun jobpec n'est l'emploi actuel est utilisé, et ni l'option-a ni l'option-r ne sont fournies. Si aucun jobpec n'est fourni, l'option-a signifie supprimer ou marquer tous les emplois; l'option-r sans argument jobspec restreint l'exploitation aux emplois courants. Retour la valeur est 0 sauf si un jobspec ne spécifie pas un emploi valide.

cela signifie qu'un simple

disown -a

va supprimer tous les emplois de la cents cinquante et une million neuf cent trente mille neuf cent vingt"

76
répondu serioys sam 2017-11-02 23:18:17

ce sont de bonnes réponses ci-dessus, je voulais juste ajouter une clarification:

Vous ne pouvez pas disown un pid ou un processus, 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 à l'arrière-plan (pas le suspendre) et ensuite le rejeter.

Question:

%  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 le contrôle des tâches Unix.

62
répondu Q Boiler 2014-05-21 00:20:34

Unrfortunately disown est spécifique à bash et ne sont pas disponibles dans tous les shells.

certaines saveurs 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

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

36
répondu Dale 2014-05-21 00:21:03

la réponse de noeud est vraiment grande, mais il a laissé ouvert la question Comment peut obtenir stdout et stderr redirigé. J'ai trouvé une solution sur Unix & Linux , mais elle n'est pas non plus complète. Je voudrais fusionner ces deux solutions. Le voici:

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 obtenir le PID de ce processus d'une certaine manière. Généralement ps -C loop.sh est 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>

ceci arrête le script (s'il tourne). 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)
 = 0

À proximité(1) renvoie zéro en cas de succès.

(gdb) call open("loop.out", 01102, 0600)
 = 1

Ouvrir (1) renvoie le nouveau descripteur de fichier s'il est réussi.

Cette ouverture 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 dit" u "pour tous les gestionnaires de fichiers std* ( FD colonne), qui est O_RDWR .

j'ai vérifié les valeurs dans /usr/include/bits/fcntl.h fichier d'en-tête.

la sortie le fichier peut être ouvert avec O_APPEND , nohup allait faire, mais ce n'est pas suggéré par man open(2) , en raison de possibles problèmes NFS.

si nous obtenons -1 comme valeur de retour, alors call perror("") affiche 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 <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 file, si nous voulons utiliser call close(2) et call open(...) à nouveau en utilisant un nom de fichier différent.

maintenant le bash ci-joint doit être libéré 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 d'un autre terminal, il continue à fonctionner. On peut revenir à loop.sh le terminal. Maintenant, il n'écrit plus rien à l'écran, mais exécute et écrit dans le fichier. Nous devons le mettre dans le fond. Appuyez sur ^Z .

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

(Maintenant nous sommes dans le même état que si ^Z a été 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
<UID>    <PID><PPID>  0 11:16 pts/36   S      0:00 /bin/bash ./loop.sh
$ jobs
[1]+  Stopped                 ./loop.sh

ainsi le processus doit être exécuté en arrière-plan et détaché du terminal. Le numéro entre crochets de la commande jobs identifie le travail à l'intérieur de bash . Nous pouvons utiliser dans les suivants construit en bash commandes 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, on peut arrêter la fête de l'appel. Le processus est encore en cours d'exécution en arrière-plan. Si nous quittons son PPID 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 truc gdb peut être automatisé en créant un fichier (par exemple boucle.gdb) contenant les commandes et lancez gdb -q -x loop.gdb -p <PID> . Ma boucle.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.

21
répondu TrueY 2017-04-13 12:36:27

pour envoyer processus en cours d'exécution à nohup ( http://en.wikipedia.org/wiki/Nohup )

nohup -p pid , il n'a pas fonctionné pour moi

puis j'ai essayé les commandes suivantes et ça a très bien fonctionné

  1. Run some SOMECOMMAND, dis /usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1 .

  2. Ctrl + Z à l'arrêt (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é quand le terminal ferme.

  5. Type exit pour sortir du shell parce que maintenant vous êtes bon à aller car l'opération va courir en arrière-plan dans son propre processus, donc il n'est pas lié à un shell.

ce processus est l'équivalent de nohup SOMECOMMAND .

6
répondu minhas23 2014-05-21 00:17:47

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 donc les commandes bg et disown n'ont pas fonctionné.

1
répondu guest 2014-05-21 00:18:26
  1. Ctrl + z - cela va interrompre le travail (ne va pas annuler!)
  2. bg - cela placera le travail en arrière-plan et le retour dans le processus en cours d'exécution
  3. disown -a - cela va couper toute la fixation avec job (de sorte que vous pouvez fermer le terminal et il fonctionnera toujours)

ces simples étapes vous permettront de fermer le terminal tout en gardant processus en cours d'exécution.

il ne mettra pas sur nohup (basé sur ma compréhension de votre question, vous n'en avez pas besoin ici).

1
répondu hi-zir 2018-04-20 16:00:33

cela a fonctionné pour moi sur Ubuntu linux tout en tcshell.

  1. Ctrl Z mettre en pause

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

  3. jobs pour obtenir son numéro d'emploi

  4. nohup %n où n est le numéro d'emploi

0
répondu eshaya 2018-04-13 02:32:58