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!
Related
This is an update to a question I had asked previously but wasn't thinking straight when I asked the question (I was taking a very backwards approach to my solution). I'm currently working with Puppeteer and I'm trying to create an association between a particular task and a puppeteer browser instance. Right now I am currently getting the browser's context id using:
const {browserContextId} = await browser._connection.send('Target.createBrowserContext');
and I am storing it in a file along with other details related to the task. My goal is to somehow be able to close that browser instance using the stored context id. I've given this issue a read on the Puppeteer's GitHub hoping that it would help in some way but it seems that it's not super helpful to me as its not really related to what I'm doing.
The real issue is that I am going to be spawning browser instances in one file and attempting to close them in another, otherwise this wouldn't be an issue at all. Right now the only thing I've been able to do is just spawn another browser instance using the context id (pretty much useless for my task) and have had no luck in closing it or disposing it.
Any help would be greatly appreciated, thanks!
P.S. If there is a better approach to solving this association issue I'm all ears!
Turns out I was thinking about it way too much and trying to make it too complex. For anyone trying to do something similar I'll leave my solution here for you.
Instead of using the browser's context id I found it much easier to just grab the browser's process id (pid). From there I could kill the process using different strategies based on where I was running the close command.
For Node.js:
// Lets say for example we're instantiating our browser like this
const browser = await puppeteer.launch({ headless: false });
// You can simply run this to get the browser's pid
const browserPID = browser.process().pid
// Then you can either store it for use later
fs.writeFile(file, JSON.stringify(jsondata, null, 4), (err) => {
if (err) console.log(err);
})
// Or just kill the process
process.kill(browserPID);
Keep in mind that if you are storing the PID you need to read the file and parse the data to pass into the process.kill command.
For React via Electron
// Require process from the electron file
const process = window.require('process');
// Then same process as before
process.kill(yourbrowserPID);
Hopefully my stupidity can help someone in the future if they are trying to do something similar. It was way easier than I was making it out to be.
process.stdin.on('data',function(data){input_std_in+=data});
What is the correct explanation for the above piece of code. I am new to Node.js and have found many variations of this on the net, but I am still not clear.
The process.stdin is used to read data from commandline (Simple Explaination) For more see here
So below you are waiting for data event of stdin ie you wait for user to type some data in terminal ,you read it and append it to some string.As node js (javascript) is event driven ,it waits for some event to happen get the data from that event and use it further ,like in the script below it appends to already declared variable.
let input_std_in="";
process.stdin.on('data',function(data){
console.log("Data",data.toString())
input_std_in+=data.toString()
});
See working here
In node.js I create child processes like this for example
child_process.spawn('powershell.exe', ['-executionpolicy', 'remotesigned', '-File', 'save_site_login_web.ps1', data.app_catalogue_url, data.ids.join(",")], { windowsHide:true });
const handler = (data) => {
// send data to client
};
watcher_shell.stdout.on('data', handler);
watcher_shell.stderr.on('data', handler);
However, in the child process, it displays a progress bar like this picture (I got this from running it manually from a powershell terminal). The area on top with the light blue background is static and stays on top, while the text in it updates.
However this progress text doesn't get captured in stdout or stderr. How can I capture this stream in node.js?
Thanks
As mklement0 stated, the progress stream is not directly redirectable.
That being said, since Windows 1809+ there is the new pseudo console (ConPTY) API, which basically allows any program to act like the console, thus capturing output that is written directly to the console.
Doing a quick search, there is the node-pty module which supposedly utilizes the ConPTY API on Windows. I haven't tried it but it looks promising (VS Code is using it for its integrated terminal).
Write-Progress output isn't part of PowerShell's system of output streams, so it cannot be captured - neither in-session from PowerShell, nor externally via stdout or stderr.
From the linked about_Redirection help topic:
There is also a Progress stream in PowerShell, but it does not support redirection.
zett42's helpful answer shows a workaround on Windows that doesn't rely on PowerShell's features.
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.
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.