クソしょうもない記事なのだが反省を込めて書く。
・経緯
シェルの環境変数を更新したいなどというときにsourceコマンドを使うということはよくあると思う。例えばhoge.shというファイルに
export HOGE=fuga
とか書いて
$ source ./hoge.sh
とすればHOGE=fugaという環境変数が今のシェルで有効になる。
同じことをcronでやろうとする。例えばhoge.shを読み込んで、現在の環境変数でHOGEが含まれるものをcrontest.logというファイルに書き出すジョブを設定したとする。
* * * * * source ./hoge.sh; env | grep HOGE >> ./crontest.log
1分くらい待ってcrontest.logの中身を見てみると... あら不思議、何も中身がないのである。sourceを使ったのに環境変数が有効になっていないのはどういうわけだろうか。
・原因
端的に言ってしまうと(Ubuntuでは)cronが実行する環境ではsourceというコマンドが存在しないためである。. (ピリオド)コマンドを使うことで解決する。
* * * * * . ./hoge.sh; env | grep HOGE >> ./crontest.log
. がsourceと同じように使えることは知っていたが、てっきりsourceが本体で、打つのを面倒がったエンジニアが適当にエイリアスとして.を作ったのだと思っていた。実際は真逆で、.の方がPOSIXで定義された由緒正しいコマンドで、sourceがその(bashでの)エイリアスなのであった。cronのシェルは/bin/shであるが、Ubuntuではこれはsh互換のdashというシェル(bashではない)へのシンボリックリンクになっているので、.しか使えなかったのであった。
$ ls -la /usr/bin/sh
lrwxrwxrwx 1 root root 4 Feb 18 02:26 /usr/bin/sh -> dash
Ubuntu以外で/bin/shのシンボリックリンクがbashに貼られているようなOSだとcronでもsourceが使えるはずではあるが、.の方が正式なのだったら.を使ったほうが良いだろう。
ずっと顔合わせてるインタフェースなのにシェルについて無知でごめんなさいという気持ちです。
