简体   繁体   中英

Run external scripts in sequence

I want to run a couple of SQL scripts from Gulp:

const gulp = require('gulp');
const dotenv = require('dotenv')
const child_process = require('child_process');

function runSQLScript(script) {
    child_process.execFile('sqlcmd', [
        '-S', process.env.DB_SERVER,
        '-U', process.env.DB_USER,
        '-P', process.env.DB_PASSWORD,
        '-d', process.env.DB_DATABASE,
        '-f', 'i:65001',
        '-i', script
    ], {
        cwd: '../sql/sqlcmd'
    }, function(error, stdout, stderr){
        if (error !== null) {
            console.log("" + stdout);
            console.error("" + error);
        }
        if (stderr.length>0) {
            console.error('' + stderr);
        }
    });
}

gulp.task('sql', ['install-app', 'load-data']);
gulp.task('install-app', function(){
    runSQLScript('install-app.sql');
});
gulp.task('load-data', function(){
    runSQLScript('load-data.sql');
});

Then I run:

gulp sql

In an earlier version I was using child_process.execFileSync() and my scripts were running in sequence as expected. I switched to child_process.execFile() to be able to report errors but now load-data.sql fails because it no longer waits for install-app.sql to finish.

What can I do to make the task wait until runSQLScript() finishes? Did I choose a wrong approach to print errors?

Looks like gulp-sequence is the best choice to use (If your gulp version is < 4).

const util = require('util');
const gulp = require('gulp');
const gulpSequence = require('gulp-sequence');
const dotenv = require('dotenv')
const execFile = util.promisify(require('child_process').execFile);

function runSQLScript(script) {
    return execFile('sqlcmd', [
        '-S', process.env.DB_SERVER,
        '-U', process.env.DB_USER,
        '-P', process.env.DB_PASSWORD,
        '-d', process.env.DB_DATABASE,
        '-f', 'i:65001',
        '-i', script
    ], {
        cwd: '../sql/sqlcmd'
    }, function(error, stdout, stderr){
        if (error !== null) {
            console.log("" + stdout);
            console.error("" + error);
        }
        if (stderr.length>0) {
            console.error('' + stderr);
        }
    });
}

gulp.task('sql', gulpSequence('install-app', 'load-data'));
gulp.task('install-app', function(){
    return runSQLScript('install-app.sql');
});
gulp.task('load-data', function(){
    return runSQLScript('load-data.sql');
});

Unfortunately, switching from .execFileSync() to .execFile() appears to be the simplest way to capture the script output in all circumstances. On error, .execFileSync() no longer returns script stdout and there isn't an obvious way to fetch it; you can redirect it to process stdout but, then, you have the problem of fetching it from there if you need further processing. Verbose and illogical as it is, asynchronous code is the least evil.

You can then use gulp-sequence() as FrankerZ's answer explains. As an alternative to util.promisify() (which requires Node/8) you can also use q to make child_process.execFile() return a promise.

Additionally, it seems that you need to catch() the promise returned by runSQLScript() . Otherwise, the second scripts executes anyway, no matter the result of the prior script.

const gulp = require('gulp');
const dotenv = require('dotenv')
const child_process = require('child_process');
const Q = require('q');

function runSQLScript(script) {
    var deferred = Q.defer();
    child_process.execFile('sqlcmd', [
        '-S', process.env.DB_SERVER,
        '-U', process.env.DB_USER,
        '-P', process.env.DB_PASSWORD,
        '-d', process.env.DB_DATABASE,
        '-f', 'i:65001',
        '-i', script
    ], {
        cwd: '../sql/sqlcmd'
    }, function(error, stdout, stderr){
        if (error !== null) {
            console.log("" + stdout);
            console.error("" + error);
            deferred.reject();
        } else {
            deferred.resolve();
        }
        if (stderr.length>0) {
            console.error('' + stderr);
        }

    });
    return deferred.promise;
}

gulp.task('sql', gulpSequence('install-app', 'load-data'));
gulp.task('install-app', function(callback){
    runSQLScript('install-app.sql')
        .then(function(){
            callback();
        })
        .catch(function(){
            callback("install-app failed, aborting");
        });
});
gulp.task('load-data', function(callback){
    runSQLScript('load-data.sql')
        .then(function(){
            callback();
        })
        .catch(function(){
            callback("load-data failed, aborting");
        });
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM