Receive output of debug function from child process in parent - node.js

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.

Related

NodeJS child process stdout not returning completly

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.

Minecraft/Node - Writing to process.stdin and Child Process Also Receiving Input

I'm trying to write a terminal application that would allow me to start and stop a Minecraft server, write arguments through readline that would first be checked by the Node process and then, if determined by the script, sent to the Minecraft server for use instead.
Running on Windows 10 with latest Node build and Minecraft JE server.
First I tested out just starting up a node process that spawned in a child process holding the Minecraft server. I set the 3 stdio arguments to 'inherit' and also 'ipc' (not 100% sure why this is necessary, but I saw others do it). Once run, if I typed anything into the terminal the Minecraft server would receive input through Node. This was great. What I wanted, though, was to be able to run readline and parse inputs and determine whether Node should process the input or if they should be sent to the Minecraft server.
So I played around with the stdio arguments and using process.stdin.write() and such, trying to figure out how to write to the child process' stdin so that the Minecraft server would receive the input, but to no avail.
So I tried running a "master" Node process that would fork a secondary Node process. The "master" would run readline, and use child.send() if any input was to be sent there. Then, in the second Node process, I would start the Minecraft server as a spawn with all 3 stdio arguments set to inherit. I would then listen with process.on('message') and if a message was received, write it to process.stdin hoping the Minecraft process would receive it through inherited input. But this also did not work.
I've tried a number of different things, but in the end I haven't had any luck. I've tried looking up as much as I could, but I haven't found anything that would help me out. Sorry if this ends up being a no-brainer.
// First Iteration
// spawns in a minecraft server and listens for input in the terminal
// effectively the same as running the equivalent run command for the minecraft server, except this runs as a Node child process
const spawn = require('child_process').spawn
var minecraft = spawn('java', ['-jar', '-Xms1G','-Xmx1G', '-Dfile.encoding=utf8', '../spigot-1.13.2.jar'], {
stdio: [
'inherit',
'inherit',
'inherit',
'ipc'
],
})
// Second Iteration
// changed cp stdin to pipe and tried to write manually via rl
const spawn = require('child_process').spawn
const readline = require('readline')
var minecraft = spawn('java', ['-jar', '-Xms1G','-Xmx1G', '-Dfile.encoding=utf8', '../spigot-1.13.2.jar'], {
stdio: [
'pipe',
'inherit',
'inherit',
'ipc'
],
})
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
}).on('line',(line)=> {
process.stdin.write(line)
})
// Later iterations involved running nested child processes, basically, but were all more or less more-abstract versions of my second iteration.
What I'd like to achieve, as I said earlier, is being able to listen for admin input from the terminal with readline and, as appropriate, send that input to the Minecraft server process. Otherwise, readline input would be processed in the Node process.
** to clarify, when I say it doesn't work, what I mean is that I get no response from the Minecraft server process. Nothing in-game, nothing on the command line. With my first iteration, I could see output from the Minecraft process both in-game and on the command line. But by the second iteration, nothing.
You cannot write to process.stdin. Did you mean to write to the stdin of the minecraft process mincraft.stdin?
minecraft.stdin.write(line)

NodeJS: exit parent, leave child alive

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).

How to start a process in node.js that thinks its being run from the commandline

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'
});

Running Node app through Grunt

I am trying to run my Node application as a Grunt task. I need to spawn this as a child process, however, to allow me to run the watch task in parallel.
This works:
grunt.registerTask('start', function () {
grunt.util.spawn(
{ cmd: 'node'
, args: ['app.js']
})
grunt.task.run('watch:app')
})
However, when changes are detected by the watch task, this will trigger the start task again. Before I spawn another child process of my Node app, I need to kill the previous one.
I can't figure out how to kill the process, however. Something like this does not work:
var child
grunt.registerTask('start', function () {
if (child) child.kill()
child = grunt.util.spawn(
{ cmd: 'node'
, args: ['app.js']
})
grunt.task.run('watch:app')
})
It appears that:
Even though I store the spawned process in a variable outside of the function context, it does not persist, so the next time the start task is run, child is undefined.
child has no kill function…
Take a look at grunt-nodemon which handles a lot of the headaches related to spawning a child process.
This is because grunt-contrib-watch currently spawns all task runs as child processes. So the variable child is not within the same process context. Fairly soon, grunt-contrib-watch#0.3.0 will be released with a nospawn option. This will let you configure the watch to spawn task runs within the same context and would make your above example work.
Take a look at this issue for a little more information:
https://github.com/gruntjs/grunt-contrib-watch/issues/45

Resources