4
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Node.js 簡単な応答バッチ処理

Last updated at Posted at 2019-11-11

はじめに

Node.jsでyまたはnの応答に従い、バッチ処理を実行するJavaSciptのサンプルを作成しました。
この辺、Promiseとasync/awaitなどを利用して対話的に同期処理を実行すると分けがわからなくところです。
初学者向けと自らの備忘録で掲載します。

前提

バッチ処理リスト

  • batchlist.json
[
    {"msg" : "★ ★ リストを確認します。(ls) 実行 = y, 中止 = n ★ ★",
     "con" : "y",
     "can" : "n",
     "cmd" : "ls"
    },
    {"msg" : "★ ★ パスを確認します。(pwd) 実行 = y, 中止 = n ★ ★",
     "con" : "y",
     "can" : "n",
     "cmd" : "pwd"
    }
]

JSON項目説明

項目 説明
msg 応答文、実行と中止を定義
con 実行(continue)の文字列を定義
can 中止(cancel)の文字列を定義
cmd 実行するコマンド(command)を定義

バッチ処理スクリプト

  • Dobatch.js

const exec = require('child_process').execFileSync;
const fs = require('fs');
const json = JSON.parse(fs.readFileSync('./batchlist.json', 'utf8'));
// コンソール標準入出力
const rl = require("readline").createInterface(process.stdin, process.stdout);
const gets=()=>new Promise(res => rl.once("line",res));

/**
 * コマンドラッパー(同期処理)
 * @param {String } cmd - コマンド
 */
 function sh(cmd) {
    try { 
        console.log(exec(cmd, { shell: true }).toString());
    } catch(error) { 
        console.log(error.stderr.toString()); }
}

// 処理実行
(async function() {
    for (var i = 0 ; json.length > i ; i++ ) {
        console.log(json[i].msg); 
        str = await gets();
        if ( str == json[i].con ) {
            console.log(json[i].cmd);
            sh(json[i].cmd);
        } else if ( str == json[i].can ) {
            process.exit();
        } else {
            console.log(str + "は入力不正です。")
            i--;
        }
    }
    process.exit();
})();

説明

  • コマンド実行はchild_processのexecFileSyncを利用して同期処理
  • JSONの読み出しもfsのreadFileSyncを利用して同期処理
  • 残るは、コンソールからの入出力応答をPromoiseとasync/awaitで同期処理
    gets関数で定義

実行

Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. All rights reserved.

PS C:\Users\~>bash --version ...①
GNU bash, version 4.4.12(2)-release (x86_64-pc-msys)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
PS C:\Users\~>bash ...②
USER MINGW64 ~/
$ node Dobatch.js ...③
★ ★ リストを確認します。(ls) 実行 = y, 中止 = n ★ ★
y
ls
batchlist.json
Dobatch.js

★ ★ パスを確認します。(pwd) 実行 = y, 中止 = n ★ ★
y
pwd
/c/Users/~/


USER MINGW64 ~/
$

説明

① bashのバージョン確認
② PowerShellからbashへ切替え
③ Dobatch.jsの実行

※ 実行で表示されるパスは出力を編集して表示しています。

まとめ

Node.jsのコンソールからの標準入力がめんどくさい、VBのMsgBox的なコーディングをしようとして悪戦苦闘した記憶がありました。ファイルの読み込みとコマンド実行を同期処理にすれば、以外と簡単にできると思います。たぶレスポンスはいまいちだと思います。
色々なシステム導入ツールがあると思いますが、JSONファイルのバッチ定義で簡易システム導入ツールとしてご利用してみてください。ただし、参考までに、例によって一切のご利用はあくまでも自己責任でお願いします。

仮想ターミナルでの実行

2019.12.19 更新
execFileSyncでコマンドを実行するたび、子プロセスを作成するので、指定した環境で連続したコマンドの実行に向かないので、spawn('bash')で子プロセスのターミナルを作成して、その子プロセスに、stdin.writeでコマンドを書き込んで実行する方法を別に作成しましたのでアップします。

  • "con" : "auto"を指定すると自動実行の機能を追加。
  • "skp" : "s" 処理のスキップ機能を追加。
  • msgの出力をカラーにしたいので、colorsを追加しました。
  • バッチリストを引数にしました。
npm install --save colors

実行

node Dobatch.js batchlist.json

Dobatch.js 改

require('colors');

// バッチリスト
if ( process.argv[2] == null ) { 
    console.log("バッチリストを指定してください。".red.bold);
    process.exit();
};

const fs = require('fs');

// バッチリスト存在チェック
try { fs.statSync(process.argv[2]);
    console.log("input list : " + process.argv[2] + "\n");
} catch(err) {
    if( err.code === 'ENOENT') {
        console.log(process.argv[2] + " が存在しません。".red.bold); 
        process.exit();        
    }
}

const json = JSON.parse(fs.readFileSync(process.argv[2]),'UTF-8');
const terminal = require('child_process').spawn('bash');

// コンソール標準入出力
const rl = require("readline").createInterface(process.stdin, process.stdout);
const gets=()=>new Promise(res => rl.once("line",res));

/**
 * コマンドラッパー
 * @param {String} cmd - コマンド
 */
function sh(cmd) {
    return new Promise((resolve) => {
        try {
            terminal.stdin.write(cmd + '\n');
            terminal.stdout.once('data', function(data) {
                console.log(data.toString());
                resolve(data.toString());
            })
        } catch(error) {
            console.log(error.stderr);
        }
        return;
    });
}

// 処理実行
(async function() {
    for (var i = 0 ; json.length > i ; i++ ) {
        console.log(json[i].msg.yellow);

        // auto判定
        if ( json[i].con == "auto" ) {
            if ( json[i].cmd == "" ) {
                continue;
            } else {
                console.log(json[i].cmd.green);
                await sh(json[i].cmd);
            }
        } else {
            str = await gets();
            if ( str == json[i].con ) {
                if ( json[i].cmd == "" ) {
                    continue;
                } else {
                    console.log(json[i].cmd.green);
                    await sh(json[i].cmd);
                }
            } else if ( str == json[i].can ) {
                process.exit();
            } else if ( str == json[i].skp ) {
                continue;
            } else {
                console.log(str + "は入力不正です。".red.bold)
                i--;
            }
        }
    }
    process.exit();
})();
4
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?