node.js - starting a cmd with an infinitely running process - node.js

i have following code on node for windows:
var spawn = require('child_process').spawn,
out = fs.openSync('./out.log', 'a'),
err = fs.openSync('./out.log', 'a');
spawn('cmd', [ '/c', 'start', '""', __dirname + tstDir + 'bin/test.bat', 'agent', ' -f ', configuration.path2lgst + 'test.conf' ], {
stdio: [ 'ignore', out, err ], // piping stdout and stderr to out.log
detached: true
}).unref();
In general i want to start a cmd which executes a .bat file that runs a process infinetly. node.js should return after this is initiated.
The problem is that what ever i try, either the cmd exits when node finished starting the cmd with the batch file or everything starts fine (like above code) but the process in node.js never returns.
Any ideas what could be done??
Cheers
Thorsten

Related

Execute bash script via Node.js and include command line parameters

I'm trying to execute a bash script from a Node application, which I have previously done successfully via:
var spawn = require('child_process').spawn;
spawn('bash', [pathToScript], {
stdio: 'ignore',
detached: true
}).unref();
It's important that I do it this way, because the script needs to continue to execute, even if/when the application is stopped.
Now, the script I need to execute requires an input value to be provided on the command line, ie.
./myScript.sh hello
But I cannot figure out how to pass this into the spawn call. I have tried the following, with no luck
var spawn = require('child_process').spawn;
spawn('bash', [pathToScript + '' + params], {
stdio: 'ignore',
detached: true
}).unref();
The second parameter in spawn is an array of arguments to pass to the command. So I think you almost have it but instead of concating the params to the path pass them in as an array:
var spawn = require('child_process').spawn;
var params = ['pathToScript','run', '-silent'];
spawn('bash', params, {
stdio: 'ignore',
detached: true
}).unref();

How to execute the command NPM init in the nodejs file

How to execute the command npm init in the nodejs file? I want to use node. / index.js to execute the command. But what should I do if the command interacts with the user?
This code is directly stuck, and the subsequent question and answer cannot be carried out.I hope users can fill in the information normally
let exec = require('child_process').exec;
exec("npm init")
To allow users to fill in the questionnaire via the CLI, consider using the child_process module's spawn() method instead of exec().
*Nix (Linux, macOS, ... )
For example:
index.js
const spawn = require('child_process').spawn;
spawn('npm', ['init'], {
shell: true,
stdio: 'inherit'
});
Note: After the user has completed the questionnaire this example (above) creates the resultant package.json file in the current working directory, i.e. the same directory from where the node command invoked index.js.
However, If you want to ensure that package.json is always created in the same directory as where index.js resides then set the value of the cwd option to __dirname. For example:
const spawn = require('child_process').spawn;
spawn('npm', ['init'], {
cwd: __dirname, // <---
shell: true,
stdio: 'inherit'
});
Windows
If you are running node.js on Windows then you need to use the following variation instead:
script.js
const spawn = require('child_process').spawn;
spawn('cmd', ['/c', 'npm init'], { //<----
shell: true,
stdio: 'inherit'
});
This also utilizes the spawn() method, however it starts a new instance of Windows command shell (cmd). The /c option runs the npm init command and then terminates.
Cross-platform (Linux, macOS, Windows, ... )
For a cross platform solution, (i.e. one that runs on Windows, Linux, macOS), then consider combining the previous examples to produce the following variation:
script.js
const spawn = require('child_process').spawn;
const isWindows = process.platform === 'win32';
const cmd = isWindows ? 'cmd' : 'npm';
const args = isWindows ? ['/c', 'npm init'] : ['init'];
spawn(cmd, args, {
shell: true,
stdio: 'inherit'
});
Assuming there doesn't need to be any user input you could do:
let exec = require('child_process').exec;
exec("npm init -y")

Pipe Node stdout in realtime

I have a spawn process running a docker pull and I'm using the following:
const proc = spawn('docker', [ 'pull', 'some/container' ], { env: process.env, cwd: process.env.HOME })
proc.stdout.pipe(process.stdout)
As it runs it breaks up and downloads the individual SHA's and the above works pretty well, however, it puts each response on a new line. I'm curious if there's a way to emulate the "normal" output so each line writes as it pull the image.
If you're just piping to process.stdout, then you could just set the stdio option like:
const proc = spawn('docker', [
'pull',
'some/container'
], {
env: process.env,
cwd: process.env.HOME,
stdio: ['pipe', process.stdout, 'pipe']
});
The end result being that docker will now see its stdout as a TTY (assuming this node script is being run from a terminal/pty of course) and not a pipe.

NodeJs execute command in background and forget

I have an endless NodeJS script.js loop and I need this script to execute another script in background as a service which is a WebSocket service actually.
var exec = require('child_process').exec;
exec('node bgService.js &');
So now both scripts are running okay!
When I do a Ctrl+C on my script.js, the bgService.js script is also removed from memory which I don't want to.
How to run something in the background and forget ?
You can do it using child_process.spawn with detached option:
var spawn = require('child_process').spawn;
spawn('node', ['bgService.js'], {
detached: true
});
It will make child process the leader of a new process group, so it'll continue running after parent process will exit.
But by default parent process will wait for the detached child to exit, and it'll also listen for its stdio. To completely detach child process from the parent you should:
detach child's stdio from the parent process, piping it to some file or to /dev/null
remove child process from the parent event loop reference count using unref() method
Here is an example of doing it:
var spawn = require('child_process').spawn;
spawn('node', ['bgService.js'], {
stdio: 'ignore', // piping all stdio to /dev/null
detached: true
}).unref();
If you don't want to loose child's stdin output, you may pipe it to some log file:
var fs = require('fs'),
spawn = require('child_process').spawn,
out = fs.openSync('./out.log', 'a'),
err = fs.openSync('./out.log', 'a');
spawn('node', ['bgService.js'], {
stdio: [ 'ignore', out, err ], // piping stdout and stderr to out.log
detached: true
}).unref();
For more information see child_process.spawn documentation
Short answer: (tl;dr)
spawn('command', ['arg', ...],
{ stdio: 'ignore', detached: true }).unref()
unref is required to prevent parent from waiting.
docs

How can I redirect a jsnode child process output to a cmd prompt?

I have an appjs application that is built to be a GUI which allows the user to run whole bunch of other .exe applications. These other .exe applications are created on a mouse click by the 'spawn()' command. Some of the .exe programs require output on the command line, however the main application doesn't use a command prompt.
So basically, I want my child processes to pipe their stdout into a command prompt window. The command prompt window is not running before hand. I am new to jsnode and I am having trouble getting this to work.
Here is the code. The name of the application is getting passed into the function and I am constructing the string and then spawning the process.
var appName = this.getAttribute('app');
processStr = './' + appName + '.exe';
var spawn = require('child_process').spawn;
cmd = spawn(processStr, [], { cwd: './', env: process.env} );
Note, even if I change it to below I cannot get the command prompt window to show up.
cmd = spawn('c:/windows/system32/cmd.exe', [], { cwd: './', env: process.env} );
var spawn = require('child_process').spawn;
var child = spawn('echo', ['Hello world!']);
child.stdout.pipe(process.stdout)

Resources