# PAM Tunnel非対話モード

## PAM Tunnel — 非対話モード

`pam tunnel start` の非対話モードでは、対話型ターミナルセッションなしに、スクリプト、CI/CDジョブ、ヘッドレスサーバー、**systemd**などのプロセススーパーバイザーからPAMトンネルを実行できます。本機能はPR #1848 (初版、2026-03-06) で導入され、PR #1993 (#1848を置き換え、2026-04-24) で確定しました。

***

### 概要

対話型トンネルワークフローはTTY上のユーザー操作を前提とします。バッチジョブ、ログインシェルのないリモートサーバー、パイプライン、監督下サービスでは、トンネルが**予測可能に起動**し、**準備完了を通知**し、方針に応じて**存続またはデタッチ**し、作業完了時に**確実に終了**する必要があります。

コマンダーは `pam tunnel start` にオプションのフラグを追加し、同一コマンドで以下が可能になります。

* **フォアグラウンド**で停止または **`--timeout`** (WebRTC待機) まで実行を継続
* 親プロセスは即座に終了し、**デタッチ**した子プロセスでバックグラウンド実行
* **単一のシェルコマンドをラップ**: トンネルを起動し、コマンドを実行し、トンネルを終了し、ラップしたコマンドの終了コードで終了

**ファイルベースのトンネルレジストリ**により、プロセス間での可視化とシャットダウンが可能です。他のコマンダーインスタンスが別プロセスで起動したトンネルを一覧表示し、シグナルで停止できます。**`keeper shell`** (対話モード) 内では、セッション中にトンネルが既に存続するため、 `--foreground` と `--background` は**スキップ**されます (エラーにならず無視)。

コマンダーは、これらの動作を適用する際に非対話環境 (TTYなし) を**自動検出**します。

**主な利用者**

* 対話型ターミナルがトンネルライフサイクルを所有しない**ヘッドレスサーバー**
* 限定ステップのためにトンネルを確実に起動・終了する必要がある**CI/CD**パイプライン
* メインPID、PIDファイル、シグナル駆動のシャットダウンを想定する**systemd**サービス (および同様のスーパーバイザー)
* トンネルポート経由の**localhost**上のサービスに対する運用コマンドをラップする**自動化スクリプト**

**実装上の注記**

PR #1993ではリリースブランチへクリーンにリベースし、変更セットを**3ファイル**に限定したうえで、以前のPR #1848実装を置き換えつつ、ここで説明するオペレーター向けの動作は維持されています。

***

### 新規フラグリファレンス (`pam tunnel start`)

**構文 (概念)**

本ページで説明する**新規**オプションのみを示します。既存の `pam tunnel start` 引数 (例: `--port`) は従来どおりです。

```
keeper pam tunnel start <UID> --port <local-port> [--foreground | --background | --run "<command>"] [--timeout <seconds>] [--pid-file <path>]
```

| フラグ            | 短縮    | 型                 | デフォルト   | 説明                                                                 |
| -------------- | ----- | ----------------- | ------- | ------------------------------------------------------------------ |
| `--foreground` | `-fg` | Boolean           | `false` | トンネルを**現在のプロセス**で実行。**Ctrl+C**または **`--timeout`** (WebRTC待機) まで存続。 |
| `--background` | `-bg` | Boolean           | `false` | **デタッチした子プロセス**を起動し、親は即座に終了。準備完了はファイルベースのトンネルレジストリの**ポーリング**で判定。   |
| `--run`        | `-R`  | String            | *(なし)*  | トンネル起動後に指定シェルコマンドを**exec**し、終了時にトンネルを終了し、**ラップしたコマンドの終了コード**で終了。   |
| `--timeout`    | —     | Integer (seconds) | `30`    | トンネル起動時の**WebRTC**接続待機の最大時間。                                       |
| `--pid-file`   | —     | Path string       | *(なし)*  | 接続成功後にプロセス**PID**を書き込む。トンネル停止時にファイルは**削除**される。                     |

新規フラグはすべて**任意**です。 `--foreground` 、 `--background` 、 `--run` は**相互排他**です (「相互排他ルール」をご参照ください)。

***

### `--foreground` (`-fg`)

#### 動作

トンネルは `keeper` 呼び出しと**同一プロセス**で実行されます。**SIGINT** (例: Ctrl+C) を受信するか、**WebRTC**接続待機が **`--timeout`** を超えるまでアクティブです。

**実務上の要点**

1. トンネルは **`keeper` プロセス**と同一プロセスで動作する。WebRTCセッションをデタッチした子プロセスに引き渡す構成にはならない。
2. **対話型割り込み** (Ctrl+C) は通常のターミナル駆動の方法 (SIGINT) でプロセスを終了させる。
3. **`--timeout`** 内にトンネルが準備完了にならない場合、他モードと同じタイムアウト意味論で起動は失敗する。

#### 利用シーン

**スーパーバイザー**または対話オペレーターがトンネルライフサイクルを所有する場合。ターミナル、単一メインプロセスのコンテナ、**`systemd`** が `MAINPID` を追跡するユニットなど。

#### 例 — 終了まで存続

```
keeper pam tunnel start <UID> --port 5432 --foreground
```

#### 例 — PIDファイル付きフォアグラウンド

接続後にPIDを書き込み、外部ツールがプロセスへシグナルを送れるようにする例。

```
keeper pam tunnel start <UID> --port 5432 --foreground --pid-file /tmp/tunnel.pid
```

***

### `--background`(`-bg`)

#### 動作

コマンダーはトンネルを所有する**デタッチした子プロセス**を起動します。起動が進むと**親は即座に終了**します。準備完了は**ファイルベースのトンネルレジストリ** (`<tmp>/keeper-tunnel-sessions/` 配下のJSONセッションファイル) の**ポーリング**で確認します。

**実務上の要点**

1. **親子の分離**: **子**がトンネルを継続し、**親**は起動開始後すぐにシェルまたはCIランナーへ制御を返す。
2. **準備完了**: 対話的にブロックせず、レジストリファイルでトンネル登録がライブセッションを反映しているかを確認する。
3. **シャットダウン**: **`--pid-file`** に記録したPIDへシグナルを送るか、 `pam tunnel stop` で停止できる (下記のプロセス間連携をご参照ください)。

#### 利用シーン

スクリプトが**直ちに制御を返す**必要がある場合。トンネル起動後に同一スクリプトでクライアントコマンドを実行し、PIDファイルまたは `pam tunnel stop` で停止する、など。

#### 例 — デーモン化、クライアント実行、PIDで停止

```
keeper pam tunnel start <UID> --port 5432 --background --pid-file /tmp/tunnel.pid
pg_dump -h localhost -p 5432 mydb > backup.sql
kill -SIGTERM $(cat /tmp/tunnel.pid)
```

***

### `--run` (`-R`)

#### 動作

コマンダーは**トンネルを起動**し、続けて指定したシェルコマンドを**実行**します。コマンド終了時に**トンネルを停止**し、プロセス全体の**終了コードはラップしたコマンドと同じ**になります。

**ライフサイクルの概要**

| フェーズ  | 動作                                                              |
| ----- | --------------------------------------------------------------- |
| 起動    | トンネルを確立し、**WebRTC**の準備完了まで最大 **`--timeout`** 待機 (デフォルト**30**秒)。 |
| 実行    | トンネルが利用可能になったあと、通常のシェル意味論で **`"<command>"`** を実行。               |
| 停止    | ラップしたコマンド終了時にトンネルを自動終了 (成功・失敗を問わない)。                            |
| 終了コード | ラップしたコマンドの終了コードを呼び出し元 (CI、スクリプト、systemd) へ伝播。                   |

#### 利用シーン

**ワンショット自動化**: データベースダンプ、マイグレーション、ヘルスチェックなど、トンネル経由のlocalhostアクセスが必要で起動・停止を手動管理したくないCLI。

#### 例 — トンネルライフサイクル付き単一コマンド

```
keeper pam tunnel start <UID> --port 5432 --run "pg_dump -h localhost -p 5432 mydb > backup.sql"
```

#### 例 — コマンド実行前のWebRTC待機時間を延長

```
keeper pam tunnel start <UID> --port 5432 --run "my_command" --timeout 60
```

***

### `--timeout` と `--pid-file`

#### `--timeout <seconds>`

トンネル起動時の**WebRTC**接続待機時間を制御します。**デフォルト: `30`** 秒。遅延や高レイテンシのネットワークでは **`--run`** などで値を増やしてください。

タイムアウトは**接続確立**に適用され、その後トンネルが存続する時間には適用されません。長時間トンネルには **`--foreground`** または \*\*`--background`\*\*を使い、外部 (シグナル、 `pam tunnel stop` 、スーパーバイザー) でライフサイクルを管理してください。

#### `--pid-file <path>`

トンネル**接続後**、プロセス**PID**を指定パスへ書き込みます。トンネル**停止時**にファイルは**削除**されます。 `--foreground` (メインプロセスへシグナル) や `--background` (デタッチした所有者へシグナル) と相性が良いです。

**運用上の注記**

* PIDファイルは `kill -SIGTERM $(cat /path/to/pid)` 形式のオーケストレーション (PRの例) の安定した連携点です。
* **systemd**では `PIDFile=` を `--pid-file` と揃え、 `$MAINPID` と `ExecStop` が同一プロセスを指すようにします (systemdサービス例をご参照ください)。

**例**

```
keeper pam tunnel start <UID> --port 5432 --foreground --pid-file /tmp/tunnel.pid
```

```
keeper pam tunnel start <UID> --port 5432 --background --pid-file /tmp/tunnel.pid
```

***

### プロセス間トンネルレジストリ

モジュール **`keepercommander/commands/tunnel_registry.py`** は、トンネルを**プロセス間で可視化**する**ファイルベースのレジストリ**を実装しています。

* セッションメタデータは以下の配下へ**アトミックなJSON書き込み**で保存されます。

  ```
  <tmp>/keeper-tunnel-sessions/<pid>.json
  ```
* セッションディレクトリは**POSIX**で **`0o700`** 権限です。
* **古いエントリ**は自動**クリーンアップ**されます。
* **重複バインド検出**により競合するトンネルエンドポイントを回避しやすくなります。

#### ファイル名とレイアウト

各JSONファイルは **`<pid>.json`** でキーされ、**`pid`** はそのレジストリエントリを所有するトンネルプロセスを識別します。親ディレクトリ **`keeper-tunnel-sessions`** はプラットフォームの一時ディレクトリ (**`<tmp>`**) 配下にあり、OSの慣例に従って解決されます。

#### 目的

プロセス間のビューがなければ、起動したコマンダープロセスだけがアクティブなトンネルを把握できます。レジストリにより**バックグラウンド**起動の観測が可能になり、トンネルが起動シェルを超えて存続しても**list** / **stop**が一貫します。**スクリプト**、**サービス**、**リモート自動化**で重要です。

このレジストリにより、**他のコマンダープロセス**で起動したトンネルとも **`pam tunnel list`** および **`pam tunnel stop`** が連携します。

***

### `pam tunnel list` と `pam tunnel stop` (プロセス間)

#### `pam tunnel list`

listコマンドでは、現在のセッションが所有するトンネルだけでなく、**ファイルレジストリ**を読み取り**他プロセス**のトンネルも表示します。**古い**レジストリエントリは**自動クリーンアップ**されます。

#### `pam tunnel stop`

stopは**ファイルレジストリ**にフォールバックし、**プロセス間**のトンネルを**POSIX**では**SIGTERM**、Windowsでは**TerminateProcess**で終了します。**`--all`** オプションもレジストリ経由で発見した**プロセス間**トンネルを停止します。

**オペレーター向け早見表**

| 目的                   | 方法                                                                                                    |
| -------------------- | ----------------------------------------------------------------------------------------------------- |
| 例のPIDファイルパターンで停止     | **`--pid-file`を読みSIGTERM**を送信 (例: **`kill -SIGTERM $(cat /tmp/tunnel.pid)`**)。                        |
| コマンダー経由でプロセス間トンネルを停止 | **`pam tunnel stop`** を実行 — **ファイルレジストリ**にフォールバックし、リモート所有者へシグナル (**SIGTERM** / **TerminateProcess**)。 |
| すべて停止                | **`pam tunnel stop --all`もレジストリで見つかったプロセス間**トンネルを停止。                                                  |
| 他プロセスのトンネルを確認        | **`pam tunnel list`** を実行 — レジストリ上のセッションが表示され、**古い**エントリは**自動クリーンアップ**。                               |

***

### systemdサービス例

PR #1993には **`[Service]`** 配線のコメント付き例が含まれています。以下は **`/etc/systemd/system/`** に配置できる完全なユニット例です (パスと **`keeper`** の位置は環境に合わせて調整してください)。

```
# [Service]
# ExecStart=/usr/bin/keeper pam tunnel start <UID> --port 5432 --foreground --pid-file /run/keeper-tunnel.pid
# ExecStop=/bin/kill -SIGTERM $MAINPID
# PIDFile=/run/keeper-tunnel.pid
```

以下のユニットはsystemd監督下でトンネルを**フォアグラウンド**実行し、接続後に**PIDファイル**を書き、**`SIGTERM`** でクリーンに停止します。

```ini
[Unit]
Description=Keeper PAM Tunnel
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/usr/bin/keeper pam tunnel start <UID> --port 5432 --foreground --pid-file /run/keeper-tunnel.pid
ExecStop=/bin/kill -SIGTERM $MAINPID
PIDFile=/run/keeper-tunnel.pid
Restart=on-failure

[Install]
WantedBy=multi-user.target
```

**`ExecStart`** のパス、**`<UID>`**、**`--port`**、**`PIDFile`** は環境に合わせて調整してください。

***

### 相互排他ルール

以下のモードは**併用できません**。

| モード      | フラグ                  |
| -------- | -------------------- |
| フォアグラウンド | `--foreground`/`-fg` |
| バックグラウンド | `--background`/`-bg` |
| 実行ラッパー   | `--run`/`-R`         |

1回の呼び出しでは、上記3つのうち**1つ**を選択してください。

**追加の動作**

* コマンダーは **TTY がない**場合に非対話利用を**自動検出**します。
* **対話型**の **`keeper shell`** セッション内では、**`--foreground`** と **`--background`** は**スキップ**されます (そのコンテキストではトンネルが既に存続)。

#### 相互作用の概要

| コンテキスト                                 | `--foreground`/`--background`                                           |
| -------------------------------------- | ----------------------------------------------------------------------- |
| コマンダーが非対話モード (**TTYなし**) を**自動検出**した場合 | 各セクションで説明どおり動作する。                                                       |
| 対話型\*\*`keeper shell`\*\*              | **`--foreground`** と **`--background`** は**スキップ** — そのセッションではトンネルが既に存続。 |

***

### 後方互換性

新規フラグのデフォルトは、リファレンス表のとおり **`false`**、**`None`**、**`30`** (`--timeout`) です。**省略した場合**、これらの変更前と `pam tunnel start` の動作は**同じ**です。既存のスクリプトや操作手順は修正なしで有効です。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.keeper.io/keeperpam/jp/commander-cli/command-reference/keeperpam-commands/pam-tunnel-non-interactive-modes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
