.bashrcや.zshrcに定義した関数を他のシェルスクリプトから呼び出す
はじめに
Unix系OSで日頃よく使うコマンドは、 .bashrc
や .zshrc
に alias や function を定義しておき、コマンドラインから呼び出すことだと思います。
僕も .bashrc
や .bashrc
に自分のお気に入りのエイリアスや関数を定義していますが、この関数を別のシェルスクリプトから呼び出したいというシーンが有りました。
ちょっと工夫をしないと呼び出せなかったこともあり、やり方を掲載したいと思います。
検証環境
$ uname -moi
x86_64 x86_64 GNU/Linux
$ bash -version | head -n 1
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
まずは .bashrc
に関数を定義してみる
まずは自分の .bashrc
に関数を定義してみます。
ただ渡された引数を出力するだけの print_params という、関数です。
$ cat <<'EOF' >>~/.bashrc
print_params() {
echo "parms are ${@}."
}
EOF
.bashrc
に追加した関数は以下のいずれかの方法で反映できます。
- ログインし直す
bash
コマンドを実行し、シェルを新しいプロセスで立ち上げる. ~/.bashrc
コマンドを実行し、現在事項中プロセスのシェルに関数を反映させる
今回は3つめの方法で反映させます。
$ . ~/.bashrc
関数が作成されたかどうか確認してみます。
# 指定された名前が関数かどうかを確認
$ type print_params
print_params is a function
print_params ()
{
echo "parms are ${@}."
}
# 関数を実行してみる
$ print_params 1 2 3
parms are 1 2 3.
正しく関数が作成されました。
ここからは、作成された関数を他のシェルから呼び出してみます。
.bashrc
に定義されている関数は別のシェルスクリプトからは呼び出せない
test.sh
というファイルを作成し、先程 .bashrc
で定義した関数を呼び出してみます。
# シェルスクリプトを作成
$ cat <<'EOF' >./test.sh
#!/usr/bin/env bash
print_params 1 1 2 3 5 8
EOF
# 実行権限を付与
$ chmod +x ./test.sh
このスクリプトを実行してみます。
$ ./test.sh
./test.sh: line 3: print_params: command not found
エラーが発生してしまいました。
print_params というコマンドが見つからない、と言っています。
親シェルプロセスで定義したシェル関数は子シェルプロセスから見えない
「親シェルプロセス」で定義した関数は「子シェルプロセス」から見えません。
Bashの関数は、現在実行中のシェルプロセス内でしか利用することはできません。
./test.sh
のように、シェルスクリプトを実行すると、「子シェルプロセス」が自動的に立ち上がり、シェルのロジックが実行されます。
したがって、「親シェルプロセス」で定義した関数 print_params が見えなかったのです。
これを解決する方法はないのでしょうか?
ビルトインコマンド export
で関数を公開する
Bashのビルトインコマンド export
は、変数を「子シェルプロセス」に 公開 するために利用します。
実は export
コマンドを使って、関数も「子シェルプロセス」に 公開 することができます。
先程の ./test.sh
を実行する前に関数を公開してみましょう。
$ export -f print_params
この状態で、先程の ./test.sh
を実行してみます。
$ ./test.sh
parms are 1 1 2 3 5 8.
エラーは表示されず、正しく実行できました。
再度ログインしてきた場合にも公開されるようにする
一度ログアウト、あるいは端末を終了し、再度Bashを起動してみましょう。./test.sh
を実行すると、またまた関数が見つからないことによるエラーが発生するかと思います。
毎回ログインするたびに export -f print_params
するのは面倒ですので、こちらも ~/.bashrc
に記述しておきましょう。
cat <<EOF >>~/.bashrc
export -f print_params
EOF
これで、今後はログインした直後に自動的に関数が子プロセスに公開されるようになります。
ちょっとしたコールバック関数を用意してみる
この仕組を利用して、ちょっとしたコールバック関数を用意することもできます。
callback
という名前の関数にコマンドライン引数をそのまま引き渡すシェルスクリプトを用意してみます。
$ cat <<'EOF' >./calc.sh
#!/usr/bin/env bash
callback $1 $2
EOF
$ chmod +x calc.sh
この状態では、当然実行するとエラーとなります。
$ ./calc.sh 3 5
./calc.sh: line 3: callback: command not found
ここで callback
という名前の関数を作成、公開してみます。
関数は2つの引数を加算した結果を出力する関数です。
callback() {
echo $(($1 + $2))
}
export -f callback
再度先程のスクリプトを実行してみます。
$ ./calc.sh 3 5
8
加算結果が返却されました。
今度は減算してみましょう。
callback() {
echo $(($1 - $2))
}
一度関数を公開していれば、関数のロジック変更後に再度公開する必要はありません。
スクリプトを実行してみます。
$ ./calc.sh 3 5
-2
ひとこと
便利そうですが、関数を使わずシェルスクリプトを使えばなんとかなるということもあり、あまり利用するケースは多くないかもしれません。
関数のメリットはシェルスクリプトの読み込みのオーバヘッドが減らせる点でしょうか。
同じロジック( echo 1
するだけ)のシェルスクリプト x.sh
と x_func
を10000回呼び出した場合の処理速度の違いは以下の通りでした。
$ time bash -c "seq 1 10000 | xargs -n 1 ./x.sh" > /dev/null
real 0m30.506s
user 0m6.018s
sys 0m13.288s
$ time bash -c "seq 1 10000 | xargs -n 1 bash -c 'x_func'" > /dev/null
real 0m12.925s
user 0m4.268s
sys 0m8.613s
ディスカッション
コメント一覧
まだ、コメントがありません