Pass REST API data back to Node command line - node.js

I’m running this command:
NODE_ENV=production grunt babel && NODE_ENV=sandbox node dist/bin/copilot.js --mode $1
copilot.js launches another JavaScript file (depending on what the mode argument is in line above); in this case it’s copilotMonitor.js
The short story is this ‘Monitor’ pings a REST API record, data is returned to it on if a mode needs to be restarted. The API will return something to copilotMonitor.js along the lines of "mode_3".
How can I then pass this command pkill -9 -f <mode> back to the command line?
I know process.argv tells me what arguments I passed into the node application, but I’d like to pass stuff back to the node app, if that makes sense.

Answer, Node Child Process!
https://nodejs.org/docs/latest-v4.x/api/child_process.html#child_process_child_process_exec_command_options_callback
I also found this video helpful: https://www.youtube.com/watch?v=9o8B3L0-d9c
const exec = require('child_process').exec;
exec(`pkill -9 -f ${mode}`, (err, stdout, stderr) => {
if (err) {
console.log(`There was an error killing mode ${mode}`);
console.error('error: ', err);
return;
}
console.log('kill restart! stdout: ', mode, stdout)
console.log('kill restart! stderr: ', mode, stderr)
});

Related

How to run linux terminal commands on windows?

I'm not sure how to ask, but I'd like run the 'bash' command on windows 10 so that some linux commands run later. I'm using the framework Electron and the Child Process.
var os = require('os')
var exec = require('child_process').exec
if (os.platform() =='win32'){
var cmd_win = 'bash'
exec(cmd_win, function(error, stdout, stderr){
console.log(error)
});
}
The code snippet gives "Error: Command failed: bash". Does anyone know why? And can you help me? I hope you understood my question.
To initialize the WSL subsystem, you must launch a (hidden) Bash console window in the background, which doesn't work if you execute bash.exe directly - it works with neither exec nor execFile.
The trick is to get the shell (cmd) process that Node.js spawns to launch bash.exe without blocking, which, unfortunately, isn't easy to do: start cannot be used, because bash.exe is a console application and therefore makes start act synchronously.
The solution is to create an aux. VBScript file that launches bash.exe, which itself can be invoked asynchronously via wscript.exe. Note that the Bash console window is launched hidden:
var os = require('os')
var exec = require('child_process').exec
if (os.platform() === 'win32') {
var cmd_win = '\
echo WScript.CreateObject("Shell.Application").\
ShellExecute "bash", "", "", "open", 0 > %temp%\launchBashHidden.vbs \
& wscript %temp%\launchBashHidden.vbs'
exec(cmd_win, function(error, stdout, stderr){
if (error) console.error(error)
});
}
Note that the aux. VBScript file %temp%\launchBashHidden.vbs lingers between invocations. Cleaning it up after every run would require more work (you can't just delete it right away, because wscript, due to running asynchronously, may not have loaded it yet).
By default, exec will use cmd.exe to execute commands in windows. What you may be looking for is the shell option specified in the docs.
shell Shell to execute the command with (Default: '/bin/sh' on UNIX, 'cmd.exe' on Windows, The shell should understand the -c switch on UNIX or /s /c on Windows. On Windows, command line parsing should be compatible with cmd.exe.)
const os = require('os')
const exec = require('child_process').exec
if (os.platform() === 'win32') {
exec('ls', {shell: 'path/to/executable.exe'}, (err, stdout, stderr) => {
if (err) {
console.error(err)
return
}
console.log(stdout)
})
}
I have found a short way to do that that is :
Install git on your computer
Add C:\Program Files\Git\usr\bin to your path variable.
and check whether you can run linux commands in cmd.

NodeJs spawn giving ENOENT error (Raspbian)

i'm having an error regarding spawning nodeJs script:
exec('node ./modules/buttons', function(error, stdout, stderr) {
if(error) console.log(error);
console.log(stdout);
if(stderr) console.log(stderr);
});
Exec Works perfectly fine. However spawn
var buttons = spawn('node ./modules/buttons.js', []);
buttons.stdout.on('data', function(data){
console.log(data);
});
Gives me the following error:
spawn node ./modules/buttons.js ENOENT
Defining the absolute path to the script results in the same error. Would appreciate it if someone could help me resolving this; I have absolutely no clue what could be the cause of this and google isn't helping me either.
exec accepts the command to be executed along with all the command line parameters, but spawn, OTOH, accepts the program to invoke and the command line arguments as an array.
In your case, Node.js is trying to execute a program called node ./modules/buttons.js, not node with ./modules/buttons.js as command line argument. That is why it is failing.
Quoting the example from the spawn docs,
const spawn = require('child_process').spawn;
const ls = spawn('ls', ['-lh', '/usr']);
The difference between exec and spawn is that, exec will be default launch the command in a shell, spawn simply invokes the program.
Note: BTW, as you are simply invoking a JavaScript file, you are better off using execFile

Cannot Launch `gksudo` using NodeJs `exec`

Goal
I want to show graphical password prompt in nodejs to elevate priviledge thus gain some power to copy file content into another, but the last is owned by root.
In the implementation, I try to execute dd along with it's argument with gksudo with exec() function.
exec = require('child_process').exec
printall = function (error, stdout, stderr) {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error) {
console.log('exec err: ' + error);
}
}
exec("gksudo dd if=/home/user/minor.txt of=/home/user/major.txt", printall)
Error
But I always fail, with no good reason.
It said,
stdout:
stderr:
exec err: Error: Command failed: /bin/sh -c gksudo dd if=/home/user/minor.txt of=/home/user/major.txt
If I reproduce the command into terminal, it missed double quotes and instead run gksudo only. Well, in nodejs, it simply fails.
Notes
I originally develop Atom package. It's my first time, so, I found out about a different version of Node (or IOJs?). I execute the whole code inside Atom.
Question
If you expect a clear question, well, possibly
How to execute gksudo within node.js to run other command along with the arguments?

fetching 'rsync' output with nodejs child_process.exec callback

Currently I'm failing to fetch the rsync output when I'm calling nodejs child_process.exec with a callback-function like in this snippet:
var sys = require('sys'),
exec = require('child_process').exec;
cmd = 'rsync -rpz test/test-files/one.txt jloos#test.mygnia.de:~/remote-test/a/b/'
exec(cmd, function(error, stdio, stderr) {
sys.print('s: ' + stdio + '\n');
sys.print('e: ' + stderr + '\n');
});
I think this is caused by the specific behavior of rsync. rsync communicates with it's counterpart via terminal. So how can I fetch the messages from rsync, if even possible?
When I use cmd = 'ls -la' I get the expected output.
Thanks
Often stdout is buffered when the program isn't running in a virtual terminal.
Many languages have a pty module which will trick the program into behaving as though it is running in a terminal.
This provides that functionality for NodeJs;
https://github.com/chjj/pty.js
Keep in mind that rsync may be writing lots of special characters or using something like ncurses to provide the updating status messages, which may make it more difficult to work with the output.

Making lftp write to stdout without having to close the process first

I'm trying to wrap the lftp program in a node.js application, using child_process. The problem is that lftp doesn't write its output to stdout, so I cannot catch its output in node.js. Sample code:
var proc = require('child_process').spawn('lftp', ['-p', port, '-u', username + ',' + password, host]);
proc.stdout.on('data', function (data) {
console.log('stdout:', data.toString('utf-8'));
});
proc.on('exit', function (code) {
console.log('process exited with code ' + code);
});
proc.stdin.write('ls');
// proc.stdin.end();
If I uncomment the line that calls stdin.end() for the lftp child process, the output from the ls command appears in my terminal as it should. If I don't the process simply hangs and nothing gets outputted.
I've also tried using unbuffer, but it doesn't seem to allow me to write to lftp's stdin anymore. It outputs the usual "[Resolving host address...]" stuff, but not the output from the ls command.
My question is: what do I have to do to be able to interact with lftp using node.js' child_process?
Well, this was dumb. I forgot to write a newline after the ls command to stdin. It seems to work without the need for unbuffer.

Resources