I am using a ffi for nodejs, which for the most part has nothing to do with this question, which is really about understanding pipes better, but does offer some context.
function exec(cmd) {
var buffer = new Buffer(32);
var result = '';
var fp = libc.popen('( ' + cmd + ') 2>&1', 'r');
var code;
if (!fp) throw new Error('execSync error: '+cmd);
while( !libc.feof(fp) ){
libc.fgets(buffer, 32, fp)
result += buffer.readCString();
}
code = libc.pclose(fp) >> 8;
return {
stdout: result,
code: code
};
}
which brings me to this bit of code that, when I run using this exec function
tr -dc "[:alpha:]" < /dev/urandom | head -c ${1-8}
I get the error:
write error: Broken pipe
tr: write error
but I do get the output I expect: 8 random numbers. This confused the hell out of me but then in some wild googling I found this stack answer which perfectly fit my situation.
I am left with some questions, though.
Why does:
tr -dc "[:alpha:]" < /dev/urandom | head -c ${1-8}
throw a broken pipe error when called with my exec command but not when called from the shell? I don`t understand why when I call:
tr -dc "[:alpha:]" < /dev/urandom
it reads endlessly, but when I pipe it to:
head -c ${1-8}
It works without throwing a broken pipe error. It seems that head
would take what it needs and tr
would just read forever. At least it should throw broken pipe; head
would consume the first 8 bytes and then tr
would still be putting out output and broken pipe would be thrown by tr
because head
has stopped running.
Both situations make sense to me, but it seems that they are some what exclusive to each other. I don't understand what is different between calling:
exec(tr -dc "[:alpha:]" < /dev/urandom | head -c ${1-8})
and
tr -dc "[:alpha:]" < /dev/urandom | head -c ${1-8}
directly from the command line, and specifically why <
an endless file into something and then |
it to something makes it not run endlessly. I've been doing this for years and never questioned why it works this way.
Lastly, is it OK to ignore this broken pipe error? Is there a way to fix it? Am I doing something wrong in my C++ ish javascript code? Am I missing some kind of popen basics?
------ EDIT
messing around some more the code
exec('head -10 /dev/urandom | tr -dc "[:alpha:]" | head -c 8')
throws no pipe error!