Linux 講座 / cronとsystemdタイマーで定期作業を自動化する

Linuxの定期作業は、簡単なスケジュールにはcronを、サービスの状態やログとともに管理する作業にはsystemdタイマーを使用できます。登録されているという事実だけでなく、予約の解釈、実際の実行記録、結果ファイルおよび失敗状態をそれぞれ確認する必要があります。

予約するコマンドは、Bashスクリプト入門のように、直接実行して結果を確認した後に登録してください。ユーザーsystemdマネージャーのログアウト後の動作やlinger設定は、実際のVMで確認する必要があり、タイマー登録だけで継続して実行されるとは考えないでください。

システム設定実習の基準は Ubuntu 26.04 LTS と Rocky Linux 9 系の一般インストール VM です。コンテナ・WSL・別のリリースでは、サービスやパッケージの構成が異なる場合があります。仮想マシン実習環境の作成で、コンソールの復旧とバージョン確認を最初に準備してください。

cronとタイマーの選択基準

基準 cron systemdタイマー
設定単位 時間フィールドとコマンド1行 timerとserviceユニット
実行確認 ジョブの出力・ディストリビューションごとのログ サービス状態・ジャーナル
環境 ログインシェルとは異なる制限された環境 ユニットに定めた実行環境
見逃した予定 一般的なcronは通常遡及しない OnCalendarとPersistentの設定確認

cronデーモンの名前とインストールの有無はディストリビューションによって異なります。Ubuntuでは通常cron、Rocky Linuxではcronie・crondを使用します。systemdタイマーの例は、ユーザーsystemdマネージャーが実行される環境が必要です。通常のcronの動作とanacronのような補助ツールの動作も区別する必要があります。

まずcron表現と環境を読む

crontab -eは現在のユーザーのジョブを編集します。ユーザーcrontabの5つの時間フィールドは分・時・日・月・曜日で、後ろにコマンドが続きます。以下は毎日02:15に実行する形式の例で、/home/USERを実際の絶対パスに置き換える必要があります。/etc/crontabはコマンドの前にユーザーフィールドが追加される別の形式です。

15 2 * * * /bin/bash /home/USER/bin/job.sh >> /home/USER/job.log 2>&1

cronはターミナルのPATH、現在のディレクトリ、環境変数をそのまま継承しません。絶対パスを使用し、スクリプト内で作業ディレクトリを指定し、秘密の値をcrontabに直接列挙しないでください。日付(日)と曜日の両方を制限すると、実装上のOR条件のため、期待とは異なる日に実行されることがあります。タイムゾーン・夏時間およびパーセント文字の特別な扱いについても、使用するcronマニュアルで確認してください。

ユーザーサービスとタイマーファイルを作成する

以下の名前のユニットがすでに存在している場合は、上書きせずに別の実習用の名前を使用します。この例では、1分間隔で日付をジャーナルに出力し、システムサービスやroot権限は必要ありません。/usr/bin/dateのパスは、まずcommand -v dateで確認し、実際のパスが異なる場合はExecStartを調整します。

mkdir -p "$HOME/.config/systemd/user"
cat > "$HOME/.config/systemd/user/linux-course-clock.service" <<'EOF'
[Unit]
Description=Linux course timestamp exercise

[Service]
Type=oneshot
ExecStart=/usr/bin/date --iso-8601=seconds
EOF
cat > "$HOME/.config/systemd/user/linux-course-clock.timer" <<'EOF'
[Unit]
Description=Run the course clock every minute

[Timer]
OnCalendar=*-*-* *:*:00
AccuracySec=1s
Persistent=true

[Install]
WantedBy=timers.target
EOF
systemd-analyze calendar '*-*-* *:*:00'
systemctl --user daemon-reload
systemctl --user enable --now linux-course-clock.timer

同じ基本名のタイマーは対応するサービスを実行します。OnCalendarはカレンダー基準の予定で、AccuracySecは実行を集めることができる許容範囲であり、リアルタイムでの実行は保証しません。Persistent=trueは停止中に逃した予定があればタイマーが再び起動したときに補完実行を試みますが、逃した回数分すべてを実行するわけではありません。

次の実行時刻と実際の実行結果を確認する

systemctl --user list-timers --all linux-course-clock.timer
systemctl --user status linux-course-clock.timer
journalctl --user -u linux-course-clock.service --since "5 minutes ago" --no-pager
systemctl --user show linux-course-clock.service -p Result -p ExecMainStatus
timedatectl

次の実行時刻を確認した後、1~2分経ったらジャーナルで日付出力と終了記録を確認します。oneshotサービスは処理が終了すると inactive 状態でも成功していることがあるため、Result と ExecMainStatus を併せて確認します。timedatectl のタイムゾーンと時刻同期の状態を確認し、サーバーの現地時間と希望する業務時間帯が一致しているか検討してください。

ログアウト後もユーザー作業を継続させる必要がある場合は、ユーザーマネージャーの存続期間と linger ポリシーを確認してください。単に enable したという理由だけで、ログアウト後や再起動後にすべての条件で実行されると想定しないでください。システムタイマーで運用する場合は、専用アカウント、絶対パス、最小権限と資源制限を別途設計します。

重複実行・失敗の管理と実習解除

通常の cron 作業が周期より長くかかる場合、次の実行と重なることがあるため、サポートされる環境では flock などのロック方式を検討します。systemd タイマーがすでに実行中の同じサービスユニットを再度有効化しようとしても、別の二つのインスタンスを自動生成することはありません。しかし、他のユニット・手動実行と資源を共有することがあるため、アプリケーションレベルでの同時実行条件は依然として必要です。

systemctl --user disable --now linux-course-clock.timer
rm -- "$HOME/.config/systemd/user/linux-course-clock.timer" "$HOME/.config/systemd/user/linux-course-clock.service"
systemctl --user daemon-reload
systemctl --user list-timers --all linux-course-clock.timer

削除コマンドは、この演習で作成した2つのファイルのみを対象とします。cron演習の行を追加した場合は、crontab -eでその行だけを削除し、crontab -lで確認します。既存の全体のcrontabを消さないでください。実際の自動化では、成功の通知よりも、失敗や未実行を発見できる別の確認および復旧手順が重要です。

公式ドキュメント