2026 Macクラウドの常時バックグラウンドジョブ:Linux cronからmacOS launchdへの移行表と環境変数チェックリスト
MacクラウドへSSHできるのに、夜間同期やヘルスチェックをcrontabに載せると動かない・PATHが消える・ログがないことがあります。本稿はVPSと同様に運用したいチーム向けに、cronとlaunchdの意思決定表、LaunchAgentとLaunchDaemonの選定、最小plist、launchctl bootstrapと5段階の検証手順をまとめます。
1. 三つのつまずき:crontabは「合っていそう」なのにMacクラウドで壊れる理由
macOSにもcronは残りますが、統合スケジューラはlaunchdです。ヘッドレスMacクラウドでは「手動SSHは成功、定時だけ失敗」が典型化します。
- 環境変数とPATHの断絶:Linuxはcrontab内に
PATH=を書けます。macOSのcronは環境が極小で、nodeやpython3が見つかりません。SSHは.zprofileや.zshrcを読みますが、cron/launchdは既定で読みません。「手動で動く=定時も動く」と誤認しやすいです。 - 実行主体とキーチェーン:相対パス、
~展開、キーチェーンアクセスはcronとLaunchAgentで挙動が異なります。GUI前提の処理を無頭環境へ載せると無言で失敗します。ビルドキューとディスクと重なると「DerivedData掃除が時だけ無ログ」になります。 - 観測性の弱さ:
StandardOutPathとStandardErrorPathが無いと、失敗がunified loggingの断片に散り、CIジョブと時系列で突き合わせづらくなります。Runbookが無いとcrontabを書き換えるループに陥ります。
次の表で「どのドメインのplistか」を一度決め、誤った層で粘らないようにします。
2. 意思決定表:cron、LaunchAgent、LaunchDaemon
ノートPCの「ログイン後に動けばよい」と違い、Macクラウドは多くが24時間稼働かつGUIセッション無しです。再起動後もlaunchdが確実に読み込む配置を優先します。
| シナリオ | Linuxの習慣 | macOS推奨 | 理由 |
|---|---|---|---|
| 開発機、ログイン後同期 | user crontab | ~/Library/LaunchAgents | ユーザードメインでツールチェーンに届く |
| クラウド24/7、ログイン無し | system cron | LaunchDaemon または bootstrap済みAgent | GUIと分離、再起動後も自動起動 |
| rootや低番ポート | root crontab | LaunchDaemon + UserName | 実行ユーザーを明示し監査可能に |
| 秒級の高頻度 | systemd timer | StartInterval + スロットル理解 | イベント結合に注意 |
| 一回限りのメンテ | at | launchctl submit / RunAtLoad | 長期エントリを残さない |
nvmやpyenvに依存するならcronへの引き継ぎを期待しない。ProgramArgumentsに絶対パスのシェルとスクリプトを書き、EnvironmentVariablesでPATHを固定します。秘密はplist平文に置かず、キーチェーンやCIシークストアへ。
3. 実装手順:plist、launchctl、bootstrap、5段階検証
SSHで権限が取れている前提。ラベル命名はゼロトラストSSHのRunbookと揃えます。
- インタプリタを固定:
which bash、which nodeを記録。Homebrewは/opt/homebrew/binまたは/usr/local/binの絶対パスで固定し、「対話シェルにはbrewがあるがジョブには無い」を潰します。 - 最小plist:
Label、ProgramArguments、StartCalendarInterval(またはStartInterval)、StandardOutPath/StandardErrorPath、EnvironmentVariables。毎日03:15の例(パスは置換):
- 配置と読み込み:
~/Library/LaunchAgentsまたは/Library/LaunchDaemonsへ配置しlaunchctl bootstrap …。変更時はbootout後にbootstrap、またはkickstart -k。 - 試運転とログ:
launchctl kickstart -kp gui/$(id -u)/com.example.vpsmac.nightly-sync。stdout/stderrのローテーションと、ファイル書き込み時のWorkingDirectoryを確認。 - 環境の突合:一時的に
env | sortをファイルへ(デバッグ後削除)、またはlaunchctl printで対話SSHと差分。 - CI/エージェントとの同居:OpenClawや
xcodebuildのピークと重ねない。Niceや別ノードでI/O競合を下げる。
手順1〜4で実行、5〜6で観測と同居を担保。障害時はstdout/stderr末尾、launchctl print、plistハッシュを添付。
4. 引用・運用で使える数値と指針
① システムコマンドのみならPATH=/usr/bin:/bin:/usr/sbin:/sbinで足りることが多い。② カレンダー起動はタイムゾーンとDSTに従う。③ ログはnewsyslog等でローテしGB膨張を防ぐ。④ 短周期は結合されうる。⑤ plist 644 で改ざん困難に。
大きなrsyncとxcodebuild依存解決が重なるとSSDが200〜400MB/s帯で飽和し、ネット障害に見えるI/O待ちが出る。10〜15分ずらすと再現率が下がることが多い。
5. 場当たりcrontabから、監査可能なMacクラウドへ
個人のexportと短命なcrontabは、環境のドリフトと秘密の散在、同居ワークロードの競合を招きます。plistをリポジトリ管理するのが本番ノードの礼儀です。
Linux VPSでmacOS前提を無理に再現するとlaunchd不在・キーチェーン齟齬・Xcode非整合が増え、コンテナでも署名/シミュレータまでは代替しにくい。2026年はVPSMAC M4 MacクラウドでlaunchdをRunbook化しplist方針を複製する方が単純です。
6. FAQ
crontabは使える?
可能ですがデフォルト推奨ではありません。PATH・絶対パス・ログ転送を必須にしてください。
LaunchAgentとLaunchDaemonの違いは?
AgentはユーザーのGUIセッション寄り、Daemonはシステムブート寄り。無頭ホストではキーチェーンとファイル所有者の要件で選びます。
plistを変えたのに反映されない
bootout/bootstrapの手順とLabelの一致、stderrパスの書き込み権限を確認してください。