child_process.exec() 実行時にエイリアスを使えるようにする
Node.js 組み込みモジュール child_process
が提供する exec()
関数は、シェルを起動して任意のコマンドが実行できる。パイプを駆使した簡単なシェルの結果をもって Node.js スクリプトを書いたりしたい時に向いている。
今回、この関数をゴリゴリに使うスクリプトを作ろうとしてつまづいたところがあるのでまとめておく。
目次
~/.bashrc
を読み込まない
child_process#exec()
でコマンドを実行すると、通常は /bin/sh
で動作する。コレは shell
オプションを指定することで Bash に変更できる。
しかし、Bash シェルを利用するようにしても、~/.bash_profile
や ~/.bashrc
が読み込まれない。つまり、これらのファイル内で定義したエイリアスを利用できないワケだ。
~/.bashrc
を読み込ませるには
~/.bashrc
などを読み込ませた状態で任意のコマンドを実行するには、次のように shopt
コマンドと source
コマンドを実行してから指定のコマンドを実行するようにしてやる。
const childProcess = require('child_process');
const util = require('util');
const execAsync = util.promisify(childProcess.exec);
// 実行したいコマンド
const inputCommand = `my_alias`;
(async () => {
try {
const result = await execAsync(`shopt -s expand_aliases ; \n source ~/.bash_profile ; \n ${inputCommand}`, {
shell: '/bin/bash',
cwd: '/PATH/TO/my-directory/'
});
console.log(result.stdout);
}
catch(error) {
console.error(error.stderr ? error.stderr : error);
}
})();
async・await で使えるように Promisify しているが、本質ではない。
shopt -s expand_aliases
でエイリアスを使用するよう設定する。; \n
でコマンドを区切り改行する。source ~/.bash_profile
ないしは source ~/.bashrc
など好きなファイルを読み込んでから、ようやく自分が実行したいコマンドを入力してやる。
exec()
に指定するコマンド文字列の中で、セミコロンや改行を用いて複数のコマンドを実行する、という発想がなかったので驚いたが、こんなやり方で実現できた。