at、cron、および systemd タイマーによるジョブのスケジュール設定

LinuxBeginner
オンラインで実践に進む

はじめに

Linux 管理者は、さまざまな方法でタスクをスケジュールします。at コマンドは単発のジョブをスケジュールし、cron は単純な時間指定フィールドを使用して定期的なジョブをスケジュールします。また、systemd タイマーは、systemd の依存関係やログ記録モデルを活用して systemd サービスをスケジュールします。

この実験では、1 つのコマンドスクリプトを作成し、それを 3 つの方法でスケジュールします。スケジューラーサービスの確認、at による単発ジョブのキューイング、cron ドロップインファイルの設定、systemd サービスとタイマーのペアの作成、そしてタイマーによって実行されるサービスの手動テストを行います。

スケジューラーの確認とジョブスクリプトの作成

このステップでは、スケジューラーサービスが実行されていることを確認し、すべてのスケジュールされたジョブから呼び出される小さなスクリプトを作成します。

プロジェクトディレクトリに移動します。

cd /home/labex/project

単発ジョブ用のデーモンと cron デーモンを確認します。systemctl is-active は、サービスが現在実行中であれば active と表示します。

systemctl is-active atd crond

既存の systemd タイマーを一覧表示します。出力には、次回の実行時間、タイマーユニット、およびそれが起動するサービスユニットが表示されます。

systemctl list-timers --all --no-pager | sed -n '1,10p'

タイムスタンプ付きの行をログファイルに追記するスクリプトを作成します。最初の引数 $1 は、どのスケジューラーがスクリプトを実行したかを識別するラベルになります。

cat > /home/labex/project/scheduled-note.sh <<'EOF'
#!/bin/bash
echo "$(date '+%F %T') $1" >> /home/labex/project/schedule-events.log
EOF

スクリプトに実行権限を付与します。

chmod 755 /home/labex/project/scheduled-note.sh

スクリプトを手動で一度実行します。

/home/labex/project/scheduled-note.sh manual-run
tail -n 1 /home/labex/project/schedule-events.log

ログの末尾が manual-run となっていれば成功です。

at による単発ジョブのキューイング

このステップでは、at を使用して単発ジョブをスケジュールします。これは、一時的なメンテナンス作業など、将来の特定の時間に一度だけ実行する必要がある作業に役立ちます。

今から 2 時間後にスクリプトが実行されるようにキューに入れます。実行するコマンドはパイプで at に渡されます。

echo "/home/labex/project/scheduled-note.sh at-job" | at now + 2 hours

キューに入れられたジョブを一覧表示します。

atq

最初の atq 行からジョブ ID を保存します。ジョブ ID は出力の最初のフィールドです。

job_id="$(atq | awk 'NR==1 {print $1}')"
echo "$job_id" > /home/labex/project/at-job.id
cat /home/labex/project/at-job.id

キューに入れられたジョブの内容を確認します。at -c は生成されたジョブスクリプトを表示します。最後の数行に、キューに入れたコマンドが含まれているはずです。

at -c "$job_id" | tail -n 12

cron ドロップインファイルの設定

このステップでは、/etc/cron.d 内のファイルを使用して、定期的な cron ジョブを設定します。このディレクトリ内のファイルにはユーザーフィールドが含まれているため、システムはどのユーザーアカウントでコマンドを実行すべきかを認識できます。

labex ユーザーとして毎分スクリプトを実行する cron ファイルを作成します。PATH 行は、cron に予測可能なコマンド検索パスを提供します。

sudo tee /etc/cron.d/rhcsa-schedule-demo >/dev/null <<'EOF'
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
* * * * * labex /home/labex/project/scheduled-note.sh cron-job
EOF

ファイルのモードを 644 に設定します。cron ファイルは読み取り可能である必要があり、通常のユーザーが書き込み可能であってはなりません。

sudo chmod 644 /etc/cron.d/rhcsa-schedule-demo

crond をリロードして、ファイルを即座に認識させます。

sudo systemctl reload crond

作成したファイルを確認します。

sudo cat /etc/cron.d/rhcsa-schedule-demo

スケジュールフィールドの * * * * * は「毎分」を意味します。

systemd サービスとタイマーの作成

このステップでは、systemd サービスとそれを起動するタイマーを作成します。タイマーはコマンドを直接実行するのではなく、サービスユニットを開始します。

システムサービスは、ユーザーの作業ディレクトリではなく、システムの実行可能パスからコマンドを実行する必要があります。スクリプトのコピーを /usr/local/bin にインストールします。

sudo install -m 755 /home/labex/project/scheduled-note.sh /usr/local/bin/rhcsa-scheduled-note
sudo restorecon /usr/local/bin/rhcsa-scheduled-note 2>/dev/null || true
ls -l /usr/local/bin/rhcsa-scheduled-note

サービスユニットを作成します。Type=oneshot は、実行して終了するコマンドに適しています。

sudo tee /etc/systemd/system/rhcsa-schedule-demo.service >/dev/null <<'EOF'
[Unit]
Description=Write RHCSA schedule demo entry

[Service]
Type=oneshot
User=labex
ExecStart=/usr/local/bin/rhcsa-scheduled-note timer-job
EOF

タイマーユニットを作成します。OnBootSec=2min は起動から 2 分後に初回実行をスケジュールし、OnUnitActiveSec=5min は前回の起動から 5 分後に次回の実行をスケジュールします。

sudo tee /etc/systemd/system/rhcsa-schedule-demo.timer >/dev/null <<'EOF'
[Unit]
Description=Run RHCSA schedule demo periodically

[Timer]
OnBootSec=2min
OnUnitActiveSec=5min
Unit=rhcsa-schedule-demo.service

[Install]
WantedBy=timers.target
EOF

systemd をリロードし、タイマーを起動時に有効化してから、今すぐ開始します。enable と start を分けることで、タイマーを永続化するコマンドと、即座にアクティブ化するコマンドの違いが明確になります。

sudo systemctl daemon-reload
sudo systemctl enable rhcsa-schedule-demo.timer
sudo systemctl start rhcsa-schedule-demo.timer

タイマーを確認します。

systemctl list-timers rhcsa-schedule-demo.timer --all --no-pager

タイマーがリストに表示され、rhcsa-schedule-demo.service をアクティブ化するようになっているはずです。

タイマーサービスの手動テストと at ジョブの削除

このステップでは、タイマーによって使用されるサービスを手動で開始します。これにより、次回のスケジュール実行を待たずにコマンドを即座に検証できます。また、練習用として作成した at ジョブを削除します。

サービスを手動で開始します。

sudo systemctl start rhcsa-schedule-demo.service

ログを確認します。

tail -n 5 /home/labex/project/schedule-events.log

1 行が timer-job で終わっているはずです。

先ほど保存したジョブ ID を使用して、キューに入れられた at ジョブを削除します。

job_id="$(cat /home/labex/project/at-job.id)"
atrm "$job_id"

ジョブがキューから削除されたことを確認します。

atq

まとめ

3 つのスケジュール方法を実践しました。atd、crond、および systemd タイマーの確認、再利用可能なスケジュールコマンドスクリプトの作成、at ジョブのキューイングと確認、cron ドロップインファイルの設定、/usr/local/bin への安全なコマンドのインストール、systemd サービスとタイマーのペアの作成、タイマーサービスの手動テスト、そして一時的な at ジョブの削除を行いました。