最終更新: 2026-04-28
先に結論を出す。MacBook を外部ディスプレイなしで蓋を閉じたまま Python を走らせ続けるのは、今の macOS では素直にできない。
pmset でスリープを 0 にしても止まった。caffeinate をかけても同じだった。3 回は同じ壁に頭をぶつけた気がする。原因が SMC レベルのハードウェアイベントだとわかったのは、ログを掘り始めてからだった。
それでも試した 3 つのアプローチを書く。動いたもの、動かなかったもの、両方ある。
蓋を閉じると Python が死ぬ理由
最初にやったのは pmset -g で現状を確認すること。出力の中に displaysleep 60 があった——1 分でスリープ、の意味。知らなかった。
$ pmset -g
System-wide power settings:
SleepDisabled 0
displaysleep 60
sleep 1
disksleep 10
hibernatemode 3
sleep 0 に変えて確認。ちゃんと 0 になっている。これで行けると思って蓋を閉じたら、30 秒後に SSH セッションが切れた。
sudo pmset -a sleep 0
sudo pmset -a displaysleep 0
pmset -g assertions でアクティブなアサーションを確認したところ、蓋を閉じた直後に LidClose が呼ばれていた。これは pmset の sleep 設定を無視して動く。macOS は蓋の開閉を SMC レベルの LidClose イベントとして処理していて、pmset パラメータより先に走る仕組みになっている。Apple の IOKit Power Management ドキュメントにもこの挙動の記載がある。
「設定値が間違っているのかと思って何度か変えて試したが、そもそもそういう仕組みだった」という話。
pmset を全部並べてみた結果
関係しそうなパラメータを全部叩いた。
sudo pmset -a sleep 0 \
displaysleep 0 \
disksleep 0 \
hibernatemode 0 \
powernap 0 \
standby 0 \
womp 0
hibernatemode 0 がメモリをディスクに退避しない設定、sleep 0 がシステムスリープの無効化。M5 MacBook Pro(macOS Sequoia 15.4)で試したが、蓋を閉じて 20 秒後に SSH が切れた。MacBook Pro M3(macOS Sonoma 14.4)では 30 秒ほど生きていたが、結局スリープした。機種と OS バージョンで挙動がズレる——同じコマンドで再現しないのが一番厄介だった。
何が起きているかはログで追える。
pmset -g log | grep -i "Sleep\|Wake\|LidClose" | tail -30
蓋を閉じた直後のタイムスタンプ付近に LidClose のエントリが並ぶ。これを見たとき、「設定変更で解決しようとするのが間違いだった」とわかった。ハードウェアイベントをソフトウェア設定で上書きする手段は、少なくとも通常の pmset の範囲にはない——という結論。
実際に動いた 3 つのアプローチ
caffeinate + プロセスラップ。これが一番シンプルだった。
caffeinate -si python3 your_script.py
-s がシステムスリープ防止、-i がアイドルスリープ防止。caffeinate にコマンドを直接渡すと、そのプロセスが終了した時点で caffeinate も自動で死ぬ。私は launchd の ProgramArguments にそのまま入れて使っている。
<key>ProgramArguments</key>
<array>
<string>/usr/bin/caffeinate</string>
<string>-si</string>
<string>/usr/bin/python3</string>
<string>/path/to/your_script.py</string>
</array>
ただし蓋を閉じた状態での動作保証はない。ユーザー離席・画面消灯によるスリープは防げるが、物理的に蓋を閉じると LidClose には勝てない。用途を絞ればこれで十分な場面も多い。
クラムシェルモードは、外部ディスプレイを繋いだ状態で蓋を閉じる方法。macOS は LidClose のスリープを発火させない。この状態で Ollama の qwen2.5:3b を使った夜間バッチを 8 時間連続稼働させたが、スリープによる停止はゼロだった。外部モニターが手元にあるなら、これが一番確実な方法。問題は「外部ディスプレイを常に繋ぐ前提」になること——持ち歩く機会が多いと制約になる。
結局、重い処理は VPS に逃がした。月 ¥500 の ConoHa VPS に Python 3.12 環境を置いて SSH で叩く。Ollama の量産バッチも夜間スクレイピングもそっちで動かしている。MacBook は操作端末に徹する——この割り切りが、バッテリー管理も蓋問題も一気に消してくれた。デバッグに溶かした数時間を返せという気持ちは少しある。
MacBook 単体で蓋を閉じたまま動かし続けるのは、現状の macOS 設計上難しい。LidClose は SMC レベルのイベントで pmset より先に来る。外部ディスプレイがあればクラムシェルモードが最も確実。なければ VPS に逃がす方が早い。