接続不能になる前に！Linuxの設定ミスを防ぐatコマンド


# はじめに
ネットワーク設定を変更したら、二度と接続できなくなったという経験ありませんか？
そんなときの“保険”として使えるのが、`at` コマンドです。
たった一行で「5分後に元に戻す」を予約できると設定ミスも怖くありません。

# インストール
```bash
sudo apt install -y at
```

# 今回利用するコマンドとフロー図
| コマンド        | 説明                     |
| --------------- | ------------------------ |
| at <時刻指定>   | ジョブを実行予約する     |
| atq             | 実行待ちジョブを表示する |
| atrm <ジョブID> | 実行待ちジョブを削除する |

```text:フロー図
[変更前にジョブ予約(at)] → [設定変更] → [動作確認OK → ジョブ削除(atrm)]  
                            ↓  
                         [NGなら→指定時間後に自動復旧が発動]
```

# atコマンドの使い方
## 1. ジョブを実行予約する
基本的な使い方は、「コマンドをパイプで渡して、実行時刻を指定する」だけです。
```bash
echo "実行したいコマンド" | at <日時指定>
```

#### 例：5分後にコマンドを実行する
```bash
echo "date > now.txt" | at now + 5 minutes
```

### 他の書き方（補足）
| 方法      | コマンド例                                 | 特徴        |
| ------- | ------------------------------------- | --------- |
| ファイルを渡す | `at -f script.sh now + 5 minutes`     | 複数行コマンド向き |
| 対話モード   | `at now + 5 minutes` → 1行ずつ入力し Ctrl+d | 簡単な入力確認向き |


### 日時指定のパターン一覧

| 書き方       | 指定例             | 説明                     | 備考                                                                                                                   |
| ------------ | ------------------ | ------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
| 相対時刻     | `now + 5 minutes`  | 現在からの相対時間で指定 | 単位: minutes, hours, days, weeks                                                                                      |
| 時刻のみ     | `12:00`            | HH:MMで指定      | 秒単位では指定できません                                                                                               |
| 日時 | `12:00 2025-05-30` | 時刻 + 日付で指定 | 日付部分のフォーマットは<br />- [CC]YY-MM-DD<br />- MM/DD/[CC]YY<br />- MMDD[CC]YY<br />- DD.MM.[CC]YY<br />秒単位では指定できません |


## 2. 実行待ちジョブを表示する
```bash:構文
atq
```

```text:atqコマンドの実行結果
19      Mon May  5 12:40:00 2025 a root
18      Mon May  5 12:35:00 2025 a root
17      Mon May  5 12:30:00 2025 a root
```
左から
- ジョブID
- 実行予定日時
- ジョブキューのID（後述）
- 予約したユーザー

## 3. 実行待ちジョブを削除する
```bash:構文
atrm <ジョブID>

# （Tips）一括削除
atq | awk '{print $1}' | xargs atrm
```

---
# 設定ミス対策の使用例（ネットワーク設定変更作業）
ネットワーク設定を変更する前後でこれらのコマンドを利用することで、万一接続できなくなっても指定時間後に自動復旧が行われます。

### ステップ1：現在の設定をバックアップ
```bash
sudo cp /etc/network/interfaces /etc/network/interfaces.bak
```

### ステップ2：5分後に自動で復旧するよう予約
```bash
# バックアップファイルから上書きし直し・リロードする処理を予約しておく
# 「ifreload -a」は「systemctl restart networking」でもOK
echo "cp /etc/network/interfaces.bak /etc/network/interfaces && ifreload -a" | \ 
at now + 5 minutes
```

### ステップ3：設定変更作業を行う
```bash
sudo nano /etc/network/interfaces
```

### ステップ4：問題なければジョブを削除
```bash
# ジョブIDを確認
atq

# 確認したジョブを削除
atrm <ジョブID>
```

### ステップ5：ミスがあっても自動復旧される
```bash:復元されたことを確認しておくとベスト
journalctl -u networking -b  # ネットワーク再起動ログの確認
diff -sq /etc/network/interfaces /etc/network/interfaces.bak # 元の設定に戻っているかの確認
```
---
# 注意点
- **atdサービスが動いている必要あり**  
  インストール時に自動起動されるものの念のため確認しましょう：`systemctl status atd`

- **相対時間は「ぴったり〇秒後」ではない**  
  ジョブ実行を担っている`atd`は1分毎にジョブを確認するため予約時刻は要注意です。
  例：`11:29:50`に`1分後`と予約すると、実際は`11:30:00`（つまり**10秒後**）に実行されてしまう。

- **ファイルのコピーだけでは戻せない作業には不向き**  
    「コマンド1つで戻す」のが難しい作業には向きません。例としては以下のようなものがあります：

    | 不適な作業例                   | 理由                                          |
    |------------------------------|----------------------------------------------|
    | DBやレプリカの削除           | レコード順や整合性の完全復元は困難           |
    | ユーザー・グループの削除     | UID/GIDやパーミッションの復元が煩雑          |
    | バージョンの変更             | 単なる上書きでは戻せないケースが多い         |
    | 複雑な構成変更               | 依存関係の整合性崩れなどが発生しやすい       |


# at / cron / systemd-timerとの比較
一時的なコマンド予約にはat、定期的な実行にはcron、サービス間の依存関係の考慮も必要な場合はsystemd-timerという使い分けが理想的です。


| 特徴                 | `at`                            | `cron`               | `systemd-timer`                     |
| -------------------- | ------------------------------- | -------------------- | ----------------------------------- |
| 実行タイミング       | **1回限り**                     | 繰り返し             | 繰り返し／1回限り 両対応            |
| 時刻指定             | 直感的（`now + 5 minutes`など） | cron式 (`* * * * *`) | 柔軟（秒単位や起動後N秒なども可）   |
| 予約中ジョブの把握   | `atq`                           | `crontab -l`         | `systemctl list-timers`                  |
| インタラクティブ実行 | 可能（対話入力）                | 不可                 | 単体では不可（スクリプトとの併用）  |
| 負荷に応じた実行制御 | あり（後述）                    | なし                 | `ConditionCPUs`などの条件指定が可能 |
| 管理のしやすさ       | 手軽／単発向き                  | 古典的／情報が多い   | 高機能／構成ファイル管理向き        |
| 向いている用途       | 一時的な保険                    | 定時実行             | 依存関係のあるタスク                |



# （ニッチな使い方）ジョブスケジューラーとしての利用
あまり知られていませんが、at コマンドは簡易のジョブスケジューラーとしても利用できます。

1. ジョブキュー（-qオプション）
    at には a〜z, A〜ZのキューID が用意されており、ジョブを特定のキューに振り分けて予約できます。

    ```bash
    echo "実行したいコマンド" | at -q <投入先のキューID（a〜z、A〜Z）> <時刻指定>
    ```
    - a〜z は通常キュー（aが最も優先度高い）
    - b は batch コマンドでも使われるデフォルトキュー
    - A〜Z は batch 用で、時間指定付きの低優先キュー

2. batch コマンド：システムが空いているときだけ実行
    batch は at と似た構文で、システムの負荷が低いときだけジョブを実行します。
    ```bash
    echo "実行したいコマンド" | batch
    ```
    - Load average が一定以下（デフォルト1.5）になるとatd によって実行されます。
    - 複数のbatchジョブは60秒以上の間隔で順番に実行されます。
    
3. 実行条件の変更（上級者向け）
    atdサービスの起動オプションを次のように変更するとチューニングも可能です。

    | オプション | 意味                       |
    | ---------- | -------------------------- |
    | -l <数値>  | 実行可能な最大load average |
    | -b <秒数>  | batchジョブ間の最小間隔    |

    ```text: /lib/systemd/system/atd.service
    ExecStart=/usr/sbin/atd -f -l 2.0 -b 30
    ```


---
# さいごに
Linuxの設定変更は、たった1つのミスでサーバにアクセスできなくなるリスクがあります。  
`at` コマンドを使えば、「やばい！戻れない！」という状況を**1行の保険**で防げます。
設定をミスしても自動復旧してくれるという安心感があるだけで、作業効率も冷静さも大きく変わるはずです。
自動化や安全性の一歩として、ぜひ日常の運用に取り入れてみてください。

# 参考情報
- [at(1) - Linux man page](https://linux.die.net/man/1/at)
- [atq(1) - Linux man page](https://linux.die.net/man/1/atq)
- [atrm(1) - Linux man page](https://linux.die.net/man/1/atrm)
- [batch(1) - Linux man page](https://linux.die.net/man/1/batch)
- [atd(8) - Linux man page](https://linux.die.net/man/8/atd)