【问题标题】:Node child_process spawn hangs when calling git shortlog -sn调用 git shortlog -sn 时节点子进程生成挂起
【发布时间】:2017-11-10 09:06:01
【问题描述】:

我的场景

在我的节点应用程序中,我使用child_process.spawn 从当前存储库中查询信息

我已经构建了一个小函数来返回一个承诺,该承诺会通过命令的响应来解决:

const spawn = require('child_process').spawn;

const gitExec = command => (
  new Promise((resolve, reject) => {
    const thread = spawn('git', command);
    const stdOut = [];
    const stdErr = [];

    thread.stdout.on('data', (data) => {
      stdOut.push(data.toString('utf8'));
    });

    thread.stderr.on('data', (data) => {
      stdErr.push(data.toString('utf8'));
    });

    thread.on('close', () => {
      if (stdErr.length) {
        reject(stdErr.join(''));
        return;
      }
      resolve(stdOut.join());
    });
  })
);

module.exports = gitExec;

调用git branch按预期工作:

gitExec(['branch'])
.then((branchInfo) => {
  console.log(branchInfo);
})

(如预期)结果

    * develop
      feature/forever
      feature/sourceconfig
      feature/testing
      master

据我了解,这证明我使用的方法确实有效。

当调用 git shortlog -sn 时,生成的进程“挂起”并且无法解决任何问题

gitExec(['shortlog', '-sn'])
.then((shortlogInfo) => {
  console.log(shortlogInfo);
})

通过命令行调用git shortlog -sn 我得到了预期的结果:

   154  Andreas Gack
    89  Some other dude
     6  Whoever else

我的(到目前为止不成功)尝试

使用spawnSync(同时更改我的 gitExec 函数以适应同步方法)返回一个记录的对象-因此该过程似乎实际上退出了-但对象outputstdoutstderr的相关道具都是空的。
对象的status0,表示命令执行成功

我了解到必须在 spawn 选项中重新定义 maxBuffer,但将其设置为(荒谬的)高值或非常小的值都不会对同步或异步方法产生影响。

shell 选项设置为true 也不会对上述所有情况产生影响。

问题出现在我的 Win10x64 以及运行 node v6.9.x 或 7.x 的 MacO 上

同时调用别名git log --pretty=short 不提供结果

我的实际问题

  • 有没有人成功通过 child_process.spawn 查询git shortlog -sn
  • 有谁知道 Node 的一个模块,它允许查询当前的本地 git-repository?

我不知何故认为git branchgit shortlog 这两个命令在内部以不同的方式处理它们的输出。

我很乐意在他们的 github 页面上创建一个问题,但我实际上不知道如何确定该问题的实际根本原因。

非常感谢任何进一步的意见!

【问题讨论】:

    标签: node.js git command-line-interface child-process spawn


    【解决方案1】:

    git shortlog 认为它需要从stdin 读取一些内容,这就是整个过程挂起的原因。要解决这个问题,您可以将主进程中的stdin 作为选项传入,并像往常一样通过管道传递其他所有内容。然后它应该运行。

    const spawn = require('child_process').spawn;
    
    const gitExec = command => (
      new Promise((resolve, reject) => {
        const thread = spawn('git', command, { stdio: ['inherit', 'pipe', 'pipe'] });
        const stdOut = [];
        const stdErr = [];
    
        thread.stdout.on('data', (data) => {
          stdOut.push(data.toString('utf8'));
        });
    
        thread.stderr.on('data', (data) => {
          stdErr.push(data.toString('utf8'));
        });
    
        thread.on('close', () => {
          if (stdErr.length) {
            reject(stdErr.join(''));
            return;
          }
          resolve(stdOut.join());
        });
      })
    );
    
    module.exports = gitExec;
    

    也许来自git documentation的更多上下文:

    如果在命令行中没有传递修订并且标准输入不是终端或者没有当前分支,git shortlog 将输出从标准输入读取的日志的摘要,没有参考到当前存储库。

    在产生子进程时就是这种情况。所以它期望通过stdin 传递一些东西。通过将stdin 设置为主进程git shortlog 知道终端,因此将运行。

    【讨论】:

    • 不幸的是,这似乎不起作用。什么(什么样的)作品是 ['ignore', 'pipe', 'pipe'] 。然而,这给我留下了空洞的回应。让我感到困惑的是git shortlog -sn 在通过常规控制台调用时不需要任何输入
    • 那么这似乎是 Windows 的问题?不幸的是,我没有 Windows 系统可以进一步测试:/
    • 好的,我刚刚找到了一个 Windows 10 安装并尝试确认 git shortlog -sn 不需要任何输入。你在尝试什么控制台?
    • 我在“常规”Windows 命令提示符以及集成在我的 IDE (Webstorm) 中的控制台上进行了测试,git shortlog -sn 需要您输入吗?
    • 您是否有机会通过npm run 运行脚本?
    【解决方案2】:

    我通过指定提交之前和之后的哈希来让它工作。

    git shortlog -sn `git log --pretty=format:'%H' --reverse | head -1` `git log --pretty=format:'%H' | head -1`"
    

    【讨论】:

      猜你喜欢
      • 2017-11-08
      • 2019-03-22
      • 2013-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多