Comment exécuter Node.js en arrière-plan et ne jamais mourir?

480

Je me connecte au serveur Linux via putty SSH. J'ai essayé de l'exécuter en arrière-plan comme ceci:

$ node server.js &

Cependant, après 2,5 heures, le terminal devient inactif et le processus meurt. Existe-t-il de toute façon que je peux maintenir le processus en vie même avec le terminal déconnecté?


Modifier 1

En fait, j'ai essayé nohup, mais dès que je ferme le terminal Putty SSH ou que je débranche mon Internet, le processus du serveur s'arrête immédiatement.

Y a-t-il quelque chose à faire dans Putty?


Edit 2 (le février 2012)

Il y a un node.jsmodule, pour toujours . Il exécutera le serveur node.js en tant que service démon.

murvinlai
la source
7
Dans mon cas, nohup fonctionne lorsque je quitte le terminal en tapant exit. Lorsque je ferme la fenêtre Putty, cela échoue.
Pawel Furmaniak

Réponses:

513

Solution simple (si vous n'êtes pas intéressé à revenir au processus, vous voulez juste qu'il continue à fonctionner):

nohup node server.js &

Il y a aussi la jobscommande pour voir une liste indexée de ces processus en arrière-plan. Et vous pouvez tuer un processus en arrière-plan en exécutant kill %1ou kill %2avec le nombre étant l'index du processus.

Solution puissante (vous permet de vous reconnecter au processus s'il est interactif):

screen

Vous pouvez ensuite vous détacher en appuyant sur Ctrl + a + d, puis rattacher en exécutant screen -r

Considérez également la nouvelle alternative à screen, tmux.

MK.
la source
1
Donc, si je lance "écran", je crée l'écran et je cours à l'intérieur, non?
murvinlai
30
oui et ensuite vous pouvez vous détacher en appuyant sur Ctrl + a, d puis vous attacher en exécutant screen -r
MK.
1
@murvinlai EC2 est un environnement et n'a rien à voir avec le privilège root. Il s'agit probablement de votre AMI. Par exemple, avec Amazon AMI, vous pouvez certainement sudo bash.
ShuaiYuan
1
man bash: Si une commande est terminée par l'opérateur de contrôle &, le shell exécute la commande en arrière-plan dans un sous-shell. Le shell n'attend pas la fin de la commande et l'état de retour est 0.
MK.
34
S'il vous plaît, à tous ceux qui lisent ceci: exécuter un serveur node.js dans un écran ou une session tmux est une solution AMATEUR ! Ne faites pas cela, sauf pour des tests rapides. Pour maintenir un processus en cours, vous devez le démonifier ! Utilisez les outils appropriés pour cela, comme forever , pm2 ou les anciens scripts init.d simples .
Victor Schröder
1119

nohup node server.js > /dev/null 2>&1 &

  1. nohupsignifie: N'interrompez pas ce processus même lorsque le stty est coupé.
  2. > /dev/nullsignifie: stdout va à / dev / null (qui est un périphérique factice qui n'enregistre aucune sortie).
  3. 2>&1signifie: stderr va également à la sortie standard (qui est déjà redirigée vers /dev/null). Vous pouvez remplacer & 1 par un chemin de fichier pour conserver un journal des erreurs, par exemple:2>/tmp/myLog
  4. &à la fin signifie: exécutez cette commande en tâche de fond.
Yoichi
la source
49
Cela devrait être la réponse acceptée, car elle est de bien meilleure qualité que celle actuellement acceptée.
L0j1k
2
@ L0j1k discutable, OP a démontré un niveau de compréhension que de plus amples explications sont nécessaires pour la réponse acceptée.
JFA
41
SO ne concerne pas autant l'OP que les milliers de personnes qui viennent demander de l'aide à OP.
L0j1k
3
Est-il nécessaire de rediriger stdout et stderr? Cela fonctionnerait-il aussi bien si je ne les redirigeais pas du tout? Ou si je les redirige vers des fichiers à la place?
Shawn
10
Envoyer stdout ET stderr à /dev/null? Belle journalisation ... Bonne chance pour essayer de déboguer ceci ...
Victor Schröder
138

Vous devriez vraiment essayer d'utiliser screen. C'est un peu plus compliqué que de le faire nohup long_running &, mais comprendre l'écran une fois qu'on ne revient plus.

Commencez votre session d'écran au début:

user@host:~$ screen

Exécutez tout ce que vous voulez:

wget http://mirror.yandex.ru/centos/4.6/isos/i386/CentOS-4.6-i386-binDVD.iso

Appuyez sur ctrl + A, puis sur d. Terminé. Votre session se poursuit en arrière-plan.

Vous pouvez répertorier toutes les sessions par screen -lset en attacher à certaines par screen -r 20673.pts-0.srv, où 0673.pts-0.srv est une liste d'entrées.

Alex Povar
la source
125

C'est une vieille question, mais elle est bien classée sur Google. Je ne peux presque pas croire aux réponses les plus votées, car l'exécution d'un processus node.js dans une session d'écran, avec &ou même avec le nohupdrapeau - tous - sont juste des solutions de contournement.

Surtout la solution screen / tmux, qui devrait vraiment être considérée comme une solution amateur . Screen et Tmux ne sont pas destinés à maintenir le fonctionnement des processus, mais à multiplexer des sessions de terminal. C'est très bien, lorsque vous exécutez un script sur votre serveur et que vous souhaitez vous déconnecter. Mais pour un serveur node.js, vous ne voulez pas que votre processus soit attaché à une session de terminal. C'est trop fragile. Pour continuer à fonctionner, vous devez démonifier le processus!

Il existe de nombreux bons outils pour le faire.

PM2 : http://pm2.keymetrics.io/

# basic usage
$ npm install pm2 -g
$ pm2 start server.js

# you can even define how many processes you want in cluster mode:
$ pm2 start server.js -i 4

# you can start various processes, with complex startup settings
# using an ecosystem.json file (with env variables, custom args, etc):
$ pm2 start ecosystem.json

Un gros avantage que je vois en faveur de PM2 est qu'il peut générer le script de démarrage du système pour rendre le processus persistant entre les redémarrages:

$ pm2 startup [platform]

platformpeut être ubuntu|centos|redhat|gentoo|systemd|darwin|amazon.

forever.js : https://github.com/foreverjs/forever

# basic usage
$ npm install forever -g
$ forever start app.js

# you can run from a json configuration as well, for
# more complex environments or multi-apps
$ forever start development.json

Scripts d'initialisation :

Je ne vais pas entrer dans les détails sur la façon d'écrire un script d'initialisation, car je ne suis pas un expert dans ce sujet et ce serait trop long pour cette réponse, mais en gros, ce sont de simples scripts shell, déclenchés par des événements du système d'exploitation. Vous pouvez en savoir plus à ce sujet ici

Docker :

Exécutez simplement votre serveur dans un conteneur Docker avec -doption et, voilá , vous avez un serveur node.js démonisé!

Voici un exemple de Dockerfile (du guide officiel de node.js ):

FROM node:argon

# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# Install app dependencies
COPY package.json /usr/src/app/
RUN npm install

# Bundle app source
COPY . /usr/src/app

EXPOSE 8080
CMD [ "npm", "start" ]

Créez ensuite votre image et exécutez votre conteneur:

$ docker build -t <your username>/node-web-app .
$ docker run -p 49160:8080 -d <your username>/node-web-app

J'espère que cela aidera quelqu'un à atterrir sur cette page. Utilisez toujours l'outil approprié pour le travail. Cela vous évitera beaucoup de maux de tête et au fil des heures!

Victor Schröder
la source
2
C'est ce que je cherchais. Avec la solution pm2, existe-t-il un moyen d'y attacher un terminal plus tard?
Quantumplation
4
@Quantumplation, non. Ce n'est pas possible car le processus ne s'exécute pas dans une session interactive. Mais vous pouvez avoir la même "sensation" en tail -fing le fichier journal généré par pm2.
Victor Schröder
1
Vous spécifiez la screensolution que de nombreuses personnes trouvent que le travail est une solution de contournement. Il existe de nombreuses façons de réaliser une tâche spécifique. Je crois qu'il arrive que (considérez la question spécifique) il se trouve qu'il accomplit la tâche spécifique d' run as background and never dieexceller pour beaucoup. Il a également l'avantage supplémentaire de permettre à l'utilisateur d'y revenir pour ré-interagir et apporter des modifications s'il le souhaite. La clé est que les composants sont backgroundet never die. Toutes les solutions ont certains bonus.
LD James
@Rakshith Ravi - Je ne suis pas d'accord. Tous ces éléments nécessitent des téléchargements / logiciels / outils supplémentaires (à l'exception de la solution init, à laquelle aucune solution n'a été fournie). La nohup est la solution. Il est intégré à Linux et c'est pour cela qu'il est là. C'est une ligne, c'est propre et cela fonctionne comme prévu, à chaque fois, indépendamment des mises à jour. Les gens devraient vraiment essayer d'éviter d'utiliser des outils tiers pour des cas d'utilisation de base comme celui-ci. L'exemple de docker (par exemple) est beaucoup plus détaillé et gourmand en ressources que la seule commande simple dans la réponse la plus votée. J'adore Docker, mais pas pour ça.
Jack_Hu
1
@Jack_Hu, je n'ai aucun doute sur les frais généraux, mais la nohupsolution ne satisfait pas à l'exigence "ne jamais mourir". Sauf si vous écrivez une trapboucle infinie très délicate ou hacky, je ne vois pas comment garder le processus démonifié sans utiliser des outils spécialement écrits à cet effet (ou un script d'initialisation écrit par vous-même, bien sûr).
Victor Schröder
24

une autre solution renie le travail

$ nohup node server.js &
[1] 1711
$ disown -h %1
myururdurmaz
la source
désavouer est exactement ce que je cherchais, mais que fait le drapeau -h? Je ne peux pas le trouver dans le manuel
Rimantas Jacikevicius
from man page: Si l'option -h est donnée, chaque jobspec n'est pas supprimé de la table, mais est marqué de sorte que SIGHUP ne soit pas envoyé au job si le shell reçoit un SIGHUP. Si aucune spécification de tâche n'est fournie, l'option -a signifie supprimer ou marquer toutes les tâches;
myururdurmaz
14

nohuppermettra au programme de continuer même après la mort du terminal. J'ai en fait eu des situations où nohupempêche la session SSH de se terminer correctement, vous devez donc également rediriger l'entrée:

$ nohup node server.js </dev/null &

Selon la nohupconfiguration, vous devrez peut-être également rediriger la sortie standard et l'erreur standard vers des fichiers.

Daniel Gallagher
la source
7

J'ai cette fonction dans mon fichier shell rc, basée sur la réponse de @ Yoichi:

nohup-template () {
    [[ "$1" = "" ]] && echo "Example usage:\nnohup-template urxvtd" && return 0
    nohup "$1" > /dev/null 2>&1 &
}

Vous pouvez l'utiliser de cette façon:

nohup-template "command you would execute here"
thiagowfx
la source
7

Nohup et screen offrent d'excellentes solutions d'éclairage pour exécuter Node.js en arrière-plan. Le gestionnaire de processus Node.js ( PM2 ) est un outil pratique pour le déploiement. Installez-le avec npm globalement sur votre système:

npm install pm2 -g

pour exécuter une application Node.js en tant que démon:

pm2 start app.js

Vous pouvez éventuellement le lier à Keymetrics.io un SAAS de surveillance réalisé par Unitech.

Donald Derek
la source
6
$ disown node server.js &

Il supprimera la commande de la liste des tâches actives et enverra la commande en arrière-plan

Skynet
la source
5

Avez-vous lu sur la commande nohup ?

S.Lott
la source
3

Pour exécuter la commande en tant que service système sur debian avec sysv init:

Copiez le script squelette et adaptez-le à vos besoins, probablement tout ce que vous avez à faire est de définir certaines variables. Votre script héritera de valeurs par défaut fines /lib/init/init-d-script, si quelque chose ne correspond pas à vos besoins - remplacez-le dans votre script. Si quelque chose ne va pas, vous pouvez voir les détails dans la source /lib/init/init-d-script. Les variables obligatoires sont DAEMONet NAME. Le script utilisera start-stop-daemonpour exécuter votre commande, START_ARGSvous pouvez définir des paramètres supplémentaires start-stop-daemonà utiliser.

cp /etc/init.d/skeleton /etc/init.d/myservice
chmod +x /etc/init.d/myservice
nano /etc/init.d/myservice

/etc/init.d/myservice start
/etc/init.d/myservice stop

Voilà comment j'exécute des trucs en python pour mon wiki wikimedia:

...
DESC="mediawiki articles converter"
DAEMON='/home/mss/pp/bin/nslave'
DAEMON_ARGS='--cachedir /home/mss/cache/'
NAME='nslave'
PIDFILE='/var/run/nslave.pid'
START_ARGS='--background --make-pidfile --remove-pidfile --chuid mss --chdir /home/mss/pp/bin'

export PATH="/home/mss/pp/bin:$PATH"

do_stop_cmd() {
    start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 \
        $STOP_ARGS \
        ${PIDFILE:+--pidfile ${PIDFILE}} --name $NAME
    RETVAL="$?"
    [ "$RETVAL" = 2 ] && return 2
    rm -f $PIDFILE
    return $RETVAL
}

Outre la définition de vars, j'ai dû remplacer à do_stop_cmdcause de python substitue l'exécutable, donc le service ne s'est pas arrêté correctement.

user3132194
la source
3

Outre les solutions intéressantes ci-dessus, je mentionnerais également les outils de supervision et de surveillance qui permettent de démarrer le processus, de surveiller sa présence et de le démarrer en cas de mort. Avec 'monit', vous pouvez également exécuter des vérifications actives comme vérifier si le processus répond à la demande http

Krzysztof Księżyk
la source
3

Pour Ubuntu, j'utilise ceci:

(exécutez PROG_SH &> / dev / null &)

Cordialement

David Lopes
la source
Point mineur: 'exec' n'est pas nécessaire si PROG_SH est un exécutable. Le point de la solution proposée par David est de dissocier l'enfant du shell en cours d'exécution. Le parent de l'enfant devient «pid 1» et ne sera pas affecté lorsque la coquille se termine.
SoloPilot
0

Essayez ceci pour une solution simple

cmd et sortie

Hunter Frazier
la source