Passing node flags/args to child process - node.js

If we fork a child_process in Node, how can we pass node parameters to the child_process?
https://nodejs.org/api/child_process.html
Specifically I would like to spawn ~20 processes, and would like to limit the memory usage of each by using --v8-options, but I can't find any examples of doing this - is this possible or do the child processes assume the same node parameters as the parent?
the parent would be:
node foo.js
and the children would be
node --some-flag=bar baz.js
...
I am looking to pass node options using
child_process.fork()
but if it's only possible with
spawn()
or
exec()
then I guess I will take what I can get.
As a simple example, the following will not run Node.js with the --harmony flag
var cp = require('child_process');
var args = ['--harmony'];
var n = cp.fork(filePath, args , Object.create(process.env));

You'll need to set the execArgv option to fork.
If you don't, you'll get the same option as the node process you're 'forking' (it actually is just a spawn, not a POSIX-fork).
So you could do something like this:
var n = cp.fork(modname, {execArgv: ['--harmony']});
If you want to pass on the node-options from the parent:
var n = cp.fork(modname, {execArgv: process.execArgv.concat(['--harmony'])}
Warning: child_process has a safeguard against the -e switch that you are circumventing with that! So don't do this from the command line with an -e or -p.
You will be creating a new process with a script that is the same as that from the parent – a fork bomb.
If you still want to be able to pass on options to fork via the environment, you could do something like this:
var cp = require('child_process');
var opts = Object.create(process.env);
opts.execArgv = ['--harmony'];
var n = cp.fork(filePath, opts);
Another option may be to alter process.execArgv (like process.execArgv.push('--harmony')) but I am pretty sure that is a bad idea and might result in strange behaviour elswhere.

Related

Wildcards in node child process [duplicate]

I want to execute a command like "doSomething ./myfiles/*.csv" with spawn in node.js. I want to use spawn instead of exec, because it is some kind of watch process and I need the stdout output.
I tried this
var spawn = require('child_process').spawn;
spawn("doSomething", ["./myfiles/*.csv"]);
But then the wildcard *.csv will not interpreted.
Is it not possible to use wildcards when using spawn()? Are there other possibilities to solve this problem?
Thanks
Torben
The * is being expanded by the shell, and for child_process.spawn the arguments are coming through as strings so will never get properly expanded. It's a limitation of spawn. You could try child_process.exec instead, it will allow the shell to expand any wildcards properly:
var exec = require("child_process").exec;
var child = exec("doSomething ./myfiles/*.csv",function (err,stdout,stderr) {
// Handle result
});
If you really need to use spawn for some reason perhaps you could consider expanding the wildcard file pattern yourself in Node with a lib like node-glob before creating the child process?
Update
In the Joyent Node core code we can observe an approach for invoking an arbitrary command in a shell via spawn while retaining full shell wildcard expansion:
https://github.com/joyent/node/blob/937e2e351b2450cf1e9c4d8b3e1a4e2a2def58bb/lib/child_process.js#L589
And here's some pseudo code:
var child;
var cmd = "doSomething ./myfiles/*.csv";
if ('win32' === process.platform) {
child = spawn('cmd.exe', ['/s', '/c', '"' + cmd + '"'],{windowsVerbatimArguments:true} );
} else {
child = spawn('/bin/sh', ['-c', cmd]);
}
Here's the simplest solution:
spawn("doSomething", ["./myfiles/*.csv"], { shell: true });
As #JamieBirch suggested in his comment, the key is telling spawn() to use the shell ({ shell: true }, see the docs), so the wildcard is properly resolved.
What OS are you using? In Unix-family OSs (e.g. Linux, MacOS), programs expect the shell process to expand wildcard filename arguments and pass the expansion in argv[]. In Windows OSs, programs usually expect to have to expand wildcards themselves (though only if they're Windows-native programs; ported Unix-family programs may at most try to run the arguments through a compatibility layer).
Your syntax looks like it's for a Unix-family system. If so, then when you call spawn() you're bypassing shell expansion, and your child process is going to treat dots and asterisks in arguments literally. Try using sh child_process in place of child_process and see if you get better results.

Prereload script into node interactive mode

Is it possibille to run node.exe, pipe a text into it, and continue the interactive session?
I want to create a shortcut bat (or bash) file for editing my database.
Usually this is what I'm doing:
$ node
>var db=require('mydb')
>db.open('myserver')
>//Now I can start access the db
>db.query...
I want to do something like that:
$ node -i perDefinedDb.js
>db.query(.... //I don't want to define the DB each time I run the node.exe
I tried some like that:
echo console.log(a) | node.exe
This is the result:
3
And the program is Finish. I want to continue the node REPL after piping something into.
In Other Words:
I want to be able to use my DB from node REPL, without defining it each time.
Launch the REPL from your js file and you can give the context you want:
const repl = require('repl');
var db = require('mydb');
db.open('myserver');
repl.start('> ').context.db = db;
Now you just have to run this file (node myREPL.js) and you can REPL as usual.

NodeJS forking a bash command using child_process

Say I want to run the following bash command: ./someCommand &. When I use the following Node:
var execute = require('child_process').exec;
execute(cmd, function (err, out) {
// Do stuff
});
I can never go inside the callback, and I think the problem is because the process is waiting for ./someCommand to end, but I've tried to fork it!! What do I do?
execute.('-cs -Some Command-', func(err, res){
//Do staff
})
cs - command shell.
And you can use spawn instead exec.
https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options
If you don't want to wait, just put your code outside, after execute.

Node-webkit execute external command?

How to execute system command in node-webkit (or node.js) external process parallel of current script.
I'm trying to use child_process. After interruption of my script subprocess is exit. However i need a simple way execute bash command without output or with output but without program stop when my script will be interrupted.
I need a correct simple way.
Thanks all.
Use detached option in spawn/execute arguments:
If the detached option is set, the child process will be made the
leader of a new process group. This makes it possible for the child to
continue running after the parent exits.
By default, the parent will wait for the detached child to exit. To
prevent the parent from waiting for a given child, use the
child.unref() method, and the parent's event loop will not include the
child in its reference count.
Example of detaching a long-running process and redirecting its output
to a file:
var fs = require('fs'),
spawn = require('child_process').spawn,
out = fs.openSync('./out.log', 'a'),
err = fs.openSync('./out.log', 'a');
var child = spawn('prg', [], {
detached: true,
stdio: [ 'ignore', out, err ]
});
child.unref();

Wildcards in child_process spawn()?

I want to execute a command like "doSomething ./myfiles/*.csv" with spawn in node.js. I want to use spawn instead of exec, because it is some kind of watch process and I need the stdout output.
I tried this
var spawn = require('child_process').spawn;
spawn("doSomething", ["./myfiles/*.csv"]);
But then the wildcard *.csv will not interpreted.
Is it not possible to use wildcards when using spawn()? Are there other possibilities to solve this problem?
Thanks
Torben
The * is being expanded by the shell, and for child_process.spawn the arguments are coming through as strings so will never get properly expanded. It's a limitation of spawn. You could try child_process.exec instead, it will allow the shell to expand any wildcards properly:
var exec = require("child_process").exec;
var child = exec("doSomething ./myfiles/*.csv",function (err,stdout,stderr) {
// Handle result
});
If you really need to use spawn for some reason perhaps you could consider expanding the wildcard file pattern yourself in Node with a lib like node-glob before creating the child process?
Update
In the Joyent Node core code we can observe an approach for invoking an arbitrary command in a shell via spawn while retaining full shell wildcard expansion:
https://github.com/joyent/node/blob/937e2e351b2450cf1e9c4d8b3e1a4e2a2def58bb/lib/child_process.js#L589
And here's some pseudo code:
var child;
var cmd = "doSomething ./myfiles/*.csv";
if ('win32' === process.platform) {
child = spawn('cmd.exe', ['/s', '/c', '"' + cmd + '"'],{windowsVerbatimArguments:true} );
} else {
child = spawn('/bin/sh', ['-c', cmd]);
}
Here's the simplest solution:
spawn("doSomething", ["./myfiles/*.csv"], { shell: true });
As #JamieBirch suggested in his comment, the key is telling spawn() to use the shell ({ shell: true }, see the docs), so the wildcard is properly resolved.
What OS are you using? In Unix-family OSs (e.g. Linux, MacOS), programs expect the shell process to expand wildcard filename arguments and pass the expansion in argv[]. In Windows OSs, programs usually expect to have to expand wildcards themselves (though only if they're Windows-native programs; ported Unix-family programs may at most try to run the arguments through a compatibility layer).
Your syntax looks like it's for a Unix-family system. If so, then when you call spawn() you're bypassing shell expansion, and your child process is going to treat dots and asterisks in arguments literally. Try using sh child_process in place of child_process and see if you get better results.

Resources