Comment empêcher l'arrêt d'un processus d'arrière-plan après la fermeture du client SSH sous Linux


291

Je travaille sur une machine Linux via SSH (Putty). Je dois laisser un processus en cours d'exécution pendant la nuit, j'ai donc pensé pouvoir le faire en démarrant le processus en arrière-plan (avec une esperluette à la fin de la commande) et en redirigeant stdout vers un fichier.

À ma grande surprise, cela ne fonctionne pas. Dès que je ferme la fenêtre Putty, le processus est arrêté.

Comment puis-je empêcher que cela se produise ??

Réponses:


301

Découvrez le programme " nohup ".


4
Comment l'arrêtez-vous ensuite?
Derek Dahmer

9
Connectez-vous et faites "kill <pid>". Utilisez "pidof" si vous ne connaissez pas le pid.
JesperE

32
Vous pouvez utiliser nohup command > /dev/null 2>&1 &pour exécuter en arrière-plan sans créer de sortie stdout ou stderr (pas de nohup.outfichier)
KCD

Et si je dois fournir des informations? Par exemple, j'ai un script de longue durée que je dois exécuter en arrière-plan, mais il demande d'abord mon mot de passe FTP. nohupn'aide pas dans ce cas. Existe-t-il un moyen de jouer avec Ctrl+Z/ bg?
Sergey

1
Comme je suis paresseux et mauvais pour mémoriser des séquences cryptiques de caractères, j'ai écrit cela , basé sur ce que @KCD a dit, et je l'ai beaucoup utilisé.
Anomalie

167

Je recommanderais d'utiliser GNU Screen . Il vous permet de vous déconnecter du serveur pendant que tous vos processus continuent de s'exécuter. Je ne sais pas comment je vivais sans elle avant de savoir qu'elle existait.


7
C'est l'un des meilleurs logiciels que j'aie jamais utilisés. Sérieusement. Je le fais fonctionner sur une boîte BSD dans laquelle je ssh de partout, et je peux simplement me reconnecter à mon écran et avoir tous mes terminaux où je fais toutes sortes de choses.
Adam Jaskiewicz

1
Je peux attester de celui-ci. L'écran est une excellente application. La possibilité de se reconnecter est incroyable et permet d'économiser beaucoup de travail potentiellement perdu.
dira ce que

Je l'utilise même sur des machines locales et attache plusieurs xterms à la même session d'écran (screen -x). De cette façon, je peux ouvrir de nombreuses fenêtres au cours de ma session d'écran et basculer librement mes différents xterms de fenêtre à fenêtre.
Adam Jaskiewicz

17
Dépend si vous devez vous reconnecter à l'application en arrière-plan ou non. Si vous le faites, alors, oui, l'écran est le seul moyen de voler. Si c'est du feu et de l'oubli, alors, rien ne convient tout aussi bien, sinon mieux.
Dave Sherohman

1
+1 pour l'écran. Ou, comme alternative, tmux (j'aime plus celui-ci que screen) ou même byobu, qui est une belle interface pour screen ou tmux. Vous pouvez simplement taper screen pour obtenir un shell à utiliser et revenir plus tard à tout moment, ou exécuter votre commande avec screen, comme "screen command": la session screen existera tant que le processus "command" existera, et si c'est quelque chose très longtemps, vous pouvez revenir en arrière et regarder sa sortie standard à tout moment.
gerlos

81

Lorsque la session est fermée, le processus reçoit le signal SIGHUP qu'il n'apparaît apparemment pas. Vous pouvez utiliser la nohupcommande lors du lancement du processus ou la commande intégrée bash disown -haprès le démarrage du processus pour éviter que cela ne se produise:

> help disown
disown: disown [-h] [-ar] [jobspec ...]
     By default, removes each JOBSPEC argument from the table of active jobs.
    If the -h option is given, the job is not removed from the table, but is
    marked so that SIGHUP is not sent to the job if the shell receives a
    SIGHUP.  The -a option, when JOBSPEC is not supplied, means to remove all
    jobs from the job table; the -r option means to remove only running jobs.

4
L'avantage ici est que la suppression fonctionne pour les processus qui ont déjà été démarrés.
Christian K.

1
Est-ce que «jobspec» signifie le pid?
Stewart

1
Pas de soucis, trouvé cette réponse ici stackoverflow.com/questions/625409/…
Stewart

42

démoniser? non? ÉCRAN? (tmux ftw, l'écran est indésirable ;-)

Faites ce que toutes les autres applications ont fait depuis le début - double fork.

# ((exec sleep 30)&)
# grep PPid /proc/`pgrep sleep`/status
PPid:   1
# jobs
# disown
bash: disown: current: no such job

Coup! Terminé :-) J'ai utilisé cela d'innombrables fois sur tous les types d'applications et sur de nombreuses vieilles machines. Vous pouvez combiner avec des redirections et ainsi de suite pour ouvrir un canal privé entre vous et le processus.

Créez en tant que coproc.sh:

#!/bin/bash

IFS=

run_in_coproc () {
    echo "coproc[$1] -> main"
    read -r; echo $REPLY
}

# dynamic-coprocess-generator. nice.
_coproc () {
    local i o e n=${1//[^A-Za-z0-9_]}; shift
    exec {i}<> <(:) {o}<> >(:) {e}<> >(:)
. /dev/stdin <<COPROC "${@}"
    (("\$@")&) <&$i >&$o 2>&$e
    $n=( $o $i $e )
COPROC
}

# pi-rads-of-awesome?
for x in {0..5}; do
    _coproc COPROC$x run_in_coproc $x
    declare -p COPROC$x
done

for x in COPROC{0..5}; do
. /dev/stdin <<RUN
    read -r -u \${$x[0]}; echo \$REPLY
    echo "$x <- main" >&\${$x[1]}
    read -r -u \${$x[0]}; echo \$REPLY
RUN
done

puis

# ./coproc.sh 
declare -a COPROC0='([0]="21" [1]="16" [2]="23")'
declare -a COPROC1='([0]="24" [1]="19" [2]="26")'
declare -a COPROC2='([0]="27" [1]="22" [2]="29")'
declare -a COPROC3='([0]="30" [1]="25" [2]="32")'
declare -a COPROC4='([0]="33" [1]="28" [2]="35")'
declare -a COPROC5='([0]="36" [1]="31" [2]="38")'
coproc[0] -> main
COPROC0 <- main
coproc[1] -> main
COPROC1 <- main
coproc[2] -> main
COPROC2 <- main
coproc[3] -> main
COPROC3 <- main
coproc[4] -> main
COPROC4 <- main
coproc[5] -> main
COPROC5 <- main

Et voilà, frayez quoi que ce soit. le <(:) ouvre un canal anonyme via la substitution de processus, qui meurt, mais le canal reste parce que vous avez une poignée dessus. Je fais habituellement un sleep 1au lieu de :parce que c'est légèrement racé, et j'obtiendrais une erreur "file occupé" - ne se produit jamais si une vraie commande est exécutée (par exemple, command true)

"sourcing hérédoc":

. /dev/stdin <<EOF
[...]
EOF

Cela fonctionne sur chaque shell que j'ai jamais essayé, y compris busybox / etc (initramfs). Je ne l'avais jamais vu faire auparavant, je l'ai découvert indépendamment tout en poussant, qui savait que la source pouvait accepter les arguments? Mais il sert souvent de forme d'évaluation beaucoup plus facile à gérer, s'il existe une telle chose.


2
pourquoi le vote négatif ... et si la question est ancienne; c'est évidemment pertinent étant donné qu'il y a 11 autres réponses qui sont nulles. cette solution est, sans systemd, la façon idiomatique et acceptée de démonifier depuis 30 ans, pas des applications inutiles, par exemple. nohup et al.
anthonyrisinger

7
peu importe la qualité de votre réponse, parfois quelqu'un sur SO ne l'aimera pas et votera contre. Il vaut mieux ne pas trop s'en inquiéter.
Alex D

1
@ tbc0 ... tryssh myhost "((exec sleep 500)&) >/dev/null"
anthonyrisinger

1
@anthonyrisinger ok, ça marche. Je pense que c'est plus propre: ssh myhost 'sleep 500 >&- 2>&- <&- &' TMTOWTDI;)
tbc0

1
C'est bien. la seule solution qui fonctionne réellement dans busybox. il mérite plus de votes positifs
Hamy

34
nohup blah &

Remplacez votre nom de processus par bla!


2
vous souhaiterez peut-être ajouter une redirection standard et une erreur standard.
David Nehme

9
nohup redirige stdout et stderr vers nohup.out (ou nohup.out et nohup.err selon la version), donc à moins que vous n'exécutiez plusieurs commandes, ce n'est pas nécessaire.
Chas. Owens

17

Personnellement, j'aime la commande 'batch'.

$ batch
> mycommand -x arg1 -y arg2 -z arg3
> ^D

Cela le met en arrière-plan, puis vous envoie les résultats. Cela fait partie de cron.


11

Comme d'autres l'ont noté, pour exécuter un processus en arrière-plan afin de pouvoir vous déconnecter de votre session SSH, vous devez que le processus en arrière-plan se dissocie correctement de son terminal de contrôle - qui est le pseudo-tty utilisé par la session SSH.

Vous pouvez trouver des informations sur la démonétisation des processus dans des livres tels que "Advanced Network Program, Vol 1, 3rd Edn" de Stevens ou "Advanced Unix Programming" de Rochkind.

J'ai récemment (au cours des deux dernières années) dû faire face à un programme récalcitrant qui ne se démonitait pas correctement. J'ai fini par gérer cela en créant un programme de démonisation générique - similaire à nohup mais avec plus de contrôles disponibles.

Usage: daemonize [-abchptxV][-d dir][-e err][-i in][-o out][-s sigs][-k fds][-m umask] -- command [args...]
  -V          print version and exit
  -a          output files in append mode (O_APPEND)
  -b          both output and error go to output file
  -c          create output files (O_CREAT)
  -d dir      change to given directory
  -e file     error file (standard error - /dev/null)
  -h          print help and exit
  -i file     input file (standard input - /dev/null)
  -k fd-list  keep file descriptors listed open
  -m umask    set umask (octal)
  -o file     output file (standard output - /dev/null)
  -s sig-list ignore signal numbers
  -t          truncate output files (O_TRUNC)
  -p          print daemon PID on original stdout
  -x          output files must be new (O_EXCL)

Le double tiret est facultatif sur les systèmes n'utilisant pas la fonction GNU getopt (); il est nécessaire (ou vous devez spécifier POSIXLY_CORRECT dans l'environnement) sous Linux etc. Puisque le double tiret fonctionne partout, il est préférable de l'utiliser.

Vous pouvez toujours me contacter (prénom dot nom de famille sur gmail dot com) si vous voulez la source pour daemonize.

Cependant, le code est maintenant (enfin) disponible sur GitHub dans mon référentiel SOQ (Stack Overflow Questions) en tant que fichier daemonize-1.10.tgzdans le sous-répertoire packages .


13
Pourquoi ne mettez-vous pas la source sur github ou bitbucket?
Rob

5
Pourquoi l'absence de la source de github justifie-t-elle un downvote?
Jonathan Leffler

7
@JonathanLeffler IMHO énumérant toutes les options intéressantes d'un programme qui n'est pas accessible au public sous quelque forme que ce soit (pas même commercialement) limite la perte de temps du lecteur.
DepressedDaniel

7

Sur un système basé sur Debian (sur la machine distante) Installez:

sudo apt-get install tmux

Usage:

tmux

exécuter les commandes que vous voulez

Pour renommer la session:

Ctrl + B puis $

définir le nom

Pour quitter la session:

Ctrl + B puis D

(cela quitte la session tmux). Ensuite, vous pouvez vous déconnecter de SSH.

Lorsque vous devez revenir / vérifier à nouveau, démarrez SSH et entrez

tmux attach nom_session

Cela vous ramènera à votre session tmux.


c'est la voie à suivre
kilgoretrout

6

Pour la plupart des processus, vous pouvez pseudo-démoniser en utilisant cette ancienne astuce de ligne de commande Linux:

# ((mycommand &)&)

Par exemple:

# ((sleep 30 &)&)
# exit

Ensuite, démarrez une nouvelle fenêtre de terminal et:

# ps aux | grep sleep

Montre que cela sleep 30fonctionne toujours.

Ce que vous avez fait, c'est démarrer le processus en tant qu'enfant d'un enfant, et lorsque vous quittez, la nohupcommande qui déclencherait normalement le processus pour quitter ne se répercute pas sur le petit-enfant, le laissant comme un processus orphelin, toujours en cours d'exécution .

Je préfère ce « set et oublier » approche, pas besoin de traiter nohup, screen, tmux, I / o redirection, ou l' une de ce genre de choses.


5

Si vous utilisez screen pour exécuter un processus en tant que root, méfiez-vous de la possibilité d'attaques d'élévation de privilèges. Si votre propre compte est compromis d'une manière ou d'une autre, il y aura un moyen direct de reprendre l'intégralité du serveur.

Si ce processus doit être exécuté régulièrement et que vous disposez d'un accès suffisant sur le serveur, une meilleure option serait d'utiliser cron pour exécuter le travail. Vous pouvez également utiliser init.d (le super démon) pour démarrer votre processus en arrière-plan, et il peut se terminer dès qu'il est terminé.


5

nohupest très bien si vous souhaitez enregistrer vos informations dans un fichier. Mais quand il passe en arrière-plan, vous ne pouvez pas lui donner de mot de passe si vos scripts le demandent. Je pense que vous devez essayer screen. c'est un utilitaire que vous pouvez installer sur votre distribution linux en utilisant yum par exemple sur CentOS yum install screenpuis accéder à votre serveur via putty ou un autre logiciel, dans votre type de shell screen. Il ouvrira l'écran [0] en mastic. Fais ton travail. Vous pouvez créer plus d'écran [1], écran [2], etc. dans la même session de mastic.

Commandes de base que vous devez connaître:

Pour démarrer l'écran

écran


Pour c réer écran suivant

ctrl + a + c


Pour passer à l' écran n ext que vous avez créé

ctrl + a + n


Pour d Etach

ctrl + a + d


Pendant le travail, fermez votre mastic. Et la prochaine fois que vous vous connectez via le type de mastic

écran -r

Pour vous reconnecter à votre écran, et vous pouvez voir votre processus toujours en cours d'exécution à l'écran. Et pour quitter l'écran, tapez #exit.

Pour plus de détails, voir man screen.


en supposant que yumc'est le bon outil, quand vous ne connaissez pas la distribution, ce n'est pas bon. vous devez indiquer clairement sur quelles distributions vous screenpouvez installer yum.
tymik

5

Nohup permet à un processus client de ne pas être tué si un processus parent est tué, comme argument lorsque vous vous déconnectez. Encore mieux, utilisez:

nohup /bin/sh -c "echo \$\$ > $pidfile; exec $FOO_BIN $FOO_CONFIG  " > /dev/null

Nohup rend le processus que vous démarrez à l'abri de la fin, ce que votre session SSH et ses processus enfants tuent lorsque vous vous déconnectez. La commande que j'ai donnée vous offre un moyen de stocker le pid de l'application dans un fichier pid afin de pouvoir le supprimer correctement par la suite et autorise le processus à s'exécuter après votre déconnexion.




2

j'irais aussi pour le programme d'écran (je sais que la réponse de some1 else était écran mais c'est un achèvement)

non seulement le fait que &, ctrl + z bg disown, nohup, etc. puisse vous donner une mauvaise surprise que lorsque vous vous déconnectez, le travail sera toujours tué (je ne sais pas pourquoi, mais cela m'est arrivé et cela ne m'a pas dérangé avec cela parce que j'ai changé pour utiliser l'écran, mais je suppose que la solution anthonyrisinger comme double fourche résoudrait cela), l'écran a également un avantage majeur par rapport à la simple mise à la terre:

screen will background your process without losing interactive control to it

et btw, c'est une question que je ne poserais jamais en premier lieu :) ... j'utilise l'écran depuis mon début de faire quoi que ce soit dans n'importe quel unix ... je (presque) ne travaille JAMAIS dans un shell unix / linux sans démarrer l'écran d'abord ... et je devrais m'arrêter maintenant, ou je commencerai une présentation sans fin de ce qu'est un bon écran et de ce qui peut faire pour vous ... regardez par vous-même, ça vaut le coup;)


PS anthonyrisinger, tu vas bien, je te donne ça mais ... 30 ans? je parie que c'est une solution quand &, bg, nohup ou screen n'était pas encore là, et aucune infraction j'apprécie vos connaissances mais c'est beaucoup trop compliqué pour l'utiliser :)
THESorcerer

2
(à part: voir Tmux ) bien que cela me soit largement antérieur [1987], &(exécution asynchrone) a été introduite par le shell Thompson en 1971 , pour la première version d'UNIX ... donc elle a littéralement "toujours été" ;-) hélas, J'étais trop conservateur - cela fait en fait 41 ans.
anthonyrisinger

2

Il y a aussi la commande démon du paquet libslack open-source.

daemon est assez configurable et se soucie de toutes les tâches fastidieuses du démon telles que le redémarrage automatique, la journalisation ou la gestion des fichiers pid.


2

Ajoutez cette chaîne à votre commande:> & - 2> & - <& - &. > & - signifie fermer la sortie standard. 2> & - signifie fermer stderr. <& - signifie fermer stdin. & signifie exécuté en arrière-plan. Cela fonctionne également pour démarrer un travail par programme via ssh:

$ ssh myhost 'sleep 30 >&- 2>&- <&- &'
# ssh returns right away, and your sleep job is running remotely
$


1

La réponse acceptée suggère d'utiliser nohup . Je préférerais plutôt utiliser pm2 . L'utilisation de pm2 sur nohup présente de nombreux avantages, tels que le maintien en vie de l'application, la gestion des fichiers journaux de l'application et bien d'autres fonctionnalités. Pour plus de détails, vérifiez cela .

Pour installer pm2, vous devez télécharger npm . Pour un système basé sur Debian

sudo apt-get install npm

et pour Redhat

sudo yum install npm

Ou vous pouvez suivre ces instructions . Après avoir installé npm, utilisez-le pour installer pm2

npm install pm2@latest -g

Une fois terminé, vous pouvez démarrer votre application en

$ pm2 start app.js              # Start, Daemonize and auto-restart application (Node)
$ pm2 start app.py              # Start, Daemonize and auto-restart application (Python)

Pour la surveillance des processus, utilisez les commandes suivantes:

$ pm2 list                      # List all processes started with PM2
$ pm2 monit                     # Display memory and cpu usage of each app
$ pm2 show [app-name]           # Show all informations about application

Gérez les processus à l'aide du nom de l'application ou de l'ID de processus ou gérez tous les processus ensemble:

$ pm2 stop     <app_name|id|'all'|json_conf>
$ pm2 restart  <app_name|id|'all'|json_conf>
$ pm2 delete   <app_name|id|'all'|json_conf>

Les fichiers journaux se trouvent dans

$HOME/.pm2/logs #contain all applications logs

Les fichiers exécutables binaires peuvent également être exécutés à l'aide de pm2. Vous devez apporter une modification dans le fichier Jason. Changez le "exec_interpreter" : "node", en "exec_interpreter" : "none".(voir la section des attributs ).

#include <stdio.h>
#include <unistd.h>  //No standard C library
int main(void)
{
    printf("Hello World\n");
    sleep (100);
    printf("Hello World\n");

    return 0;
}

Compilation au-dessus du code

gcc -o hello hello.c  

et l'exécuter avec np2 en arrière-plan

pm2 start ./hello

Peut-il être utilisé pour exécuter des exécutables binaires?
GetFree

@GetFree; Oui. Vous pouvez.
haccks

Ajoutez un exemple s'il vous plaît. La réponse telle qu'elle est actuellement semble être bonne uniquement pour les fichiers de script.
GetFree

@GetFree; Ajout de l'exemple. Faites-moi savoir si vous avez un problème.
haccks

1

Sur systemd / Linux, systemd-run est un bel outil pour lancer des processus indépendants de la session. Les haineux continueront de détester

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.