4

Emacs lisp 命令调用node hello.js

(call-process "node" nil t nil "hello.js")

的两种变体hello.js

  • hello_1.js

    console.log('Hello world!');
    

    输出:

    Hello world!
    0
    
  • hello_2.js

    console.log('Hello world!');
    process.exit(5);
    

    输出(日志语句没有输出!):

    5
    

process.exit(5)导致输出被抑制的原因是什么?

笔记:

  • 在 MARVIN 上的 2013-03-17 的 GNU Emacs 24.3.1 (i386-mingw-nt5.1.2600) 中遇到了这个问题,结合Node.js v0.10.18Windows XP/SP3/32上运行。

  • 我尝试EShell执行节点命令行:没有输出

  • process.exit()调用低电平process.reallyExit(),导致问题:没有输出

    process.reallyExit()在 C++ 中实现:

    void Exit(const FunctionCallbackInfo<Value>& args) {
      HandleScope scope(node_isolate);
      exit(args[0]->IntegerValue());
    }
    

    [...]

    NODE_SET_METHOD(process, "reallyExit", Exit);
    
4

1 回答 1

1

呸,我自己想通了。首先,我发现延迟会导致输出出现:

hello_3.js

console.log('Hello world!');
setTimeout(function () {
    process.exit(5);
}, 1000);

输出:

Hello world!
5

所以我仔细检查了 Node.js 文档console发现

当目标是终端或文件时,控制台函数是同步的(以避免在过早退出的情况下丢失消息),而当它是管道时是异步的(以避免长时间阻塞)。

然后我决定确保不使用管道并编写了一个批处理脚本 hello_2.bat

@ECHO OFF
node hello_2.js >test
TYPE test

调用脚本时的输出(call-process "cmd.exe" nil t nil "/C" "hello_2.bat")

Hello world!
0

(返回值为 0 而不是 5,但我不在乎)

回答我的问题:

  1. 看起来call-process在 Windows 上的 Emacs 中使用管道从程序中检索输出。

    正如我还提到的 EShell:它似乎没有被 Windows 上的 Node.js 识别为终端,并且可能 EShell 在内部使用call-process或类似的方式来运行程序。

  2. 将管道检测为标准输出的目标会导致console.log 异步运行。

  3. process.exit(5)在 Windows 上的 Node.js 中似乎丢弃了所有计划的异步任务,因此没有生成输出。

    这一假设得到了 Windows 命令提示符内拼命将输出定向到管道的结果的支持:

    C:\Temp> node hello_2.js | MORE
    
    C:\Temp>
    

最后,我发现这个问题从大约一年前(截至 2013 年 9 月)就已为人所知。

于 2013-09-12T22:40:07.937 回答