Node.js why does a child process not start right away? - javascript

I'm trying to write a global node command line program that will take any (windows or unix) console command I give to it and execute it in a new console window. I also want the program to exit after it has spawned its process so the console I'm using isn't blocked by a node script that has a child process running.
This is a simple version of what I have so far:
myScript.js:
var exec = require('child_process').exec;
exec("start startScript.cmd"); // windows start command opens a new cmd window
process.exit(0);
startScript.cmd:
mkdir test
I have also tried this (But this doesn't work even without the process.exit):
myScript.js:
var spawn = require('child_process').spawn;
var child = spawn('start', ['startScript.cmd'], { detached: true, stdio: ['ignore', 'ignore', 'ignore']});
child.unref();
process.exit(0);
The problem is, calling process.exit() seems to prevent the child process from fully starting and so nothing happens unless I do some setTimeout shenanigans. However the behavior seems random. On a different computer it behaves like I want it to. Both computers have the same version of node (v0.10.33).
The directory test is never made unless I remove the process.exit line or use a setTimeout on it.
Any idea why this happens or how to get around it? Keep in mind I don't want to wait until the child process is finished. I want to be able to return to my command line immediately.
Thanks!

I figured it out.
The answer is: don't use exec and don't use start or call or any other weird windows command in the spawn call. Set the CWD if need be in the spawn options and either spawn what you want directly or make a OS specific script that calls your command if it still isn't working. One example of a windows script is literally just:
%*
That way, start or any other weird windows command will be executed correctly (but do you really need them?).

Related

Node spawn child process doesn't execute the command after exec child process in aws node 10 lambda

I am attempting to run 2 child processes, but one seems to be blocked and eventually times out the node lambda.
Environment:
AWS node 10 lambda running in a docker container.
Accesses ffmpeg and ffprobe via a lambda layer in the /opt/bin directory.
child_process.exec
I am running ffprobe in a child_process.exec to get the file format of an audio file. I am using exec because the output is a small json response (which shouldn't consume much memory).
child_process.spawn
Shortly after I run ffmpeg to convert the audio file to mp3 using child_process.spawn.
The problem is the FFMPEG child_process.spawn command doesn't run after ffprobe (even though ffprobe successfully completes). If I don't run the ffprobe command the FFMPEG command runs perfectly.
Which leads me to believing this is an issue with how I am dealing with child processes in node.
Is it possible the child_process.exec ffprobe command is somehow still running/ blocking the new ffmpeg (child_process.spawn) command from running - if so how do I check this?
When I access the running processes in the docker container only the new ffmpeg command seems to be running, although it consumes no memory and just hangs - seemingly doing nothing. I even tried launching the ffmpeg command from the docker cli (avoiding using the node env) and this works fine and runs as expected.
So it seems my issue wasn't really between exec and spawn, I am not 100% sure but I think it could be that the child process was preserved in the container and resumed in the next invocation of the lambda.
Changing to child_process.spawnSync waits until the child process exits and keeps things cleaner and I haven't encountered this problem since using this.
A more thorough explanation from someone else would be really appreciated.

Node.js script hangs on require, but works fine in the REPL

I'm running node.js on Ubuntu 18.04 LTS. I appear to be getting different behaviour using require depending on whether I use it in the REPL or in a script. Specifically, I used npm to download lightstreamer-client-node. Now, I open up a terminal and do the following:
colin#colin-XPS-15-9550:~$ node
> var x = require('lightstreamer-client-node')
This works perfectly.
Now I want to use this package in a script. I create a text file node_test.js containing just the line:
var x = require('lightstreamer-client-node')
and I open up a terminal and run the command:
colin#colin-XPS-15-9550:~$ node /home/colin/node_test.js
This hangs indefinitely on a blinking cursor.
I'm brand new to node.js and JavaScript so perhaps this is expected behaviour. I've done some reading about the require function and can't seem to find an explanation for it. Note that if I replace lightstreamer-client-node with some other node module, e.g. safe-buffer, then everything works fine, whether I use REPL or script.
The process seems to hang because the library lightstreamer-client installs a timer, with the function setInterval, for its internal activities, and nodejs doesn't allow a graceful shutdown when there are active tasks. So the only way to terminate the script is by using the function process.exit.

Is each node call run its own version of node

If i run app by node index.js and then i do it again before the first process finishes. Do each call have it´s own separate nodejs instance with it´s own call stack?
What is the overheas of doing this?
Indeed, each run gets its own process, you will not be able to link the processes in a normal way.
Furthermore, if both processes listen to the same port, the second run will fail with an error:
Error: listen EADDRINUSE: address already in use

How to fork a process of another module

TL;DR : How does one fork a process that is located outside of the current running process?
I'm trying to use child_process of Nodejs in order to start another nodejs process on the parent's process exit.
I successfully executed the process with the exec but I need the child process be independent of the parent, so the parent can exit without waiting for the child, hence I tried using spawn with the detached: true, stdio: 'ignore' option and unref()ing the process:
setting options.detached to true makes it possible for the child process to continue running after the parent exits.
spawn('node MY_PATH', [], {detached: true, stdio: 'ignore'}).unref();
This yields the :
node MY_PATH ENOENT error. which unfortunately I've failed resolve.
After having troubles achieving this with spawn and reading the documentationagain i figured i should actually use fork:
The child_process.fork() method is a special case of child_process.spawn() used specifically to spawn new Node.js processes.
fork() doesnt take a command as its' first argument, but a modulePath which i can't seem to fit since the script I'm trying to run as a child process isnt in the directory of the current running process, but in a dependency of his.
Back to the starting TL;DR - how does one fork a process that is located outside of the current running process?
Any help would be much appreciated!
EDIT:
Providing a solution to the spawn ENOENT error could be very helpfull too!
Following code should allow you to do what you need.
var Path = require('path');
var Spawn = require('child_process').spawn;
var relative_filename = '../../node_modules/bla/bla/bla.js';
Spawn('node', [Path.resolve(__dirname, relative_filename)], {detached: true, stdio: 'ignore'}).unref();
process.exit(0);

Node.js Detached child process is invoked as interactive foreground process

I am invoking a detached child_process (in windows) like this
var stdout = fs.openSync('./out.log', 'a');
var stderr = fs.openSync('./out.log', 'a');
var child = child_process.spawn('node', ['./main.js'], {
detached: true,
stdio: [ 'ignore', stdout, stderr ],
env: process.env
});
child.unref();
The spawned process, i.e. main.js in turn forks some workers using child_process.fork.
Normally the child and sub-children processes should run in background, correct me if I am wrong. But in when I try, the sub-children processes are running as interactively in foreground. I don't know what is causing them to behave like this. Could anyone point what could be the problem?
If I set detached to false, it works fine, but then the original parent can't exit without having all children exited.
I think this may be a problem with node on windows.
I tried both your code and the sample code on the node documentation you are for sure referencing yourself at http://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options on my Ubuntu virtual machine and it works just fine. Process is detached and keeps running and there is no output anywhere but to out.log because it is running successfully in the background.
I ran both a simple ping command and also ran a node instance on a javascript file like you are trying to do and both worked just fine.
I would recommend you do the same with a ping command in windows. . .
var child = child_process.spawn('ping', ['-n','25','localhost'],. . .
If that works like you would expect, there may be something inside your main.js that is causing the issue. If it doesn't work either, I would say you are up against a bug in node on windows and should report it.
Hope that helps some!

Categories