I'm trying to do a series of interactive commands in node.
The first command I want to run is lftp and when it will returned continue with a few more.
The problem is I'm not seeing any response. Here is my code
var childProcess = require('child_process');
var lftp = childProcess.spawn("lftp");
lftp.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
lftp.stdin.write("This is a test to see if something changes"); //it doesn't
lftp.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
lftp.on('close', function (code) {
console.log('child process exited with code: ' + code);
});
But stdout.on() is never activate. I played with the spwan parameters a lot and in some cases I got the stderr.on() to be called but never stdout. When I run the lftp command from shell I get:
$ lftp
lftp :~>
I couldn't find any similar problems so I guess I'm doing something wrong, question is what is it?
Related
First of all, I'm a complete noob and started using Node.JS yesterday (it was also my first time using Linux in years) so please be nice and explicit
I'm currently making a Node.JS program which has to, among other things, launch shell commands (mainly : mount an usb drive).
I'm currently using
var spawn = require('child_process').spawnSync;
function shspawn(command) {
spawn('sh', ['-c', command], { stdio: 'inherit' });
}
shspawn('echo Hello world');
shspawn('mkdir newdir');
etc. which is a really comfortable way to do it for me.
The problem is that I'd like to store the output of, for example, a "ls" command in a variable, in a way like
var result = shspawn('ls -l')
I've read some examples online but they rarely use spawn and when they do, it doesn't work for me (I guess I may do something wrong, but again I'm a noob in Node)
If you guys have a better idea than using child_process_spawnSync I'm open to any idea, but I'd like as long as possible to keep my program package-free :)
EDIT : I need it to work synchronously ! That's why I've started using spawnSync. I will be using some commands like dd, that takes time and needs to be fully finished before the program moves on to another command.
You can do it something like below.
var spawn = require('child_process').spawn;
// Create a child process
var child = spawn('ls' , ['-l']);
child.stdout.on('data',
function (data) {
console.log('ls command output: ' + data);
});
child.stderr.on('data', function (data) {
//throw errors
console.log('stderr: ' + data);
});
child.on('close', function (code) {
console.log('child process exited with code ' + code);
});
Update: with spawnSync
var spawn = require('child_process').spawnSync;
var child = spawn('ls' , ['-l','/usr']);
console.log('stdout here: \n' + child.stdout);
How can I get all current running process on my node server? I tried using ps-node (https://www.npmjs.com/package/ps-node) but failed to fetch the list.
I'm looking for something like the following command in C#:
// Get all processes running on the local computer.
Process[] localAll = Process.GetProcesses();
Is it possible?
Here is an example using the above mentioned forever tool, gnu awk and the built-in child_process node library:
var spawn = require('child_process').spawn,
forever = spawn('forever', ['list', '--plain']),
awk = spawn('awk', ['NR>2{print $4,$5,$6,$7,"\t",$9}']);
forever.stdout.on('data', function (data) {
awk.stdin.write(data);
});
forever.stderr.on('data', function (data) {
console.log('forever stderr: ' + data);
});
forever.on('close', function (code) {
if (code !== 0) {
console.log('forever process exited with code ' + code);
}
awk.stdin.end();
});
awk.stdout.on('data', function (data) {
// data is your result as Buffer
// print data as string
console.log('' + data);
});
awk.stderr.on('data', function (data) {
console.log('awk stderr: ' + data);
});
awk.on('close', function (code) {
if (code !== 0) {
console.log('awk process exited with code ' + code);
}
});
What's happening here, basically is:
$ forever list --plain | awk '{NR>2{print $4,$5,$6,$7,"\t",$9}}'
Of course, the variables awk prints depend on the forever list output... To test the correct solution I would start from printing $0 to get the whole output, then trim it down such that it reports only the informations you need.
I'm trying to have nodejs interact with adventure, an old text based game. The idea is to open adventure as a child process and then play the game by writing to its stdin and placing an event listener on stdout.
When the game starts, it prints an initial:
Welcome to Adventure!! Would you like instructions?
So to illustrate my problem, I have a nodejs+express instance with:
var childProcess = require('child_process');
var spawn = childProcess.spawn;
var child = spawn('adventure');
console.log("spawned: " + child.pid);
child.stdout.on('data', function(data) {
console.log("Child data: " + data);
});
child.on('error', function () {
console.log("Failed to start child.");
});
child.on('close', function (code) {
console.log('Child process exited with code ' + code);
});
child.stdout.on('end', function () {
console.log('Finished collecting data chunks.');
});
But when I start the server, the text from the game doesn't reach the event listener:
spawned: 24250
That's all the output I get. The child.stdout.on even listener is never called. Why isn't that initial line from the game being picked up?
If I append the following line to the above block of javascript, then the program output appears at once. So adventure runs, and I can now force it to trigger the child.stdout.on event listener... but this also ends the child process, which defeats the purpose of reading and writing to it.
...
child.stdout.on('end', function () {
console.log('Finished collecting data chunks.');
});
child.stdin.end();
Now the output is:
spawned: 28778
Child data:
Welcome to Adventure!! Would you like instructions?
user closed input stream, quitting...
Finished collecting data chunks.
Child process exited with code 0
I'm sure its a trivial oversight on my part, I appreciate any help figuring this out though.
After going through the Nodejs documentation a few more times, I convinced myself I was either missing something pretty big, or the spawn command wasn't working correctly. So I created a github issue.
And the answer was immediately posted: the child process can't buffer output if you want fast access.
So to achieve what I was originally looking for:
var childProcess = require('child_process');
var spawn = childProcess.spawn;
var child = spawn('unbuffer', 'adventure');
console.log("spawned: " + child.pid);
child.stdout.on('data', function(data) {
console.log("Child data: " + data);
});
child.on('error', function () {
console.log("Failed to start child.");
});
child.on('close', function (code) {
console.log('Child process exited with code ' + code);
});
child.stdout.on('end', function () {
console.log('Finished collecting data chunks.');
});
With the functional difference being the use of unbuffer, a command that disables output buffering.
Why isn't that initial line from the game being picked up?
I had the same problem on a project that called a compiled C++ program from node.js. I realized the problem was in the compiled C++ program: I wasn't flushing the stdout stream. Adding fflush(stdout); after printing a line solved the issue. Hopefully you still have access to the source of the game!
The data passed is a buffer type, not a string. Therefore, you need a decoder to read that buffer and then do the logging.
Here's how to do that.
var StringDecoder = require('string_decoder').StringDecoder;
var decoder = new StringDecoder('utf8');
child.stdout.on('data', function (data) {
var message = decoder.write(data);
console.log(message.trim());
});
Is it possible to make nodejs execute some code after it has been launched.
After Node.js started, I hope it can loads some code interprets and executes them.
Is there any module can do this?
Your comment welcome
You might take a look at the child process in the Node API, specifically exec for an easy example of executing a command from within Node.
Copied from the API doc:
var exec = require('child_process').exec,
child;
child = exec('cat *.js bad_file | wc -l',
function (error, stdout, stderr) {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
});
There were already a few questions here about node.js executing commands and outputting the data, but I still can't get this working. What I want is that using node.js I want to execute a python script that runs for a long time and produces some intermediate outputs. I want to stream these outputs to the client as soon as they are produced. I have tried the following, but what I get is that I get the whole output only once the command has finished. How can I make it pass on the data into the socket in real time? Thanks.
function run_cmd(cmd, args) {
var spawn = require('child_process').spawn,
child = spawn(cmd, args);
return child;
}
io.sockets.on('connection', function (socket) {
var foo = new run_cmd('python', ['test.py']);
foo.stdout.setEncoding('utf-8');
foo.stdout.on('data', function(data) {
console.log('sending data');
io.sockets.emit('terminal', {output: data});;
});
);
all your node.js code is okay.your code sends data only once because your code gets data only once.
The point is puts or print commands are not enough to trigger foo.stdout.on
try adding '$stdout.flush' at the point you want to send chunk in ruby code.
You need to order explicitly to output data.
here is my test code.
js
var spawn = require('child_process').spawn;
var cmd = spawn('ruby', ['testRuby.rb']);
var counter = 0;
cmd.stdout.on('data', function(data) {
counter ++;
console.log('stdout: ' + data);
});
cmd.stderr.on('data', function(data) {
console.log('stderr: ' + data);
});
cmd.on('exit', function(code) {
console.log('exit code: ' + code);
console.log(counter);
});
testRuby.rb
def execute_each_sec(sleep_sec)
yield
sleep sleep_sec
end
5.times do
execute_each_sec(1) do ||
puts "CurrentTime:#{Time.now}"
$stdout.flush
end
end
as you can see I'm calling $stdout.flush to output data explicitly in testRuby.rb.
if I remove that,node.js won't get anything until execution of testRuby.rb's finished.
edited
lol my bad. I used ruby instead of python.
in the case of python, use sys.stdout.flush() like svkk says
Edit:
In python you can also use -u flag to force it to flush after each print.