2

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.

3
  • you'll have to consider using execFile since it's a file Commented Jul 21, 2016 at 7:38
  • What does update.sh look like? Your code works for me with a simple bash script. (Y'know, unless there's other routes that might be conflicting that you didn't mention) Commented Jul 24, 2016 at 4:11
  • Here are the lines from update.sh, shebang at the top... #!/bin/bash, git pull, npm install, npm run build, forever restartall. Commented Jul 24, 2016 at 22:26

3 Answers 3

1
+50

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();
  });
});
Sign up to request clarification or add additional context in comments.

1 Comment

1. Totally awesome. 2. I can't believe I didn't realize this, now I feel dumb!
1
  1. If error is not empty then output is undefined => fail
  2. 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}))

2 Comments

see my edit above to address this answer... no luck.
You can try to do: 1. Turn off Forever and see console; 2. Replace callback function to one line res.json({}) (perhaps it's not reason to fault); 3. error = error || ''; don't do it because you lost error message; 4. Simplify update.sh to one line e.g. echo 'ok'. Also verify that update.sh is accessable and you have permission to execute it.
0

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 ]);

2 Comments

that syntax is part of ES6
@WayOfTheFuture: Ah, but my solution will still fix your code. Only my explanation may be wrong. See Aikon's answer for why this will fix your code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.