How to restart a Node.js application and handover the new process to the console - node.js

The following Node.js script can restart itself and will even still print to the correct console (or terminal if you prefer), but it will no longer be running in the foreground, as in you can't exit it with Ctrl+C anymore (see screenshot) etc:
console.log("This is pid " + process.pid);
setTimeout(function () {
process.on("exit", function () {
require("child_process").spawn(process.argv.shift(), process.argv, {
cwd: process.cwd(),
detached : true,
stdio: "inherit"
});
});
process.exit();
}, 5000);
I've already tried detached: true vs detached: false, but obviously this didn't solve the problem...
Is there a way to make the new node process run in the foreground, replacing the old one? Or this this not possible?
I know that in Bash you can pull a program back from the background like this:
$ watch echo "runs in background" &
$ fg # pulls the background process to the foreground
But I'm not looking for a Bash command or so, I'm looking for a programmatic solution within the Node.js script that works on any platform.

No, once a process has exited it cannot perform any more operations, and there's no such thing as a "please foreground this after I exit"-type API for terminals that I've ever heard of.
The proper way to solve this is via a wrapper which monitors your process for failures and restarts. The wrapper then has control of stdio and passes those to its children.
You could achieve this via a simple bash loop, another node script, or you might just be able to leverage the NodeJS cluster module for this.

As Jonny said, you'd need to have a process manager that handles the running of your application. Per the Node.js documentation for child_process, spawn() functions similar to popen() at the system level, which creates a forked process. This generally doesn't go into the foreground. Also, when a parent process exits, control is returned to either the calling process or the shell itself.
A popular process management solution is PM2, which can be installed via npm i -g pm2. (Not linking to their site/documentation here) PM2 is cross-platform, but it does require an "external" dependency that doesn't live within the codebase itself.
I would also be curious as to why you want a script that on exit restarts itself in the manner you're describing, since it seems like just re-running the script -- which is what PM2 and similar do -- would yield the same results, and not involve mucking around with process management manually.

Related

pm2-runtime inside docker container receives SIGTERM - why?

I'm running a virtual machine with docker, which implements our CI/CD infratructure.
docker-compose has an nginx reverse proxy and another service. Essentially, this docker container's start command is a shell script, which creates local copies of files from a central repository. Then this shell script starts (by means of yarn start) a nodejs script that selects a couple of services and creates a pm2 application startup json file.
Finally, pm2-runtime is launched with this application definition file. This is done by
const child = exec(`pm2-runtime build/pm2startup.json`)
child.stdout.on("data", data => { process.stdout.write(data); })
child.stderr.on("data", data => { process.stderr.write(data); })
child.on("close", (code,signal) => {
process.stdout.write((`pm2-runtime process closed with code ${code}, signal ${signal}\n`));
})
child.on("error", error => {
process.stderr.write((`pm2-runtime process error ${error}\n`));
})
child.on("exit", (code, signal) => {
process.stdout.write((`pm2-runtime process exited with code ${code}, signal ${signal}\n`));
})
There are about 10 apps managed by pm2, docker stats say, the container has memory consumption greater than 850MB. However, I have nowhere put any explicit memory limits. I cannot find any implicit either.
Every now and then the container of services is restarted. According to the dockerd logs its task has exited. That's true: the pm2-runtime process (see above) is reported to be closed because of SIGTERM.
And that's the only message I get related to this. No other pm2 message, no service message, no docker event.
Now I'm seeking advice how to find the cause of this SIGTERM because I'm running out of ideas.
As it turned out, it was indeed the snippet inside the question that caused the problem.
pm2startup.json references long-running apps. Over time, depending on usage, they produce quite a few logs on stdout and/or stderr. At some point a certain buffer kept by exec is filled up and the node process that runs pm2-runtime stops. Unfortunately it stops without any kind of hint specifying the reason of the crash. But that's another story.
Solution in my case was to do without exec or execFile, but take spawn instead with the stdio option {stdio: "inherited"} (or the verbose version ["inherited", "inherited", "inherited"]).

How do spawned child processes behave when a Node app is stopped [duplicate]

I am using child_process.spawn() to start a script from my Node.JS application running on Ubuntu. As far as I know, standard forked or spawned *nix processes don't generally die when the parent dies, but when spawning processes from Node.JS, they seem to get killed when my application crashes, or is aborted with ctrl-c etc.
Why is this and is there a way around this? I can't seem to find any obvious option in the child_process API.
My application starts some quite long-running tasks that should run in the background, and if my node server crashes or is restarted for some other reason I don't want to interrupt the tasks, instead I want the node server to come back up and gracefully resume monitoring the progress of those running tasks.
you need to set the detached option
If the detached option is set, the child process will be made the
leader of a new process group. This makes it possible for the child to
continue running after the parent exits.
var child = spawn('prg', [], {
detached: true,
stdio: [ 'ignore', out, err ]
});

Spawn process that keeps running after app.quit()

How can I launch a user-defined application from an electron application. After the application is launched the electron application should quit, and restart after the program has finished. This to free system resources.
I was hoping to be able to use a child_process.spawn with detach option and unref.
let command= 'notepad.exe && ./electron.exe'
const launched_application = child_process.spawn(command,[],{detached:true,stdio:'ignore',shell:true})
launched_application.unref()
app.quit()
When the code hits app.close() the child_process is also killed. Is there a way to keep the child_process running after app.quit()
This also gives an arror on the && part, which I'm planning to fix using a .bat file. Any recommendations regarding this are also welcome.
if you want to relaunch app again then you should just close or hide all windows and activate setInterval to keep checking if child process is alive or not with help of pid ...
after that you can create new window again or show hidden window... and if you want fresh process then you should relaunch app after you get callback of user quitting that child application....

Node.JS child processes being killed when parent dies

I am using child_process.spawn() to start a script from my Node.JS application running on Ubuntu. As far as I know, standard forked or spawned *nix processes don't generally die when the parent dies, but when spawning processes from Node.JS, they seem to get killed when my application crashes, or is aborted with ctrl-c etc.
Why is this and is there a way around this? I can't seem to find any obvious option in the child_process API.
My application starts some quite long-running tasks that should run in the background, and if my node server crashes or is restarted for some other reason I don't want to interrupt the tasks, instead I want the node server to come back up and gracefully resume monitoring the progress of those running tasks.
you need to set the detached option
If the detached option is set, the child process will be made the
leader of a new process group. This makes it possible for the child to
continue running after the parent exits.
var child = spawn('prg', [], {
detached: true,
stdio: [ 'ignore', out, err ]
});

Send command to running node process, get back data from inside the app

I start a node.js app per commandline in linux.
I see the app running, e.g. by entering "top".
Is there a way to send some command to the running app (maybe to the pid?) and get back info from inside it (maybe listen for some input and return requested info)?
Use repl module. There are examples in the doco doing exactly what you need: run JS in the context of your application and return output.
One simple solution is to use process signals. You can define a handler for a signal in your program to output some data to the console (or write to a file or to a database, if your application is running as a service not attached to a terminal you can see):
process.on('SIGUSR1', function() {
console.log('hello. you called?');
});
and then send a signal to it from your shell:
kill --signal USR1 <pid of node app.js>
This will invoke the signal handler you have defined in your node.js application.

Resources