I get an ENOENT when executing the js file containing the exact code below. And I don't know how to fix this.
Any explanation or advice is welcome but I would prefer a solution for the way I'm trying to do it. (Except if I'm doing something really stupid of course)
I have written this fake request function for testing purpose:
(function imaginaryRequest(req, res)
{
getDiskInfo('/dev/simfs', info =>
{
console.log(info.ratio)
})
}())
It is supposed to use the getDiskInfo
function that uses child_process.spawn to get the df -Ph
output and store it into an object.
/**
* Get information on the disk space of the specified File system
* @param {string} sysFile (ex: /dev/sda)
* @param {function} callback
* @return {object} df -Ph output stored into object
*/
function getDiskInfo(sysFile, callback) {
const spawn = require('child_process').spawn
const df_Ph = spawn("df -Ph | grep " + sysFile);
df_Ph.stdout.on('data', data => {
let info = data
.split(' ')
.filter(el => el != '')
callback({
maxSpace: info[1],
used: info[2],
unused: info[3],
ratio: info[4],
})
})
df_Ph.stderr.on('data', (data) => {
console.log(`stderr: ${data}`);
});
df_Ph.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
}
And here is the error I get in the shell:
events.js:160
throw er; // Unhandled 'error' event
^
Error: spawn df -Ph | grep /dev/simfs ENOENT
at exports._errnoException (util.js:1022:11)
at Process.ChildProcess._handle.onexit (internal/child_process.js:193:32)
at onErrorNT (internal/child_process.js:359:16)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickCallback (internal/process/next_tick.js:98:9)
at Module.runMain (module.js:607:11)
at run (bootstrap_node.js:420:7)
at startup (bootstrap_node.js:139:9)
at bootstrap_node.js:535:3
Thank you.
First, arguments to your spawned process must be passed in an array as the second argument to spawn. You are getting ENOENT, because spawn is looking for a command called df -Ph | grep /dev/simfs
, not df
. You also can't use a pipe in spawn (since a pipe is not an argument to a process). That is a feature of a shell, so one way to do what you want would be to spawn a shell instead:
const df_Ph = spawn("sh", ["-c", "df -Ph | grep " + sysFile]);
Another is to spawn df -Ph
and grep
separately and pipe the first processes stdout to the stdin of the grep process. I believe that to be the better option, although it is slightly more code, it avoids spawning an unnecessary sh
process and is more readable IMO. It would look something like this:
const df = spawn('df', ['-Ph']);
const grep = spawn('grep', [sysFile], { stdio: [df.stdout, 'pipe', 'pipe'] } );
grep.stdout.on( 'data', data => {
...