Javascript ps au| grep ssh在Node.js(使用spawn/pipe)和shell中的结果不同
我正在处理节点流和子进程。因此,我想用管道模拟下一个shell命令:Javascript ps au| grep ssh在Node.js(使用spawn/pipe)和shell中的结果不同,javascript,node.js,pipe,child-process,Javascript,Node.js,Pipe,Child Process,我正在处理节点流和子进程。因此,我想用管道模拟下一个shell命令: ps au | grep ssh 所以我写了下一个代码: var spawn = require('child_process').spawn; var ps = spawn('ps', ['au']); var grep = spawn('grep', ['ssh']); ps.stdout.pipe(grep.stdin); grep.stdout.on('data', function(data) {
ps au | grep ssh
所以我写了下一个代码:
var spawn = require('child_process').spawn;
var ps = spawn('ps', ['au']);
var grep = spawn('grep', ['ssh']);
ps.stdout.pipe(grep.stdin);
grep.stdout.on('data', function(data) { console.log(data) });
然后我运行它,但什么也没发生。我做错了什么
附言-我知道:
require('child_process')
.exec('ps au | grep ssh', function(err, stdout, stderr) {
...
}).
我只是在玩Node.js,我想了解这个示例的错误
更新1:似乎使用grep
bash
程序可以按预期工作,但使用grepssh
则没有结果。尽管ps au | grep ssh
给出了以下结果:
vagrant 11681 0.0 0.1 10464 916 pts/0 S+ 07:54 0:00 grep --color=auto ssh.
我在ps之前就已经产生了grep,现在它工作得很好。我想这一定是时间问题。试试这个
var spawn = require('child_process').spawn;
var grep = spawn('grep', ['ssh']);
var ps = spawn('ps', ['au']);
ps.stdout.pipe(grep.stdin);
grep.stdout.on('data', function(data) {
console.log(data.toString("utf8"));
});
当您调用
ps
时,它将列出与传递的选项匹配的所有当前正在运行的进程。它可能会查找以下内容:
tniese 3251 0,0 0,0 2479028 3004 s000 S+ 4:06am 0:00.03 -bash
root 4453 0,0 0,0 2452408 876 s004 R+ 4:06pm 0:00.00 ps au
当您在shell中调用ps au | grep ssh
时,grep
将过滤该结果,以仅显示包含ssh
的行
如果在ps
创建列表之前,shell启动了grep
,则过滤前的输出将是:
tniese 3251 0,0 0,0 2479028 3004 s000 S+ 4:06am 0:00.03 -bash
root 4453 0,0 0,0 2452408 876 s004 R+ 4:06pm 0:00.00 ps au
tniese 4478 0,0 0,0 2441988 596 s000 R+ 4:06pm 0:00.00 grep ssh
tniese 4478 0,0 0,0 2441988 596 s000 R+ 4:06pm 0:00.00 grep ssh
grep
进程将匹配它自己的条目,因为它包含传递的参数,因此过滤结果将是:
tniese 3251 0,0 0,0 2479028 3004 s000 S+ 4:06am 0:00.03 -bash
root 4453 0,0 0,0 2452408 876 s004 R+ 4:06pm 0:00.00 ps au
tniese 4478 0,0 0,0 2441988 596 s000 R+ 4:06pm 0:00.00 grep ssh
tniese 4478 0,0 0,0 2441988 596 s000 R+ 4:06pm 0:00.00 grep ssh
让我们看看您的代码发生了什么:
var spawn = require('child_process').spawn;
var ps = spawn('ps', ['au']);
var grep = spawn('grep', ['ssh']);
ps.stdout.pipe(grep.stdin);
使用spawn命令操作系统启动进程,ps
,ps
无需等待运行,直到输出可以通过管道传输到任何地方,但可以在此之前启动,它可能只有在尝试写入its输出流时才被迫等待。然后您的spawngrep
,但在启动grep
时ps
可能已经在内部创建了进程列表,因此它不包含grep
进程。然后将ps
的输出传递给grep。但由于该输出缺少grepshgrepsh
,因此它不会显示该行
grep是否会出现在您的列表中取决于操作系统。通常,您应该假设它是随机的,无论它是否列出。或者您需要等到ps
退出,然后启动grep
您需要始终记住,当前操作系统具有抢占式多任务,并且调度程序可能会在spawn('ps',['au')之后立即暂停节点
并在创建/请求列表后立即继续该过程
我希望这个解释比我的评论更清楚一些。你的代码对我来说很有用(除了
bash
而不是ssh
)。如果在shell提示符下执行ps au | grep ssh
,是否看到输出?@mscdex-Hmm,很有趣。它使用bash
命令工作(结果与ps au | grep bash
相同)。使用ssh
没有结果。尽管ps au | grep ssh
给我结果:vagrant 11681 0.0 0.1 10464 916 pts/0 S+07:54 0:00 grep--color=auto ssh
。这些nodejs脚本运行在哪个用户ID下?可能没有人或web用户,而不是您的登录用户?我认为存在某种时间问题,因为我有时可以看到输出,但并不总是如此。@Paul我从控制台调用此脚本:node pipe\u example.js
使用vagrant(使用OS Linux Ubuntu 14.04的虚拟机)。所以用户-vagrant
,用户id-1000
。一年,它工作了!但我不明白为什么?对我来说,这完全不合逻辑。我会等一会儿——也许有人知道一些关于它的事情,也许它是一个功能,而不是一个bug。如果没有-将您的答案标记为已接受,并在节点github repositoryYear中创建问题。我明白你的意思。我想没有人能解释得更好,所以请把你的回答标记为已接受。但最后一个问题是:您不认为节点必须为stdout流中的ps
命令缓冲结果数据吗?或者至少有这样做的选项?创建for节点。让核心团队来决定这种行为的正确性。@alexpods我假设节点或操作系统本身已经为生成的进程的stdout进行了缓冲,但这对您描述的问题并不重要。只要ps
是在grep
之前生成的,则grep
很可能不会出现在列表中,而不会出现在列表中,但这取决于系统的调度程序会发生什么。对于命令ps au | grep ssh
shell很可能会在生成ps
之前生成grep
,这就是为什么您会在shell中看到grep
。这两种行为都没有错。