- Macのcronが動かない原因はスリープにある。実行時刻に寝ていればスキップされる
- pmsetでスリープ復帰を自動化し、cronの実行タイミングに間に合わせる
- 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が起動すらしていないと判断できます。
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秒長押し → 再起動 |
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

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
フルディスクアクセスの付与(必須)
macOSのセキュリティにより、cronやPythonがファイルにアクセスできない場合があります。以下の2つをフルディスクアクセスに追加してください。
システム設定 → プライバシーとセキュリティ → フルディスクアクセス → + ボタン → Cmd + Shift + G でパスを入力して追加します。
| 追加するパス | 対象 |
|---|---|
/usr/sbin/cron |
cronデーモン |
| Pythonの実行パス | Python本体(which python3 で確認可能) |
最終構成と動作確認コマンド
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ファイルを作成します。HourとMinuteの値を変更すれば実行時刻を調整できます。
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
まとめ
- Macのcronはスリープ中に動かないため、pmsetで事前にスリープ解除が必要
- pmsetで起動してもすぐスリープに戻る問題は、caffeinateの-dimsオプションで防止する
- pmsetが効かない場合はlaunchdを使えば、Macを開いた時点で自動実行される
まずは自分の環境で pmset -g log を実行し、スリープ解除が効いているかどうかを確認してみてください。そこから最適な方法を選ぶのが近道です。
よくある質問
-
Qcronとlaunchdはどちらを使うべきですか?
-
A
pmsetでスリープ解除が確実に動く環境であれば、cronの方がシンプルで管理しやすいです。pmsetが効かない場合や、実行時刻に多少のずれが許容できる場合はlaunchdが確実な選択肢となります。
-
Q蓋を閉じたままでもcronは実行されますか?
-
A
蓋を閉じるとMacはスリープに入るため、cronは実行されません。今回の検証では、蓋を開いた状態+電源アダプタ接続の組み合わせでpmsetの自動復帰が安定しました。
-
Qcaffeinate -u だけでは効かないのはなぜですか?
-
A
-uはユーザーアクティビティをシミュレートするだけで、システムスリープ自体を防止しません。実際のログでは-u指定後もIdle Sleepに入っていました。-dimsでディスプレイ・アイドル・ディスク・システムの4種類すべてを防止する必要があります。
-
QOperation not permittedエラーが出た場合は?
-
A
cronとPython本体の両方をフルディスクアクセスに追加する必要があります。システム設定 → プライバシーとセキュリティ → フルディスクアクセスから、
/usr/sbin/cronと使用しているPythonのパスを追加してください。
-
QApple Silicon(M1/M2)のMacでも同じ手順で動きますか?
-
A
cron・launchd・caffeinateの設定手順は同じです。ただしSMCリセットの手順がIntel Macと異なります。pmsetの挙動もチップによって異なる場合があるため、
pmset -g logで実際の動作を確認することをおすすめします。



コメント