- systemd タイマーは
cron の実務的な代替であり、スケジュールに応じて .service のようなユニットを実行し、履歴・出力・環境管理をより明確にしてくれる
- 伝統的な
cron は、あいまいな $PATH、失われやすい stdout/stderr、追跡しづらい実行履歴、読みにくいスケジュール構文が弱点
- タイマーは同じステムの
.timer と .service を結び付け、OnCalendar、OnBootSec、OnUnitActiveSec で時刻・イベント基準の実行を表現する
systemd-analyze calendar と systemctl list-timers で時間表現と次回実行時刻を確認でき、WakeSystem= はスリープ状態からでも実行のために復帰させられる
RandomizedOffsetSec と FixedRandomDelay= は同時実行のピークを減らし、Persistent= は非アクティブ中に取り逃した実行をオンライン直後に補完する
systemd タイマーを cron の代替として使う理由
cron job は実際の cron デーモンでなくても、「毎日これを実行」「毎月あれを実行」のように、スケジュールに従って処理を実行するコンピューティングの基本要素を指す言葉として広く使われている
- systemd timer は特定のスケジュールに従って別のユニット、通常は
.service を実行する systemd ユニットであり、伝統的な cron デーモンの機能的な代替になりうる
- 伝統的な
cron にはいくつか実務上の弱点がある
- あいまいな
$PATH 設定 のため、スクリプト実行結果の予測が難しい
stdout と stderr の出力がブラックホールに消えたり、ホストのメールシステムに送られたりしがち
- 実行履歴を追跡・問い合わせしづらい
01,31 04,05 1-15 1,6 * のようなスケジュール構文は人間にとって読みやすくも直感的でもない
- systemd タイマーはこうした問題を減らしつつ、
cron スタイルの表現に近いカレンダー設定も提供する
基本構造: サービスとタイマー
- systemd タイマーには実行対象が必要で、
.service ユニットは論理的にはスクリプトのように見なせる
- 例として
/etc/systemd/system/roulette.service に次のユニットを置くと、10分の1の確率でコンピューターをシャットダウンするサービスをインストールできる
[Unit]
Description=1 in 10 chance to break your chains
[Service]
ExecStart=/usr/bin/env bash -c '[[ $(($RANDOM % 10)) == 0 ]] && systemctl poweroff || echo LIVE ANOTHER DAY'
ExecCondition= は条件付き実行を systemd サービスオプションとして表現する、より統合された方法であり、「実行を続けるべきか?」をユニットレベルでより明確に示す
[Unit]
Description=1 in 10 chance to break your chains
[Service]
ExecCondition=/run/current-system/sw/bin/bash -c '[[ $(($RANDOM % 10)) == 0 ]]'
ExecStart=/run/current-system/sw/bin/systemctl poweroff
- 条件が満たされない場合、ジャーナルにはより明確な文言が残る
May 05 11:05:32 diesel systemd[3117]: Condition check resulted in 1 in 10 chance to break your chains being skipped.
- 一般に、systemd が提供するオプションを活用したほうが、直接スクリプトを書くより良い体験になる
OnFailure= はサービススクリプトの失敗に反応したいときに使える
Restart= は一時的な失敗からの復旧を試みたいときに使える
タイマーユニットの接続と実行
- 同じファイルステムを持つ
/etc/systemd/system/roulette.timer を置けば、roulette.service とタイマーを接続できる
[Unit]
Description=impending destruction
[Timer]
OnCalendar=10:00
[Install]
WantedBy=timers.target
- デフォルトでは、タイマーの
Unit= 設定 は同じステムに .service が付いたサービスユニットを選ぶ
- この例では
roulette.service が選ばれる
- 別名のサービスユニットを実行したいなら
Unit= を変更できる
ExecStart= の対象はデフォルトではシェルコマンドとして実行されない
- 絶対パスの対象は、スクリプトそのものか、文字列引数としてスクリプトを受け取るインタープリターのように扱う必要がある
ExecStart=/usr/bin/echo Hello | /usr/bin/awk はこの文脈ではパイプに意味がないため動作しない
ExecStart= の引数はデフォルトでは、一部のシステムマネージャー既定値を除いて環境変数を継承しない
- デフォルトの
$PATH はほとんど空に近い
/usr/bin/env を実行すると、systemctl のような項目を使えるようにする簡単な安全策になる
ExecStart=/usr/bin/bash だけを書いた場合でも $PATH には既定の項目が入るが、env の使用は追加の安全策になる
- タイマーなしでサービスを直接実行することもできる
systemctl start roulette
[Install] セクションのないサービスは enable できず、この構成ではタイマーがサービスを一貫して実行する標準的な方法になる
systemctl は明示的な接尾辞がなくても、デフォルトで roulette.service に対して動作する
.timer ユニットに systemctl start を適用するとタイマーを稼働状態にはするが、実際の Unit= 対象サービスを即座に実行はしない
systemctl start roulette.timer
status はタイマーが次にいつ実行されるかを表示する
systemctl status roulette.timer
Trigger: Sat 2026-04-18 10:00:00 MDT; 35min left
- 最も単純な流れは、実行対象サービスを作成し、スケジュール付きのタイマーを同じ場所に置き、対象ではなくタイマーを起動するというもの
- タイマーユニットの
[Install] に WantedBy= があれば、起動時にもタイマーを立ち上げられる
systemctl enable roulette.timer
時間表現: カレンダーイベントと期間
- タイマーではスケジュール表現の方式が重要で、繰り返しの時間区間と、カレンダーイベントまたはタイムスタンプを区別する必要がある
systemd.time(7) マニュアルは例が十分にあり、タイマー作成時の最初の参考資料として使える
systemd-analyze は時間式を検証し、説明できる
systemd-analyze calendar '*-*-* *:*:*'
Normalized form: *-*-* *:*:*
Next elapse: Sat 2026-04-18 16:44:26 MDT
(in UTC): Sat 2026-04-18 22:44:26 UTC
From now: 431ms left
- systemd タイマーは、繰り返しの壁時計ベースの時刻だけでなく、伝統的な
cron と違って、ある以前のイベントを基準に繰り返す期間も定義できる
daily の完全な形は、毎年・毎月・毎日 00:00:00 に実行されることを意味する
*-*-* 00:00:00
│ │ │ │ │ ╰── at second 00
│ │ │ │ ╰───── at minute 00
│ │ │ ╰──────── at hour 00
│ │ ╰────────── every day
│ ╰──────────── every month
╰────────────── every year
daily のような省略形、完全な形式、systemd.time(7) のその他のサポート値を使え、systemd-analyze で前提を検証できる
イベント基準の実行がより適している場合
- 実際の作業では、「毎日同じ時刻に実行する」よりも「別のイベントの後に実行する」ほうが適していることが多い
- 一時ディレクトリを空にする作業は、起動直後に
cron 式の時刻が過ぎていたなら /tmp に片付けるものがほとんどないかもしれない
- 「コンピューターが起動してから1時間後に実行し、その後は毎時間実行する」と表現したほうが、サービスの実際の動作とスケジュールの論理によく合う
[Timer]
OnBootSec=1h
OnUnitActiveSec=1h
OnBootSec=1h は、マシン起動の1時間後に一度実行することを意味する
OnUnitActiveSec=1h は、Unit= が実行されてから1時間後に再度実行することを意味し、タイマーを暗黙的に繰り返し動作させる
- このような周期的な期間表現は、「毎時間この分に実行する」といった表現よりも、「ときどき1回ずつ実行する」用途に合うことが多い
- Advent of Code API をポーリングする Slack ボットの例では、
*/15 の cron 式は API の「15分ごと」というポリシーを守るが、全員が同じようにポーリングするとトラフィックが集中しうる
- コード修正後にタイマーを起動し、以後15分経つたびに実行されるようにすれば、必要な動作を満たしつつ thundering herd 問題を減らせる可能性がある
タイマーの状態をひと目で確認する
systemctl list-timers は、1台のマシンにおけるタイマーの状況を要約して表示する高レベルコマンド
systemctl list-timers
NEXT LEFT LAST PASSED UNIT ACTIVATES
Mon 2026-04-20 15:15:00 MDT 1min 40s Mon 2026-04-20 15:00:05 MDT 13min ago zfs-snapshot-frequent.timer zfs-snapshot-frequent.service
Mon 2026-04-20 15:32:16 MDT 18min Mon 2026-04-20 14:22:15 MDT 51min ago fwupd-refresh.timer fwupd-refresh.service
Mon 2026-04-20 16:00:00 MDT 46min Mon 2026-04-20 15:00:05 MDT 13min ago logrotate.timer logrotate.service
Mon 2026-04-20 16:00:00 MDT 46min Mon 2026-04-20 15:00:05 MDT 13min ago zfs-snapshot-hourly.timer zfs-snapshot-hourly.service
Tue 2026-04-21 00:00:00 MDT 8h Mon 2026-04-20 09:43:22 MDT 5h 29min ago zfs-snapshot-daily.timer zfs-snapshot-daily.service
Tue 2026-04-21 07:31:28 MDT 16h Sun 2026-04-19 20:15:47 MDT 7h ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service
Mon 2026-04-27 00:00:00 MDT 6 days Mon 2026-04-20 09:43:22 MDT 5h 29min ago zfs-snapshot-weekly.timer zfs-snapshot-weekly.service
Mon 2026-04-27 01:09:27 MDT 6 days Mon 2026-04-20 09:43:22 MDT 5h 29min ago fstrim.timer fstrim.service
Mon 2026-04-27 04:28:38 MDT 6 days Mon 2026-04-20 09:43:22 MDT 5h 29min ago zpool-trim.timer zpool-trim.service
Fri 2026-05-01 00:00:00 MDT 1 week 3 days Wed 2026-04-01 10:07:51 MDT 1 week 1 day ago zfs-snapshot-monthly.timer zfs-snapshot-monthly.service
Fri 2026-05-01 03:17:17 MDT 1 week 3 days Wed 2026-04-01 10:07:51 MDT 1 week 1 day ago zfs-scrub.timer zfs-scrub.service
11 timers listed.
Pass --all to see loaded but inactive timers, too.
- 1つのコマンドだけで、タイマースケジュールに従って実行される項目の全体像を把握できる
list-timers は、よく使われる systemd のサブコマンド群の一部
list-units も有用
list-paths は systemctl に比較的新しく追加されたサブコマンド
スリープ状態から復帰して実行する
WakeSystem= は、時間が来たタイマーによってシステムをスリープ状態から復帰させられる
WakeSystem=
Takes a boolean argument. If true, an elapsing timer will
cause the system to resume from suspend, should it be
suspended and if the system supports this.
...
- この機能は、人がノートPCのふたを開ける物理的な操作をしなくても重要なスクリプトを実行する必要がある場合に便利
- Arch や NixOS のように、使用前にパッケージ更新のダウンロードをサポートするディストリビューションでは、深夜に更新パッケージを先に取得しておき、朝にキーボードの前で更新できる
.service が終了した後に再びスリープ状態へ戻すには、手動で再度スリープ処理を行う必要があるとマニュアルにある
実行時刻の分散と thundering herd の緩和
- thundering herd 問題は、多数のプロセスが同時に目覚めるときに発生するシステム上の問題
- もし世界中の Debian システムがすべて
00:00:00 に apt update するようハードコードされていたら、深夜0時は誰にとっても好ましくないトラフィックピークになる
FixedRandomDelay= と RandomizedOffsetSec= は実行時刻の分散に役立つ
FixedRandomDelay=
Takes a boolean argument. When enabled, the randomized delay
specified by RandomizedDelaySec= is chosen deterministically,
and remains stable between all firings of the same timer,
even if the manager is restarted. ...
RandomizedOffsetSec=
Offsets the timer by a stable, randomly-selected, and evenly
distributed amount of time between 0 and the specified time
value. ...
- ソフトウェア更新を確認する実システムでこうした設定を使える
- 実行を均等分布でばらけさせることで、thundering herd 問題を減らし、動作を一貫させ、分散サービスを調整中のデーモン再起動のような妨害要因を避ける助けになる
- タイミングオプションは全体として非常に設定可能で、細かな制御を提供する
取り逃した実行を即座に補完する
Persistent= は、スリープ中のノートPCのために飛ばしてはいけないが、WakeSystem= までは不要なスケジュールスクリプトに特に適している
Persistent=
Takes a boolean argument. If true, the time when the service
unit was last triggered is stored on disk. When the timer is
activated, the service unit is triggered immediately if it
would have been triggered at least once during the time when
the timer was inactive. ...
- 構成管理チェックインを予定していたシステムがダウンタイムを経験したなら、
.timer に Persistent= を置くだけで、オンライン直後に正しい状態へ収束できる
Persistent= がなければ、タイマーの通常実行時刻まで待つ必要があり、その時間が長くなることもある
- 取り逃したアクティベーションを検知したときに待つべきでない他の作業として、システム更新、バッチ処理の確認などがある
タイマー作成時の注意点
systemctl --user で扱う ユーザーマネージャー 文脈のタイマーも有効だが、[Install] に書くターゲットには注意が必要
- ディストリビューションによっては、ユーザータイマーに適したターゲットは
default.target の場合がある
cron と同様、正確なシステムクロックを維持する必要があるという一般的な注意点はそのまま当てはまる
- systemd ユーザーは
timedatectl timesync-status で同期状態を確認できる
- 多くのエディターは systemd ユニットファイル形式を標準サポートしており、ユニットファイルが大きくなってくると助けになる
- Emacs では emacs systemd パッケージを利用できる
2件のコメント
Hacker Newsの意見
systemdタイマーを十分に使い込んだわけではないので反論しづらいが、cronの $PATHが曖昧だ という話はよく分からない
crontab内で直接
PATHを設定できるし、/etc/bashrc、~/.bashrc、~/.profile、~/.bash_profile、/etc/systemd/…のような場所で設定されるものより予測しにくいと考える理由があるだろうか1994年からLinuxを使っているが、cronの文法を暗記しているわけではない。ただ、crontabのコメントに
m h dom mon dow commandとあらかじめ書いてあるので、見出しに合わせて数字を入れればよいほかの不満点は理解できるし、次にcronジョブが必要になったらsystemdタイマーを一度試してみるつもりだ
カンマ、スラッシュ、アスタリスク、その組み合わせがあり、ランダム化が必要なら通常はcron自体ではできず、コマンドの中に書かなければならない。少し込み入った cron仕様 を書くのは簡単ではない
誰かが
5,3/4 4-8,11 1 4,5,6,9-11 */2のようなものを入れると、実際に何を意図したのかをリバースエンジニアリングする楽しみが生まれるが、たいていは書いた本人の意図どおりの意味ではないここに一部のcron環境でしかサポートされない拡張まで入ってくると、さらに複雑になる
systemdタイマーのほうがずっと管理しやすかった。長時間走るジョブの 重複実行を許可するかどうか を制御したり、固定時刻ではなく開始から終了までの間にジョブを実行する機能は大きな改善だ
以前、バックアップジョブがシンボリックリンクのループにはまり、VPSが落ちたことがあるが、cronは終了していないバックアップがあるのに次々と新しいバックアップジョブを起動していた
CRON固有の
PATHのせいでコマンドやスクリプトを書き直さなければならなかったのも不便だったが、一部のsystemdタイマーでも似たことはありうる。それでも、crontabを30秒後に実行されるよう変更して待つ必要なく、タイマーを手動実行できる$PATHをハードコードしてcronジョブをテストしたいとは思わないハードコードしなければ、cronが実行するときの
$PATHと、直接コマンドを試すときの$PATHが異なる。systemctl start foo.serviceはタイマーが発火するときと同じ環境でコマンドを開始するので、同じように動くか分かる一方でcronジョブはcrontabに指定した時刻に実行される。systemdタイマーもたいていは指定時刻に発火するが、systemdのロジックバグのせいで 2月29日 に一度実行されたあと二度と実行されなかったり、タイマーユニットを「restart」したときに発火することもあればしないこともある
systemdでは何がトリガーしても実際に実行されるユニットは同じなので、ギャップがない
基本環境が何かは依然として把握しておく必要があるが、シェルの影響を受けないほぼクリーンな環境だ。これはsystemdの利点だと思う
PATHが曖昧とまでは言わないが、cronにはPATHに関する問題があるデフォルト値に
/usr/local/binやroot用の/usr/sbinのような期待される値が入っておらず、Arch Linuxのような一部ディストリビューションではマニュアルページにデフォルトのパスや設定推奨すら書かれていない特定のスクリプトひとつにだけパスを追加したいなら、
envで包むかラッパースクリプトで設定するか、項目の前でパスを変えて後で戻す必要があるPATHの中で~や$HOMEを使えず、完全な絶対パスを書かなければならないので、ユーザーcrontabでは特に面倒だ回避は難しくないが、デフォルトでほかのサービスと同じパスを使う systemdタイマー のほうがよりよい体験だと思う
cronieからsystemdタイマーへ移行した理由は、システム起動時刻 に対してより柔軟だからだ
バックアップ戦略は毎日決まった時刻にborgアーカイブ項目を作ることだが、cronieでは予約時刻にシステムが起動している必要がある。systemdタイマーはこの状況に耐え、システムが利用可能になり次第すぐにサービスを実行する
バックアップ自動化リポジトリは https://github.com/gchamon/borg-automated-backups だ
/etc/cron.hourly/0anacronを呼び出し、最も早い実行時刻を逃していても/etc/cron.{daily,weekly,monthly}ジョブを実行する。ランダム遅延も設定可能だ/etc/anacrontabを編集すればカスタムスケジュールを作れるユーザーレベルでは
@hourly anacron -t /path/to/anacrontab -S /path/to/spooldirのような項目をユーザーcrontabに入れられるはずだが、自分では試していない多くのcron実装にも似たような仕組みがある
@rebootオプションがあり、いくつかのスクリプトで使っているが、うまく動いている@rebootメタトリガーはないのか?Canonのプリンターは、しばらく放置するとノズルが詰まることがあるので信用できない。そこでClaudeにsystemdスクリプトを作らせて、毎週子犬の写真を印刷するようにした。プリンターにしっかり負荷がかかるよう、CMYKスペクトラムが十分入るようにもしている
月曜日に机に向かうと、プリンターから突然写真が出てくるのはなかなか気分のいい驚きだ
少なくとも子どもの科学コンテストのプロジェクト案くらいにはなりそうだ
亡くなってから何年ものあいだ電源も切れたまま使われていなかったが、カラー印刷が必要になって電源をつないで印刷してみた
1ページの1/5くらい進んだところで全色が戻り、その後20ページほどを問題なく印刷できた
ハードウェアというよりソフトウェアの問題っぽかったが、プリンターをコンピュータにつないだまま1週間以上放置すると、単に印刷が止まってしまった
ログを掘ることもできただろうが、代わりに月曜と木曜にテストページを印刷するcronジョブを作った。テストページの上には
LOL PRINTER WORKSのような文言だけがあった思ったほど無駄ではなかった。数学の授業をたくさん取っていて、問題を解くための裏紙が大量に必要だったので、失敗した印刷物やテスト印刷を先に使い、そのあとで白紙を使っていた
最大解像度は600dpiしかなかったが、色はとても良く均一で、トナーが乾かないことが兄の重要な購入基準だった。HPのインクジェットは何度も詰まった
systemdタイマーが大好きだ。Ansibleで配布していたcronジョブを少しずつ全部タイマーに移し、今ではAnsibleでコピーするだけで済む
journalctlとの統合が特に良く、Debian 13のようにsyslogがなくなった最近のOSではなおさらだ。デバッグのためにサービスを手動起動できるのも便利動かないcronジョブはコピペしたり追加のシェルスクリプトを書いたりしなければならない面倒さがあり、cronジョブの標準出力が消えるブラックホールは言うまでもない
既存のsystemdサービスと同じように監視し、失敗通知も受け取れる。オープンソースプロジェクトが配布方法としてタイマーをますます推奨しているのも好ましい
NixOSではsystemdが標準なので、管理の第一級要素として使っている。macOSのlaunchdを使っていた身には特にありがたい
NixOS向けのツールを配布するときに、systemdを後付けの継ぎはぎとしてではなく自然に活用できる点も良い
ただ、Linuxユーザー全体を対象にライフサイクル管理の多いツールを配布するなら、systemdがどこにでもあるわけではないのでどうすべきか気になる
btrfsプールの月次scrubをsystemdタイマーで回している。ユーザーが手動でscrubを開始したら次の予定を飛ばすのか、月次ジョブなのに機器が6か月止まっていた場合にジョブを積み上げるのか1回に畳むのか、といったことを決められるのでかなり便利だ
systemd.services.sync-recyclarr = { serviceConfig.Type = "oneshot"; path = [ pkgs.podman ]; script = '' podman exec -it recyclarr recyclarr sync radarr podman exec -it recyclarr recyclarr sync sonarr ''; };systemd.timers.sync-recyclarr = { timerConfig = { OnCalendar = "daily"; Persistent = true; Unit = "sync-recyclarr.service"; }; partOf = [ "sync-recyclarr.service" ]; requires = [ "podman-recyclarr.service" ]; wantedBy = [ "timers.target" ]; };flake.nixファイルの中に直接定義しているのか気になる自分もNixOSを使っているが、設定はすべて元の形式のままにして、Nixではシンボリックリンクを張るだけにしている。そうすればnon-NixOSのシステムでも設定を簡単に持ち込める
問題は、NixOSが
~/.config/systems/userフォルダに置いたsystemdタイマーやサービスを拾って実行してくれないようで、WantedBy=default.targetのようなものも効かないことだだから再起動後にすべてのサービスを手動で再起動してから、systemdタイマーは素晴らしいと同意することになる
タイマーは必ずしも同名のサービスユニットだけでなく、任意のユニットとも連携できるので意外と柔軟だ
自分のサーバーには、毎朝ランダムな開始時刻と通知付きで
restic backup、restic prune、restic forgetの一連のバックアップサイクルを実行するbackup.targetを起動するタイマーがある実際の
restic-*ユニットはPodman Quadletなので、サーバーにPodmanとSystemdさえあれば、構成自体はサーバーの中身に依存せず動くただしタイマーは、日常的に使うにはsystemdのユニット種別の中でもかなり無骨な部類だ。2つのファイルに分かれ、startとenableの文法が違う理由は分かるが、たまには単に1ファイル作ってスクリプトを実行して終わりにしたくなる
LLM時代には大した問題ではないのかもしれないが、毎回少しだけ面倒に感じる
systemdのどの面も常に大好きだったわけではないが、この感想にはおおむね同意する。
「システム」レベルの定期実行では、ほぼ完全にcronの使用をやめて systemdタイマー を好むようになった。特定アプリケーションの範囲のスケジューリングにはQuartzのようなものを組み込むこともある。
理由は漠然としていて説明しにくいのだが、systemdのやり方のほうが「動作の仕組みはこうあるべきだ」という自分の頭の中のモデルに、よりすっきり合っている。過去にはcronスクリプト実行で
PATHが曖昧で予測しづらかったこともかなりあったし、それだけが理由でもない。systemdタイマーが普遍的・客観的にcronより優れていると主張するつもりはないが、少なくとも自分を納得させることには成功している。
systemdタイマー入門としてとても良く、ついに使ってみようと思えるほど説得力があった。
list-timersも気に入っている。cronでは、1台のマシンで動いているすべてのcronジョブを一目で把握するのが簡単ではなかった。全ユーザーのcrontab、/etc/cron.d/、daily/hourly/monthlyディレクトリを確認しなければならなかった。実際、起動後およそ5分後に1回実行し、その後はおよそ12時間ごとに実行すべきユースケースがあるのだが、systemdタイマーがこれを処理してくれるのは良い。
systemd-analyzeやsystemctl list-timersのような ツールの使い方 を身につけるのは本当に価値があると感じる。systemdは最初は複雑に見えるが、使っていると他のものを使いたくなくなる。すべてを
systemctlで管理できるのが便利だ。たとえば、ユニット定義がなぜ必ずディスク上の実ファイルでなければならないのかわからない。デーモンを再読み込みするとき、変更されたファイルだけでなくすべてのファイルを再読込する。プログラム的にユニットを追加するAPIがあってもよかったのではないかと思う。似たようなものはあるが、制約が多く柔軟ではない。
1つのファイル内で複数のユニットを宣言できないのも疑問だ。ファイルシステム中心に設計されていて、別レベルの抽象化をしないという選択は賢く見えない。特にUnix哲学に従っているわけでもない。
ユニット定義の形式も、もし当時TOMLがあったなら、もっと理にかなったものを使っていただろうと思う。
もちろん、自分が年を取ったからなのだろう。どうせ
systemd-*だけが唯一正しい道で、違う見方をする人はみな口出し屋なのだろうし。Linuxを20年以上、systemdを10年以上使ってきた。
それでも常に新しく学ぶことがあり、実際また1つの有用なツールとして考えるようになった。
Lobste.rsの意見
systemdは完璧ではないが、多くの設計判断は、より伝統的な過去のやり方から得た学びに基づいているように感じる
最近、Lennart Poetteringがその背景を説明したCREの2015年のエピソードを聴き直したが、今でもおすすめできる
根っからのsystemd嫌いではあるが、systemd.timersはこの製品の中では「まだましな」概念の一つだと思う
だからこそ、筆者がもっともな不満を持つ人たちを見下すような形で擁護していたのは少し意外だった
それでも
atコマンドと併用するのは良い。特定時刻に一度だけ実行するコマンドはat、それ以外はsystemdタイマーと単純なユニットファイルを使う、という運用だいちばん改善してほしいのは、どのユーザーがタイマーを実行しているのか分かるようにすることだ。2026年にシェルボックスを運営している数少ない人間の一人ではあるが、毎秒ディスクを叩くタイマーをどのユーザーが作ったのか分かると便利だ
loginctl enable-lingerを使えば、アクティブなユーザーセッションがなくても実行できるはずだ。もちろん、それでは足りないユースケースもあるだろうし、具体的な状況は分からないsystemdタイマーは、特にユーザー管理の面で初期負担がもっと低いとよいと思う
必要な設定量を見ると、
crontab -eに勝つのは本当に難しいcronスクリプトのログを体系的に集める方法を長いこと考えていたが、単にsystemdタイマーを使えばいいのだと気づいた
ロギングの問題が解決する。もうcronを使い直す理由はなく、もっと早く知っていればよかった
loggerにパイプするか、ログファイルに>>で追記するか、デフォルトのままメールを受け取ればいいのでは?古臭いと言われてもいいが、サーバーから自分に届くメールは今でも設定してある
自動化しておけば新しいホストごとにおまけで付いてくるし、普段からかなり便利だ
例えば、マルチプレクサを一つ開いて
long_running_process | mail root@localhost -s "done $?"を実行して、そのまま忘れておく、といった使い方だ良い記事で、私も似たような記事の下書きを持っていたが、最近また参照する必要があった
私のようにsystemdのウサギ穴に入り込むなら、関連プロジェクトのフォルダーにあるユニットファイルやタイマーを
/etc/systemd/system/にシンボリックリンクしておくのをおすすめするsystemdへの不満の一つは、ディストリビューションがインストールしたユニットと自分で書いたユニットを区別してくれないことだが、シンボリックリンクを使えばその分離を自分で維持できる
システム/パッケージ/ディストリビューションのユニットは
/usr/lib/systemd/systemに入り、ローカルオーバーライドやローカルユニットは/etc/systemd/systemに入る