Как запустить приложение node.js в качестве фоновой службы?

Поскольку этот пост привлек много внимания на протяжении многих лет, я перечислил лучшие решения для каждой платформы в нижней части этого поста.


Исходное сообщение:

Я хочу, чтобы мой сервер node.js работал в фоновом режиме, то есть: когда я закрываю свой терминал, я хочу, чтобы мой сервер продолжал работать. Я гуглил это и придумал этот урок, однако он не работает как задумано. Поэтому вместо того, чтобы использовать этот демон-сценарий, я подумал, что просто использовал перенаправление вывода (2>&1 >> file часть), но это тоже не выходит - я получаю пустую строку в моем терминале, как будто он ожидает вывода / ошибок.

Я также пытался перевести процесс в фоновый режим, но как только я закрываю свой терминал, процесс также прекращается.

Так, как я могу оставить это работающим, когда я выключаю свой локальный компьютер?


Лучшие решения:

32 ответа

Решение

Копирование моего собственного ответа из Как я могу запустить приложение Node.js как его собственный процесс?

Ответ 2015 года: почти каждый дистрибутив Linux поставляется с systemd, что означает, что навсегда, monit и т. Д. Больше не нужны - ваша ОС уже выполняет эти задачи.

Делать myapp.service file (заменив 'myapp' на имя вашего приложения, очевидно):

[Unit]
Description=My app

[Service]
ExecStart=/var/www/myapp/app.js
Restart=always
User=nobody
# Note Debian/Ubuntu uses 'nogroup', RHEL/Fedora uses 'nobody'
Group=nogroup
Environment=PATH=/usr/bin:/usr/local/bin
Environment=NODE_ENV=production
WorkingDirectory=/var/www/myapp

[Install]
WantedBy=multi-user.target

Обратите внимание, если вы новичок в Unix: /var/www/myapp/app.js должен иметь #!/usr/bin/env node на самой первой линии.

Скопируйте файл службы в /etc/systemd/system,

Начни с systemctl start myapp,

Включить его при загрузке с systemctl enable myapp,

Смотрите логи с journalctl -u myapp

Это взято из того, как мы разворачиваем приложения для узлов в Linux, выпуск 2018, который также включает команды для генерации AWS/DigitalOcean/Azure CloudConfig для построения серверов Linux/ узлов (включая .service файл).

ОБНОВЛЕНИЕ - Как упоминалось в одном из ответов ниже, в PM2 есть действительно хорошая функциональность, которой не хватает навсегда. Подумайте об этом.

Оригинальный ответ

Используйте nohup:

nohup node server.js &

РЕДАКТИРОВАТЬ Я хотел бы добавить, что принятый ответ действительно путь. Я навсегда использую случаи, когда нужно не ложиться спать. я люблю делать npm install -g forever так что это в пути узла, а затем просто сделать forever start server.js

Вы можете использовать Forever, простой инструмент CLI для обеспечения непрерывной работы данного скрипта узла (т. Е. Навсегда): https://www.npmjs.org/package/forever

Это может быть неприемлемым способом, но я делаю это с экраном, особенно в процессе разработки, потому что я могу восстановить его и, если необходимо, обмануть.

screen
node myserver.js
>>CTRL-A then hit D

Экран отсоединится и выживет после выхода из системы. Затем вы можете вернуть его обратно с помощью screen -r. Нажмите на руководство по экрану для более подробной информации. Вы можете назвать экраны и еще много чего, если хотите.

Обновление 2016 года: в серии node-windows/mac/linux используется общий API для всех операционных систем, поэтому это абсолютно актуальное решение. Тем не мение; node-linux создает системные файлы инициализации. По мере того как популярность systemd продолжает расти, это действительно лучший вариант для Linux. PR приветствуется, если кто-то хочет добавить поддержку systemd в node-linux:-)

Оригинальная тема:

Сейчас это довольно старый поток, но ноды-окна предоставляют еще один способ создания фоновых сервисов в Windows. Это свободно основано на nssm Концепция использования exe Обертка вокруг вашего узла скрипта. Тем не мение; оно использует winsw.exe вместо этого и предоставляет настраиваемую оболочку узла для более детального контроля над тем, как процесс запускается / останавливается при сбоях. Эти процессы доступны как любой другой сервис:

Модуль также запекает в некоторых журналах событий:

Демонизация вашего скрипта осуществляется с помощью кода. Например:

var Service = require('node-windows').Service;

// Create a new service object
var svc = new Service({
  name:'Hello World',
  description: 'The nodejs.org example web server.',
  script: 'C:\\path\\to\\my\\node\\script.js'
});

// Listen for the "install" event, which indicates the
// process is available as a service.
svc.on('install',function(){
  svc.start();
});

// Listen for the "start" event and let us know when the
// process has actually started working.
svc.on('start',function(){
  console.log(svc.name+' started!\nVisit http://127.0.0.1:3000 to see it in action.');
});

// Install the script as a service.
svc.install();

Модуль поддерживает такие вещи, как закрытие перезапусков (чтобы плохие скрипты не мешали вашему серверу) и увеличение временных интервалов между перезапусками.

Поскольку службы узлов Windows работают, как и любые другие, можно управлять / контролировать службу с помощью любого программного обеспечения, которое вы уже используете.

Наконец, нет make зависимостей. Другими словами, просто npm install -g node-windows буду работать. Вам не нужна Visual Studio, .NET или магия нод-гипса, чтобы установить это. Кроме того, это MIT и BSD лицензированы.

В полном раскрытии я являюсь автором этого модуля. Он был разработан для облегчения боли, которую испытал ОП, но с более тесной интеграцией в функциональность, которую уже обеспечивает операционная система. Я надеюсь, что будущие зрители с таким же вопросом найдут его полезным.

Если вы просто хотите запустить скрипт без перерыва до его завершения, вы можете использовать nohop как уже упоминалось в ответах здесь. Однако ни один из ответов не предоставляет полную команду, которая также регистрирует stdin а также stdout,

nohup node index.js >> app.log 2>&1 &
  • >> значит добавить к app.log,
  • 2>&1 гарантирует, что ошибки также отправляются stdout и добавил к app.log,
  • Концовка & убедитесь, что ваш текущий терминал отключен от команды, чтобы вы могли продолжить работу.

Если вы хотите запустить сервер узла (или что-то, что должно запуститься при перезагрузке сервера), вы должны использовать systemd / systemctl.

ОБНОВЛЕНИЕ: я обновил, чтобы включить последние от pm2:

во многих случаях использование службы systemd является самым простым и наиболее подходящим способом управления процессом узла. для тех, кто выполняет многочисленные процессы узлов или независимо запускает микросервисы узлов в одной среде, pm2 является более полнофункциональным инструментом.

https://github.com/unitech/pm2

http://pm2.io/

  • он имеет действительно полезную функцию мониторинга -> симпатичный графический интерфейс для мониторинга нескольких процессов с помощью командной строки pm2 monit или список процессов с pm2 list
  • организованный журнал управления -> pm2 logs
  • другие вещи:
    • Конфигурация поведения
    • Поддержка исходной карты
    • PaaS совместимый
    • Смотреть и Перезагрузить
    • Модульная система
    • Макс перезагрузка памяти
    • Кластерный режим
    • Горячая перезагрузка
    • Рабочий процесс разработки
    • Скрипты запуска
    • Авто завершение
    • Рабочий процесс развертывания
    • Мониторинг ключевых показателей
    • API

Попробуйте запустить эту команду, если вы используете nohup -

nohup npm start 2>/dev/null 1>/dev/null&

Вы также можете использовать навсегда, чтобы запустить сервер

forever start -c "npm start" ./ 

Если вы работаете с OSX, то самый простой способ создать настоящий системный процесс - это использовать launchd запустить его.

Создайте список, подобный этому, и поместите его в /Library/LaunchDaemons с именем top-level-domain.your-domain.application.plist (вам нужно быть пользователем root при размещении):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>top-level-domain.your-domain.application</string>

    <key>WorkingDirectory</key>
    <string>/your/preferred/workingdirectory</string>

    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/node</string>
        <string>your-script-file</string>
    </array>

    <key>RunAtLoad</key>
    <true/>

    <key>KeepAlive</key>
    <true/>

</dict>
</plist>

Когда закончите, выпустите это (как root):

launchctl load /Library/LaunchDaemons/top-level-domain.your-domain.application.plist
launchctl start top-level-domain.your-domain.application

и ты бежишь.

И вы все равно будете работать после перезагрузки.

Для других вариантов в листе списка просмотрите man-страницу здесь: https://developer.apple.com/library/mac/documentation/Darwin/Reference/Manpages/man5/launchd.plist.5.html

Я просто использую модуль демона npm:

var daemon = require('daemon');

daemon.daemonize({
    stdout: './log.log'
  , stderr: './log.error.log'
  }
, './node.pid'
, function (err, pid) {
  if (err) {
    console.log('Error starting daemon: \n', err);
    return process.exit(-1);
  }
  console.log('Daemonized successfully with pid: ' + pid);

  // Your Application Code goes here
});

В последнее время я также использую mon(1) от TJ Holowaychuk для запуска и управления простыми приложениями для узлов.

Я использую Supervisor для разработки. Это просто работает. Когда вы вносите изменения в файл.js, Supervisor автоматически перезапускает ваше приложение с этими загруженными изменениями.

Вот ссылка на его страницу Github

Установить:

sudo npm установить супервизор -g

Вы можете легко заставить его смотреть другие расширения с -e. Другая команда, которую я часто использую, это -i, чтобы игнорировать определенные папки.

Вы можете использовать nohup и supervisor, чтобы приложение вашего узла работало в фоновом режиме даже после выхода из системы.

руководитель sudo nohup myapp.js &

Node.js в качестве фонового сервиса в Windows XP

Монтаж:

  1. Установите WGET http://gnuwin32.sourceforge.net/packages/wget.htm через исполняемый файл установщика
  2. Установите GIT http://code.google.com/p/msysgit/downloads/list через исполняемый файл установщика
  3. Установите NSSM http://nssm.cc/download/?page=download скопировав nnsm.exe в папку%windir%/system32
  4. Создайте c:\node\helloworld.js

    // http://howtonode.org/hello-node
    var http = require('http');
    var server = http.createServer(function (request, response) {
        response.writeHead(200, {"Content-Type": "text/plain"});
        response.end("Hello World\n");
    });
    server.listen(8000);
    console.log("Server running at http://127.0.0.1:8000/");
    
  5. Откройте командную консоль и введите следующее (setx, только если установлен Resource Kit)

    C:\node> set path=%PATH%;%CD%
    C:\node> setx path "%PATH%"
    C:\node> set NODE_PATH="C:\Program Files\nodejs\node_modules"
    C:\node> git config --system http.sslcainfo /bin/curl-ca-bundle.crt    
    C:\node> git clone --recursive git://github.com/isaacs/npm.git    
    C:\node> cd npm    
    C:\node\npm> node cli.js install npm -gf   
    C:\node> cd ..    
    C:\node> nssm.exe install node-helloworld "C:\Program Files\nodejs\node.exe" c:\node\helloworld.js    
    C:\node> net start node-helloworld
    
  6. Отличный пакетный вкус - создать c:\node\ServiceMe.cmd

    @echo off
    nssm.exe install node-%~n1 "C:\Program Files\nodejs\node.exe" %~s1
    net start node-%~n1
    pause
    

Управление сервисом:

  • Сами службы теперь доступны через Пуск-> Выполнить-> services.msc или через Пуск-> Выполнить-> MSCONFIG-> Службы (и отметьте "Скрыть все службы Microsoft").
  • Сценарий будет префикс каждого узла, созданного с помощью пакетного сценария, с помощью 'node-'.
  • Также их можно найти в реестре: "HKLM \ SYSTEM \ CurrentControlSet \ Services \ node-xxxx"

Принятый ответ, вероятно, является лучшим производственным ответом, но для быстрого взлома, выполняя работу разработчика, я нашел это:

nodejs scriptname.js & не работал, потому что nodejs, казалось, сожрал &, и поэтому это не позволило мне продолжать использовать терминал без сценария script.js.

Но я поставил nodejs scriptname.js в файле.sh, иnohup sh startscriptname.sh & работал.

Определенно не производственная вещь, но она решает проблему "мне нужно продолжать использовать мой терминал и не хочу запускать 5 разных терминалов".

Обновление за июнь 2017 года:
Решение для Linux: (Red Hat). Предыдущие комментарии не работают для меня. Это работает для меня на Amazon Web Service - Red Hat 7. Надеюсь, что это работает для кого-то там.

A. Create the service file 
sudo vi /etc/systemd/system/myapp.service
[Unit]
Description=Your app
After=network.target

[Service]
ExecStart=/home/ec2-user/meantodos/start.sh
WorkingDirectory=/home/ec2-user/meantodos/

[Install]
WantedBy=multi-user.target

B. Create a shell file
/home/ec2-root/meantodos/start.sh
#!/bin/sh -
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to 8080
npm start

then:
chmod +rx /home/ec2-root/meantodos/start.sh
(to make this file executable)

C. Execute the Following

sudo systemctl daemon-reload
sudo systemctl start myapp
sudo systemctl status myapp

(If there are no errors, execute below.  Autorun after server restarted.)
chkconfig myapp -add

Если вы используете nodejs на Linux-сервере, я думаю, что это лучший способ.

Создайте сценарий службы и скопируйте в /etc/init/nodejs.conf

запуск службы: запуск узла sudo servicejs

остановка службы: остановка службы sudo

Сервисный скрипт

description "DManager node.js server - Last Update: 2012-08-06"
author      "Pedro Muniz - pedro.muniz@geeklab.com.br"

env USER="nodejs" #you have to create this user 
env APPNAME="nodejs" #you can change the service name
env WORKDIR="/home/<project-home-dir>" #set your project home folder here
env COMMAND="/usr/bin/node <server name>" #app.js ?

# used to be: start on startup
# until we found some mounts weren't ready yet while booting:
start on started mountall
stop on shutdown

# Automatically Respawn:
respawn
respawn limit 99 5

pre-start script
    sudo -u $USER echo "[`date -u +%Y-%m-%dT%T.%3NZ`] (sys) Starting" >> /var/log/$APPNAME.log
end script

script
    # Not sure why $HOME is needed, but we found that it is:
    export HOME="<project-home-dir>"  #set your project home folder here
    export NODE_PATH="<project node_path>"

    #log file, grant permission to nodejs user
    exec start-stop-daemon --start --make-pidfile --pidfile /var/run/$APPNAME.pid --chuid $USER --chdir $WORKDIR --exec $COMMAND >> /var/log/$APPNAME.log 2>&1
end script

post-start script
   # Optionally put a script here that will notifiy you node has (re)started
   # /root/bin/hoptoad.sh "node.js has started!"
end script

pre-stop script
    sudo -u $USER echo "[`date -u +%Y-%m-%dT%T.%3NZ`] (sys) Stopping" >> /var/log/$APPNAME.log
end script

Поскольку мне не хватает этой опции в списке предоставленных ответов, я хотел бы добавить подходящую опцию с 2020 года: докер или любую эквивалентную платформу контейнера. Помимо обеспечения работы вашего приложения в стабильной среде, существуют дополнительные преимущества безопасности, а также улучшенная переносимость.

Существует поддержка докеров для Windows, macOS и большинства / основных дистрибутивов Linux. Установка докера на поддерживаемую платформу довольно проста и хорошо документирована. Настроить приложение Node.js так же просто, как поместить его в контейнер и запустить этот контейнер, убедившись, что он перезапускается после завершения работы.

Создать образ контейнера

Предполагая, что ваше приложение доступно в /home / me / my-app на этом сервере, создайте текстовый файл Dockerfile в папке /home / me / my-app с содержимым, аналогичным этому:

FROM node:lts-alpine
COPY /my-app /app
CMD ["/app/server.js"]

Создайте изображение с помощью такой команды:

docker build -t myapp-as-a-service /home/me

Примечание. Последний параметр - это выбор папки, содержащей этот Dockerfile, вместо самого Dockerfile. Вы можете выбрать другой, используя опцию -f.

Запустить контейнер

Используйте эту команду для запуска контейнера:

docker run -d --restart always -p 80:3000 myapp-as-a-service

Эта команда предполагает, что ваше приложение прослушивает порт 3000, и вы хотите, чтобы оно было доступно на порту 80 вашего хоста.

Конечно, это очень ограниченный пример, но это хорошая отправная точка.

Используйте модуль pm2. модуль узла pm2

Используйте nssm лучшее решение для windows, просто скачайте nssm, откройте cmd в каталоге nssm и введите

nssm install <service name> <node path> <app.js path> 

eg: nssm install myservice "C:\Program Files\nodejs" "C:\myapp\app.js" 

при этом будет установлена ​​новая служба Windows, которая будет указана на сайте services.msc, откуда вы можете запускать или останавливать службу, эта служба будет запускаться автоматически, и вы можете настроить ее перезагрузку в случае сбоя.

Чтобы завершить различные предлагаемые варианты, вот еще один: daemon команда в GNU/Linux, о которой вы можете прочитать здесь: http://libslack.org/daemon/manpages/daemon.1.html. (извинения, если это уже упоминалось в одном из комментариев выше).

Я немного опоздал. Простое решение — выполнить следующие две команды в терминале, как показано ниже.

      nohup node ./server.js &
disown -h %1 

Затем закройте сеанс ssh, и программа узла продолжит работать. Проверено на Ubuntu 18.

PM2 - это менеджер производственных процессов для приложений Node.js со встроенным балансировщиком нагрузки. Это позволяет вам поддерживать приложения в актуальном состоянии, перезагружать их без простоев и облегчать общие задачи системного администратора. https://github.com/Unitech/pm2

Я использую tmux для среды разработки нескольких окон / панелей на удаленных хостах. Отсоединить и поддерживать процесс в фоновом режиме очень просто. Посмотрите на Tmux

Кто -нибудь заметил тривиальную ошибку позиции "2>&1"?

2>&1 >> file

должно быть

>> file 2>&1

Для людей, использующих более новые версии модуля daemon npm - вам нужно передавать файловые дескрипторы вместо строк:

var fs = require('fs');
var stdoutFd = fs.openSync('output.log', 'a');
var stderrFd = fs.openSync('errors.log', 'a');
require('daemon')({
    stdout: stdoutFd, 
    stderr: stderrFd
});

Проверьте фугу! Помимо запуска многих рабочих, вы также можете демонизировать процесс вашего узла!

http://github.com/pgte/fugue

Если вы используете pm2, вы можете использовать его с autorestart установлен в false:

Экосистема $ pm2

Это сгенерирует образец ecosystem.config.js:

module.exports = {
  apps: [
    {
      script: './scripts/companies.js',
      autorestart: false,
    },
    {
      script: './scripts/domains.js',
      autorestart: false,
    },
    {
      script: './scripts/technologies.js',
      autorestart: false,
    },
  ],
}

$ pm2 запустить экосистему.config.js

Я удивлен, что никто не упомянул Гувнора

Я пробовал навсегда, pm2 и т. Д. Но, когда речь заходит о надежном контроле и показателях производительности в сети, я обнаружил, что Guvnor безусловно лучший. Плюс, это также полностью с открытым исходным кодом.

Редактировать: Тем не менее, я не уверен, работает ли он на окнах. Я использовал это только на Linux.

Я получил следующую ошибку при использовании принятого ответа mikemaccana на экземпляре RHEL 8 AWS EC2: (code=exited, status=216/GROUP)

Это произошло из-за использования пользователя / группы, установленного на: «никто».

При поиске в Google кажется, что использование пользователя / группы как «никто» / «nogroup» является плохой практикой для демонов, как указано здесь на обмене стеками unix.

Он отлично работал после того, как я установил пользователя / группу для моего фактического пользователя и группы.

Вы можете войти whomai и groups чтобы увидеть доступные варианты, чтобы исправить это.

Мой служебный файл для приложения с полным стеком node с mongodb:

      [Unit]
Description=myapp
After=mongod.service

[Service]
ExecStart=/home/myusername/apps/myapp/root/build/server/index.js
Restart=always
RestartSec=30
User=myusername
Group=myusername
Environment=PATH=/usr/bin:/usr/local/bin
Environment=NODE_ENV=production
WorkingDirectory=/home/myusername/apps/myapp

[Install]
WantedBy=multi-user.target

Вы можете запустить приложение узла в фоновом режиме с помощью&в юниксе. Убедитесь, что в вашем приложении узла не должно быть интерактивного режима, например получения данных из ввода.

      node src/index.js -p 1234 --another-options &

В случае, если для целей локальной разработки вам необходимо запустить несколько экземпляров приложения NodeJS (экспресс, fastify и т. д.), тогдаconcurrentlyможет быть вариант. Вот настройка:

Предпосылки

  • Ваше приложение NodeJS (экспресс, fastify и т. д.) размещено по адресу/opt/mca/www/mca-backend/appпуть.
  • Предполагая, что вы используете узел v.16, установленный черезbrew install node@16

Настраивать

  1. Установить одновременно:npm install -g concurrently

  2. Создать файл

            <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Label</key>
        <string>mca.backend</string>
        <key>LimitLoadToSessionType</key>
        <array>
            <string>Aqua</string>
            <string>Background</string>
            <string>LoginWindow</string>
            <string>StandardIO</string>
            <string>System</string>
        </array>
        <key>ProgramArguments</key>
        <array>
            <string>/usr/local/bin/concurrently</string>
            <string>--names</string>
            <string>dev,prd</string>
            <string>--success</string>
            <string>all</string>
            <string>--kill-others</string>
            <string>--no-color</string>
            <string>MCA_APP_STAGE=dev  node ./server.mjs</string>
            <string>MCA_APP_STAGE=prod node ./server.mjs</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>EnvironmentVariables</key>
        <dict>
            <key>PATH</key>
            <string>/usr/local/opt/node@16/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin</string>
        </dict>
        <key>WorkingDirectory</key>
        <string>/opt/mca/www/mca-backend/app</string>
        <key>StandardErrorPath</key>
        <string>/opt/mca/www/mca-backend/err.log</string>
        <key>StandardOutPath</key>
        <string>/opt/mca/www/mca-backend/out.log</string>
    </dict>
    </plist>
    
  3. Загрузите и запустите:launchctl bootstrap gui/`id -u` $HOME/Library/LaunchAgents/mca.backend.plist

  4. Получить статус:launchctl print gui/`id -u`/mca.backend

  5. Останавливаться:launchctl kill SIGTERM gui/`id -u`/mca.backend

  6. Старт/Перезапуск:launchctl kickstart -k -p gui/`id -u`/mca.backend

  7. Выгрузить, если больше не нужно:launchctl bootout gui/`id -u`/mca.backend

ВАЖНО : После того, как вы загрузите службу с любыми изменениями, внесенными в файл~/Library/LaunchAgents/mca.backend.plistне будет работать, пока вы не выгрузите службу (используяlaunchctl bootout), а затем загрузите его снова (используяlaunchctl bootstrap).

Поиск неисправностей

Смотрите журналы запуска по адресу:/private/var/log/com.apple.xpc.launchd/launchd.log

Другие вопросы по тегам