Назад | Перейти на главную страницу

Сервер Node.js изначально выдает ошибку systemd EADDRNOTAVAIL

Мне нужно запустить сценарий для HTTP-запроса на получение с внешнего компьютера, и я использую для этого Node.js. Я хочу, чтобы сервер запустился вместе с системой. Все работает, за исключением того, что кажется, что сервер запускается слишком рано в процессе загрузки:

-- Logs begin at Mon 2017-01-23 09:55:21 UTC, end at Mon 2017-01-23 10:36:20 UTC. --
Jan 23 09:55:24 powercontrol systemd[1]: Starting Energenie Listener...
Jan 23 09:55:24 powercontrol systemd[1]: Started Energenie Listener.
Jan 23 09:55:28 powercontrol node[474]: events.js:160
Jan 23 09:55:28 powercontrol node[474]: throw er; // Unhandled 'error' event
Jan 23 09:55:28 powercontrol node[474]: ^
Jan 23 09:55:28 powercontrol node[474]: Error: listen EADDRNOTAVAIL 192.168.40.62:8001
Jan 23 09:55:28 powercontrol node[474]: at Object.exports._errnoException (util.js:1022:11)
Jan 23 09:55:28 powercontrol node[474]: at exports._exceptionWithHostPort (util.js:1045:20)
Jan 23 09:55:28 powercontrol node[474]: at Server._listen2 (net.js:1249:19)
Jan 23 09:55:28 powercontrol node[474]: at listen (net.js:1298:10)
Jan 23 09:55:28 powercontrol node[474]: at doListening (net.js:1397:7)
Jan 23 09:55:28 powercontrol node[474]: at _combinedTickCallback (internal/process/next_tick.js:77:11)
Jan 23 09:55:28 powercontrol node[474]: at process._tickCallback (internal/process/next_tick.js:98:9)
Jan 23 09:55:28 powercontrol node[474]: at Module.runMain (module.js:607:11)
Jan 23 09:55:28 powercontrol node[474]: at run (bootstrap_node.js:420:7)
Jan 23 09:55:28 powercontrol node[474]: at startup (bootstrap_node.js:139:9)
Jan 23 09:55:28 powercontrol systemd[1]: energenie_listener.service: main process exited, code=exited, s
Jan 23 09:55:28 powercontrol systemd[1]: Unit energenie_listener.service entered failed state.
Jan 23 09:55:30 powercontrol systemd[1]: energenie_listener.service holdoff time over, scheduling restar
Jan 23 09:55:30 powercontrol systemd[1]: Stopping Energenie Listener...
Jan 23 09:55:30 powercontrol systemd[1]: Starting Energenie Listener...
Jan 23 09:55:30 powercontrol systemd[1]: Started Energenie Listener.
Jan 23 09:55:31 powercontrol node[565]: events.js:160
Jan 23 09:55:31 powercontrol node[565]: throw er; // Unhandled 'error' event
Jan 23 09:55:31 powercontrol node[565]: ^
Jan 23 09:55:31 powercontrol node[565]: Error: listen EADDRNOTAVAIL 192.168.40.62:8001
Jan 23 09:55:31 powercontrol node[565]: at Object.exports._errnoException (util.js:1022:11)
Jan 23 09:55:31 powercontrol node[565]: at exports._exceptionWithHostPort (util.js:1045:20)
Jan 23 09:55:31 powercontrol node[565]: at Server._listen2 (net.js:1249:19)
Jan 23 09:55:31 powercontrol node[565]: at listen (net.js:1298:10)
Jan 23 09:55:31 powercontrol node[565]: at doListening (net.js:1397:7)
Jan 23 09:55:31 powercontrol node[565]: at _combinedTickCallback (internal/process/next_tick.js:77:11)
Jan 23 09:55:31 powercontrol node[565]: at process._tickCallback (internal/process/next_tick.js:98:9)
Jan 23 09:55:31 powercontrol node[565]: at Module.runMain (module.js:607:11)
Jan 23 09:55:31 powercontrol node[565]: at run (bootstrap_node.js:420:7)
Jan 23 09:55:31 powercontrol node[565]: at startup (bootstrap_node.js:139:9)
Jan 23 09:55:31 powercontrol systemd[1]: energenie_listener.service: main process exited, code=exited, s
Jan 23 09:55:31 powercontrol systemd[1]: Unit energenie_listener.service entered failed state.
Jan 23 09:55:33 powercontrol systemd[1]: energenie_listener.service holdoff time over, scheduling restar
Jan 23 09:55:33 powercontrol systemd[1]: Stopping Energenie Listener...
Jan 23 09:55:33 powercontrol systemd[1]: Starting Energenie Listener...
Jan 23 09:55:33 powercontrol systemd[1]: Started Energenie Listener.
Jan 23 09:55:34 powercontrol node[572]: Server running at http://192.168.40.62:8001/

Как видите, после пары сбоев сервер в конце концов запускается и после этого работает нормально. В .service файл выглядит следующим образом:

[Unit]
Description=Energenie Listener
After=network.target systemd-journald.service

[Service]
ExecStart=/usr/bin/node /var/opt/energenie/energenie_listener.js
Restart=always
RestartSec=2
User=root
Group=root
Environment=PATH=/usr/bin:/usr/local/bin
Environment=NODE_ENV=production
WorkingDirectory=/var/opt/energenie

[Install]
WantedBy=multi-user.target

Так же как After=network.target ..., Я попытался network-online.target, но это не имеет значения.

Стоит ли ждать другой услуги? Который из?

У меня есть одна мысль: у этой машины статический IP-адрес, но он назначается через DHCP. Если проблема в том, что network.targetnetwork-online.target) работает, но IP-адрес, который я пытаюсь заявить в сценарии узла, еще не назначен, предположительно мне нужна служба, которая будет гарантировать, что IP-адрес полностью настроен. Может ли это быть проблемой, и если да, то есть ли подходящий сервис, на который можно положиться?

Это может быть интересным применением для действий на основе сокетов. Вместо того, чтобы запускать вашу службу во время загрузки, она будет запускаться при первом поступлении сетевого запроса на ее активацию. К тому времени назначение сети DHCP должно быть завершено!

В файле служебной единицы вы добавляете запись в [Service] раздел, чтобы объявить, откуда берется STDIN:

StandardInput=socket

Затем сделайте .socket файл с тем же именем, что и ваш .service файл, который выглядит примерно так:

[Unit]
Description=Energenie Listener Socket

[Socket]
# Depending your app, you might also use ListenStream= 
# or ListenSequentialPacket= See man systemd.socket for details
ListenDatagram=192.168.40.62:8001
# Allow binding to addresses that may not be configured yet.
FreeBind=true

[Install]
WantedBy=sockets.target

Обязательно бежать systemd enable на сокете перед перезагрузкой.

Для получения дополнительной информации см. man systemd.socket или найдите сообщения о [активации сокета systemd].

Я изменил IP-адрес, который сервер прослушивал, с определенного в журналах вопросов на подстановочный знак, 0.0.0.0. Похоже, это решило проблему (что наводит на мысль, что мои подозрения о том, что адрес DHCP не был назначен, могли быть правильными).

Это не идеальное решение (потому что я все еще не знаю, как дождаться, пока станет доступен адрес, назначенный DHCP), но поскольку это не имеет никакого практического значения для данного конкретного случая, оно решает непосредственную проблему зарегистрированные ошибки.