Cronジョブが動かない「no MTA installed, discarding output」をLinuxで修正する

beginner🐧 Linux2026-05-11| Linux(Ubuntu、Debian、CentOS、RHEL)— 出力を生成するcrontabエントリを持つcron/crondデーモン

Error Message

no MTA installed, discarding output
#cron#crontab#スケジューラ#デーモン

状況の説明

crontabエントリを設定して実行を待っても、何も起きません。出力もログもエラーもない。そして/var/log/syslog(RHEL/CentOSの場合は/var/log/cron)を確認すると、こんなメッセージが見つかります:

CRON[12345]: (root) CMD (/opt/scripts/backup.sh)
CRON[12345]: (CRON) info (no MTA installed, discarding output)

実はジョブは実行されています。cronが実行したのです。しかし、スクリプトが生成した出力は、それを配信するメール転送エージェント(MTA)がインストールされていないため、静かに破棄されてしまいました。スクリプトがエラーコード1で終了していたとしても、あなたには一切わかりません。

なぜこうなるのか

cronはジョブの出力をcrontabの所有者にメールで送るよう設計されています。最小構成のUbuntuやCentOSサーバーには、postfixsendmailssmtpなどのMTAが存在しないため、cronはその警告をログに記録して出力を破棄します。

本番環境では、これは深刻な問題です。バックアップスクリプトが毎晩午前2時に失敗し続けていても、その痕跡がまったく残らないことになります。

手っ取り早い解決策:crontabで出力をリダイレクトする

パッケージのインストールは不要です。crontabエントリの中で直接、標準出力と標準エラー出力をリダイレクトするだけです:

# すべての出力をログファイルに追記する
*/5 * * * * /opt/scripts/backup.sh >> /var/log/backup-cron.log 2>&1

# すべての出力を破棄する(スクリプト自身がログを持つ場合のみ使用)
*/5 * * * * /opt/scripts/backup.sh > /dev/null 2>&1

cronが出力をメールする先がなくなれば、MTAの警告は表示されなくなります。

どちらのオプションが適切かを判断するには:

  • スクリプトに内部ログがない場合は>> /var/log/backup-cron.log 2>&1を使用してください。特に午前3時に何か問題が起きたとき、記録が必要になります。
  • スクリプトがすでに構造化されたログを書き込んでいる場合、または出力が本当に不要な場合にのみ> /dev/null 2>&1を使用してください。

修正を確認する

crontabを更新した後、次のスケジュール実行を待ってsyslogを確認します:

# cronのアクティビティをリアルタイムで監視する
tail -f /var/log/syslog | grep CRON

# RHEL/CentOSの場合
tail -f /var/log/cron

正常な実行はこのようになります — CMDの行が表示され、その後にMTA警告が続きません:

CRON[12346]: (root) CMD (/opt/scripts/backup.sh)

次に、ログファイルに書き込まれていることを確認します:

tail -f /var/log/backup-cron.log

恒久的な解決策:crontabの先頭にMAILTOを設定する

5つのcronジョブを管理していますか?各行に2>&1リダイレクトを追加するのはすぐに面倒になります。よりすっきりしたアプローチとして、ファイルの先頭でMAILTOを一度だけ空に設定する方法があります。cronはそのファイル内のすべてのジョブのメール配信をスキップします。

crontab -e
MAILTO=""

*/5 * * * * /opt/scripts/backup.sh >> /var/log/backup-cron.log 2>&1
0 2 * * * /opt/scripts/db-dump.sh >> /var/log/db-dump.log 2>&1
30 6 * * 1 /opt/scripts/weekly-report.sh >> /var/log/weekly.log 2>&1

>> logfile 2>&1のリダイレクトはそのまま残しておいてください — MAILTO=""は警告を黙らせますが、出力を有用な場所に送る仕組みは引き続き必要です。

ジョブが本当に実行されていない場合

no MTA installedのメッセージは、実はジョブが実行されたことを確認する意味で安心材料です。しかし、syslogにCMDの行がまったく存在しない場合は、別の問題があります。以下の点を順番に確認してください:

1. cronデーモンが動作していることを確認する

# Debian/Ubuntu
systemctl status cron

# RHEL/CentOS
systemctl status crond

停止している場合は起動してください:sudo systemctl start cron(またはcrond)。

2. crontabの構文を確認する

crontab -l

crontabを静かに壊してしまう3つのよくあるミス:

  • 末尾の改行がない — ファイルの最後のエントリは改行で終わる必要があります。そうでないとcronはそれを無視します
  • エスケープされていない%記号 — cronは%を改行文字として扱います。date +%Y-%m-%dのようなコマンドでは\%とエスケープしてください
  • フィールドの順番が間違っている — 形式は分 時 日 月 曜日 コマンドです

cronが正常に動作しているか確認したいですか?毎分実行されるテストジョブを追加してみましょう:

* * * * * echo "cron alive $(date)" >> /tmp/cron-test.log 2>&1

/tmp/cron-test.logに60秒ごとに新しい行が追加されれば、cronは正常です。問題はスクリプト側にあります。

3. スクリプトのパーミッションを確認する

ls -l /opt/scripts/backup.sh
chmod +x /opt/scripts/backup.sh

スクリプトに実行権限が必要です。また、crontabを所有するユーザーがそのファイルを読み取り・実行できることを確認してください — 特にスクリプトが制限されたパーミッションのディレクトリに存在する場合は注意が必要です。

4. cron内のPATHは最小限

cronのデフォルトPATHは通常/usr/bin:/binだけです。シェルで正常に動作するpython3awsnodeなどのコマンドが、まったく見つからない場合があります。対処方法は2つあります:

# オプションA:crontabの先頭でPATHを設定する
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

*/5 * * * * /opt/scripts/backup.sh >> /var/log/backup-cron.log 2>&1

# オプションB:スクリプト内で絶対パスを使用する
/usr/bin/python3 /opt/scripts/process.py

5. 環境変数が読み込まれない

cronは.bashrc.bash_profileを読み込みません。AWS_PROFILEJAVA_HOMEDATABASE_URLなどの変数は、明示的に設定しない限り存在しません。スクリプトの先頭に以下を追加してください:

#!/bin/bash
source /etc/environment
# または変数を直接設定する
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
export AWS_PROFILE=production

クイックリファレンス

  • 警告が表示されるがジョブは実行された: crontabエントリに>> /logfile 2>&1を追加するか、先頭にMAILTO=""を設定する
  • syslogにCMDの行がない: デーモンの状態、crontabの構文、ファイルのパーミッション、PATHを確認する
  • 手動では動くがcron経由では動かない: ほぼ必ずPATHか環境変数の不足が原因

Related Error Notes