クソしょうもない記事なのだが反省を込めて書く。
・経緯
シェルの環境変数を更新したいなどというときに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
が使えるはずではあるが、.
の方が正式なのだったら.
を使ったほうが良いだろう。
ずっと顔合わせてるインタフェースなのにシェルについて無知でごめんなさいという気持ちです。