Démarrer automatiquement pour toujours (nœud) au redémarrage du système

191

J'utilise le module forever de node pour maintenir mon serveur de nœuds en marche. Forever cependant se termine quand il y a un redémarrage du système. Existe-t-il un moyen de démarrer automatiquement le serveur de nœuds (pour toujours) lorsque le système redémarre?

kehers
la source
1
Ce serveur est-il dans le cloud? Avez-vous des scripts de démarrage pour cela?
Jorge Aranda
6
Découvrez PM2 ! Il prend également en charge la génération de scripts de démarrage (systemd, systemv ...) pm2.keymetrics.io/docs/usage/startup
Unitech

Réponses:

344

Je suggérerais d'utiliser crontab. C'est facile à utiliser.

Comment

  1. Pour commencer l'édition, exécutez ce qui suit en remplaçant "testuser" par l'utilisateur d'exécution souhaité pour le processus de nœud. Si vous choisissez un autre utilisateur que vous, vous devrez l'exécuter avec sudo.

    $ crontab -u testuser -e
  2. Si vous ne l'avez jamais fait auparavant, il vous demandera avec quel éditeur vous souhaitez éditer. J'aime vim, mais je recommanderai nano pour sa facilité d'utilisation.

  3. Une fois dans l'éditeur, ajoutez la ligne suivante:

    @reboot /usr/local/bin/forever start /your/path/to/your/app.js
  4. Enregistrez le fichier. Vous devriez obtenir des informations indiquant que le cron a été installé.

  5. Pour une confirmation supplémentaire de l'installation du cron, exécutez ce qui suit (en remplaçant à nouveau "testuser" par votre nom d'utilisateur cible) pour lister les crons actuellement installés:

    $ crontab -u testuser -l 

Notez qu'à mon avis, vous devez toujours utiliser des chemins complets lors de l'exécution de binaires dans cron. De plus, si le chemin d'accès à votre script forever n'est pas correct, exécutez which foreverpour obtenir le chemin complet.

Étant donné que les foreverappels node, vous pouvez également fournir le chemin complet vers node:

@reboot /usr/local/bin/forever start -c /usr/local/bin/node /your/path/to/your/app.js

Lectures complémentaires

Julian Lannigan
la source
2
Cette approche est bonne, mais uniquement pour les cas où le système est redémarré. Si le serveur est arrêté puis mis sous tension, cette tâche cron ne s'exécutera pas.
ecdeveloper
6
Qu'est ce qui te fait penser ça? en.wikipedia.org/wiki/Cron#Predefined_scheduling_definitions Explique que @rebootcron est exécuté sur le démon cron à partir de. Pour ajouter, je n'ai jamais rencontré de situation qui suggérerait que mes cron qui sont définis sur @rebootne fonctionnent pas au démarrage du système. La façon dont vous l'arrêtez n'a pas d'importance pour cela.
Julian Lannigan
16
il semble qu'il /homen'est pas encore monté, donc cela ne fonctionnera pas si votre code existe /home.
chovy
6
J'ai trouvé que ce qui précède a échoué pour moi car le nœud n'est pas dans le chemin lorsque cron essaie de s'exécuter pour toujours, même avec l'option -c. Cependant, il s'avère que vous pouvez ajouter une instruction PATH = directement dans la crontab tant qu'elle se trouve au-dessus des instructions de planification. Une fois PATH défini, l'instruction @reboot fonctionnait comme un rêve.
YorkshireKev
2
Merci pour votre commentaire @chovy, c'était très utile. Pour ceux qui utilisent les variables d'environnement de bashrc, faites attention à son commentaire. Puisque / home n'est pas monté, cela ne fonctionnera pas. Définissez les variables à la commande crontab comme@reboot varname=value ...
lsborg
123

Vous pouvez utiliser forever-service pour ce faire.

npm install -g forever-service
forever-service install test

Cela mettra à disposition app.js dans l'annuaire actuel en tant que service pour toujours. Le service redémarrera automatiquement à chaque redémarrage du système. Une fois arrêté, il tentera également un arrêt progressif. Ce script provisionne également le script logrotate.

URL Github: https://github.com/zapty/forever-service

REMARQUE: je suis l'auteur de forever-service.

arva
la source
2
Utilisez l'option -e "PORT = 80 ENV = prod FOO = bar"
arva
2
Je ne sais pas comment exécuter le service pour toujours. Qu'est-ce que ce "test" dans le "test d'installation de service permanent"? Ma commande pour démarrer mon application pour toujours est: "/ usr / local / bin / forever start -c / usr / local / bin / node / home / alex / public / node_modules / http-server / bin / http-server -s - d faux ". Que devrais-je écrire?
Alex
3
test voici le nom du service. lorsque vous exécutez le test d'installation de service permanent, il crée un service appelé test, pour exécuter app.js dans ce répertoire pour être exécuté en tant que service. Je suggérerais de lire la documentation d'aide sur la page gihub et d'y ajouter un problème si vous ne parvenez pas à le comprendre.
arva
6
@Alex - pour clarifier le commentaire d'arva - dans l'exemple forever-service install test, testsera le nom du service , mais pas le nom du fichier .js du programme / nœud à exécuter. Par défaut, il prend le nom du programme est app.js, mais vous pouvez la remplacer par le --scriptdrapeau, comme suit: forever-service install test --script main.js. (Non testé, veuillez donc me corriger s'il y a un détail de syntaxe incorrect.)
Dan Nissenbaum
3
@DanNissenbaum Merci d'avoir répondu. J'utilise maintenant PM2 qui fonctionne à merveille. Instructions: digitalocean.com/community/tutorials/…
Alex
27
  1. Installez PM2 globalement à l'aide de NPM

    npm install pm2 -g

  2. Commencez votre script avec pm2

    pm2 start app.js

  3. générer un script de démarrage actif

    pm2 startup

    REMARQUE: le démarrage de pm2 sert à démarrer le PM2 lors du redémarrage du système. PM2 une fois démarré, redémarre tous les processus qu'il gérait avant l'arrêt du système.

Si vous souhaitez désactiver le démarrage automatique, utilisez simplement pm2 unstartup

Si vous souhaitez que le script de démarrage soit exécuté sous un autre utilisateur, utilisez simplement l' -u <username>option et le--hp <user_home>:

fsamuel
la source
Veuillez ne pas publier la même réponse à plusieurs questions.
FelixSFD
J'adore la façon dont PM2 est raffiné et est livré avec un outil de surveillance génial. J'espère que cela est davantage mis en évidence pour les autres. @ rv7 Je suis sûr que vous avez vu cela, mais il existe une solution Windows: npmjs.com/package/pm2-windows-service . Je n'ai pas essayé moi-même.
John Lee
26

Ce cas est valable pour Debian.

Ajoutez ce qui suit à /etc/rc.local

/usr/bin/sudo -u {{user}} /usr/local/bin/forever start {{app path}}

  • {{user}} remplace votre nom d'utilisateur.
  • {{app path}}remplace le chemin de votre application. Par exemple,/var/www/test/app.js
NiLL
la source
2
Cette méthode ne gère pas les arrêts progressifs, bien que pour beaucoup de gens, ce ne soit probablement pas un problème.
UpTheCreek
6
BTW - Je pense que vous devriez éditer /etc/rc.local, pas/etc/init.d/rc.local
UpTheCreek
Convenez avec @UpTheCreek que /etc/rc.local est l'endroit le plus approprié pour ajouter ceci - voir: unix.stackexchange.com/a/59945 pour une excellente explication.
So Over It
2
En outre, vous voudrez peut-être spécifier le `` répertoire de travail actuel '' app.jspour vous assurer que les fichiers relatifs sont chargés correctement - process.chdir('/your/path/to/your/app'); Node.js ref docs here
So Over It
1
Si vous avez besoin de définir des variables d'environnement pour votre script Node.JS (comme $ PORT pour express), l'ajout de la ligne suivante a /etc/rc.localfait l'affaire pour moi:( cd /path/to/project && /usr/bin/sudo -u {{user}} env PORT={{port number}} PATH=$PATH:/usr/local/bin sh -c "forever start app.js" )
sffc
11

Une méthode crontab alternative inspirée de cette réponse et de cet article de blog.

1. Créez un fichier de script bash (remplacez bob par l'utilisateur souhaité).

vi /home/bob/node_server_init.sh

2. Copiez et collez-le dans le fichier que vous venez de créer.

#!/bin/sh

export NODE_ENV=production
export PATH=/usr/local/bin:$PATH
forever start /node/server/path/server.js > /dev/null

Assurez-vous d'éditer les chemins ci-dessus en fonction de votre configuration!

3. Assurez-vous que le script bash peut être exécuté.

chmod 700 /home/bob/node_server_init.sh

4. Testez le script bash.

sh /home/bob/node_server_init.sh

5. Remplacez "bob" par l'utilisateur d'exécution du nœud.

crontab -u bob -e

6. Copiez et collez (changez bob à l'utilisateur souhaité).

@reboot /bin/sh /home/bob/node_server_init.sh

Enregistrez le crontab.

Vous avez atteint la fin, votre prix est un redémarrage (à tester) :)

Emre
la source
Cette méthode a fonctionné le mieux pour moi. Forever quitterait lorsque je mettrais un chemin complet vers le fichier server.js. Si je l'exécutais dans le même répertoire, Foreveer fonctionnerait bien. La raison pour laquelle il a échoué est que le fichier server.js comprenait d'autres fichiers, mais les chemins étaient erronés. En utilisant cette méthode, je pourrais CD dans mon script .sh dans le répertoire, puis exécuter tout ce qui s'y rapporte.
BeardedGeek
9

Réponse copiée de la question ci- jointe .

Vous pouvez utiliser PM2 , c'est un gestionnaire de processus de production pour les applications Node.js avec un équilibreur de charge intégré.

Installez PM2

$ npm install pm2 -g

Lancer une application

$ pm2 start app.js

Si vous utilisez express, vous pouvez démarrer votre application comme

pm2 start ./bin/www --name="app"

Liste de tous les processus en cours:

$ pm2 list

Il listera tous les processus. Vous pouvez ensuite arrêter / redémarrer votre service en utilisant l'ID ou le nom de l'application avec la commande suivante.

$ pm2 stop all                  
$ pm2 stop 0                    
$ pm2 restart all               

Pour afficher les journaux

$ pm2 logs ['all'|app_name|app_id]
Vikash Rajpurohit
la source
Comment démarre-t-il AUTOMATIQUEMENT au démarrage du système? Vous venez de copier / coller la saisie manuelle de la CLI
Vert
@Green, Exécuter, $pm2 startupAprès cela, vous verrez pm2 demander d'exécuter manuellement une commande, de la copier et de l'exécuter. Ensuite, $pm2 savemaintenant, votre app.js survivra aux redémarrages du système
yajnesh
7

Vous devez créer un script shell dans le dossier /etc/init.d pour cela. C'est un peu compliqué si vous ne l'avez jamais fait, mais il y a beaucoup d'informations sur le Web sur les scripts init.d.

Voici un exemple de script que j'ai créé pour exécuter un site CoffeeScript avec pour toujours:

#!/bin/bash
#
# initd-example      Node init.d 
#
# chkconfig: 345 
# description: Script to start a coffee script application through forever
# processname: forever/coffeescript/node
# pidfile: /var/run/forever-initd-hectorcorrea.pid 
# logfile: /var/run/forever-initd-hectorcorrea.log
#
# Based on a script posted by https://gist.github.com/jinze at https://gist.github.com/3748766
#


# Source function library.
. /lib/lsb/init-functions


pidFile=/var/run/forever-initd-hectorcorrea.pid 
logFile=/var/run/forever-initd-hectorcorrea.log 

sourceDir=/home/hectorlinux/website
coffeeFile=app.coffee
scriptId=$sourceDir/$coffeeFile


start() {
    echo "Starting $scriptId"

    # This is found in the library referenced at the top of the script
    start_daemon

    # Start our CoffeeScript app through forever
    # Notice that we change the PATH because on reboot
    # the PATH does not include the path to node.
    # Launching forever or coffee with a full path
    # does not work unless we set the PATH.
    cd $sourceDir
    PATH=/usr/local/bin:$PATH
    NODE_ENV=production PORT=80 forever start --pidFile $pidFile -l $logFile -a -d --sourceDir $sourceDir/ -c coffee $coffeeFile

    RETVAL=$?
}

restart() {
    echo -n "Restarting $scriptId"
    /usr/local/bin/forever restart $scriptId
    RETVAL=$?
}

stop() {
    echo -n "Shutting down $scriptId"
    /usr/local/bin/forever stop $scriptId
    RETVAL=$?
}

status() {
    echo -n "Status $scriptId"
    /usr/local/bin/forever list
    RETVAL=$?
}


case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    status)
        status
        ;;
    restart)
        restart
        ;;
    *)
        echo "Usage:  {start|stop|status|restart}"
        exit 1
        ;;
esac
exit $RETVAL

Je devais m'assurer que le dossier et les PATH étaient explicitement définis ou disponibles pour l'utilisateur root car les scripts init.d sont exécutés en tant que root.

Hector Correa
la source
2
Si vous avez des dépendances également démarrées avec init.d, vous pourriez avoir des problèmes d'ordre de chargement.
UpTheCreek
@ alexandru.topliceanu J'ai corrigé le lien.
Hector Correa
6

Utilisez le PM2

Quelle est la meilleure option pour exécuter le serveur de production du serveur

Quels sont les avantages d'exécuter votre application de cette façon?

  • PM2 redémarrera automatiquement votre application si elle plante.

  • PM2 gardera un journal de vos exceptions non gérées - dans ce cas, dans un fichier à /home/safeuser/.pm2/logs/app-err.log.

  • Avec une seule commande, PM2 peut garantir que toutes les applications qu'il gère redémarrent lorsque le serveur redémarre. Fondamentalement, votre application de nœud démarrera en tant que service.

réf: https://www.digitalocean.com/community/tutorials/how-to-use-pm2-to-setup-a-node-js-production-environment-on-an-ubuntu-vps

Vishnu Mishra
la source
5

Forever n'a pas été conçu pour que les applications de nœud s'exécutent en tant que services. La bonne approche consiste soit à créer une entrée / etc / inittab (anciens systèmes Linux) soit à créer une entrée (systèmes Linux plus récents).

Voici une documentation sur la façon de configurer cela comme un parvenu: https://github.com/cvee/node-upstart

snez
la source
Upstart m'a échoué sur CentOS et j'ai lu que ça allait disparaître. Créer une entrée init.d n'est pas vraiment le moyen le plus convivial, mais c'est linux je suppose :)
Jorre
5

crontabne fonctionne pas pour moi sur CentOS x86 6.5. @reboot semble ne pas fonctionner.

Enfin, j'ai eu cette solution:

Éditer: /etc/rc.local

sudo vi /etc/rc.local

Ajoutez cette ligne à la fin du fichier. Changez USER_NAMEet PATH_TO_PROJECTfaites votre propre. NODE_ENV=productionsignifie que l'application s'exécute en mode production. Vous pouvez ajouter plus de lignes si vous devez exécuter plusieurs applications node.js.

su - USER_NAME -c "NODE_ENV=production /usr/local/bin/forever start /PATH_TO_PROJECT/app.js"

Ne définissez pas NODE_ENVdans une ligne distincte, votre application fonctionnera toujours en mode de développement, car pour toujours ne pas obtenir NODE_ENV.

# WRONG!
su - USER_NAME -c "export NODE_ENV=production"

Enregistrez et quittez vi (appuyez sur ESC : w q return). Vous pouvez essayer de redémarrer votre serveur. Après le redémarrage de votre serveur, votre application node.js devrait s'exécuter automatiquement, même si vous ne vous connectez à aucun compte à distance via ssh.

Vous feriez mieux de définir l' NODE_ENVenvironnement dans votre shell. NODE_ENVsera défini automatiquement lorsque votre compte se USER_NAMEconnectera.

echo export NODE_ENV=production >> ~/.bash_profile

Ainsi, vous pouvez exécuter des commandes comme pour toujours stop / start /PATH_TO_PROJECT/app.jsvia ssh sans configurer à NODE_ENVnouveau.

Vince Yuan
la source
a eu le même problème sur debian 7.6. Cela a résolu pour moi. Merci beaucoup.
Daniele Vrut
Juste au cas où vous ne voudriez pas utiliser 'pour toujours', vous pouvez changer la ligne en 'su - USER_NAME -c "NODE_ENV = production node / PATH_TO_PROJECT / bin / www"'.
yaobin
3

J'ai écrit un script qui fait exactement ceci:

https://github.com/chovy/node-startup

Je n'ai pas essayé depuis toujours, mais vous pouvez personnaliser la commande qu'il exécute, donc cela devrait être simple:

/etc/init.d/node-app start
/etc/init.d/node-app restart
/etc/init.d/node-app stop
chovy
la source
2

Le problème avec rc.local est que les commandes sont accessibles en tant que root, ce qui est différent de la connexion en tant qu'utilisateur et de l'utilisation de sudo.

J'ai résolu ce problème en ajoutant un script .sh avec les commandes de démarrage que je veux etc / profile.d. Tout fichier .sh dans profile.d se chargera automatiquement et toute commande sera traitée comme si vous utilisiez le sudo normal.

Le seul inconvénient est que l'utilisateur spécifié doit se connecter pour que les choses commencent, ce qui dans ma situation a toujours été le cas.

Moe Elsharif
la source
1

J'ai essayé beaucoup des réponses ci-dessus. Aucun d'eux n'a fonctionné pour moi. Mon application est installée dans /homeet en tant qu'utilisateur, pas en tant que root. Cela signifie probablement que lorsque les scripts de démarrage mentionnés ci-dessus s'exécutent, ils /homene sont pas encore montés, donc l'application n'est pas démarrée.

Ensuite, j'ai trouvé ces instructions par Digital Ocean:

https://www.digitalocean.com/community/tutorials/how-to-use-pm2-to-setup-a-node-js-production-environment-on-an-ubuntu-vps

Utiliser PM2 comme expliqué était très simple et fonctionne parfaitement: mes serveurs virtuels ont eu deux plantages physiques depuis - le temps d'arrêt n'était que d'environ une minute.

Alex
la source
PM2 a beaucoup plus d'étoiles (2x) sur github, que pour toujours, et il a également plus de fonctionnalités. Je pense que la plupart des réponses sont obsolètes ici.
inf3rno
0

exemple complet de crontab (situé dans / etc / crontab).

#!/bin/bash

# edit this file with .. crontab -u root -e
# view this file with .. crontab -u root -l

# put your path here if it differs
PATH=/root/bin:/root/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin

# * * * * * echo "executes once every minute" > /root/deleteme

@reboot cd /root/bible-api-dbt-server; npm run forever;
@reboot cd /root/database-api-server; npm run forever;
@reboot cd /root/mailer-api-server; npm run forever;
danday74
la source
-2

Vous pouvez utiliser la commande suivante dans votre shell pour démarrer votre nœud pour toujours:

forever app.js //my node script

Vous devez garder à l'esprit que le serveur sur lequel votre application s'exécute doit toujours être activé.

Gaurav Singh
la source