Javascript node.js shell命令执行

Javascript node.js shell命令执行,javascript,node.js,shell,Javascript,Node.js,Shell,我仍在努力掌握如何在node.js中运行linux或windows shell命令并捕获输出的细节;最终,我想做这样的事情 //pseudocode output = run_command(cmd, args) 重要的一点是,输出必须可用于全局范围的变量(或对象)。我尝试了以下函数,但由于某种原因,我得到了未定义的打印到控制台 函数运行\u cmd(cmd、args、cb){ var spawn=require('child_process')。spawn var child=spawn(c

我仍在努力掌握如何在node.js中运行linux或windows shell命令并捕获输出的细节;最终,我想做这样的事情

//pseudocode
output = run_command(cmd, args)
重要的一点是,
输出
必须可用于全局范围的变量(或对象)。我尝试了以下函数,但由于某种原因,我得到了
未定义的
打印到控制台

函数运行\u cmd(cmd、args、cb){
var spawn=require('child_process')。spawn
var child=spawn(cmd,args);
var me=这个;
child.stdout.on('data',函数(me,data){
cb(me,数据);
});
}
foo=newruncmd('dir',['/B'],函数(me,data){me.stdout=data;});

console.log(foo.stdout);//产生“未定义”在
run\u cmd
函数中存在变量冲突:

  var me = this;
  child.stdout.on('data', function(me, data) {
    // me is overriden by function argument
    cb(me, data);
  });
只需将其更改为:

  var me = this;
  child.stdout.on('data', function(data) {
    // One argument only!
    cb(me, data);
  });
要查看错误,请始终添加以下内容:

  child.stderr.on('data', function(data) {
      console.log( data );
  });
编辑您的代码失败,因为您试图运行
目录
,而该目录不是作为单独的独立程序提供的。它是
cmd
过程中的一个命令。如果您想使用文件系统,请使用本机
require('fs')


或者(我不推荐)您可以创建一个批处理文件,然后运行该文件。请注意,操作系统默认情况下通过
cmd

触发批处理文件这里有三个问题需要解决:

首先是异步使用stdout时需要同步行为。
run\u cmd
函数中的所有调用都是异步的,因此它将生成子进程并立即返回,而不管是否从stdout读取了部分、全部或任何数据。因此,当你跑步时

console.log(foo.stdout);

此时,您将得到存储在foo.stdout中的任何内容,但无法保证会是什么,因为您的子进程可能仍在运行

第二个是stdout是一个,因此1)可以多次调用数据事件,2)为回调提供缓冲区,而不是字符串。易于补救;换衣服

foo = new run_cmd(
    'netstat.exe', ['-an'], function (me, data){me.stdout=data;}
);
进入

因此,我们将缓冲区转换为字符串,并将该字符串附加到stdout变量

第三个是当您收到“end”事件时,您只能知道您已收到所有输出,这意味着我们需要另一个侦听器和回调:

function run_cmd(cmd, args, cb, end) {
    // ...
    child.stdout.on('end', end);
}
那么,您的最终结果是:

function run_cmd(cmd, args, cb, end) {
    var spawn = require('child_process').spawn,
        child = spawn(cmd, args),
        me = this;
    child.stdout.on('data', function (buffer) { cb(me, buffer) });
    child.stdout.on('end', end);
}

// Run C:\Windows\System32\netstat.exe -an
var foo = new run_cmd(
    'netstat.exe', ['-an'],
    function (me, buffer) { me.stdout += buffer.toString() },
    function () { console.log(foo.stdout) }
);

实际上,您并没有从run\u cmd函数返回任何内容

function run_cmd(cmd, args, done) {
    var spawn = require("child_process").spawn;
    var child = spawn(cmd, args);
    var result = { stdout: "" };
    child.stdout.on("data", function (data) {
            result.stdout += data;
    });
    child.stdout.on("end", function () {
            done();
    });
    return result;
}

> foo = run_cmd("ls", ["-al"], function () { console.log("done!"); });
{ stdout: '' }
done!
> foo.stdout
'total 28520...'

很好用。:)

我也遇到了类似的问题,最后为此编写了一个节点扩展。您可以查看git存储库。它是开源的,免费的,还有所有的好东西

Excel是一个用C++编写的执行shell命令的节点扩展 一个接一个地将命令的输出输出到 实时的。存在可选的链接方式和未链接方式;意思 您可以选择在命令失败后停止脚本 (锁链),或者你可以继续,就好像什么都没发生一样

有关使用说明,请参阅。请随时提出请求或提交问题


我觉得值得一提。

一个简化版的公认答案(第三点)对我来说很有用

function run_cmd(cmd, args, callBack ) {
    var spawn = require('child_process').spawn;
    var child = spawn(cmd, args);
    var resp = "";

    child.stdout.on('data', function (buffer) { resp += buffer.toString() });
    child.stdout.on('end', function() { callBack (resp) });
} // ()
用法:

run_cmd( "ls", ["-l"], function(text) { console.log (text) });

run_cmd( "hostname", [], function(text) { console.log (text) });

我用得更简洁一些:

var sys = require('sys')
var exec = require('child_process').exec;
function puts(error, stdout, stderr) { sys.puts(stdout) }
exec("ls -la", puts);

它工作得很好。:)

最简单的方法就是使用ShellJS库

$ npm install [-g] shelljs
执行示例:

require('shelljs/global');

// Sync call to exec()
var version = exec('node --version', {silent:true}).output;

// Async call to exec()
exec('netstat.exe -an', function(status, output) {
  console.log('Exit status:', status);
  console.log('Program output:', output);
});
支持许多映射为NodeJS函数的常见shell命令,包括:

  • cd
  • chmod
  • cp
  • dirs
  • 回声
  • exec
  • 退出
  • 查找
  • grep
  • ln
  • ls
  • mkdir
  • mv
  • popd
  • pushd
  • pwd
  • rm
  • sed
  • 测试
  • 哪个

    • @TonyO'Hagan的回答比较全面,但我想强调一下他的回答的同步版本:

      var shell = require('shelljs');
      var output = shell.exec('netstat -rn', {silent:true}).output;
      console.log(output);
      
      同步一行:

      require('child_process').execSync("echo 'hi'", function puts(error, stdout, stderr) {
        console.log(stdout) 
      });
      

      最佳答案的预期版本:

        runCmd: (cmd, args) => {
          return new Promise((resolve, reject) => {
            var spawn = require('child_process').spawn
            var child = spawn(cmd, args)
            var resp = ''
            child.stdout.on('data', function (buffer) { resp += buffer.toString() })
            child.stdout.on('end', function () { resolve(resp) })
          })
        }
      
      使用:

       runCmd('ls').then(ret => console.log(ret))
      

      谢谢你的帮助。。。但是,即使在运行
      C:\Windows\System32\netstat.exe
      时,这仍然不会产生结果。。。我的确切语法是
      foo=newrun_cmd('netstat.exe',['-an'],function(me,data){me.stdout=data;})。。。我还尝试了完整的路径,但没有成功,因此我认为只要正确设置对象属性,就不需要返回
      返回
      “无法保证会发生什么,因为您的子进程可能仍在运行”关闭…但可以保证不会在该时间点设置它,并且只有在最终调用回调时才会设置,正如您所指出的,这是一个非常好的答案,对一些非常重要的JS概念进行了很好的解释。美好的您将要执行
      this.stdout=“”
      run()
      函数中,否则使用
      console.log(foo.sdtout)
      将以
      undefined
      作为前缀。返回值如何,当进程返回非零时,如何获取它?
      child.stdout.on('close',(errCode)=>{console.log(errCode)})
      在最终解析中,您应该设置
      me.stdout=“”cmd_exec()
      中使用code>以防止将
      未定义的
      连接到结果的开头。嘿,最终解析代码非常糟糕,如果执行netstat所需时间超过0.25秒怎么办?嗯。。。也许可以使用我奖励的答案中的一个,这个可能的副本工作得很好,并且不需要任何额外的节点模块。我喜欢
      sys.put()
      在2中被弃用
        runCmd: (cmd, args) => {
          return new Promise((resolve, reject) => {
            var spawn = require('child_process').spawn
            var child = spawn(cmd, args)
            var resp = ''
            child.stdout.on('data', function (buffer) { resp += buffer.toString() })
            child.stdout.on('end', function () { resolve(resp) })
          })
        }
      
       runCmd('ls').then(ret => console.log(ret))