経緯
- CentOS鯖が2本ある
- Let's encryptの自動更新をしたくてシェルスクリプトを書き、cronに食わせた
- 2本の内1本から「コマンドが見つかりません」とエラーメールが飛んできた
環境
原因
両方とも失敗していたが片方しかrootメールアドレスを設定していなかった。
結論
PATH
もMAILTO
もcrontab -e
で一緒に書いちゃった方がいい。
デフォルト値はCronのコード内で定義されていた。
PATHはどんな値?
crontabの環境変数PATHについて調べてみた · DQNEO起業日記
*/1 * * * * printenv > /tmp/printenv.txt
SHELL=/bin/sh
USER=root
PATH=/usr/bin:/bin
PWD=/root
LANG=ja_JP.UTF-8
SHLVL=1
HOME=/root
LOGNAME=root
出た
Q.ユーザー環境変数は引き継がれるの?
A.されない
Crontabの環境変数はどうなっているのか、調べる - それマグで!
まぁカスタムしたPATHとか.bash_profile
に書いてあるし、cronが使えるとは思ってない。
ただ、/root/bin
も放り出されているなんて…
システム的な初期値は何?
PATH="/sbin:/usr/sbin:/bin:/usr/bin"
export PATH
「CentOS でデフォルトで設定される環境変数について」(1) Linux Square − @IT
まったく一致しない……。
もはや答えはソースを見るしかない
cronie-1.4.4-15.el6_7.1.x86_64
2018/01/18 追記: fedorahosted.orgが引退した結果使用できなくなったリンク( https://git.fedorahosted.org/git/cronie.git )を差し替え
.
./anacron
./contrib
./man
./pam
./src
cron の意外な落とし穴! - もろず blog
問題のPATHを探す
src/pathnames.h:# define _PATH_DEFPATH "/usr/bin:/bin"
幸運なことにあからさまな要素がHit。
この値が利用される箇所を確認する。
src/cron.c:177: if (putenv("PATH=" _PATH_DEFPATH) < 0) {
src/entry.c:299: if (glue_strings(envstr, sizeof envstr, "PATH", _PATH_DEFPATH, '=')) {
src/pathnames.h:61:
src/pathnames.h:62:
cron.c 134行目から
int main(int argc, char *argv[]) {
if (putenv("PATH=" _PATH_DEFPATH) < 0) {
log_it("CRON", pid, "DEATH", "can't putenv PATH", errno);
exit(1);
}
}
大当たりだ。
C言語なんてめっきり触っておらず("PATH=" _PATH_DEFPATH)
なる記法にウッときた。
(業務でC言語に振れたのはせいぜいがObjective-Cでsqlite直接使ったときくらい)
参考リンク
起動デーモン(rc.d)
cron
rootメールアドレス設定