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)
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 making a cli tool with Node.JS. I run another binary file from within node, and the other process asks for a password at some point.
So what I need is to simply launch the other process, and put it "in charge" of the terminal, so the other process handles the prompts and the console output.
You can use 'inherit' for the stdio option of spawn:
const spawn = require( 'child_process' ).spawn;
spawn( '/path/to/binary', [], { stdio: 'inherit' } );
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.
I've got two NodeJS servers running on Windows, one listening for incoming requests which then shapes the request and then hands the request off to a worker server. The worker server will take the inputs from the controller and perform several functions: log the event with the DB, shell out to perform an action through a child process, evaluate the results and finally return the results back to the controller.
When I run both processes through Powershell or cmd everything runs fine. If I run the Controller as a service with NSSM and the Worker on Powershell everything works fine. However, if I run the Worker server as a service with NSSM the child processes fail (console.logs or using something like bunyon seem to be swallowed up so debugging is difficult). Is there any way to run NodeJS as a server if it needs to execute child processes?
If I understood you correctly, you can try redirecting the stdout and stderr stream of the worker using
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();
This way while spawning, we are giving an fd to the worker process to write the output to the file.
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'
});