我有一个需要从外部机器的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.target (和network-online.target )已经启动,但是我想要在Node脚本中声明的IP尚未分配,那么推测我需要一个服务来等待,这将保证IP地址已完全configuration。 难道这就是问题吗?如果是这样的话,有没有合适的服务要依靠?
这对于基于套接字的动作可能是一个有趣的用法。 它不会在启动时启动服务,而是在第一次启动networking请求时启动服务。 那么DHCPnetworking分配应该完成!
在服务单元文件中,将条目添加到[Service]部分以声明STDIN来自哪里:
StandardInput=socket
然后用与你的.service文件同名的.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或search有关[systemd套接字激活]的文章。
我将服务器正在侦听的IP地址从问题日志中的特定IP地址更改为通配符0.0.0.0 。 这似乎解决了这个问题(这表明我对未被分配的DHCP地址的怀疑可能是正确的)。
这不是一个完美的解决scheme(因为我还不知道如何等待DHCP分配的地址可用),但是对于这种特殊情况,这并没有什么实际意义,它解决了当前的问题logging错误。