When you call ps
it will list all currently running processes matching the passed options. Which might look for ps au
something like this:
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
When you call ps au | grep ssh
in the shell grep
will filter that result to only show the lines containing ssh
.
If the grep
is launched by the shell before ps
creates its listing then the output before the filtering would be:
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
The grep
process will match its own entry as it contains the passed parameters, so the filtered result would be:
tniese 4478 0,0 0,0 2441988 596 s000 R+ 4:06pm 0:00.00 grep ssh
Lets look what is happening with your code:
var spawn = require('child_process').spawn;
var ps = spawn('ps', ['au']);
var grep = spawn('grep', ['ssh']);
ps.stdout.pipe(grep.stdin);
With spawn you tell the OS to start the process ps
, ps
does not need to wait to run until the output could be piped to anyplace but could start before that, it might only be forced to wait when it tries to write to the its output stream. Then your spawn grep
, but at the time grep
is launched ps
might already created the process listing internally and cause of that it does not contain the grep
process. The output of ps
is then passed to grep. But as this output is missing grep ssh
it won't show that line.
Wether grep
will appear in your listing or not is highly OS dependent. Generally you should assume that it is random if it is listed or not. Or you would need to wait until ps
exits and launch grep
after that.
You need to always keep in mind that current OS have preemptive multitasking and that the scheduler might pause node right after spawn('ps', ['au']);
and continue the process right after ps
created/requested the listing.
I hope this explanation is a bit clearer then my comment.
bash
instead ofssh
). If you dops au | grep ssh
at your shell prompt, do you see output? – Nubblybash
command it works (result is the same asps au | grep bash
). Withssh
there is no result. Althoughps au | grep ssh
give me result:vagrant 11681 0.0 0.1 10464 916 pts/0 S+ 07:54 0:00 grep --color=auto ssh
. – Exeternode pipe_example.js
using vagrant (virtual machine with OS Linux Ubuntu 14.04). So user -vagrant
, user id -1000
. – Exeterpipe
command must push new data to grep.stdin, so we must have data on grep.stdout. – Exeterps.stdout.pipe(grep.stdin)
into process.nextTick. After this program begin works somtimes, but not always (as you already said) – Exetervagrant 11681 0.0 0.1 10464 916 pts/0 S+ 07:54 0:00 grep --color=auto ssh.
is thegrep ssh
process. If you dops au | grep ssh
it is up shell if it starts grep beforeps au
is launched, but this is not necessary as it also could buffer the result ofps au
while startinggrep
, so whether you'll see thegrep ssh
of the pipe in the listing ofps au
depends on the behavior of the used shell and the scheduling of the OS. The sample ofDongho Yoo
might randomly not displaygrep
in the process listing, but that it very unlikely – Concoffstreams
[nodejs.org/api/stream.html#stream_class_stream_readable] says there are two modeflowing
andnon-flowing
. Innon-flowing
mode all data is buffered, inflowing
mode data is processed (emittingdata
event). You can switch to 'flowing' mode only by adding listener todata
event, or by callingstream.resume()
method, or by callingpipe()
method. So there must be no differences which command (ps
orgrep
) run first. Data fromps
command must be buffered and passed togrep
command afterpipe(grep.stdin)
call. – Exeter