Pour toute personne confrontée au même problème: rappelez-vous que même si vous tapez yourExecutable &et que les sorties continuent à apparaître sur l'écran et Ctrl+Cne semblent rien arrêter, tapez simplement aveuglément disown;et appuyez Entermême si l'écran défile avec les sorties et que vous ne pouvez pas voir ce que vous tapez. Le processus sera désavoué et vous pourrez fermer le terminal sans que le processus ne meure.
Nav
Réponses:
1367
Utilisation du Job Control de bash pour envoyer le processus en arrière-plan:
Ctrl+ Zpour 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ù [job-spec] est le numéro de la tâche (comme %1pour la première tâche en cours d'exécution; recherchez votre numéro avec la jobscommande) afin que la tâche ne soit pas supprimée à la fermeture du terminal.
Comme la question était de savoir comment "le mettre sous nohup", c'est disown -hpeut-être la réponse la plus exacte: "faire en sorte que désavoué se comporte plus comme nohup (c'est-à-dire que les travaux resteront dans l'arbre de processus de votre shell actuel jusqu'à ce que vous quittiez votre shell). Cela vous permet de voir tous les travaux que cet obus a commencé. " (depuis [ quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/… )
-Philip Gehrcke
8
Comment récupérer le travail plus tard? Je peux le voir fonctionner en utilisant ps -e.
Paulo Casaretto
26
Vous ne pouvez pas voir la sortie d'un travail après un disown, disown fait d'un processus un démon, ce qui signifie que les entrées / sorties standard sont redirigées vers / dev / null. Donc, si vous envisagez de renoncer à un travail, il vaut mieux le démarrer en vous connectant à un fichier, par exemplemy_job_command | tee my_job.log
rustyx
8
est-il possible de faire quelque chose comme 'my_job_command | tee my_job.log ' après l' exécution de la commande?
2012 à 12h53
23
disowndissocie tous les tuyaux du processus. Pour rattacher des tuyaux, utilisez gdbcomme décrit dans ce fil . Plus précisément, ce poste .
mbrownnyc
185
Supposons que pour une raison quelconque Ctrl+ Zne fonctionne pas non plus, allez sur un autre terminal, trouvez l'identifiant du processus (en utilisant ps) et exécutez:
kill -SIGSTOP PID
kill -SIGCONT PID
SIGSTOPsuspendra le processus et SIGCONTreprendra le processus en arrière-plan. Alors maintenant, la fermeture de vos deux terminaux n'arrêtera pas votre processus.
Oui, c'est un problème de système d'exploitation, kill ne fonctionne pas avec Cygwin sous Windows.
Pungs
6
Très utile également si le travail est démarré à partir d'une autre session ssh.
Amir Ali Akbari, du
5
N'oubliez pas de faire le disown %1dans le premier terminal avant de le fermer.
Fred
1
C'est utile puisque j'ai démarré une interface graphique avec une console (dans mon cas je suis parti de konsole kwinaprès un crash sans penser aux conséquences). Donc, si j'avais arrêté kwin, tout aurait gelé et je n'avais aucune possibilité de courir bg!
Michele
@fred Je n'ai pas fait ça et ça a semblé continuer à fonctionner. Possible ou ai-je atteint le mauvais PID?
Personne le
91
La commande pour séparer un travail en cours d'exécution du shell (= ne le fait pas) est disownune commande shell de base.
Depuis bash-manpage (man bash):
renoncer [-ar] [-h] [jobspec ...]
Sans option, chaque spécification de tâche est supprimée de la table des tâches actives. Si l'option -h est donnée, chaque spécification de travail n'est pas supprimée de la table, mais est marquée de sorte que SIGHUP ne soit pas envoyé au travail si le shell reçoit un SIGHUP. Si aucune spécification de tâche n'est présente et que ni l'option -a ni l'option -r n'est fournie, la tâche actuelle est utilisée. Si aucune spécification de tâche n'est fournie, l'option -a signifie supprimer ou marquer toutes les tâches; l'option -r sans argument jobspec limite l'opération aux travaux en cours d'exécution. La valeur de retour est 0, sauf si une spécification de travail ne spécifie pas de travail valide.
Cela signifie qu'un simple
disown -a
supprimera tous les travaux de la table des travaux et les rendra nohup
disown -asupprime tous les travaux. Un simple disownsupprime uniquement le travail en cours. Comme le dit la page de manuel de la réponse.
Rune Schjellerup Philosof du
73
Ce sont de bonnes réponses ci-dessus, je voulais juste ajouter une clarification:
Vous ne pouvez pas disownun pid ou un processus, vous disownun 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 en arrière-plan (pas le suspendre), puis le renier.
Malheureusement, disownest 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 nohupcommande elle-même qui peut être appliquée à un processus en cours d'exécution:
Uniquement pour AIXet Solaris. "Les versions AIX et Solaris de nohup ont une option -p qui modifie un processus en cours pour ignorer les futurs signaux SIGHUP. Contrairement à la fonction de désabonnement de bash décrite ci-dessus, nohup -p accepte les ID de processus.". Source
AlikElzin-kilaka
27
La réponse de Node est vraiment excellente, mais elle a laissé ouverte la question de savoir comment obtenir stdout et stderr redirigés. J'ai trouvé une solution sur Unix et Linux , mais elle n'est pas non plus complète. Je voudrais fusionner ces deux solutions. C'est ici:
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, obtenez le PID de ce processus d'une manière ou d'une autre. ps -C loop.shEst généralement 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 gdbdevrait être attaché à 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 STATchamp 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.
Cette ouverture est égale à open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR). Au lieu de O_RDWRO_WRONLYpourrait être appliqué, mais /usr/sbin/lsofdit «u» pour tous les gestionnaires de fichiers std * ( FDcolonne), ce 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 pourrait être ouvert avec O_APPEND, comme ce nohupserait le cas, mais cela n'est pas suggéré par man open(2), en raison de problèmes NFS possibles.
Si nous obtenons -1 comme valeur de retour, call perror("")imprime alors le message d'erreur. Si nous avons besoin de l'errno, utilisez la commande p errnogdb.
Nous pouvons maintenant vérifier le fichier nouvellement redirigé. /usr/sbin/lsof -p <PID>impressions:
Si nous voulons, nous pouvons rediriger stderr vers un autre fichier, si nous voulons utiliser call close(2)et à call open(...)nouveau en utilisant un nom de fichier différent.
Maintenant, la pièce jointe bashdoit être libérée et nous pouvons quitter gdb:
(gdb) detachDetaching from program:/bin/bash, process <PID>(gdb) q
Si le script a été arrêté par gdbun 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'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 sommes dans le même état que si on ^Zavait appuyé au début.)
Nous pouvons maintenant vérifier l'état de la tâche:
$ ps -f 24522
UID PID PPID C STIME TTY STAT TIME CMD<UID><PID><PPID>011: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 dans la jobssortie de la commande entre crochets identifie le travail à l'intérieur bash. Nous pouvons utiliser les bashcommandes intégrées suivantes en 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>011:16 pts/36 S 0:00/bin/bash ./loop.sh
Et maintenant, nous pouvons quitter le bash appelant. 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 commande devient inconnu.
$ ps -f <PID>
UID PID PPID C STIME TTY STAT TIME CMD<UID><PID>1011:16? S 0:00/bin/bash ./loop.sh
$ /usr/bin/lsof -p <PID>...
loop.sh <PID> truey 0u CHR 136,3638/dev/pts/36(deleted)
loop.sh <PID> truey 1u REG 0,26112715008411/home/truey/loop.out
loop.sh <PID> truey 2u CHR 136,3638/dev/pts/36(deleted)
COMMENTAIRE
Le truc gdb peut être automatisé en créant un fichier (par exemple loop.gdb) contenant les commandes et exécuter gdb -q -x loop.gdb -p <PID>. Mon loop.gdb ressemble à ceci:
Très instructif en effet, et susceptible de bien fonctionner dans des cas simples. Mais attention, les cas plus complexes peuvent échouer lamentablement. J'en ai eu un aujourd'hui: mon processus a engendré un autre processus qui a fait la sortie (vraisemblablement vers stderr), mais a stdout connecté pour communiquer avec son maître. La redirection des FD maîtres n'a pas eu d'effet car l'enfant avait hérité de stderr, et la fermeture de la sortie enfant a échoué le maître qui attendait à l'autre extrémité du tuyau. X- | Bettern connaît bien vos processus avant d'essayer.
cmaster - réintègre monica le
@cmaster Vous pouvez vérifier si une poignée est redirigé en utilisant lsof(le nom du descripteur de fichier est pipe, pas comme /dev/pts/1) ou ls -l /proc/<PID>/fd/<fd>(cela montre le lien symbolique de la poignée). De même, les sous-processus peuvent toujours ne pas avoir redirigé les sorties, qui doivent être redirigées vers un fichier.
Ensuite, j'ai essayé les commandes suivantes et cela a très bien fonctionné
Exécutez SOMECOMMAND, par exemple /usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1.
Ctrl+ Zpour 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 interrompu à la fermeture du terminal.
Tapez exitpour 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, donc elle n'est pas liée à un shell.
Ce processus est équivalent à l'exécution nohup SOMECOMMAND.
Cela a bien fonctionné. Il a continué d'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 bget disownne fonctionnaient pas.
Je pense que le comportement pour le reniement -a est de couper l'attachement avec tous les travaux. Cependant, il ne ferme pas les pipelines stdin / stdout, ce qui signifie que le processus essaiera toujours d'écrire (/ lire) depuis le terminal
Kelthar
-2
Cela a fonctionné pour moi sur Ubuntu linux en tcshell.
yourExecutable &
et que les sorties continuent à apparaître sur l'écran etCtrl+C
ne semblent rien arrêter, tapez simplement aveuglémentdisown;
et appuyezEnter
même si l'écran défile avec les sorties et que vous ne pouvez pas voir ce que vous tapez. Le processus sera désavoué et vous pourrez fermer le terminal sans que le processus ne meure.Réponses:
Utilisation du Job Control de bash pour envoyer le processus en arrière-plan:
bg
pour l'exécuter en arrière-plan.disown -h [job-spec]
où [job-spec] est le numéro de la tâche (comme%1
pour la première tâche en cours d'exécution; recherchez votre numéro avec lajobs
commande) afin que la tâche ne soit pas supprimée à la fermeture du terminal.la source
disown -h
peut-être la réponse la plus exacte: "faire en sorte que désavoué se comporte plus comme nohup (c'est-à-dire que les travaux resteront dans l'arbre de processus de votre shell actuel jusqu'à ce que vous quittiez votre shell). Cela vous permet de voir tous les travaux que cet obus a commencé. " (depuis [ quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/… )disown
, disown fait d'un processus un démon, ce qui signifie que les entrées / sorties standard sont redirigées vers / dev / null. Donc, si vous envisagez de renoncer à un travail, il vaut mieux le démarrer en vous connectant à un fichier, par exemplemy_job_command | tee my_job.log
disown
dissocie tous les tuyaux du processus. Pour rattacher des tuyaux, utilisezgdb
comme décrit dans ce fil . Plus précisément, ce poste .Supposons que pour une raison quelconque Ctrl+ Zne fonctionne pas non plus, allez sur un autre terminal, trouvez l'identifiant du processus (en utilisant
ps
) et exécutez:SIGSTOP
suspendra le processus etSIGCONT
reprendra le processus en arrière-plan. Alors maintenant, la fermeture de vos deux terminaux n'arrêtera pas votre processus.la source
disown %1
dans le premier terminal avant de le fermer.kwin
après un crash sans penser aux conséquences). Donc, si j'avais arrêté kwin, tout aurait gelé et je n'avais aucune possibilité de courirbg
!La commande pour séparer un travail en cours d'exécution du shell (= ne le fait pas) est
disown
une commande shell de base.Depuis bash-manpage (man bash):
Cela signifie qu'un simple
supprimera tous les travaux de la table des travaux et les rendra nohup
la source
disown -a
supprime tous les travaux. Un simpledisown
supprime uniquement le travail en cours. Comme le dit la page de manuel de la réponse.Ce sont de bonnes réponses ci-dessus, je voulais juste ajouter une clarification:
Vous ne pouvez pas
disown
un pid ou un processus, vousdisown
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 en arrière-plan (pas le suspendre), puis le renier.
Problème:
Voir http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/ pour une discussion plus détaillée sur Unix Job Control.
la source
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
nohup
commande elle-même qui peut être appliquée à un processus en cours d'exécution:Voir http://en.wikipedia.org/wiki/Nohup
la source
AIX
etSolaris
. "Les versions AIX et Solaris de nohup ont une option -p qui modifie un processus en cours pour ignorer les futurs signaux SIGHUP. Contrairement à la fonction de désabonnement de bash décrite ci-dessus, nohup -p accepte les ID de processus.". SourceLa réponse de Node est vraiment excellente, mais elle a laissé ouverte la question de savoir comment obtenir stdout et stderr redirigés. J'ai trouvé une solution sur Unix et Linux , mais elle n'est pas non plus complète. Je voudrais fusionner ces deux solutions. C'est ici:
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.
Maintenant, obtenez le PID de ce processus d'une manière ou d'une autre.
ps -C loop.sh
Est généralement 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.Cela arrête le script (s'il est en cours d'exécution). Son état peut être vérifié par
ps -f <PID>
, où leSTAT
champ est 'T +' (ou en cas de ^ Z 'T'), ce qui signifie (man ps (1))Close (1) renvoie zéro en cas de succès.
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 deO_RDWR
O_WRONLY
pourrait être appliqué, mais/usr/sbin/lsof
dit «u» pour tous les gestionnaires de fichiers std * (FD
colonne), ce qui estO_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 cenohup
serait le cas, mais cela n'est pas suggéré parman open(2)
, en raison de problèmes NFS possibles.Si nous obtenons -1 comme valeur de retour,
call perror("")
imprime alors le message d'erreur. Si nous avons besoin de l'errno, utilisez la commandep errno
gdb.Nous pouvons maintenant vérifier le fichier nouvellement redirigé.
/usr/sbin/lsof -p <PID>
impressions:Si nous voulons, nous pouvons rediriger stderr vers un autre fichier, si nous voulons utiliser
call close(2)
et àcall open(...)
nouveau en utilisant un nom de fichier différent.Maintenant, la pièce jointe
bash
doit être libérée et nous pouvons quittergdb
:Si le script a été arrêté par
gdb
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'exécute et écrit dans le fichier. Nous devons le mettre en arrière-plan. Alors appuyez sur^Z
.(Maintenant, nous sommes dans le même état que si on
^Z
avait appuyé au début.)Nous pouvons maintenant vérifier l'état de la tâche:
Le processus doit donc être exécuté en arrière-plan et détaché du terminal. Le nombre dans la
jobs
sortie de la commande entre crochets identifie le travail à l'intérieurbash
. Nous pouvons utiliser lesbash
commandes intégrées suivantes en appliquant un signe «%» avant le numéro de travail:Et maintenant, nous pouvons quitter le bash appelant. 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 commande devient inconnu.
COMMENTAIRE
Le truc gdb peut être automatisé en créant un fichier (par exemple loop.gdb) contenant les commandes et exécuter
gdb -q -x loop.gdb -p <PID>
. Mon loop.gdb ressemble à ceci:Ou on peut utiliser la doublure suivante à la place:
J'espère que c'est une description assez complète de la solution.
la source
lsof
(le nom du descripteur de fichier estpipe
, pas comme/dev/pts/1
) ouls -l /proc/<PID>/fd/<fd>
(cela montre le lien symbolique de la poignée). De même, les sous-processus peuvent toujours ne pas avoir redirigé les sorties, qui doivent être redirigées vers un fichier.Pour envoyer le processus en cours à nohup ( http://en.wikipedia.org/wiki/Nohup )
nohup -p pid
, ça n'a pas marché pour moiEnsuite, j'ai essayé les commandes suivantes et cela a très bien fonctionné
Exécutez SOMECOMMAND, par exemple
/usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1
.Ctrl+ Zpour 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 interrompu à la fermeture du terminal.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, donc elle n'est pas liée à un shell.Ce processus est équivalent à l'exécution
nohup SOMECOMMAND
.la source
Sur mon système AIX, j'ai essayé
Cela a bien fonctionné. Il a continué d'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
etdisown
ne fonctionnaient pas.la source
bg
- cela mettra le travail en arrière-plan et reviendra dans le processus en coursdisown -a
- cela coupera toute la pièce jointe avec le travail (vous pouvez donc 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
nohup
(selon ma compréhension de votre question, vous n'en avez pas besoin ici).la source
Cela a fonctionné pour moi sur Ubuntu linux en tcshell.
CtrlZ pour le mettre en pause
bg
courir en arrière-planjobs
pour obtenir son numéro de travailnohup %n
où n est le numéro de tâchela source
nohup: failed to run command '%1': No such file or directory