サーバー保守 サーバー管理

cronに登録したジョブが動いているか確認するとき、journalctl -u crondで見るのはやめたほうがいいです。実行ユーザーによってはジョブが1件も表示されず、動いているのに「動いていない」と判断してしまいます。

正しくは_COMM=crondでプロセス名を指定します。

sudo journalctl _COMM=crond --since today --no-pager \
  | grep -oE "\(.*\) CMD \(.*\)$" | sort | uniq

-u crond で消えるのはユーザー指定のジョブだけ

やっかいなのは、-u crondでも何かは表示されることです。OS標準のcron.hourlyはroot実行なので出てきます。そのため「cron自体は動いているのに、自分が登録したジョブだけ影も形もない」という見え方になり、設定ファイルの書式ミスや配置ミスを疑い始めてしまいます。

同じ日のログを2つの方法で数えた実測値です。実行ユーザーごとに内訳を出しました。

$ sudo journalctl _COMM=crond --since today --no-pager \
    | grep -oE "\((root|apache)\) CMD \(" | sort | uniq -c
  38 (apache) CMD (
  10 (root) CMD (

$ sudo journalctl -u crond --since today --no-pager \
    | grep -oE "\((root|apache)\) CMD \(" | sort | uniq -c
  10 (root) CMD (

rootの10件はどちらでも同じです。/etc/cron.dにapache実行で書いた38件が、-u crondでは丸ごと欠けています。

原因はjournald上のユニット名が実行ユーザーで変わること

ログのメタデータを取り出すと理由がはっきりします。_SYSTEMD_UNITがジョブごとに違っていました。

実行ユーザー _SYSTEMD_UNIT
root(cron.hourly) crond.service
apache(/etc/cron.dで指定) session-515.scopeなど都度別

ユーザーを指定して実行されるジョブはログインセッション扱いになり、実行のたびに別のスコープに入ります。-u crondcrond.serviceだけを絞り込むフィルタなので、これらは対象外になります。

_COMMはユニットではなくプロセス名(この場合crond)で絞るため、どのスコープに入っていても拾えます。

ジョブの成否はCMDOUTで見る

ジョブの起動はCMD (...)、その標準出力・標準エラーはCMDOUT (...)として記録されます。「起動はしているが中身が失敗している」を切り分けるにはCMDOUT側を見ます。

sudo journalctl _COMM=crond --since today --no-pager \
  | grep -iE "CRITICAL|ERROR"

cronの設定を移設した翌朝にこれを流したところ、全ジョブが時刻どおりに起動している一方で、コマンド側がPHPの例外で軒並み失敗しているのが分かりました。「cronが動かない」と「ジョブが失敗する」はまったく別の問題なので、先にCMDで起動を確認し、次にCMDOUTで中身を見る順番にすると迷いません。

そもそも/var/log/cronが無い環境がある

Amazon Linux 2023などrsyslogを積んでいないディストリビューションでは、/var/log/cron自体が存在しません。ここでファイルを探して見つからず、「ログが出ていない=cronが動いていない」と誤解することがあります。ログはjournaldに入っているので、上のコマンドで読めます。

なお--since todayは問題なく使えます。時刻まで付けた--since "today 00:00"Failed to parse timestampになるので、日付だけか"2026-08-07 00:00:00"のように完全な形式で書いてください。