「毎朝、この処理を勝手に動かしておいてほしいんです」。AIエージェントに仕事を渡し始めると、この要望が出てきます。
ところが、時刻で動かす仕組みをmacOSで選ぼうとすると、cronとlaunchdという2つの名前が並びます。どちらでも書けてしまうので、たいていは手近なほうで組みます。そして、動いていない日が来てから、はじめて違いに気づきます。
この記事は、その違いを3か所に絞って並べます。設定ファイルと登録手順、それに「書いたのに動いていない」を見つける数え方まで添えるので、読み終えたら自分の業務でどちらを選ぶかを決められます。
検証環境は claude-opus-5 / Claude Code v2.1.x / macOS 15(2026-08-03検証)です。挙動はApple公式ドキュメントと、この環境で実行したmanコマンドの出力の両方で確かめています。
こんなふうに調べていませんか
- 毎朝この処理を自動で動かしたいが、cronとlaunchdのどちらで書けばいいのか決められない
- 設定は書いた。それでも、思った時刻に動いていないことがある
- ノートPCの蓋を閉じているあいだ、予定していた処理がどうなるのかが分からない
この記事を読み終えたときに手に入るもの
- 発火の起点・眠りをまたいだふるまい・記録の残り方の3か所で、2つを見分けられるようになります
- 自分の業務でどちらを既定にするかを、3つの問いだけで決められるようになります
- 書いた設定が本当に載っているかを、その場で数え直せるようになります
結論30秒でわかる、この記事の結論
- cronとlaunchdの違いが出るのは、発火の起点・眠りをまたいだときのふるまい・記録の既定という3か所だけです。
- 眠っているあいだに予定が過ぎたとき、あとから追いつけるのは
StartCalendarIntervalだけです。 - 書いた設定の数と、いま載っている設定の数は別ものです。動いた証拠は、後者でしか取れません。
進行役は3人です。若葉さんが言葉の側から、高梨課長が自分の手で動かす側から聞き、鈴木さん(本誌監修)が答えます。
01cronとlaunchdの違いは、AIエージェントの定期実行で何に効くんですか?
若葉さんcronもlaunchdも「時間になったら動かす」ものですよね。どちらでもよさそうに見えてしまって。
鈴木さん目覚まし時計と、玄関に貼った予定表くらい違うと思っています。目覚ましは、鳴る瞬間に誰も聞いていなければそのまま流れます。予定表のほうは、出かけて帰ってきてからでも「今日これがあったな」と気づけます。
結論は3点です。
- cronは1分ごとに全
crontabを確認し、時刻が一致した行を実行します。launchdはStartInterval(秒の間隔)とStartCalendarInterval(暦の指定)という2つのキーで、発火条件そのものを分けています。 - 眠っているあいだに予定が過ぎたとき、あとから追いつけるのは
StartCalendarIntervalだけです。cronとStartIntervalは、その回を取りこぼします。 - 記録の残し方も既定が違います。cronは実行結果を既定でメール送信し、launchdは
StandardOutPath・StandardErrorPathで出力先のファイルを指定します。
言葉で並べると近く見えるので、表にして置き場所を分けます。
| 比較軸 | cron | launchd |
|---|---|---|
| 発火の起点 | 1分ごとの巡回チェック | イベント駆動の起動条件 |
| スリープ中の予定 | 取りこぼす | StartCalendarIntervalのみ復帰後にまとめて実行 |
| 電源オフ中の予定 | 取りこぼす | 取りこぼす(次の予定を待つ) |
| ログの既定 | 実行結果をオーナーへメール送信 | 既定では宛先を選べずStandardOutPath等で指定 |
| 設定の単位 | 共有のcrontabファイル1つに追記 | ジョブごとに個別のplistファイル |
この章のまとめ
違いは3か所にしか出ません。どこで差がつくかを先に知っておけば、選ぶのに時間はかかりません。
02生成AIの処理を時刻で動かしたいとき、cronやlaunchdではなくhooksでは何が足りないんですか?
先に、時計とは無関係な仕組みを外しておきます。AIエージェントの処理そのものを、Claude Codeのhooksで時刻起点に動かすことはできません。hooksはイベント駆動の仕組みで、時刻や間隔での発火には対応していないためです(出典: Claude Code公式ドキュメント)。どんなイベントがあるかはClaude Code hooksの一覧|30種類から選ぶ2つの軸で扱っています。
つまり、時刻で動かしたい処理はOS側へ渡すことになります。渡す先が、cronかlaunchdです。
左右で違うのは、待っているものです。片方は出来事を待ち、もう片方は時計を待ちます。優劣の話ではなく、待つ対象が違うので置き換えが効きません。
この章のまとめ
hooksは出来事を待つ仕組みです。時計を待つ仕事は、はじめからOS側へ渡します。
03AIエージェントにlaunchdで定期実行を任せる前に、決めておくことは何ですか?
若葉さん渡す先が決まったら、すぐ設定ファイルを書けばいいんですか。
鈴木さんその前に3つだけ決めておくと、あとで書き直さずに済みます。何を動かすか、誰の権限で動かすか、動いたことをどこで見るか。この順番です。
着手前に決めるのは、次の3つです。
- 何を定期実行させるか。コマンド1つで完結する処理を選びます。Claude Codeを
-p付きで呼ぶラッパースクリプトなどが典型です。 - どのユーザー権限で動かすか。ログイン中のユーザーとして動く
LaunchAgentsか、ログインの有無を問わないLaunchDaemonsかを選びます。 - 動いたことをどう確認するか。ログファイルの場所と
launchctl listのどちらを見るかを、着手前に決めます。
置き場所は、2つ目の選択にそのまま直結します。個人用のLaunchAgentsは~/Library/LaunchAgents/に置きます。システム全体で動くLaunchDaemonsは/Library/LaunchDaemons/に置きます(出典: Apple公式ドキュメント)。
つまり、権限を決めた時点でファイルの置き場も決まります。あとから権限だけ変えようとすると、置き場所ごと引っ越すことになります。
この章のまとめ
先に決めるのは設定の中身ではなく、誰の権限で動かすかです。そこが置き場所を連れてきます。
04cronは、AIエージェントをどんな仕組みで時刻どおりに起こすんですか?
cronは1分ごとにcrontabを巡回し、時刻が一致した行だけを実行します。この巡回そのものが、cronの正体です。
もっとも、macOSの基盤であるDarwinのマニュアルには、cronの機能はlaunchdに吸収されたと明記されています。cron自体もlaunchdによって起動される仕組みです(crontabのマニュアルをmanで確認)。cronを選んだつもりでも、下ではlaunchdが動いていることになります。
05crontabの5フィールドは、AIエージェントを動かす1行にどう書くんですか?
書式は5つの時刻フィールドとコマンドの組み合わせです。
| フィールド | 許容値 | 例 |
|---|---|---|
| 分 | 0〜59 | */5(5分おき) |
| 時 | 0〜23 | 9-18(9時から18時) |
| 日 | 1〜31 | *(毎日) |
| 月 | 1〜12 | *(毎月) |
| 曜日 | 0〜7(0と7は日曜) | 1-5(平日のみ) |
crontabコマンドの操作体系は、IEEE Std 1003.2(POSIX.2)に準拠しています(crontabのマニュアルをmanで確認)。書式が古びて見えても、根拠のある古さです。
*/5 * * * * /usr/bin/python3 /path/to/agent_watch.py >> /tmp/agent_watch.log 2>&15分おきにスクリプトを実行するcrontabの1行です。末尾の>> 2>&1に注目してください。標準出力と標準エラーを、自分でファイルへ流し込んでいます。cron側は何もしてくれません。
流れにすると、cronがやっていることの少なさが見えます。見て、合っていれば起こす。それだけです。取りこぼしの記録も、出力の保管も、cronの仕事には入っていません。
この章のまとめ
crontabの1行に書いてあるのは、いつ起こすかと何を起こすかだけです。残りは全部、書き手の受け持ちになります。
06launchdは、AIエージェントの発火条件をどう分けているんですか?
launchdはStartIntervalとStartCalendarIntervalという2つのキーで、発火条件を分けます。StartIntervalは秒単位の間隔、StartCalendarIntervalは分・時・日・曜日・月を指定する暦の間隔です。暦のほうは、指定しなかったキーがワイルドカード扱いになります(出典: Apple公式ドキュメント)。
たとえに置きかえると、選ぶ基準がはっきりします。片方は「置いてから何秒」で鳴るもの、もう片方は「何時何分」で鳴るものです。同じ「時間になったら」でも、数えている対象が違います。
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>9</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<key>StandardOutPath</key>
<string>/tmp/agent_watch.log</string>
<key>StandardErrorPath</key>
<string>/tmp/agent_watch.error.log</string>DayやMonthを書いていないので、この設定は毎日9時0分に起動します。書かなかった欄が「毎回」に化けるのが、暦指定の読み方です。なお、この構成は典型例であり、WEBMARKSの実ファイルそのものではありません。
この章のまとめ
launchdの2つのキーは、細かさの違いではありません。数えている対象が、秒の経過か暦の一致かという違いです。
07スリープをまたぐとき、cronとlaunchdの違いはAIエージェントのどこに出ますか?
高梨課長ノートPCで動かすつもりなんです。蓋を閉じているあいだに予定の時刻が来たら、どうなりますか。
鈴木さんそこが、この2つを分ける一番大きな場所です。何も起きずに消えるか、起きたときに1回だけ追いつくか。どちらになるかは、書いたキーで決まります。
高梨課長「何も起きずに消える」というのは、あとから分かりますか。
鈴木さん分かりません。消えたことは、どこにも書かれないんです。
3つの方式で、扱いが分かれます。
| 仕組み | 単位 | スリープ中に予定が来たら |
|---|---|---|
| cron | 分(crontabの5フィールド) | 巡回自体が止まり、実行されない |
StartInterval | 秒 | その回を取りこぼす |
StartCalendarInterval | 分・時・日・曜日・月 | 復帰後にまとめて1回実行する |
cronとStartIntervalは、次の発火予定が来た瞬間にシステムが眠っていると、その回を落とします。StartInterval側の取りこぼしはkqueueの制約によるものだと、launchd.plistのマニュアルに明記されています(manで確認)。
StartCalendarIntervalだけが違うふるまいをします。システムが復帰した直後に、ジョブを起動します(出典: Apple公式ドキュメント)。眠っているあいだに複数回分の予定が過ぎていても、まとめて1回だけ実行します(launchd.plistのマニュアルをmanで確認)。
時系列で追うと、分かれ目が1点しかないことが見えます。眠る前まで、3つの方式は同じ動きをします。差がつくのは目覚めた直後の一瞬だけで、そこを過ぎればまた同じ動きに戻ります。
なお、電源そのものが落ちていた場合は、どちらも取りこぼします。launchdは次の予定を待つだけです。「まとめて1回」が効くのは、眠っていた場合に限られます。
この章のまとめ
分かれ目は、目覚めた直後の一瞬だけです。そこで何も起きない設計を選ぶなら、取りこぼしても困らない処理に限ります。
08AI活用の記録として、cronとlaunchdのログの違いは何を残しますか?
cronは実行結果を既定でメール送信します。宛先はcrontab内のMAILTO変数で指定でき、MAILTO=""と書けば送信自体を止められます(crontabのマニュアルをmanで確認)。
ファイルへ残したいなら、コマンド側で>>と2>&1を使って自分でリダイレクトします。前に出したcrontabの例も、この方式でメールではなくファイルへ書き出していました。
launchdには、メール送信の仕組みがそもそもありません。ファイルへ残すには、前の章のplistのようにパスを明示します。使うキーはStandardOutPathとStandardErrorPathの2つです(launchd.plistのマニュアルをmanで確認)。
並べると、どちらも「放っておくと読まない場所へ行く」という点では同じです。片方は郵便受けへ、もう片方はどこにも残りません。読む場所へ持ってくる作業は、結局どちらでも書き手がやることになります。
09AIエージェントの定期実行を、launchdジョブとして登録する手順はどうなりますか?
plistを書いたら、構文チェック・登録・確認の3ステップで進めます。入力はplistファイルのパス、確認方法は各コマンドの出力です。
# 1) 構文が壊れていないかを見る(入力: plistのパス/確認: 何も言われないこと)
plutil -lint ~/Library/LaunchAgents/com.example.agent-watch.plist
# 2) いまログインしている自分のGUIドメインへ載せる
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.example.agent-watch.plist
# 3) 載ったかどうかを名前で引く
launchctl list | grep agent-watch3つ目のコマンドの出力は、PID・直前の終了コード・ラベルの3列です(launchctlのマニュアルをmanで確認)。
- 0 com.example.agent-watchPID列の-は待機中を意味し、実行中なら数値が入ります。終了コードが負の数なら、その絶対値がジョブを止めたシグナル番号です。たとえば-15はSIGTERMを指します。
plistを書き換えたあとは、launchctl bootoutで一度取り外してからbootstrapをやり直します。登録したままの上書きは、基本の手順には含まれていません。図に戻り矢印を描いているのは、この一手を飛ばしやすいからです。
この章のまとめ
登録は3ステップですが、書き換えたときだけ手順がひとつ戻ります。ここを飛ばすと、古い設定のまま動き続けます。
10AIエージェントが思った時刻に動かないとき、cronとlaunchdのどこを疑うんですか?
高梨課長書いたとおりに動いていない気がします。まず何から見ればいいですか。
鈴木さん出やすいつまずきが3つあります。どれも画面には何も出ないので、症状から逆に引くのが早いです。
落とし穴1:crontabの5フィールドの順序を書き間違える。 分と時を逆に書くと、意図した時刻とはずれた時刻に実行されます。cronは黙って指定どおりに動くため、ログを見るまで気づけません。
落とし穴2:StartIntervalとStartCalendarIntervalを両方書き、両方そろったときだけ発火すると思い込む。 実際は独立に評価されるので、想定より多い回数で発火します。処理の実行回数が想定を超えていることで発覚します。
落とし穴3:スリープしないデスクトップ機だけで検証し、ノートPCへそのまま展開する。 「まとめて1回」というふるまいは、スリープする環境でしか再現しません。ノートPC側で実行回数が想定より少ないことから発覚します。
3つを並べると、発覚のしかたが逆を向いていることが分かります。落とし穴2は多すぎることで、落とし穴3は少なすぎることで表に出ます。落とし穴1だけは回数が変わらないので、いちばん長く気づかれません。
この章のまとめ
つまずきは、実行回数の増減として表に出ます。時刻がずれるだけのものは回数が変わらないので、最後まで残ります。
11書いたlaunchdジョブが本当に載っているかは、AIエージェントの運用でどう数えるんですか?
症状から引けないときは、目で追うのをやめて数えます。WEBMARKSはlaunchctl listで毎回実測しており、2026-07-28時点で定義済みのlaunchdジョブ8本のうち、ロードされていたのは1本でした。
替えたのは精度ではなく、数える対象です。書いた数は自分の記憶で答えられますが、載っている数はコマンドに聞かないと出てきません。差が出た本数が、そのまま「書いたのに効いていない」ぶんになります。
数え終えたら、次の項目で動作を確かめます。
launchctl list | grep <ラベル>でラベルが表示される- PID列が、実行中は数値・待機中は
-になっている - 終了コード列が0になっている(異常時は別の数値か負の数)
StandardOutPathに指定したファイルが実際に生成されている- 意図した時刻に、そのファイルの更新時刻が変わっている
- スリープを挟む端末なら、復帰後に
StartCalendarIntervalのジョブが動いたことを確認した
12結局うちのAI導入では、定期実行をcronとlaunchdのどちらで組むんですか?
選び方は、3つの問いに集約されます。
- スリープや電源オフをまたいで、取りこぼした分をあとから実行してほしいか。必要ならlaunchdの
StartCalendarIntervalが候補になります。 - 1分単位の粗さで足りるか。足りなければ、秒単位を指定できるlaunchdの
StartIntervalを使います。 - 複数のスクリプトを1つのファイルでまとめて管理したいか。それなら共有の
crontabのほうが手早く書けます。
区画に置いてみると、迷いどころが1か所に寄ることが分かります。取りこぼしても困らず、粗さでも足りる区画に入る処理は、どちらで組んでも実務上は変わりません。ここに入るものを先に外してしまえば、残りは自動的に決まります。
AIエージェントの定期実行は、無人で動く時間が長いほど、取りこぼしに気づきにくくなります。取りこぼしが業務に影響するかどうかで、既定の選択は変わります。影響するならlaunchdのStartCalendarIntervalを軸にし、影響しないならcrontabの手軽さを優先しても差し支えありません。
自動化を層に分けたときの全体設計は、AIエージェントの自動化は4層|着手する順番と稼働の数え方にまとめています。この記事は、そのうち定期実行の層だけを2択に絞って掘り下げたものです。
この章のまとめ
先に決めるのは「どちらを使うか」ではありません。取りこぼしが業務に響くかどうかです。そこが決まれば、道具は自動的に決まります。
13よくある質問
cronとlaunchdは同時に使ってもいいですか
使えます。ただし、同じ処理を両方に登録すると二重に実行されます。移行の途中では、片方を無効にしてから進めてください。両方に書いたまま様子を見る、という進め方が、いちばん原因を追いにくい状態を作ります。どちらを正とするかを先に決めておくと、あとの調査がかなり楽になります。
launchdのジョブがスリープ中に何度も予定を過ぎたら、何回実行されますか
StartCalendarIntervalは、複数回分をまとめて1回だけ実行します。溜まった回数ぶん連続で実行されるわけではありません(launchd.plistのマニュアルをmanで確認)。処理の中身が「前回からの差分をすべて処理する」形になっていれば、この挙動でつじつまが合います。1回ぶんしか処理しない作りだと、抜けが残ります。
crontabは直接ファイルを編集してもいいですか
crontab -e経由での編集を使ってください。ファイルを直接書き換えると、更新の検知が働かず反映されないことがあります。反映されていないことは画面に出ないので、書いたのに動かない状態の入口になりやすい操作です。編集の入口をコマンドに固定しておくと、この種の取り違えが起きにくくなります。
AIエージェントの常駐処理もcronやlaunchdで動かせますか
起動はできますが、役割が違います。常駐は起動後に生き続ける前提の設計です。一方、cronとlaunchdが担うのは、時刻で起動して終わったら閉じる定期実行です。常駐させたい処理を定期実行の枠で動かすと、同じプロセスが重なって増えていくことがあります。どちらの前提で書かれた処理かを、先に確かめてください。
Appleは今後cronを廃止しますか
明言はありませんが、Apple公式ドキュメントは非推奨だと明記しています(出典: Apple公式ドキュメント)。新規に組む定期実行は、特別な理由がなければlaunchdを基準にするのが無難です。すでにcronで動いているものを急いで書き換える必要はありませんが、新しく足すぶんから寄せていくと、置き場所が散らからずに済みます。
14まとめ|今日やる3つのこと
違いが出るのは3か所だけでした。分かれ目は、眠りから目覚めた直後の一瞬にあります。そして、書いた設定は載っているかどうかを数えるまで、動いていないものとして扱います。
今日はこの順で手をつけます
自動で動かしたい処理を1つ選び、取りこぼしたら困るかどうかを書き添える
ここが決まらないと、道具は選べません
選んだ処理を
StartCalendarIntervalのplistで書き、plutil -lintまで通す構文の崩れは、載せる前なら短時間で分かります
launchctl listで載っている数を数え、書いた数と突き合わせる差が出たぶんが、書いたのに効いていないものです
AI検索では、こう聞かれています
cronとlaunchdの違いって、結局どこに出るんですか?
「cronとlaunchdの違いは、AIエージェントの定期実行で何に効くんですか?」の章で3か所に絞っています
ノートPCが眠っている間、予定していた定期実行はどうなるんですか?
「スリープをまたぐとき、cronとlaunchdの違いはAIエージェントのどこに出ますか?」の章で扱っています
書いたlaunchdジョブが本当に動いているかは、どこで確かめるんですか?
「書いたlaunchdジョブが本当に載っているかは、AIエージェントの運用でどう数えるんですか?」の章に数え方があります
AIエージェントの定期実行は、cronとlaunchdのどちらで組めばいいんですか?
「結局うちのAI導入では、定期実行をcronとlaunchdのどちらで組むんですか?」の章で3つの問いに整理しています
次に読むなら、この記事です