🐧 Linux 総合学習プラットフォーム
自動化/定期実行 ・ 中級

環境変数と PATH の注意点

cron で動かしたスクリプトが「手で打つと動くのに失敗する」最大の原因は環境変数の違いです。cron はログインシェルを通さないため PATH が最小限で、.bashrc も読み込まれません。対策として、コマンドは絶対パスで書く、スクリプト内で必要な環境変数を明示的に設定する、crontab の先頭で PATH= を定義する、のいずれかを取ります。systemd の service でも同様で、Environment= や EnvironmentFile= で明示します。

コマンド自体は正しい。ターミナルで手打ちすると問題なく動く。なのに cron に登録すると失敗する。自動化でいちばん多く、そしていちばん厄介なのがこの現象だ。

原因が見えにくいのは、コマンドを疑ってしまうからだ。結論から言うと、その大半は環境変数の違い、とりわけ PATH の違いが原因である。

💡
ポイント「手では動くのに cron だと失敗する」の大半は、コマンドではなく環境変数、とりわけ PATH の違いが原因。

なぜそうなるのかという理屈を一度きちんと理解しておけば、この症状に出くわしても落ち着いて切り分けられるようになる。

逆に理屈を知らないままだと、コマンドを疑って何度も書き直す、という的外れな試行錯誤に陥りがちだ。

🔀 同じコマンドなのに、なぜ cron だと環境が違うのか

あなたがターミナルでコマンドを打つとき、シェルは起動時に /etc/profile や ~/.bashrc、~/.bash_profile といった設定ファイルを読み込む。

この過程で PATH に各種ディレクトリが追加され、別名(alias)や独自の環境変数も設定される。つまり日頃の対話シェルは、これらの設定をすべて読み込んだ「お膳立てされた状態」なのだ。

手打ち(対話シェル)~/.bashrc などを読むPATH が豊富 / alias あり/usr/local/bin も入るcron 実行時設定ファイルを読まないPATH が最小限 / alias 無しPATH=/usr/bin:/bin同じコマンドでも、cron は貧弱で違う環境で走る。だから手では動くのに失敗する

ところが cron がジョブを起動するときは、ログインシェルを通さず、それらの設定ファイルを一切読み込まない。

その結果、cron 実行時の PATH は /usr/bin:/bin といったごく最小限のものだけになる。~/.bashrc で足したパスや、そこで定義した環境変数・alias はすべて存在しない状態でコマンドが走る。

つまずきcron はログインシェルを通さず ~/.bashrc などを一切読まない。PATH は /usr/bin:/bin 程度、alias や独自の環境変数も無い。

さらに、起動の起点となるカレントディレクトリも対話時とは異なり、ホームディレクトリなど決まった場所になる。

「手では動くのに cron で動かない」のは、コマンドが間違っているのではない。この貧弱で違う環境のせいなのだ。同じ理由で、at や systemd の service でも環境は最小限になる。

🚫 その違いは、どんな失敗となって現れるのか

PATH が最小限だと、/usr/local/bin などにインストールされたコマンドが「command not found」となって失敗する。自分で入れたツールや言語ランタイムに多い。

つまずきPATH が最小限だと、/usr/local/bin などに入れた node・python3・docker・自作スクリプトが「command not found」になりやすい。

たとえば普段 node や python3、docker、自作スクリプトを名前だけで呼んでいるとしよう。cron 環境ではそのパスが PATH に無いため見つからない。

また、~/.bashrc で export していた API キーや言語の設定(LANG など)も読まれない。日本語が文字化けする、設定値が見つからないとエラーになる、相対パスで参照していたファイルが見つからない、といった形で表面化する。

ここで重要なのは、こうした冪等な定期処理を安定して回すには、実行環境を実行のたびに同じ・既知の状態にそろえることが前提になる、という発想だ。

🔗
たとえ冪等な処理も、毎回そろわない環境で走らせれば「動いたり動かなかったり」とぶれる。土台が揺れていれば、その上の家もぐらつく。

環境がそのつど変わると、冪等であるはずの処理も「動いたり動かなかったり」とぶれてしまう。自動化の信頼性が根本から崩れてしまう。

🧭 対策その1 — 絶対パスと、crontab での PATH 定義

もっとも確実な対策は、コマンドを絶対パスで書くことだ。node ではなく /usr/local/bin/node、自作スクリプトなら /usr/local/bin/backup.sh と、フルパスで指定すれば PATH に依存しなくなる。

コツどのコマンドがどこにあるかは which node や command -v node で分かる。出た絶対パスをそのまま crontab に書き写せばよい。

どのコマンドがどこにあるかは、対話シェルで which node や command -v node と打てば絶対パスが分かる。それをそのまま crontab やスクリプトに書き写す。

使うコマンドが多い場合は、crontab ファイルの先頭で PATH をまとめて定義する方法も有効だ。crontab の冒頭に PATH=/usr/local/bin:/usr/bin:/bin と1行書いておくと、それ以降のジョブはその PATH のもとで実行される。

crontab の冒頭に PATH=/usr/local/bin:/usr/bin:/bin と書くと、それ以降のジョブはその PATH で実行される。

あわせて SHELL=/bin/bash(ジョブを動かすシェルの指定)や MAILTO=you@example.com(実行結果メールの宛先)も、同様に crontab 冒頭で指定できる設定だ。

つまずきPATH・SHELL・MAILTO などの宣言は、5フィールドの予定行より前に置く必要がある。後ろに書くと効かない。

これらの宣言は5フィールドの予定行より前に置く必要がある点に注意してほしい。

🧰 対策その2 — スクリプト自身に、環境を整えさせる

もう1つの王道は、呼び出されるスクリプトの側で、自分が必要とする環境を明示的に作ることだ。

スクリプト冒頭で export PATH=/usr/local/bin:$PATH のように PATH を補い、export DATA_DIR=/srv/data のように必要な変数も自分で設定する。

スクリプト冒頭で export PATH=/usr/local/bin:$PATH のように PATH を補い、必要な環境変数も export DATA_DIR=/srv/data のように自分で設定する。

コツAPIキーなどの秘密は直書きせず、権限を絞った別ファイルに置いて source /etc/myapp/env で読み込むと、安全で見通しよく管理できる。

秘密の値(APIキーやパスワードなど)は、スクリプトに直書きすると漏えいの危険がある。権限を絞った別ファイルに置いて source /etc/myapp/env のように読み込むと、安全かつ見通しよく管理できる。

こうしておけば、cron から呼ばれても、手で実行しても、同じ環境で動くようになり、再現性が高まる。

「実行環境を呼び出し元任せにせず、スクリプトが自分で完結して用意する」のが堅実な設計だ。どこから・どんな状況で起動されても結果がぶれなくなる。

🔍 systemd でも同じか、そしてつまずいたら何を見るか

同じ問題は systemd の service ユニットにもある。service も最小限の環境で実行されるため、必要な環境変数は明示する必要がある。

service ユニットでは Environment=\"PATH=/usr/local/bin:/usr/bin:/bin\" と個別に書くか、EnvironmentFile=/etc/myapp/env で別ファイルから読み込む。

service ユニット内では Environment=\"PATH=/usr/local/bin:/usr/bin:/bin\" のように個別に書くか、別ファイルにまとめて EnvironmentFile=/etc/myapp/env で読み込む。

考え方は cron とまったく同じだ。「実行時の環境はデフォルトでは貧弱なので、必要なものは自分で与える」という一点に尽きる。

コツ動かないときは推測でコマンドを直す前に、ジョブの中で env >> /tmp/cronenv.log を実行し、実際に見えている PATH・環境変数をログに吐かせて確かめる。

最後に、つまずいたら、まずこれ。動かないときは推測でコマンドを直す前に、ジョブの中で env コマンドを実行し、その出力を env >> /tmp/cronenv.log のようにログへ吐かせてみてほしい。

すると cron や service の実行時に、実際どんな PATH・環境変数が見えているかを直接確認できる。手で打ったときの env の出力と見比べれば、何が足りないのかが一目で分かる。ほとんどの「手では動くのに自動だと動かない」問題はここで決着する。

この項目に出てくる用語

冪等性べきとうせい
同じ操作を何度実行しても結果が変わらない性質。自動化処理の安全性の鍵。

関連コマンド

crontabsystemctl

▶ 学習アプリでこの続きを学ぶ・演習する