shellscript の '$@' は、とても便利だった
概要
shell script には、 全コマンドライン引数を扱う $@ という値が用意されています。
先日、 $@ のユースケースを学ぶ機会があり、その効果に驚きました。
学んだユースケースと共に、 $@ の効果を少しでも伝えられればと思います。
$@ とは
シェルスクリプトにて使用できる、全コマンドライン引数を格納した変数です。
$@ を参照することで、全コマンドライン引数をまとめて扱うことが出来ます。
echo "$@"
$ bash at_sample.sh hoge fuga
hoge fuga
$ bash at_sample.sh foo bar hogera
foo bar hogera
ユースケース
shell script 内で疑似エイリアス
コマンドを短縮するためのエイリアスは便利ですが、シェルスクリプト内では展開されず、そのまま実行されるため「command not found」エラーになります。
$ alias ll
alias ll='ls -alF'
$ cat ll_sample.sh
ll
$ bash ll_sample.sh
ll_sample.sh: line 1: ll: command not found
設定にて、シェルスクリプト内でのエイリアス展開を有効に出来ますが、意図しない動作の原因となるリスクがあります。
$@ を使用することで、エイリアスと同じような挙動を実現できます。
以下は、postgresql へ接続する汎用コマンドの例です。
#!/bin/bash
# 各種環境変数は設定済みという想定
function connect_psql(){
PGPASSWORD=${PGPASSWD} psql --host ${HOST} --port ${PORT} --user ${USER} "$@"
}
#!/bin/bash
source connect_psql.sh ## 上記 connect_psql関数を読み込む
connect_psql -c 'select * from my_table;' ## select
connect_psql -q --csv -f 'sql/get_users.sql' ## 任意のオプションも、 `$@` にて全部渡すことが出来る
$@ で任意の引数を扱えるため、 psql の任意のオプションを渡すことが出来ます。
コンテナイメージにて、 CMD 実行前に初期化スクリプトを実行させる
CMD で指定したコマンドを実行する前に、任意の初期化処理を行う init.sh を割り込ませます。
FROM any_image
COPY init.sh entrypoint.sh /usr/local/bin
COPY main.sh .
ENTRYPOINT [ "entrypoint.sh" ]
CMD [ "Bash", "main.sh" ]
#!/bin/bash
set -e
init.sh
exec "$@"
echo "insert init script here." | tee sample.txt
これにより、 CMD で指定したコマンドは、 ENTRYPOINT の値と併せて、以下のようなコマンドとなります。
entrypoint.sh Bash main.sh
entrypoint.sh では、最初に init.sh を実行し、続く引数を exec コマンドで評価します。
結果として、処理順は以下のようになります。
- entrypoint.sh
- init.sh
- Bash main.sh (
CMDで設定したコマンド)
後は、 init.sh に、任意の初期化処理を実装するだけです。
開発側は、 entrypoint.sh の存在を意識することなく、 CMD を好きに上書きできます。
所感
$@ の存在自体は知っていましたが、こういった活用方法は思いつきませんでした。
単純にして、非常に強力な値だと感じました。
色々と使い道を探っていきたいと思います。
Discussion