i am writing an utility. One command of this utility is to run an external application.
var child_process = require('child_process');
var fs = require('fs');
var out = fs.openSync('.../../log/out.log', 'a');
var err = fs.openSync('.../../log/err.log', 'a');
exports.Unref = function(app, argv) {
var child = child_process.spawn(app, argv, {
detached: true,
stdio: [ 'ignore', out, err ]
});
child.unref();
//process.exit(0);
};
Currently:
$ utility run app --some-args // run external app
// cant enter next command while app is running
My Problem is that if i run this command, the terminal is locked while the "external" Application is running.
But the terminal window shouldn't be locked by the child_process.
i wanna run:
$ utility run app --some-args
$ next-command
$ next-command
The external Application (a desktop application) will be closed by hisself.
Like this:
$ subl server.js // this runs Sublime Text and passes a file to the editor
$ npm start // The terminal does not locked - i can execute next command while Sublime is still running
You know what i mean ^^?
Appending ['>>../../log/out.log', '2>>../../log/err.log'] to the end of argv instead of leaving two files open should work since it's the open file handles that are keeping the process alive.
Passing opened file descriptors in stdio in addition to detached: true will not work the way you expect because there is no way to unref() the file descriptors in the parent process and have it still work for the child process. Even if there was a way, I believe that when the parent process exited, the OS would clean up (close) the file descriptors it had open, which would cause problems for the detached child process.
The only possible way that this might have been able to work would have been by passing file descriptors to child processes, but that functionality was dropped several stable branches ago because the same functionality did not exist on some other platforms (read: Windows).
Related
I'm running the following code using node and I always get only about 80% of what stdout is supposed to return when the file is past 12ko or so. If the file is 240ko it will still output 80% of it. If it's under 12 it will output completely.
When I open a cmd and run the command manually I always get the full output.
I tried exec, execFile, I tried increasing the max buffer or changing the encoding and it's not the issue. I tried to add options {shell: true, detached: true} but it vain, in fact, when I run it as detached it seems to be running completely fine as it does open an actual console but I'm not able to retrieve the stdout when the process is completed.
const spawn = require('child_process').spawn;
const process = spawn(
'C:\\Users\\jeanphilipped\\Desktop\\unrtf\\test\\unrtf.exe',
['--html' ,'C:\\Users\\jeanphilipped\\Desktop\\unrtf\\test\\tempaf45.rtf'],
);
let chunks = [];
process.stdout.on('data', function (msg) {
chunks = [...chunks, ...msg];
});
process.on('exit', function (msg) {
const buffer = Buffer.from(chunks);
console.log(buffer.toString());
});
Any clues ? It seems to be Node since when I run it manually everything works fine.
according to nodejs documentation, all of the child_process commands are asynchronous . so when you try to access your chunk variable there is no guarantee that you command has been finished , maybe your command is still on process. so it is recommended you should wrap your entire child_process command in async/await function.
I'm trying to make this little QoL app that can trigger my scripts inside package.json of any project I throw at it (react, polymer, etc.).
So far, it works as it should. At least until I kill the app or want to terminate the specific process (like using ctrl+c while running a npm start in a console).
I'm currently calling the command this way:
const exec = require("child_process").execFile;
...
let ps = exec("command.bat", [path, command], (error, stdout, stderr)=>{}) //command.bat contains only: cd "%1" \n npm "%2"
Previously I've used node-powershell like so:
const Shell = require('node-powershell');
...
let sh = new Shell();
sh.addCommand(`cd ${fs.realpathSync(path)}`);
sh.addCommand(`npm ${command}`);
sh.invoke();
And I've already tried using ps-tree in hopes that this will list all the processes started by my process so I can kill them but no luck and because it creates additional process or two it's getting out of hands really quickly.
const cp = require('child_process');
...
psTree(ps.pid, function (err, children) {
cp.spawn('kill', ['-9'].concat(children.map(function (p) { return p.PID })));
});
So if there is some solution I would be really grateful. I'm also open to any different solution if there is any.
Thanks in advance.
so, what am I trying to achieve:
I am running master process, which forks 2 other node processes. I am using this debug library from npm and I need it's output (of the debug function function) of child processes to be piped to parent's outputs (stdout, stderr).
Currently what I'm getting successfully piped is console.log("..."); but not:
var log = require('debug')('service');
log.color = 3;
log("...");
I am forking child processes using this code:
var fork = require('child_process').fork;
var child_options = {
cwd: __dirname,
env: process.env,
stdio: [ 'ignore', process.stdout, process.stderr, 'ipc' ],
deatached: false,
shell: true
};
var job_node = fork('job_node', [], child_options);
Could anyone help me find out what the problem might be? Thank you :)
EDIT:
This problem is probably not caused by some kind of error in stream piping -
instead there is something with existing/non-existing console window, attached terminal.
When I tried to run the server from within PhpStorm, using built-in tools, it showed ONLY the console.log function outputs even from master process.
TheKronnY
Solved:
Just for the sake of trying, I tried to use debug.enable function in the master process and it worked.
I used debug.enable('master,job,service'); to enable used namespaces in other processes and it worked, so I do not know why, but other namespaces, created in the child processes were disabled by default.
Usecase: On large projects it can be nice to separate small projects into folders of their own with their own build process.
The following setup basically works on both windows and mac - I get the output of the child gulp process logged in the console - only problem is that it's not colored like the output of the parent process.
var spawnCmd = require('spawn-cmd');
gulp.task('default', function () {
// Run all the parent projects tasks first
// ....
// ....
// ....
// When done, cd to child directory
process.chdir('./some-dir-that-has-a-gulpfile');
// Run `gulp` in the child directory
var child = spawnCmd.spawn('gulp', ['default']);
// And pipe the output to the current process
child.stdout.pipe(process.stdout);
});
My question is how to display the output of the child gulp process in exactly the same way as the normal gulp process.
Edit: Duplicate of Is it possible for child processes in Node.js to preserve colored output?
You should inherit the stdio of the parent process. This correctly pipes the output to the same output, with colors and all.
Because you are using gulp, you should also add the --color always flag, in order for gulp to properly detect that you want colors.
var spawnCmd = require('spawn-cmd');
gulp.task('default', function () {
// When done, cd to child directory
process.chdir('./some-dir-that-has-a-gulpfile');
// Run `gulp` in the child directory
var child = spawnCmd.spawn('gulp', ['default', '--color', 'always'], {stdio: 'inherit'});
});
I'm running require('child_process').exec('npm install') as a child process in a node.js script, but I want it to retain console colors. I'm running in windows, but want this script to be portable (e.g. to linux). How do I start a process that think's it's being run from the console?
Note: I'd rather not have npm-specific answers, but an answer that allows me to trick any command.
You can do this by letting the child process inherit the master process' stdio streams. This means you need to user spawn rather than exec, and this what you'd do:
var spawn = require('child_process').spawn;
var child = spawn('npm', ['install'], {
stdio: 'inherit'
});