Wayne Bunch
Wayne Bunch

Reputation: 21

A Promise with child_process running a Python script in Node.js - Process exits before all data

I'm trying to get sublist3r to run in a node app. It runs, however, it only shows the banner and then exits out in about 5 seconds. The script is supposed to reach out to the web and takes about 30 seconds to run. If I don't use a promise, it will work just fine. Does it have something to do with pyrog.stdout.on('data') not waiting before it outputs? I've read around and tried 'end' with no luck.

Tried everything on this article if it didn't involve editing python script (I don't think I should need to ?!)

Also read the Node.js Child Process but it doesn't mention using promises with spawn, and I believe that's what I need to use for running a Python script.

sublist3r screen shot

Am I using Promises wrong?

Any help is much appreciated

Edit: Added await to runPy, verified same issue. Have also tried making it a variable, let test = await runPy ... with no success

var express = require('express');
var router = express.Router();

let runPy = new Promise((success, nosuccess) => {
    const {spawn} = require('child_process')
    const pyprog = spawn('python',['/path/to/sublist3r.py', '-d', 'domain.com'] )

    pyprog.stdout.on('data', (data) => {
        success(data)
    })

    pyprog.stderr.on('data', (data) => {
        nosuccess(data)
    })

    pyprog.on('close', (code) => {
        console.log(`child process ended with ${code}`);
    })
})


/* GET home page. */
router.get('/', async (req, res) => {

    // EDIT:  Added await and verified same issue.
    await runPy.then(fromRunPy => {
        console.log(fromRunPy.toString());
    })

    // It works fine below, but I want a promise for no other reason that I can't get it to work...
    // const { spawn } = require('child_process');
    // const pyProg = spawn('python', ['/home/wayne/BugHunterJS/controllers/Sublist3r/sublist3r.py', '-d', req.body.domain]);
    
    // console.log('inside post');
    // pyProg.stdout.on('data', function(data) {
    //     let sublist3rData = data.toString();
    //     console.log(sublist3rData);
    // });

  });

module.exports = router

Upvotes: 0

Views: 753

Answers (1)

Wayne Bunch
Wayne Bunch

Reputation: 21

Not shortly after I asked, I found a solution if anyone is looking. I'm still not really sure how it works, got to figure that out later. I think pushing it to the array is the key.

const {
    spawn
} = require('child_process')
const logOutput = (name) => (data) => console.log(`[${name}] ${data}`)


function run() {
    return new Promise((resolve, reject) => {
        const process = spawn('python', ['/path/sublist3r.py', '-d', 'domain.com']);

        const out = []
        process.stdout.on(
            'data',
            (data) => {
                out.push(data.toString());
                logOutput('stdout')(data);
            }
        );

        const err = []
        process.stderr.on(
            'data',
            (data) => {
                err.push(data.toString());
                logOutput('stderr')(data);
            }
        );

        process.on('exit', (code, signal) => {
            logOutput('exit')(`${code} (${signal})`)
            if (code === 0) {
                resolve(out);
            } else {
                reject(new Error(err.join('\n')))
            }
        });
    });
}

(async () => {
    try {
        const output = await run()
        logOutput('main')(output)
        process.exit(0)
    } catch (e) {
        console.error('Error during script execution ', e.stack);
        process.exit(1);
    }
})();

Upvotes: 2

Related Questions