I have a bash script that I am running server side from meteor. I have tested that I am successfully able to run shell commands by running 'ls' and getting the expected response back. However, when I run my shell script no output is ever logged to the server console and none of the intended effects of the script are successful. I am printing stderr,stdout, and error yet they print nothing when I run my script.
Meteor.methods({
grade: function(unittest, code) {
this.unblock();
var sys = Npm.require('sys');
var exec = Npm.require('child_process').exec;
// exec('/bin/ls /srv/srcalyzer/scripts', function(error,stdout,stderr){
// console.log('error: ',error);
// console.log('stdout: ',stdout);
// console.log('stderr: ',stderr);
// });
console.log('running grade')
exec('/bin/bash /srv/srcalyzer/scripts/grade.sh', function(error,stdout,stderr){
console.log('error: ',error);
console.log('stdout: ',stdout);
console.log('stderr: ',stderr);
});
console.log('just finished.');
},
Although it is currently commented out the /bin/ls /some/path logs the expected output to console. However when I run the /bin/bash /path/to/.sh that I know is in place. The console output looks like
I20161207-15:22:07.031(-5)? running grade
I20161207-15:22:07.045(-5)? just finished.
The script does take a short time to run (~15-20 seconds). I am uncertain if this is relevant or not.
Can someone please help me understand what is happening?
there's a hint here:
I20161207-15:22:07.031(-5)? running grade
I20161207-15:22:07.045(-5)? just finished.
that's only taking a few ms to run. meaning, your Meteor method is likely exiting before the exec() finishes. i've never run an exec() in Meteor, so i'm unsure if that shell script keeps running after your method exits.
what you need is to run a future in your Meteor method, so it doesn't exit until your shell script comes back.
something like:
let future = new Future();
exec('/bin/bash /srv/srcalyzer/scripts/grade.sh', function(error,stdout,stderr){
console.log('error: ',error);
console.log('stdout: ',stdout);
console.log('stderr: ',stderr);
future.return(stdout.toString());
});
return future.wait();
now your Meteor method will wait until your script finishes.
(caveat: i didn't try this, just typing this solution from memory on my non-work machine)
Related
I have a huge script (3 modules x 2000 lines each one) which runs about 3000 times per day. Few times a week it freezes. Nodejs process is still running on Linux server, but nothing happens, it just stops working without any understandable reason. I've tried to write logs everywhere it was possible with try ... catch, but there is still no errors or warnings. It hangs in different places, different loops. There are also no errors in server logs.
Are there any other ways to debug such problem?
in your main file( the file which your start app) put these codes :
// to log all bugs that occured in synchronus code but not handlled anywhere (add below code on top of your main file)
process.on('uncaughtException', err => {
console.log('uncaughtException!! shutting down...');
console.log(err.name, err.message);
process.exit(1);
});
// to log all unhandledRejection in you APP (Async Code)
process.on('unhandledRejection', (err) => {
console.error(`Error Name : ${err.name}\nError Message : ${err.message}`);
console.error(`unhandledRejection!💥 Shutting Down...`);
process.exit(1); // 0 for success & 1 for uncaught exeptions
});
By these lines of codes, when any problem happen in your app you can observe errors wich you haven't handle on your code.
I've been trying to solve this issue for a few days with absolutely no luck. I have a node.js application that is spawning a child process - it's looking at the STDOUT of that child process and reacting to it. A snippet looks like:
var childProc = spawn('/opt/Game/LaunchGame.sh');
childProc.stdout.on('data', function(data) {
console.log("stdout: " + data);
});
childProc.on('close', function(code){
console.log('child process exited with code ' + code);
});
If I run the bash script by itself, all the log messages appear as I'd expect, but when its run through Node, I never see any "stdout: " messages.
Any ideas?
I've an app which initially creates static config files (once) and after files were written I need to reinitialize/restart the application.
Is there something to restart a node.js app from itself?
This is required cause I've an application running in two runlevels in node.js.
The initial one starts completly synchronus and after this level has been completed app is in async runlevel in a previously started environment.
I know there are tools like nodemon but that's not what I need in my case.
I tried to kill the app via process.kill() which is working but I can't listen to the kill event:
// Add the listener
process.on('exit', function(code) {
console.log('About to exit with code:', code);
// Start app again but how?
});
// Kill application
process.kill();
Or is there a better, cleaner way to handle this?
Found a working case to get node.js restarted from app itself:
Example:
// Optional part (if there's an running webserver which blocks a port required for next startup
try {
APP.webserver.close(); // Express.js instance
APP.logger("Webserver was halted", 'success');
} catch (e) {
APP.logger("Cant't stop webserver:", 'error'); // No server started
APP.logger(e, 'error');
}
// First I create an exec command which is executed before current process is killed
var cmd = "node " + APP.config.settings.ROOT_DIR + 'app.js';
// Then I look if there's already something ele killing the process
if (APP.killed === undefined) {
APP.killed = true;
// Then I excute the command and kill the app if starting was successful
var exec = require('child_process').exec;
exec(cmd, function () {
APP.logger('APPLICATION RESTARTED', 'success');
process.kill();
});
}
The only con I can see here is to loose outputs on console but if anything is logged into logfiles it's not a problem.
I am working with node.js, and I am trying to embed a console in the web browser to work in a remote server. The web application do the connection so the user does not need to do the ssh username#host but only type commands.
I have tried the node.js' ssh2 module and other modules which use ssh2. But I'm experiencing always the same problem. Every time I execute a command programmatically using exec(), the ssh session is restarted. I'll explain it better with an example.
> ls
returns the content of home directory, one of the directories in the home directory is mydir
> cd mydir
> ls
returns the content of my home directory again, because after a command is executed the ssh session is closed/restarted.
Any node.js library which can do the job? or even a library of other technology different to javascript?
Edit: Other example for clarifying, using the node.js' module ssh-exec
The server has to execute some commands in other machine using ssh. A function in the server contains the following code
var c = exec.connection('username#host.com'); // It takes the ssh key from the default location
exec('cd mydir', c).pipe(process.stdout);
exec('ls -lh', c).pipe(process.stdout);
As you can see I am not ending the connection after the first exec but the output I obtain is the content of the home directory not the content of mydir directory, because the ssh session is reset after each exec.
The maintainer of node.js' ssh2 module provided the solution.
To use the method shell() instead of the method exec().
The method shell() creates an interactive session with the server we are connecting.
The method shell() provides a stream as a parameter of its callback (like the method exec()).
Like when using exec(), stream.on('data', function(data, extended) {...}); can be used to get the output of the commands. However, in this case, to provide commands (input) to the machine you connected with, you need to use stream.write(yourcommand+'\n');
PS. Feel free to edit to improve the accuracy of the answer.
I have to guess a bit, but you do something like child = exec('ssh username#host ls')?
You can do something like
child = exec('ssh username#host');
upfront and in the "loop" of your browser
child.stdin.write('ls\n');
When finished, just close stdin:
child.stdin.end()
which also finishes the child process.
I know this link is old but I figured this may help someone if they're looking for a solution. The
To use the method shell() instead of the method exec().
Works. Here's another solution. Use absolute file paths i.e.
conn.exec("mkdir -p /home/user/Direc/{one,two,three}/", function(err, stream) {
if (err) throw err;
stream.on('data', function(data) {
console.log('STDOUT: ' + data);
}).stderr.on('data', function(data) {
console.log('STDERR: ' + data);
});
});
conn.exec("ls -la /home/user/", function(err, stream) {
if (err) throw err;
stream.on('close', function(code, signal) {
console.log('Stream :: close :: code: ' + code + ', signal: ' + signal);
conn.end();
}).on('data', function(data) {
console.log('STDOUT: ' + data);
}).stderr.on('data', function(data) {
console.log('STDERR: ' + data);
});
});
I'm trying to download a lot of files using nodejs and the exec command, simplified like this:
var cmd = 'wget -O output.csv URL';
var child = exec(cmd, function(err) {
console.log('DONE');
});
However, the callback is triggered before the file was actually downloaded through wget, leading to a file that contains garbage like '��0O�6D�1n�]v�����#�'. Shouldn't the callback be triggered once wget is done? When running the same command on the command line it takes rougly 5 seconds, since the file has several MB.
Btw: I'm not using the request module since it's slower and I ran into emitter listener issues (EventEmitter memory leak detected. 11 listeners added).
Thanks!
This will involve some debugging.
Can you please try running your script as:
var cmd = 'wget -O output.csv URL';
var child = exec(
cmd,
function (error, stdout, stderr) {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
}
);
It would be interesting to see what stdout and stderr say.
Right, you provided me your stderr which said:
http://productdata.zanox.com/exportservice/v1/rest/22791753C32335607.csv?ticket=BC4B91472561713FD43BA766542E9240AFDD01B95B123E40B2C0375E3A68C142
This URL the command line gets is missing everything after the ampersand (& character). This indicates a problem with escaping.
To get around this try replacing \& with \\\&.