Killing a NodeJS Child Process with child.kill('SIGHUP') - javascript

Here is my code:
test.js
const {exec} = require("child_process")
var c = exec("php artisan serve", {
cwd: "C:/Users/DELL/Laravel Projects/lktest3"
}, (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
console.log(`stdout: ${stdout}`);
console.log(`stderr: ${stderr}`);
})
setTimeout(() => {
c.kill('SIGHUP')
}, 10000);
When I run node test.js, I get this error:
$ node test.js
internal/child_process.js:397
throw errnoException(err, 'kill');
^
Error: kill ENOSYS
at exports._errnoException (util.js:1018:11)
at ChildProcess.kill (internal/child_process.js:397:13)
at Timeout.setTimeout (C:\Users\DELL\Documents\laravel-kit\test.js:14:7)
at ontimeout (timers.js:386:14)
at tryOnTimeout (timers.js:250:5)
at Timer.listOnTimeout (timers.js:214:5)
I wrote this code as it is said in NodeJS Child Process API. But it's not working.

Use childProcess.spawn(command) (docs) instead of childProcess.exec, as “exec” creates a new shell and runs the command in that shell.

I used tree-kill module to kill the child process on Windows.
Use it like this:
var kill = require('tree-kill');
kill(your_child_process.pid, 'SIGKILL', function(err) {
// Do things
});

Related

How to change file permission of hello.sh file from Nodejs

I have this code written and want to run my hello.sh file from my node. it fails the error is
error: Command failed: ./hello.sh > output.txt
/bin/sh: 1: cannot create output.txt: Permission denied
How can I change the permission of hello.sh file to executable.
fs.chmod("hello.sh",0o777,(err)=>{
if(err){
console.log(err)
return
}
})
exec("./hello.sh > output.txt", (error, stdout, stderr) => {
if (error) {
console.log(`error: ${error.message}`);
return;
}
if (stderr) {
console.log(`stderr: ${stderr}`);
return;
}
console.log(`stdout: ${stdout}`);
});
When creating output files, first create them in /tmp to avoid these kind of issues. Then move them to where they need to go, re-read them to stream them async, etc.
Try like this :
fs.chmod("hello.sh",0o777,(err)=>{
if(err){
console.log(err);
return;
}
exec("./hello.sh > output.txt", (error, stdout, stderr) => {
if (error) {
console.log(`error: ${error.message}`);
return;
}
if (stderr) {
console.log(`stderr: ${stderr}`);
return;
}
console.log(`stdout: ${stdout}`);
});
});
You also need to make sure that the directory where hello.sh is running is writable.
Because the executed command is: hello.sh > output.txt
As the error message is: cannot create output.txt: Permission denied
it must not be writable.
Chmod the directory that contain hello.sh to make it writable, or change your exec command to: ./hello.sh > /tmp/output.txt

Child Process Exec Failed Electron App Calling nodejs SpeedTest

I tried to execute a nodejs command inside electron.
const { execFile } = require('child_process');
const child = execFile('node', ['--version'], (error, stdout, stderr) => {
if (error) {
throw error;
}
console.log(stdout);
});
That one above is fine! And give an output nicely.
But then once i execute :
npm install --global --save speed-test
under one of my Electron App.
And try to execute a different command such as:
const { execFile } = require('child_process');
const child = execFile('speed-test', null, (error, stdout, stderr) => {
if (error) {
throw error;
}
console.log(stdout);
});
it gaves me an error:
Uncaught Error: spawn speed-test ENOENT
at Process.ChildProcess._handle.onexit (internal/child_process.js:264)
at onErrorNT (internal/child_process.js:456)
at processTicksAndRejections (internal/process/task_queues.js:80)
The more interesting part is that, If i execute the command itself under CommandPrompt of Nodejs, it's perfect! So... i'm confused.
What the things that i need to modify under the Electron App anyway?

browser.saveScreenshot() hangs when called

Hi I am writing automation tests for a Cordova application.
I want to save screenshots of each page, here is my code.
it("should take screenshot", function() {
return browser.contexts().then(function(cnt){
console.log(cnt[1]);
return browser.context(cnt[1]);
}).then(function(){
return browser.saveScreenshot("/Users/User/Documents/dev/engineerappcopy/VGimages/nexLogin.png")
});
});
Here is my Appium console:
[HTTP] --> GET /wd/hub/session/610d95af-6501-4c72-ac38-0184a8608dfd/screenshot {}
[MJSONWP] Driver proxy active, passing request on via HTTP proxy
[JSONWP Proxy] Proxying [GET /wd/hub/session/610d95af-6501-4c72-ac38-0184a8608dfd/screenshot] to [GET http://127.0.0.1:9515/wd/hub/session/4d5f3f8a24e28f7fbf65eebc47cc02d8/screenshot] with body: {}
[HTTP] --> GET /wd/hub/status {}
[MJSONWP] Calling AppiumDriver.getStatus() with args: []
[MJSONWP] Responding to client with driver.getStatus() result: {"build":{"version":"1.5.3"...
[HTTP] <-- GET /wd/hub/status 200 14 ms - 83
Im new to automation and JS, thanks for any advice.
It turns out savescreenshot(), is not compatible with cordova applications.
However I did find a solution!
Using these commands we can take a screen shot directly from the emulator:
adb pull /sdcard/screenshot.png screenshot.png
adb shell /system/bin/screencap -p /sdcard/screenshot.png
So how can we do this programmatically?
well nodeJS has 'child_process' which can call commands to the terminal!
it("should take screenshot", function() {
const exec = require('child_process').exec;
exec('adb shell /system/bin/screencap -p /sdcard/tester.png', (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
console.log(`stdout: ${stdout}`);
console.log(`stderr: ${stderr}`);
});
exec('adb pull /sdcard/tester.png tester.png', (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
console.log(`stdout: ${stdout}`);
console.log(`stderr: ${stderr}`);
});
});
So using something like this ^, I can take a screenshot that is saved to the emulators sd card, and then pull this screenshot onto my directory!

NodeJs Error: spawn C:\Windows\system32\cmd.exe; ENOENT

This is my script :
var exec = require('child_process').exec;
exec('dir', function(error, stdout, stderr) { // 'dir' is for example
if (error) {
console.error(`exec error: ${error}`);
return;
}
console.log(`stdout: ${stdout}`);
console.log(`stderr: ${stderr}`);
});
And in the console I have :
exec error: Error: spawn C:\Windows\system32\cmd.exe; ENOENT
Someone can help me ?
This can also be caused if you are feeding in ExecOptions the options parameter, specifically 'cwd', and the path you provide is invalid
e.g:
cp.exec(<path_to_executable>, {
cwd: <path_to_desired_working_dir>
}, (err, stdout, stderr) => {
//......
})
If is not valid, the callback will be called with err equal to
Error: spawn C:\Windows\system32\cmd.exe ENOENT
I got to resolve the issue the problem is to remove the semicolon(;) from an end of the
ComSpec path C:\Windows\System32\cmd.exe
Mycomputer>properties>Advance System Settings>Environment Variables>System Variables
add this path:
ComSpec C:\Windows\System32\cmd.exe
The problem for me was that my solution directory was on a different drive than windows. Creating my solution on my C drive solved the issue.
Increasing the maxBuffer solved the problem for me.
const child_process = require('child_process');
var command = 'git ls-files . --ignored --exclude-standard --others';
child_process.execSync(command, {
maxBuffer: 1024 ** 6,
});

Why can't I respond with output from child process in Node JS?

I am using Node JS with Express and trying to execute a script and return the output of that script to the client via AJAX. The script is completing successfully, but for some reason I cannot get the output to show in the post response.
let childProcess = require('child_process');
router.post('/update', (req, res) => {
childProcess.exec('/home/dir/app/update.sh', { shell: '/bin/bash' }, (error, stdout, stderr) => {
res.json({ error, stdout, stderr });
});
});
The Node process is run using Forever. If I look at the forever log, it shows:
Forever detected script was killed by signal: SIGKILL
Not sure what that means. It appears the script is completing successfully though.
EDIT
To address Aikon's answer below. I tried the following and still no go.
router.post('/update', (req, res) => {
console.log('start...');
childProcess.exec('/home/dir/app/update.sh', { shell: '/bin/bash' }, (error, stdout, stderr) => {
console.log('done');
error = error || '';
stdout = stdout || '';
stderr = stderr || '';
res.json({ error, stdout, stderr });
});
});
It's as if the success function is never firing because it never logs "done" in the console. It just logs "start..." and the SIGKILL error above in the console.
Your script kill(and restart) itself before it can read output from child process.
Look at your update.sh again:
#!/bin/bash
git pull
npm install
npm run build
#this command restarts your script
forever restartall
You could remove last line of update.sh, and after sending response, the script just exits, forever should restart it with updated version.
router.post('/update', (req, res) => {
childProcess.exec('/home/dir/app/update.sh', { shell: '/bin/bash' },
(error, stdout, stderr) => {
res.json({ error, stdout, stderr });
process.exit();
});
});
If error is not empty then output is undefined => fail
After stringify error is empty object.
'use strict';
let error = new Error('err');
let str = 'text';
let obj = {a: 10, b: 15}; // Try comment to get fall
console.log(JSON.stringify({error, str, obj}))
You have a syntax error in your code. Try:
res.json({ error: error, output: stdout, error_log: stderr });
alternatively you can do:
res.json([ error, stdout, stderr ]);

Categories

Resources