【问题标题】:Use child_process.execSync but keep output in console使用 child_process.execSync 但将输出保留在控制台中
【发布时间】:2015-07-19 23:36:51
【问题描述】:

我想使用在 NodeJS 0.12 中添加的 execSync 方法,但在我运行 Node 脚本的控制台窗口中仍有输出。

例如如果我运行具有以下行的 NodeJS 脚本,我想在控制台中查看 rsync 命令“live”的完整输出:

require('child_process').execSync('rsync -avAXz --info=progress2 "/src" "/dest"');

我了解execSync 返回命令的输出,我可以在执行后将其打印到控制台,但这样我就没有“实时”输出...

【问题讨论】:

    标签: node.js child-process


    【解决方案1】:

    如果你想要的话,你可以传递parent´s stdio to the child process

    require('child_process').execSync(
        'rsync -avAXz --info=progress2 "/src" "/dest"',
        {stdio: 'inherit'}
    );
    

    【讨论】:

    • stdio[0,1,2]是什么意思?
    • 表示子进程将使用父进程的stdin、stdout和stderr流。因此,当子进程写入其中任何一个时,它实际上会直接写入父流。
    • 这是一个非常有价值的答案,因为官方文档并没有明确说明预期的语法。
    • 我用'inherit'代替[0,1,2],相当于[process.stdin, process.stdout, process.stderr][0,1,2]docs
    • @Booligoosh 不能简单地添加{stdio:'inherit'},您必须添加.toString(),然后手动调用console.log 并获取结果。此外,它甚至不满足看到命令输出“实时”的问题要求。我不认为它“简单得多”,事实上我认为它一点也不简单。
    【解决方案2】:

    您可以简单地使用.toString()

    var result = require('child_process').execSync('rsync -avAXz --info=progress2 "/src" "/dest"').toString();
    console.log(result);
    

    这已经在节点v8.5.0 上测试过了,我不确定以前的版本。根据@etov,它不适用于v6.3.1 - 我不确定中间情况。


    编辑:回顾这一点,我意识到它实际上并没有回答具体问题,因为它不会“实时”向您显示输出 - 只有在命令完成运行后。

    但是,我将这个答案留在这里,因为我知道很多人遇到这个问题只是为了寻找如何在执行后打印命令的结果。

    【讨论】:

    • 这在失败时不起作用(状态码!= 0),因为.execSync() 会抛出一个Error 实例。
    • 对我不起作用,即仅在命令完成后才写入输出。这是否适用于特定版本?我的节点-v:v6.3.1
    • 请考虑更新答案以注意它仅适用于某些节点版本 - 这将使其对其他人更有用
    • 投反对票,因为 ti 现在与执行命令期间有关输出的问题有关。
    【解决方案3】:

    除非您按照公认答案建议重定向 stdout 和 stderr,否则使用 execSync 或 spawnSync 是不可能的。如果不重定向 stdout 和 stderr,这些命令只会在命令完成时返回 stdout 和 stderr。

    要在不重定向 stdout 和 stderr 的情况下执行此操作,您将需要使用 spawn 来执行此操作,但这非常简单:

    var spawn = require('child_process').spawn;
    
    //kick off process of listing files
    var child = spawn('ls', ['-l', '/']);
    
    //spit stdout to screen
    child.stdout.on('data', function (data) {   process.stdout.write(data.toString());  });
    
    //spit stderr to screen
    child.stderr.on('data', function (data) {   process.stdout.write(data.toString());  });
    
    child.on('close', function (code) { 
        console.log("Finished with code " + code);
    });
    

    我使用了一个递归列出文件的 ls 命令,以便您可以快速测试它。 Spawn 将您尝试运行的可执行文件名称作为第一个参数,作为第二个参数,它采用一个字符串数组,表示您要传递给该可执行文件的每个参数。

    但是,如果您设置使用 execSync 并且由于某种原因无法重定向 stdout 或 stderr,您可以打开另一个终端,如 xterm 并传递如下命令:

    var execSync = require('child_process').execSync;
    
    execSync("xterm -title RecursiveFileListing -e ls -latkR /");
    

    这将允许您查看您的命令在新终端中执行的操作,但仍具有同步调用。

    【讨论】:

    • 使用 spawn 的示例可能是正确的,但关于不打算使用 execSync 的开场白并不准确。查看@gregers 的回答
    【解决方案4】:

    简单地说:

     try {
        const cmd = 'git rev-parse --is-inside-work-tree';
        execSync(cmd).toString();
     } catch (error) {
        console.log(`Status Code: ${error.status} with '${error.message}'`;
     }
    

    参考:https://stackoverflow.com/a/43077917/104085

    // nodejs
    var execSync = require('child_process').execSync;
    
    // typescript
    const { execSync } = require("child_process");
    
     try {
        const cmd = 'git rev-parse --is-inside-work-tree';
        execSync(cmd).toString();
     } catch (error) {
        error.status;  // 0 : successful exit, but here in exception it has to be greater than 0
        error.message; // Holds the message you typically want.
        error.stderr;  // Holds the stderr output. Use `.toString()`.
        error.stdout;  // Holds the stdout output. Use `.toString()`.
     }
    

    命令运行成功时:

    【讨论】:

      【解决方案5】:

      在选项中添加{"encoding": "utf8"}

      execSync(`pwd`, {
        encoding: "utf8"
      })
      

      【讨论】:

        猜你喜欢
        • 2015-08-28
        • 2013-02-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-23
        • 2013-06-09
        • 1970-01-01
        • 2023-02-01
        相关资源
        最近更新 更多