📜 ⬆️ ⬇️

Node.js daemon for FreeBSD: forever + rc.d

In the process of working on a project using Node.js as a serverside, the task of running a JS script as a service arose, with all the bunks of type start, stop, restart. On this topic, in principle, there is already enough information, but it basically comes down to using Monit + Init under Linux, or short tips like “use nodemon, Luke”.

In my case, the production server was a FreeBSD machine. As a utility that runs a JS file as a process, I liked forever. This thing, unlike nodemon, is able to follow the processes running under it and lift them when it falls without waiting for a change in the script sources, which is very convenient on the production. In addition, forever is able to show the current list of running processes, with the display of their uptime, well, and allows you to stop / restart processes by name or index.

Without thinking, the rc.d script was written:

')
# cat /usr/local/etc/rc.d/factory
#!/bin/sh # PROVIDE: factory # REQUIRE: NETWORKING SERVERS DAEMON # BEFORE: LOGIN # KEYWORD: shutdown . /etc/rc.subr name="factory" forever="/usr/local/bin/node /usr/local/bin/forever" workdir="/usr/home/www/factory" script="index.js" rcvar=`set_rcvar` start_cmd="start" stop_cmd="stop" restart_cmd="restart" load_rc_config $name eval "${rcvar}=\${${rcvar}:-'NO'}" start() { HOME=/root NODE_ENV=production ${forever} start -a -l /var/log/forever.log -o /dev/null -e ${workdir}/logs/node_err.log --sourceDir ${workdir} ${workdir}/node/${script} } stop() { ${forever} stop ${workdir}/node/${script} } restart() { ${forever} restart ${workdir}/node/${script} } run_rc_command "$1" 


The following line was added to /etc/rc.conf: factory_enable = "YES". After that, a test run was made: /usr/local/etc/rc.d/factory start and the script happily started. After checking the restart and stop work, I was pleased with myself and went to pour myself some tea. At the same time, in order to check the launch of the script in combat conditions, I sent a server to the reboot.

Returning to the tea, I opened the browser and found that the server did not start. The forever log contained the following:
 # cat /var/log/forever.log ... warn: Forever restarting script for 11119 time warn: Forever detected script exited with code: 127 warn: Forever restarting script for 11120 time warn: Forever detected script exited with code: 127 warn: Forever restarting script for 11121 time warn: Forever detected script exited with code: 127 warn: Forever restarting script for 11122 time warn: Forever detected script exited with code: 127 warn: Forever restarting script for 11123 time warn: Forever detected script exited with code: 127 warn: Forever restarting script for 11124 time 


Thus, from the moment the service “started”, the child JS-process managed to fall / rise 11,124 times, while I was drowning a tea bag in boiling water.

Whenever something starts from the console but does not work when started in a “clean” environment, the internal voice whispers the same thing: “The environment variables are the same!”. But how so? I pointed out the HOME about which they write everywhere, and NODE_ENV = production is necessary for the work of express. What else does?

But it is necessary to compare the difference between the user environment and the environment at the start of the system. As a result of this comparison, three more environment variables were added to the rc.d script, to the “start” section: USER, PATH, and PWD. After that, the JS-script started to start correctly. Actually the working version of the rc.d script began to look like this:

 #!/bin/sh # PROVIDE: factory # REQUIRE: NETWORKING SERVERS DAEMON # BEFORE: LOGIN # KEYWORD: shutdown . /etc/rc.subr name="factory" forever="/usr/local/bin/node /usr/local/bin/forever" workdir="/usr/home/www/factory" script="index.js" rcvar=`set_rcvar` start_cmd="start" stop_cmd="stop" restart_cmd="restart" load_rc_config $name eval "${rcvar}=\${${rcvar}:-'NO'}" start() { USER=root PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/root/bin PWD=/root HOME=/root NODE_ENV=production ${forever} start -a -l /var/log/forever.log -o /dev/null -e ${workdir}/logs/node_err.log --sourceDir ${workdir} ${workdir}/node/${script} } stop() { ${forever} stop ${workdir}/node/${script} } restart() { ${forever} restart ${workdir}/node/${script} } run_rc_command "$1" 


Having rummaged in “these your Internet sites”, I was surprised at the lack of information about the fail-safe launch of the node.js service in this way on the machine running FreeBSD. Actually what I decided to write about, suddenly it will be useful to someone.

Source: https://habr.com/ru/post/137857/


All Articles