【问题标题】:Node's spawn() silently failing when called from a forever script scheduled on boot从启动时安排的永久脚本调用时,节点的 spawn() 静默失败
【发布时间】:2016-01-29 08:18:40
【问题描述】:

这有点笨拙。这个问题很可能与服务器有关,所以我的第一个办法是AskUbuntu over here

我正在尝试让 crontab 或 rc.local 或 init.d 在启动时启动 forever 脚本。它将一个服务器连接到一个端口,我可以用一些信息 ping 并让它为我运行一个无头浏览器。

也就是说,我似乎无法从 Node.js 的spawn() 得到回复:

var CASPER_PATH = '/home/ubuntu/dev/casperjs/bin/casperjs'; // actual binary location, not a symlink
var SCRIPTS_PATH = '/home/custom_user/endpoints/server.js';

var fileName = req.body.source + '_' + req.body.type + '.coffee'; // looks like: mysource_my_scrape_type.coffee
var scrapeId = 'test_scrape';
var user = 'user123';
var pass = 'pass123';
if (fs.existsSync(SCRIPTS_PATH + fileName)) {
  // If file is in place, spawn casperjs
  var sP = spawn(CASPER_PATH, 
    [SCRIPTS_PATH + fileName, '--ssl-protocol=any', '--user='+user, '--scrapeId='+scrapeId, '--pass='+pass], 
    { detached: true }, 
    function (err, stdout, stderr) {});
  sP.stdout.on('data', function(data) { console.log('stdout', data.toString('utf8')); });
  sP.stderr.on('data', function(data) { console.log('stderr', data.toString('utf8')); });
  sP.stdout.on('close', function(code) { console.log('close', code); });
  res.send({ scheduled: true, key: scrapeId });
} else {
  res.send({ scheduled: false, error: 'Incorrect source, type or the script is missing.' });
}

在我将 PHANTOMJS_EXECUTABLE 环境添加到 crontabrc.local 之前(无论用户级别如何似乎都无关紧要),stdout 很有用:

stdout 致命:[Errno 2] 没有这样的文件或目录;你安装了吗 幻影?

关闭错误

现在环境变量已经存在,spawn() 之后根本没有输出。

请注意,如果用户(任何特权级别)从 bash 运行 node/forever,Casper 启动正常。

我如何查看spawn() 失败的原因?

【问题讨论】:

  • 您能提供您的脚本的完整源代码吗? spawn 到底是什么?我刚刚查看了docs 并没有对 child_process.spawn() 的错误回调,如果您使用此spawn 然后尝试添加 sP.on('error', ..) 处理程序并检查输出。如果您发布您的 crontab 或 init.d 也会很好,这样会更容易重现您的问题。

标签: javascript linux node.js phantomjs casperjs


【解决方案1】:

这实际上看起来像是永远、spawn 和 casperjs(可能是 phantomjs)之间的组合错误。 我能够重现您的问题,here is 我的测试应用程序的完整代码。

你没有展示完整的代码,所以我猜你有一个 express 应用程序并且有一个特殊的 URL 来运行 casperjs 脚本。

我构建了一个这样的简单应用程序,它的行为方式是这样的:

  • 只需使用 node script.js 启动应用程序(script.js 是在 server.js 中运行 casperjs 脚本的快速应用程序) - 它工作正常,呈现响应并将子进程事件处理程序的输出写入控制台
  • 使用 init.d 脚本以 root 身份启动应用程序 - 不起作用,一旦生成子项,就不会触发任何事件处理程序
  • 使用 init.d 脚本以 root 身份启动应用程序,将 casperjs 替换为 echo - 相同,但不起作用(请参阅,这里我们仅以 root 身份运行 foreverspawn 和 @987654329 存在此问题@)
  • 使用 init.d 以普通用户(非 root)身份启动应用程序,将 casperjs 替换为 'echo' - 它可以工作,触发事件处理程序,在这里我几乎可以确定问题已解决,但是 ... :(
  • 使用 init.d 以普通用户(非 root)身份启动应用程序,放回 casperjs - 它不再工作,事件处理程序未触发

对此的实际解决方案是使用pm2,我这样做了:

# install pm2
sudo npm install -g pm2
# generate init.d scripts for pm2
# this command will fail, but hint about the correct format with sudo
pm2 startup ubuntu
# do this in the folder with your application
pm2 start script.js
# remember your application
pm2 save
# also useful
# sudo service stop/start/restart pm2
# pm2 stop/start/restart script

现在pm2 将随系统自动启动并启动您的应用程序。一切正常,子进程事件处理程序被触发。

【讨论】:

    【解决方案2】:

    我没有完全理解你的要求。但我在 Ubuntu 无头服务器上确实有类似的情况。

    我在这里尝试做的就是我所做的

    首先,我的 crontab 怎么样?

    crontab -u USER -e
    
    @reboot exec sudo -u USER /bin/bash /home/USER/SHELL_SCRIPT.sh
    

    看,这里我实际上是在启动一个 shell 脚本,而不是一个节点服务器

    现在在这个 shell 脚本中(SHELL_SCRIPT.sh)

        #! /bin/bash
        # SHELL_SCRIPT.sh
        cd /home/USER/
        /home/USER/.npm-packages/bin/forever start -p /home/USER -a -d --watch false --pidFile /home/USER/forever.pid -l /home/USER/forever.log -o /home/USER/forever.out -e /home/USER/forever.err /home/USER/MY_NODE.js
    

    即使在我的 MY_NODE.js 中,我也遵循绝对路径,我只是忽略 $PATH,并且不使用它。

    在这个节点服务器中,我做了 100 次生成

    现在,我大约在 2 年前就这样做了,所以如果你问我为什么这样做,我无法回答

    【讨论】:

    • 你是专门生成 casper 还是 phantom?
    • 不,我产生了很多其他的东西,即使在那个产生的过程中我也避免使用 $PATH
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-03
    • 1970-01-01
    • 1970-01-01
    • 2014-08-30
    相关资源
    最近更新 更多