ガイド

Macのlaunchdで定期実行する方法

結論、Macで処理を定期実行するなら標準機能のlaunchdが定石です。plistに実行コマンドと時刻を書き、launchctlで読み込めばバックグラウンドで回せます。

launchdとは何か

launchdはmacOSの起動・常駐・定期実行を束ねる仕組みです。システム全体用のLaunchDaemonsと、ユーザ単位のLaunchAgentsがあり、個人の自動化では多くの場合 ~/Library/LaunchAgents/ に設定ファイル(plist)を置きます。詳しいコマンド操作はApple公式のlaunchd解説(ターミナルガイド)で確認できます。

Linuxなどで馴染みのあるcronと比べると、次の点が実務上効いてきます。

観点launchdcron(macOS)
OS上の位置づけ標準のジョブ管理互換のため残っている側面が強い
設定の持ち方XML形式のplistcrontabの1行記述
ログや環境標準出力先や作業ディレクトリを明示しやすいシェル環境に依存しやすい
向く用途ログイン後の定期処理・常駐単純な分刻みの実行(ただし推奨はlaunchd)

「とにかく毎日このスクリプトを動かしたい」という用途なら、まずlaunchdのカレンダー指定を覚えると十分なケースが多いです。

最小構成の作り方

手順は次の4ステップです。

  1. 実行したいコマンド(シェルスクリプトやCLI)を用意する
  2. plistを書いて ~/Library/LaunchAgents/ に置く
  3. launchctl bootstrap(または環境に応じたload相当の操作)で登録する
  4. ログと launchctl print で動いたかを確認する

サンプルplist

毎日12:05に、ホーム配下のスクリプトを実行する例です。Labelは逆DNS形式が慣例で、ファイル名もLabelと揃えると管理しやすいです。

<?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.daily-job</string>

  <key>ProgramArguments</key>
  <array>
    <string>/bin/bash</string>
    <string>/Users/あなたのユーザ名/scripts/daily-job.sh</string>
  </array>

  <key>StartCalendarInterval</key>
  <dict>
    <key>Hour</key>
    <integer>12</integer>
    <key>Minute</key>
    <integer>5</integer>
  </dict>

  <key>StandardOutPath</key>
  <string>/Users/あなたのユーザ名/logs/daily-job.out.log</string>
  <key>StandardErrorPath</key>
  <string>/Users/あなたのユーザ名/logs/daily-job.err.log</string>

  <key>RunAtLoad</key>
  <false/>
</dict>
</plist>

ポイントは次のとおりです。

  • パスは絶対パスにする: launchdから起動される環境は対話シェルとPATHが違う。pythonnodeの短縮名だけに頼ると見つからないことがある
  • 標準出力・標準エラーをファイルに逃がす: 動かないときの第一の手がかりになる
  • StartCalendarInterval: 毎日・毎週など「何時何分」向き。数分おきならStartInterval(秒)を使う

登録と確認

plistを置いたあと、ユーザ用ドメインへ読み込みます(macOSの版によってコマンド表記は前後します。手元のman launchctlも合わせて確認してください)。

# 登録例(ユーザAgents)
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.example.daily-job.plist

# 状態確認
launchctl print gui/$(id -u)/com.example.daily-job

# 手動で一度走らせる
launchctl kickstart -k gui/$(id -u)/com.example.daily-job

設定を直したあとは、一度無効化してから読み直すと古い定義が残りにくいです。削除するときはbootoutで外してからplistを片付けます。

よく使うスケジュール指定

  • 毎日決まった時刻: StartCalendarIntervalHourMinute
  • 平日だけ: 同じキーに Weekday(0=日曜〜6=土曜)を足す
  • N秒ごと: StartInterval に秒数(例: 3600で約1時間ごと)
  • ロード直後にも一度動かす: RunAtLoad を true にする(テスト時に便利)

複数時刻に動かしたい場合は、StartCalendarInterval を配列にしてdictを並べる書き方があります。複雑になったらスクリプト側で「今日やるべきか」を判定する設計の方が読みやすいことも多いです。

つまずきやすいポイント

  • Macがスリープしていると時刻どおりに走らない: ノートを閉じたまま外出していると、昼のジョブが欠ける。Apple公式ドキュメントによれば、スリープ中に複数回分の予定が過ぎても起床時に1回にまとめて実行される(電源が落ちていた場合は補われない)。投稿や締切付き処理では事故りやすい
  • 相対パス・PATH依存でコマンドが見つからない: スクリプト先頭で使うコマンドはフルパスにするか、スクリプト内でPATHを明示する
  • 権限・プライバシー設定: フルディスクアクセスや自動化の許可が必要な操作は、GUIから一度許可しないと裏で失敗し続ける
  • ログイン前にはAgentsが動かない: 電源は入っていてもユーザ未ログインだとLaunchAgentsは期待どおり動かないことがある。電源投入直後から動かしたい処理は設計を分ける
  • 二重起動: 前の実行が終わらないうちに次が来ると競合する。ロックファイルや「既に動いていたら終了」のガードをスクリプト側に入れる

向いていない人

  • Macを頻繁にスリープ・シャットダウンする人: 時刻厳守の処理は欠勤しやすい。常時起動のマシンやクラウド側へ寄せた方が楽
  • GUI操作そのものを自動化したい人: クリックやキー入力前提の処理は権限と画面状態に弱く、launchd単体では安定させにくい
  • 複数台・チームで同じジョブを共有したい人: 個人Mac上のplistは共有と監査がしづらい。サーバやワークフローツールに寄せた方が運用が単純になる
  • シェルやパスの扱いにまだ慣れていない人: 設定ミスの切り分けに時間がかかりやすい。まずは手動実行できるスクリプトを完成させてからplistに載せる方が安全

ローカル定期実行の限界とクラウド移行

launchdは「自分のMacが起きているあいだの自動化」には十分です。一方で、次のような条件が重なるとローカル定期実行の摩擦が大きくなります。

  • 外出中・スリープ中でも止められない
  • スマホから実行状況を見たい
  • 同じ処理を別マシンでも再現したい
  • API連携や分岐が多いワークフローになってきた

この段階では、Mac上のlaunchdに処理を増やし続けるより、常時稼働できる環境へ寄せる選択が現実的です。セルフホストでワークフローを組むならn8nのセルフホスト手順が次の受け皿になります。n8n公式の料金ページによれば、セルフホスト(Community版)は無料のオープンソースソフトウェアで、クラウド版は有料プランのみです(2026年7月時点)。Macが寝ていると困るジョブだけ先に移し、ローカルに残すものと切り分けると移行コストを抑えやすいです。

開発作業の定型化(手順の登録や操作前後のフック)は、定期実行とは別レイヤの話です。Claude Code側で繰り返す作業を仕組み化したい場合は、SkillsとHooksの作り方も参照してください。

AIエージェント(Claude Codeなど)自体を定期実行の対象にしたい場合は、launchdの設定手順に加えて非対話実行特有の注意が必要です。承認プロンプトが効かない・認証情報の受け渡し・暴走防止といった論点はAIエージェントを定期実行する仕組みと設定手順にまとめています。

FAQ

Q. launchdとcronはどちらを使えばいいですか? A. macOSではlaunchdが標準の定期実行手段です。cronも動く場合がありますが、スリープ復帰後の扱いなどOS側の仕様はlaunchd前提で設計されています。新規に組むならlaunchdから検討するのが無難です。

Q. Macがスリープ中でもスケジュールどおり動きますか? A. スリープ中は実行されないことがあります。起床後にまとめて動くこともありますが、時刻厳守が必要な処理には向きません。確実に動かしたい場合はスリープ設定の見直し、caffeinate、または常時稼働のサーバへ移す選択があります。

Q. 設定したジョブが動かないときはどこを見ますか? A. まずplistのXMLが壊れていないか、Labelとファイル名の対応、ProgramArgumentsのパスが絶対パスかを確認します。次にlaunchctl printで登録状態を確認し、StandardOutPath/StandardErrorPathにログを出してエラー内容を追うと原因が切り分けやすいです。

Q. GUIアプリやログインが必要な処理も定期実行できますか? A. LaunchAgentsはユーザログイン後に動く想定です。画面操作やキーチェーン依存の処理は環境変数や権限の影響を受けやすく、ヘッドレス用途には向かないことがあります。サーバ側やAPIベースの処理に切り替える方が安定しやすいです。

まとめ

launchdは、Mac標準で定期実行を組むための仕組みです。やることは「動くスクリプトを用意する → plistに時刻と絶対パスを書く → launchctlで登録 → ログで確認する」の繰り返しにすぎません。まずは失敗しても差し支えない1本のジョブで、登録・手動起動・ログ確認まで通すと、あとの拡張が楽になります。

Macの電源状態に処理を縛られたくなったら、ローカル定期実行に固執せず、n8nセルフホストなど常時稼働できる側へ段階的に移す判断もセットで持っておくと安全です。