Mac cronが動かない原因と解決策|pmset+caffeinate設定ガイド

じたばたIT実践録
Mac cronが動かない原因と解決策|pmset+caffeinate設定ガイドを3行で要約
  • Macのcronが動かない原因はスリープにある。実行時刻に寝ていればスキップされる
  • pmsetでスリープ復帰を自動化し、cronの実行タイミングに間に合わせる
  • caffeinateで起動後のスリープ戻りを防止すれば、安定した自動実行が実現できる
Macでcronがスリープ時に実行されない問題をcaffeinateで解決する漫画。
①夜にMacでcronの設定を完了し翌朝の自動実行を期待する猫。②翌朝6時になってもMacはスリープ状態でcronが実行されず焦る。③ログに記録がなくMacがスリープしていた事実に気づき絶望する。④デプロイ太郎がcaffeinateという解決策を提案し猫が納得する。

毎日決まった時間にPythonスクリプトを自動で動かしたい。Macのcronで設定したのに、翌朝ログが残っていない――そんな状況に困っていないでしょうか。

原因はほぼ間違いなくスリープです。この記事では、実際にMacBook Pro 2020(Intel)で自動実行環境を構築した際にハマったポイントと解決策をすべて記録しています。

pmsetでのスリープ解除、caffeinateでのスリープ戻り防止、さらにlaunchdによる代替手段まで、実際のエラーログ付きで解説していきます。

[ユーザー名] や [プロジェクトフォルダ] の部分は、ご自身の環境に合わせて読み替えてください。

Macのcronが実行されない原因はスリープ

cronが動かない最大の原因は、実行時刻にMacがスリープ状態であることです。Macが寝ている間はスケジュール自体が停止し、指定時刻を過ぎてもスキップされたまま終わります。

蓋を閉じていても、開いたまま放置していても、一定時間操作がなければMacは自動でスリープに入ります。つまり朝6時にcronを設定しても、6時にMacが寝ていればその回は実行されません。

実際に設定直後、cronのメール通知を確認すると以下のエラーが記録されていました。

cat /var/mail/[ユーザー名]

出力結果がこちらです。

Subject: Cron <[ユーザー名]@[ホスト名]> cd /Users/[ユーザー名]/Documents/[プロジェクトフォルダ] && /usr/bin/python3 [スクリプト名].py >> [ログファイル名].log 2>&1

/bin/sh: [ログファイル名].log: Operation not permitted

このエラーはcronのファイル書き込み権限の問題ですが、そもそもスリープ中はこのエラーすら出ません。ログが一切残っていない場合は、cronが起動すらしていないと判断できます。

cronのログ出力先を /tmp/ に変更すると、Operation not permittedエラーは回避できる

pmsetでスリープから自動復帰させる設定手順

pmsetコマンドを使えば、指定時刻にMacをスリープから自動復帰させることが可能です。macOS Ventura以降ではシステム設定から該当画面が削除されたため、ターミナルから設定する必要があります。

設定コマンド

以下のコマンドで、毎日6時にスリープ解除を設定できます。

sudo pmset repeat wakeorpoweron MTWRFSU 06:00:00

MTWRFSUは月〜日の全曜日を意味しています。sudoが付いているため、実行時にMacのパスワード入力を求められます。

確認・変更・解除方法

現在の設定を確認するコマンドはこちらです。

pmset -g sched

以下のように表示されれば設定済みとなります。

Repeating power events:
  wakeorpoweron at 6:00AM every day

時刻の変更は、同じコマンドを別の時刻で再実行すれば上書きされます。

sudo pmset repeat wakeorpoweron MTWRFSU 07:00:00

設定を解除するコマンドは以下の通りです。

sudo pmset repeat cancel

pmsetが効かない場合の事前準備

今回の環境(MacBook Pro 2020 Intel)では、以下の対応を行うまでスリープ解除が安定しませんでした。

確認項目 推奨設定
電源アダプタ 接続した状態にする
蓋(ディスプレイ) 開いたままにする
Power Nap sudo pmset -a powernap 1 で有効化
SMCリセット(Intel Mac) シャットダウン → 電源ボタン10秒長押し → 再起動
SMCリセットは、Intel Macでpmsetの挙動が不安定な場合に有効です。Apple T2チップ搭載モデルでは、シャットダウン後に電源ボタンを10秒長押しして離し、数秒待ってから再度電源を入れる手順となります。

caffeinateでスリープ戻りを防止する

pmsetで起動しても、操作がなければ数十秒でスリープに戻ってしまいます。caffeinateコマンドでスリープ防止の設定が必要です。

実際に今回の環境では、pmsetで6:00に起動した後、わずか77秒でスリープに戻る現象が発生しました。

2026-02-19 06:00:02 +0800 Wake  Wake from Deep Idle : due to EC.RTC/UserActivity Assertion  77 secs
2026-02-19 06:01:19 +0800 Sleep Entering Sleep state due to 'Idle Sleep'

cronの実行時刻が6:01だったため、スリープに入った直後で間に合いませんでした。

launchdでcaffeinateを自動起動する

caffeinateをpmsetと同じ時刻に自動起動させるため、launchdの設定ファイルを作成します。以下のコマンドをターミナルに貼り付けて実行してください。

cat > ~/Library/LaunchAgents/com.keepawake.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.keepawake</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/caffeinate</string>
        <string>-dims</string>
        <string>-t</string>
        <string>3600</string>
    </array>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>6</integer>
        <key>Minute</key>
        <integer>0</integer>
    </dict>
</dict>
</plist>
EOF

-dimsオプションの各文字が、それぞれ異なる種類のスリープを防止します。

オプション 効果
-d ディスプレイスリープを防止
-i システムのアイドルスリープを防止
-m ディスクスリープを防止
-s システムスリープを防止

-t 3600は3600秒(60分間)スリープを防止する指定です。作成したファイルを登録し、確認します。

launchctl load ~/Library/LaunchAgents/com.keepawake.plist
launchctl list | grep keepawake
最初に -u オプション単体で試したが効果がなく、-dims に変更して初めてスリープ防止が機能した。環境によって必要なオプションが異なる点に注意

caffeinateの -u が効かなくて半日悩んだ。結局 -dims の4つ全部指定したら動いたよ

cronの設定方法とフルディスクアクセス

Macが起きている状態を維持できれば、あとはcronで実行時刻を指定するだけです。ターミナルからcrontab -eで設定できます。

cronの設定手順

crontab -eを実行するとviエディタが開きます。操作手順は以下の通りです。

操作 キー
入力モードに切り替え i
入力モード終了 esc
保存して閉じる :wq + Enter
保存せず閉じる :q! + Enter

設定例は以下の通りです。毎日6:01にPythonスクリプトを実行します。

1 6 * * * cd /Users/[ユーザー名]/Documents/[プロジェクトフォルダ] && /Library/Frameworks/Python.framework/Versions/3.13/bin/python3 [スクリプト名].py >> /tmp/[ログファイル名].log 2>&1

cronの時刻指定は、スペースで区切られた5つの数値で表現します。

位置 意味
1番目 分(0〜59) 1 → 1分
2番目 時(0〜23) 6 → 6時
3番目 日(1〜31) * → 毎日
4番目 月(1〜12) * → 毎月
5番目 曜日(0〜7) * → 毎曜日

確認・変更・削除

# 現在の設定を確認
crontab -l
# 設定を編集
crontab -e
# 設定をすべて削除
crontab -r
crontab -r は登録内容をすべて削除します。特定の行だけ消したい場合は crontab -e で該当行を削除して保存してください。

フルディスクアクセスの付与(必須)

macOSのセキュリティにより、cronやPythonがファイルにアクセスできない場合があります。以下の2つをフルディスクアクセスに追加してください。

システム設定プライバシーとセキュリティフルディスクアクセス → + ボタン → Cmd + Shift + G でパスを入力して追加します。

追加するパス 対象
/usr/sbin/cron cronデーモン
Pythonの実行パス Python本体(which python3 で確認可能)
この設定を忘れると Operation not permitted エラーが出てスクリプトが実行されない。cronとPythonの両方を追加する点がポイント

最終構成と動作確認コマンド

pmset + caffeinate + cronを組み合わせた最終構成は以下の通りです。毎朝この流れで自動実行されます。

時刻 動作 使うツール
6:00 スリープから自動復帰 pmset
6:00 60分間スリープ防止 caffeinate(launchd経由)
6:01 Pythonスクリプト実行 cron

成功時のpmsetログは以下のようになります。caffeinateが起動し、スリープに戻らずcronが実行されていることを確認できます。

2026-02-21 06:00:01 +0800 Assertions PID 15949(caffeinate) Created UserIsActive "caffeinate command-line tool"
2026-02-21 06:00:02 +0800 Wake       Wake from Deep Idle : due to EC.RTC/UserActivity Assertion Using AC

cronのログにも正常終了が記録されていました。

2026-02-21 06:10:22,895 [INFO] ========== 全タスク完了 ==========

動作確認コマンド一覧

スリープ復帰・スリープ防止の履歴を確認するコマンドです。

pmset -g log | grep -E "Wake from|Entering Sleep|caffeinate" | tail -20

cronのログを確認するコマンドです。

cat /tmp/[ログファイル名].log

cronのエラーメールを確認するコマンドです。

cat /var/mail/[ユーザー名]

pmset起動 → caffeinate防止 → cron実行の3段構え。ここに到達するまでに何度もスリープに泣かされた…

pmsetが効かない場合の代替手段:launchd

pmsetでスリープ復帰ができないMacでは、launchdが代替手段になります。設定時刻にスリープ中だった場合、Macを開いた時点でスクリプトが自動実行される仕組みです。

launchdの動作イメージ

状況 実行タイミング
設定時刻より前にMacを開いた 設定時刻に実行される
設定時刻にスリープ中で、後から蓋を開けた 開けた時点で実行される

設定ファイルの作成と登録

以下のコマンドでplistファイルを作成します。HourMinuteの値を変更すれば実行時刻を調整できます。

cat > ~/Library/LaunchAgents/com.example.dailytask.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.example.dailytask</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Library/Frameworks/Python.framework/Versions/3.13/bin/python3</string>
        <string>/Users/[ユーザー名]/Documents/[プロジェクトフォルダ]/[スクリプト名].py</string>
    </array>
    <key>WorkingDirectory</key>
    <string>/Users/[ユーザー名]/Documents/[プロジェクトフォルダ]</string>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>7</integer>
        <key>Minute</key>
        <integer>0</integer>
    </dict>
    <key>StandardOutPath</key>
    <string>/tmp/[ログファイル名].log</string>
    <key>StandardErrorPath</key>
    <string>/tmp/[ログファイル名]_error.log</string>
</dict>
</plist>
EOF

作成したファイルの登録コマンドです。

launchctl load ~/Library/LaunchAgents/com.example.dailytask.plist

登録確認のコマンドです。

launchctl list | grep dailytask

手動テストで即時実行するコマンドです。

launchctl start com.example.dailytask

設定を解除するコマンドです。

launchctl unload ~/Library/LaunchAgents/com.example.dailytask.plist
launchdで使うPythonのパスは which python3 で確認してください。/usr/bin/python3 と普段使っているPythonが異なると、ライブラリが見つからず ModuleNotFoundError になります。

まとめ

  • Macのcronはスリープ中に動かないため、pmsetで事前にスリープ解除が必要
  • pmsetで起動してもすぐスリープに戻る問題は、caffeinateの-dimsオプションで防止する
  • pmsetが効かない場合はlaunchdを使えば、Macを開いた時点で自動実行される

まずは自分の環境で pmset -g log を実行し、スリープ解除が効いているかどうかを確認してみてください。そこから最適な方法を選ぶのが近道です。

よくある質問

Q
cronとlaunchdはどちらを使うべきですか?
A

pmsetでスリープ解除が確実に動く環境であれば、cronの方がシンプルで管理しやすいです。pmsetが効かない場合や、実行時刻に多少のずれが許容できる場合はlaunchdが確実な選択肢となります。

Q
蓋を閉じたままでもcronは実行されますか?
A

蓋を閉じるとMacはスリープに入るため、cronは実行されません。今回の検証では、蓋を開いた状態+電源アダプタ接続の組み合わせでpmsetの自動復帰が安定しました。

Q
caffeinate -u だけでは効かないのはなぜですか?
A

-u はユーザーアクティビティをシミュレートするだけで、システムスリープ自体を防止しません。実際のログでは -u 指定後もIdle Sleepに入っていました。-dims でディスプレイ・アイドル・ディスク・システムの4種類すべてを防止する必要があります。

Q
Operation not permittedエラーが出た場合は?
A

cronとPython本体の両方をフルディスクアクセスに追加する必要があります。システム設定 → プライバシーとセキュリティ → フルディスクアクセスから、/usr/sbin/cron と使用しているPythonのパスを追加してください。

Q
Apple Silicon(M1/M2)のMacでも同じ手順で動きますか?
A

cron・launchd・caffeinateの設定手順は同じです。ただしSMCリセットの手順がIntel Macと異なります。pmsetの挙動もチップによって異なる場合があるため、pmset -g log で実際の動作を確認することをおすすめします。

出典・参考リンク

コメント

タイトルとURLをコピーしました