node.js - [node-startup]如何正确地编写和使用service脚本?
怪我咯
怪我咯 2017-04-17 11:16:24
[Node.js讨论组]

目前有一个Node.js应用,如用parent.js管理(两个)child.js进程,在parent.js中的做法是:

var cp = require('child_process');
function spawn(server, config) {
    logger.log('spawn ' + server); // 输出spawn /usr/local/app/child.js
    worker = cp.spawn('node', [server, config]);
    worker.on('exit', function(code) {
        if(code !== 0) {
            logger.log('code = ' + code); // 输出code = 8
            spawn(server,config);
        }
    });
    return worker;
}
var worker = spawn('./child.js');
  • 在终端中启动
    node parent.js正常
  • 编写自启动脚本app,拷贝到/etc/init.d目录

    • 使用/etc/init.d/app start启动正常
    • 使用service app start启动出错

出错可以参照parent.js源码的注释部分。
附自启动脚本的写法:

#!/bin/sh

NODE_ENV="production"
NODE_APP='app.js'
APP_DIR='/var/www/example.com';
PID_FILE=$APP_DIR/pid/app.pid
LOG_FILE=$APP_DIR/log/app.log
CONFIG_DIR=$APP_DIR/config
PORT=3000
NODE_EXEC=`which node`

###############

# REDHAT chkconfig header

# chkconfig: - 58 74
# description: node-app is the script for starting a node app on boot.
### BEGIN INIT INFO
# Provides: node
# Required-Start:    $network $remote_fs $local_fs
# Required-Stop:     $network $remote_fs $local_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: start and stop node
# Description: Node process for app
### END INIT INFO

start_app (){
    if [ -f $PID_FILE ]
    then
        echo "$PID_FILE exists, process is already running or crashed"
        exit 1
    else
        echo "Starting node app..."
        PORT=$PORT NODE_ENV=$NODE_ENV NODE_CONFIG_DIR=$CONFIG_DIR $NODE_EXEC $APP_DIR/$NODE_APP  1>$LOG_FILE 2>&1 &
        echo $! > $PID_FILE;
    fi
}

stop_app (){
    if [ ! -f $PID_FILE ]
    then
        echo "$PID_FILE does not exist, process is not running"
        exit 1
    else
        echo "Stopping $APP_DIR/$NODE_APP ..."
        echo "Killing `cat $PID_FILE`"
        kill `cat $PID_FILE`;
        rm -f $PID_FILE;
        echo "Node stopped"
    fi
}

case "$1" in
    start)
        start_app
    ;;

    stop)
        stop_app
    ;;

    restart)
        stop_app
        start_app
    ;;

    status)
        if [ -f $PID_FILE ]
        then
            PID=`cat $PID_FILE`
            if [ -z "`ps ef | awk '{print $1}' | grep "^$PID$"`" ]
            then
                echo "Node app stopped but pid file exists"
            else
                echo "Node app running with pid $PID"

            fi
        else
            echo "Node app stopped"
        fi
    ;;

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

github地址:https://github.com/chovy/node-startup/blob/master/init.d/node-app

问题解决:
1. 在shell脚本中加入export NODE_PATH=/usr/local/lib/node_modules
2. 执行app时,先cd $APP_DIR

UPDATE:
1. 在start_app方法中创建/var/lock/subsys/app文件,这样系统关机时才会调用app脚本的stop_app方法。

怪我咯
怪我咯

走同样的路,发现不同的人生

全部回复(3)
PHPz

总结下答案:

  1. 在shell脚本中加入export NODE_PATH=/usr/local/lib/node_modules
  2. 执行app时,先cd $APP_DIR
  3. start_app方法中创建/var/lock/subsys/app文件,这样系统关机时才会调用app脚本的stop_app方法。
ringa_lee

最好 cd 到 app 目录去,这样才能确保找到你安装到本地的 node_modules。

cd $APP_DIR && PORT=$PORT NODE_ENV=$NODE_ENV NODE_CONFIG_DIR=$CONFIG_DIR $NODE_EXEC $NODE_APP  1>$LOG_FILE 2>&1 &

我猜你在执行 /etc/init.d/app start 的时候恰好就在 parent.js 所在的目录,于是恰好就能正常找到 node_modules,给你造成了启动脚本没问题的错觉。而使用 service 运行时,这个 service 脚本重置了 $PWD,让 node 找不到 node_modules,从而导致问题。

总是先 cd 再执行 node 脚本是避免出错的最好方法~

天蓬老师

使用绝对路径试试:

var worker = spawn('/usr/local/app/child.js')
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号