# 帳票設計書 34-ruptime

## 概要

本ドキュメントは、FreeBSDのruptimeコマンドが生成するリモートホスト稼働状況レポートの設計を記述する。ruptimeはネットワーク上のホストのステータス（稼働時間、ユーザー数、ロードアベレージ）を一覧表示するCLIユーティリティである。

### 本帳票の処理概要

ruptimeコマンドは、rwhod(8)デーモンが収集した/var/rwho/ディレクトリ内のwhod.XXXファイルを読み取り、ネットワーク上のホストの稼働状況をレポートする。各ホストのup/down状態、稼働時間、ログインユーザー数、ロードアベレージを一覧形式で出力する。

**業務上の目的・背景**：分散コンピューティング環境において、複数のホストの稼働状況を一元的に確認することは、システム管理者にとって重要な作業である。ruptimeはrwho(1)と同様にrwhodプロトコルに基づくが、各ホストのサマリー情報を提供する。

**帳票の利用シーン**：複数ホストの稼働状況一括確認、ダウンしたホストの検出、ロードバランシングのための負荷状況確認、メンテナンス後の復旧確認に利用される。

**主要な出力内容**：
1. ホスト名
2. up/down状態と稼働/停止時間
3. ログインユーザー数（downでない場合）
4. 1/5/15分ロードアベレージ（downでない場合）

**帳票の出力タイミング**：ユーザーがコマンドラインからruptimeコマンドを実行した際に即時出力される。

**帳票の利用者**：システム管理者、ネットワーク管理者

## 帳票種別

一覧表

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| N/A | CLIターミナル | N/A | `ruptime [options] [host ...]` コマンド実行 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | テキスト（標準出力） |
| 用紙サイズ | N/A（ターミナル出力） |
| 向き | N/A |
| ファイル名 | N/A（標準出力） |
| 出力方法 | 標準出力（stdout） |
| 文字コード | ASCII |

### PDF固有設定

該当なし

### Excel固有設定

該当なし

## 帳票レイアウト

### レイアウト概要

```
┌──────────────────────────────────────────────────────────────────┐
│  ホスト名  状態 稼働/停止時間, ユーザー数  ロードアベレージ          │
├──────────────────────────────────────────────────────────────────┤
│  host1    up   10+12:34,  3 users,  load 1.00, 0.50, 0.25       │
│  host2   down       ??:??                                        │
│  host3    up     5:42,  1 user,   load 0.10, 0.05, 0.01         │
└──────────────────────────────────────────────────────────────────┘
```

### ヘッダー部

ヘッダー行は出力されない。

### 明細部

#### upホストの場合（行262-271）

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | hostname | ホスト名 | whod.wd_hostname | "%-*.*s" | 動的（hostnamewidth） |
| 2 | status | 状態（"  up"） | interval()戻り値 | "%s" | 16文字固定 |
| 3 | uptime | 稼働時間 | wd_sendtime - wd_boottime | "D+HH:MM" or "HH:MM" | interval()生成 |
| 4 | nusers | ユーザー数 | whoent配列のカウント | "%*d user(s)" | 動的（userswidth） |
| 5 | load-1 | 1分ロードアベレージ | wd_loadav[0] / 100.0 | "%*.2f" | 動的（loadavwidth[0]） |
| 6 | load-5 | 5分ロードアベレージ | wd_loadav[1] / 100.0 | "%*.2f" | 動的（loadavwidth[1]） |
| 7 | load-15 | 15分ロードアベレージ | wd_loadav[2] / 100.0 | "%*.2f" | 動的（loadavwidth[2]） |

#### downホストの場合（行256-260）

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | hostname | ホスト名 | whod.wd_hostname | "%-*.*s" | 動的 |
| 2 | status | 状態（"down"） | interval()戻り値 | "%s" | 16文字固定 |
| 3 | downtime | 停止時間 | now - wd_recvtime | "D+HH:MM" or "??:??" | interval()生成 |

### フッター部

該当なし

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| host引数 | 特定ホストのみ表示（省略時は全ホスト） | No |
| LEFTEARTH | 4日以上応答がないホストは除外 | Yes（暗黙） |
| -aフラグ | 1時間以上アイドルのユーザーもカウント | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 | 選択オプション |
|-------|------|---------|--------------|
| デフォルト | ホスト名アルファベット順 | 昇順 | （なし） |
| -l | ロードアベレージ | 降順 | -l |
| -t | 稼働時間 | 降順 | -t |
| -u | ユーザー数 | 降順 | -u |
| -r | 逆順 | 反転 | -r |

### 改ページ条件

改ページなし

## データベース参照仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| /var/rwho/whod.* | ホスト情報の読み取り | ファイル名 |

### テーブル別参照項目詳細

#### struct whod（whodファイル）

| 参照項目 | 帳票項目との対応 | 取得条件 | 備考 |
|---------|----------------|---------|------|
| wd_hostname | hostname | read()によるファイル読取 | ホスト名 |
| wd_recvtime | down判定・downtime計算 | read() | 最終受信時刻 |
| wd_sendtime | uptime計算 | read() | 送信時刻 |
| wd_boottime | uptime計算 | read() | ブート時刻 |
| wd_loadav[3] | ロードアベレージ | read() | 100倍された値 |
| wd_we[] | ユーザー数カウント | read() | whoentエントリー配列 |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| uptime | wd_sendtime - wd_boottime | 秒→分（60秒単位で切り上げ） | interval()関数 行111-134 |
| downtime | now - wd_recvtime | 秒→分（同上） | interval()関数 |
| ISDOWN判定 | now - wd_recvtime > 11 * 60 | N/A | 11分以上応答なし→down（行51） |
| LEFTEARTH判定 | now - wd_recvtime > 4*24*60*60 | N/A | 4日以上→除外（行50） |
| nusers | count(wd_we[i]) where aflg or we_idle < 3600 | N/A | -aフラグ時はアイドルもカウント（行233） |
| ロードアベレージ | wd_loadav[i] / 100.0 | 小数点以下2桁 | 行270 |
| hostnamewidth | max(strlen(wd_hostname)) | N/A | 表示幅79カラムに収まるよう制限（行251-252） |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[コマンド実行] --> B[getoptによるオプション解析]
    B --> C[chdir _PATH_RWHODIR]
    C --> D[opendir]
    D --> E[ruptime関数呼び出し]
    E --> F[readdirループ]
    F --> G{whod.ファイル?}
    G -->|No| F
    G -->|Yes| H[read whod構造体]
    H --> I{LEFTEARTH?}
    I -->|Yes| F
    I -->|No| J{host引数マッチ?}
    J -->|No| F
    J -->|Yes| K[hs配列に追加]
    K --> L[hostnamewidth/loadavwidth/userswidth計算]
    L --> F
    F -->|完了| M[qsortでソート]
    M --> N[出力ループ]
    N --> O{ISDOWN?}
    O -->|Yes| P[down行出力]
    O -->|No| Q[up行出力（ユーザー数/ロードアベレージ含む）]
    P --> N
    Q --> N
    N -->|完了| R[終了]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| ディレクトリ不在 | /var/rwhoが存在しない | "err: /var/rwho" | rwhodデーモン起動確認 |
| ホスト不在 | 指定ホストのwhodファイルなし | "host X not in /var/rwho" | ホスト名確認 |
| ファイルなし | whodファイルが1つもない | "no hosts in /var/rwho" | rwhodデーモン稼働確認 |
| メモリ不足 | realloc失敗 | "err: NULL" | システムリソース確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 数台〜数百台のホスト |
| 目標出力時間 | ミリ秒単位（ローカルファイル読み取り） |
| 同時出力数上限 | 制限なし |

## セキュリティ考慮事項

- rwhodプロトコルは暗号化されていないため、ネットワーク上のホスト情報が平文で伝送される
- /var/rwho/ディレクトリの読み取り権限が必要
- rwhodが収集する情報にはログインユーザー情報が含まれるため、プライバシーに配慮が必要

## 備考

- rwhodデーモンが稼働している環境でのみ使用可能
- hs配列は40エントリーずつ動的拡張される（行204-208）
- 表示幅は79カラムに収まるよう自動調整される（行251-252）
- qsortのソート比較関数はオプションにより切り替え可能（hscmp/lcmp/tcmp/ucmp）

---

## コードリーディングガイド

本帳票を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ruptime.c | `usr.bin/ruptime/ruptime.c` | 行46-49: struct hs定義（whod構造体+ユーザー数） |
| 1-2 | ruptime.c | `usr.bin/ruptime/ruptime.c` | 行50-52: LEFTEARTH/ISDOWN/WHDRSIZEマクロ |

**読解のコツ**: ISDOWN判定は11分（11*60秒）、LEFTEARTH判定は4日（4*24*60*60秒）が閾値。whodの最終受信時刻との差で判定する。

#### Step 2: エントリーポイント（main）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ruptime.c | `usr.bin/ruptime/ruptime.c` | 行68-109: main関数 |

**主要処理フロー**:
1. **行76-95**: getoptによるオプション解析（a/l/r/t/u）とソート比較関数選択
2. **行99**: chdir(_PATH_RWHODIR) + opendir
3. **行102-107**: host引数ごとにruptime()呼び出し

#### Step 3: データ収集・出力処理（ruptime関数）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ruptime.c | `usr.bin/ruptime/ruptime.c` | 行177-275: ruptime関数 |

**主要処理フロー**:
- **行196-241**: readdirループでwhod.*ファイルを読み取り、hs配列に蓄積
- **行249**: qsort()で指定比較関数によるソート
- **行253-272**: ホストごとの出力（up/downで分岐）

#### Step 4: interval関数（時間表示）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ruptime.c | `usr.bin/ruptime/ruptime.c` | 行111-134: interval関数 |

**処理内容**: 秒数を"D+HH:MM"（日あり）または"HH:MM"（日なし）形式に変換。負の場合は"??:??"。

### プログラム呼び出し階層図

```
main() [ruptime.c:68]
    |
    +-- getopt() [オプション解析]
    +-- chdir(_PATH_RWHODIR) + opendir()
    |
    +-- ruptime() [ruptime.c:177]
            |
            +-- rewinddir() + readdir() ループ
            |       +-- open() / read() / close() [whodファイル]
            |
            +-- qsort() [ソート]
            |       +-- hscmp() [ホスト名順]
            |       +-- lcmp() [ロードアベレージ順]
            |       +-- tcmp() [稼働時間順]
            |       +-- ucmp() [ユーザー数順]
            |
            +-- printf() ループ [出力]
                    +-- interval() [時間フォーマット]
```

### データフロー図

```
[入力]                          [処理]                     [出力]

/var/rwho/whod.* ──────> read(struct whod)          ──> hs配列
                              |                             |
time(now) ────────────> ISDOWN/LEFTEARTH判定        ──> up/down分類
                              |                             |
hs配列 ──────────────> qsort(比較関数)              ──> ソート済みhs配列
                              |                             |
ソート済みhs配列 ──────> printf()                    ──> 標準出力
                              |
                        interval() ──> 時間文字列
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ruptime.c | `usr.bin/ruptime/ruptime.c` | ソース | メインプログラム（全機能を単一ファイルに実装） |
| Makefile | `usr.bin/ruptime/Makefile` | 設定 | ビルド設定 |
| rwhod.h | `/usr/include/protocols/rwhod.h` | ヘッダ | struct whod/whoent定義 |
| /var/rwho/ | N/A | データ | rwhodデーモンが収集したホスト情報ファイル群 |
