Close another process from node on Windows - node.js

How can I kill a process from node on Windows?
I'm making a updater. It needs close a windows executable (.exe) to download the updates. (The update process is download and overwrite). I read that this is possible with process.kill(pid[, signal])
But, How can I get the PID of the process if I know the name of the process?

According to the documentation, you simply access the property.
process.kill(process.pid, 'SIGKILL');
This is a theoretical, untested, psuedo function that may help explain what I have in mind
exec('tasklist', (err, out, code) => { //tasklist is windows, but run command to get proccesses
const id = processIdFromTaskList(processName, out); //get process id from name and parse from output of executed command
process.kill(id, "SIGKILL"); //rekt
});

Use node-windows to get pid of process you want to kill so that you can call process.kill. The library also provides an api to kill task.

Related

Node JS - Cannot Kill Process Executed with Child Process Exec

We are trying to kill the process of a chrome browser launched with nodes child_process exec command
var process = cp.exec(`"chrome.exe" --app="..."`, () => {}); // working great
But when we try
process.kill(); //nothing happens...
Does the process refer to the chrome window or something else? if not, how can we get a hold of the newly opened chrome window process, PID, etc...?
Any help would be great...
Note - we have tried using the chrome_launcher NPM but it didn't help because we couldn't open chrome in kiosk mode without fullscreen, but this is an issue for a different question...
Try the PID hack
We can start child processes with {detached: true} option so those processes will not be attached to main process but they will go to a new group of processes.
Then using process.kill(-pid) method on main process we can kill all processes that are in the same group of a child process with the same pid group. In my case, I only have one processes in this group.
var spawn = require('child_process').spawn;
var child = spawn('your-command', {detached: true});
process.kill(-child.pid);
I built a cross platform npm package that wraps up spawning and killing child processes from node, give it a try.
https://www.npmjs.com/package/subspawn
I am not able to add comment, so I am saying it directly in the answer:
How to kill process with node js
If you check the link above you need library as follows
https://www.npmjs.com/package/fkill
Usage Example taken from stackoverflow question
const fkill = require('fkill');
fkill(1337).then(() => {
console.log('Killed process');
});
fkill('Safari');
fkill([1337, 'Safari']);
I also found this library to check running processes
https://github.com/neekey/ps

How can i show progress of node chid_process commands?

I have to show progress of node chid_process commands on UI. I am not able to track the progress of commands using any js lib like progress-bar.
How can i show say "git clone" progress on UI so that user knows the status of the process ?
If you mean in general and not for functions you define specifically for this purpose and want to run separately as child process, you really can't unless the child process provides this information itself via for example STDOUT.
And if so, you can only grab this raw output for then having to parse it to find something you could use to indicate progress. This of course, has its own quirks as the output is typically buffered which require you to think through how you parse the buffer(ing).
On top of that you can run into cases where the output format or order changes in the future in such a way that your program no longer can find the key information it needs.
In the case of git, there is really no progress per-se, only stages - which is fine and can act as a form of progress (stage 1 of 4 etc.).
To grab the output you would use something like:
const spawn = require("child_process").spawn;
const child = spawn("git" , ["clone", "https://some.rep"]);
child.stdout.on("data", data => {
// parse data here...
});
...
and the same for stderr. See Node documentation for more details.
Try the farmhand package.
As the description goes, It is an abstration over child_process that makes it easy to run a function in the background, get its progress, result, and cancel if necessary.
Hope this helps!

I get a wrong pid with child_process.spawn

I have problem in an Electron app and reduce the problem to a simple testspawn.js run in node
var spawn = require('child_process').spawn,
exp = spawn('explorer', ['d:'],{detached:true}); //same thing detached or not
console.log('Spawned child pid: ' + exp.pid);
When I run node testspawn.js an explorer in the D: directory is showing but the console say: Spawned child pid: 5880.
BUT the Task Manager of Windows say :
As I want at the end kill the explorer when I don't need it anymore, noway to have the right pid. What is the thing I'm missing ? . Completely lost ...
Not exactly sure what electron is doing, but the process you get back is actually the parent of the process you are trying to kill. I was able to successfully kill the "actual" process by using tree-kill. If you want to get the actual pid of the grandchild process you can use something like process-tree to iterate over the process tree.
Further to my last comment, I don't have all the aswers but my case got a workaround ...

How to send "CTRL+C" to child process in Node.js?

I tried to spawn child process - vvp (https://linux.die.net/man/1/vvp). At the certain time, I need to send CTRL+C to that process.
I am expecting that simulation will be interrupted and I get the interactive prompt. And after that I can continue the simulation by send command to the child process.
So, I tried something like this:
var child = require('child_process');
var fs = require('fs');
var vcdGen = child.spawn('vvp', ['qqq'], {});
vcdGen.stdout.on('data', function(data) {
console.log(data.toString())
});
setTimeout(function() {
vcdGen.kill('SIGINT');
}, 400);
In that case, a child process was stopped.
I also tried vcdGen.stdin.write('\x03') instead of vcdGen.kill('SIGINT'); but it isn't work.
Maybe it's because of Windows?
Is there any way to achieve the same behaviour as I got in cmd?
kill only really supports a rude process kill on Windows - the application signal model in Windows and *nix isn't compatible. You can't pass Ctrl+C through standard input, because it never comes through standard input - it's a function of the console subsystem (and thus you can only use it if the process has an attached console). It creates a new thread in the child process to do its work.
There's no supported way to do this programmatically. It's a feature for the user, not the applications. The only way to do this would be to do the same thing the console subsystem does - create a new thread in the target application and let it do the signalling. But the best way would be to simply use coöperative signalling instead - though that of course requires you to change the target application to understand the signal.
If you want to go the entirely unsupported route, have a look at https://stackoverflow.com/a/1179124/3032289.
If you want to find a middle ground, there's a way to send a signal to yourself, of course. Which also means that you can send Ctrl+C to a process if your consoles are attached. Needless to say, this is very tricky - you'd probably want to create a native host process that does nothing but create a console and run the actual program you want to run. Your host process would then listen for an event, and when the event is signalled, call GenerateConsoleCtrlEvent.

Using forever with Node.js

I have a few, possibly trivial, questions with using forever with Node.js. From what I have read, forever can be used programatically and it maintains a list with all the scripts that use forever. When that process dies, it automatically spawns a new one until it is stopped.
However, my question is, how does forever do this? Does it add these scripts to be started on boot as well?
You can use forever programatically like this:
Using an instance of Forever inside a node.js script:
var forever = require('forever-monitor');
var child = new (forever.Monitor)('your-filename.js', {
max: 3,
silent: true,
options: []
});
child.on('exit', function () {
console.log('your-filename.js has exited after 3 restarts');
});
child.start();
You should take a minute and read over the options available in the excellent documentation for Forever in the README.md
You have a number of events that can be listened for in Forever as well:
error [err]: Raised when an error occurs
start [process, fvrFile, data]: Raise when the target script is first started.
stop [process]: Raised when the target script is stopped by the user
save [path, data]: Raised when the target Monitor saves the pid information to disk.
restart [forever]: Raised each time the target script is restarted
exit [forever]: Raised when the target script actually exits (permenantly).
stdout [data]: Raised when data is received from the child process' stdout
stderr [data]: Raised when data is received from the child process' stderr
It does this by attaching event listeners to the script you're trying to run and handling them in a graceful manner.
The code is pretty well documented if you want to take a look at exactly how it does it.
You should also read this excellent tutorial on how to keep a process running forever.
As for the second question: No, it does not add it to start at boot. For that, you'd need to add it as an upstart job or use something like Monit to monitor and start it. For that, you should take a look at Deploying Node.js with Upstart and Monit. It's a great tutorial.
This is an old post, but I stumbled across this on Google - its a little out of date, as forever branched the command line version from the programatic version. You need to use forever-monitor instead of forever. The example code should now be;
var forever = require('forever-monitor');
var child = new (forever.Monitor)('your-filename.js', {
max: 3,
silent: true,
options: []
});
child.on('exit', function () {
console.log('your-filename.js has exited after 3 restarts');
});
child.start();
I tried to suggest an edit to the original answer, but the powers that be rejected it. Figured I could spare some others the time it took me to figure out why the example code doesn't work :-)

Resources