はじめに
Linux 環境の運用では、コマンド実行中にパスワード入力を求められたり、確認プロンプト(Yes/No)で処理が一時停止したりする「対話処理」が、バッチスクリプトによる自動化の障壁になります。この対話を自動応答させるためのツールが expect です。本記事では Ubuntu 環境での基本的な使い方から、実務で頻出する SSH 自動ログインのスクリプト例、現行 OpenSSH への対応、そして安全な代替手段との使い分けまでを解説します。
- expect が対話処理を自動化する仕組みと 4 つの主要コマンド
- Ubuntu でのインストール手順とバージョン確認方法
- SSH 自動ログインスクリプトの作成例と、現行 OpenSSH プロンプトへの対応
- 平文パスワードのリスクと、SSH 公開鍵認証・sshpass との使い分け
expect は、システムの出力を監視して事前に定義した文字列を自動送信することで、SSH 接続や sudo などの対話処理をスクリプト化するツールです。Ubuntu では sudo apt install expect で導入でき、spawn・expect・send・interact の 4 コマンドで SSH 自動ログインを構成できます。ただしパスワードを平文で扱う性質上、サーバー間の自動化では SSH 公開鍵認証を優先し、expect は鍵非対応のレガシー機器などに用途を絞る使い分けが現実的です。
expect コマンドとは ── 対話処理を自動化する仕組み
Linux の標準的なシェルスクリプト(bash など)は、記述されたコマンドを上から順に実行する直列処理を得意とします。しかし、途中でユーザーからの入力を待機する処理(プロンプト)が発生すると、そこで処理がブロックされます。
コマンドラインにおける「対話(プロンプト待機)」の課題
例えば ssh コマンドでリモートサーバーに接続する際や、sudo コマンドを実行する際、システムはパスワード入力を求めて一時停止します。これらのコマンドは、標準入力(パイプやリダイレクト)からパスワードを受け付けない仕様になっていることが多いため、単純なシェルスクリプトでは自動化が困難です。
expect が自動応答を実現する仕組み
expect は、このような対話処理を自動化するために設計されたプログラムです。仕組みはシンプルで、「システムが出力する文字列を監視(expect)」し、あらかじめ設定した特定の文字列(password: など)を検知すると、「事前に定義した文字列を送信(send)」します。この「出力の監視」と「入力の送信」を組み合わせることで、人間がキーボードで応答しているかのように、対話処理をスクリプト上で完結させられます。

公式マニュアルでも、まず 4 つの中核コマンドから理解することが案内されています。
参考: Expect マニュアルページ(tcl-lang.org)
“start by reading the descriptions of spawn, send, expect, and interact”
(spawn、send、expect、interact の説明から読み始めるとよい)
https://www.tcl-lang.org/man/expect5.31/expect.1.html
expect のインストールと基本構文
Ubuntu / Debian 系 Linux では、標準のパッケージマネージャー(apt)から expect をインストールできます。expect の安定版は 5.45.4(2018 年公開)で、長期にわたり仕様は安定しています。
Ubuntu / Debian 環境へのインストール手順
# パッケージリストの更新
sudo apt update
# expect のインストール
sudo apt install expectインストール後、expect -v でバージョン情報が表示されれば準備完了です(-v はバージョンを表示して終了するオプションです)。
中核となる 4 つの主要コマンド
expect スクリプトの中核となるコマンドは以下の 4 つです。これらの組み合わせで、多くの対話処理を自動化できます。
spawn: 自動化したいコマンド(ssh や ftp など)を、expect の管理下で子プロセスとして起動する。expect: システムからの出力(プロンプトなど)を監視し、指定した文字列にマッチするまで待機する。send: マッチした文字列に対して、応答として文字列(パスワードなど)を送信する。interact: expect による自動処理を終了し、人間によるキーボード操作に制御を戻す。
send で文字列を送る際は、文末に改行を含めます。端末(pty)相手の対話では、\n よりも復帰文字 \r を用いるほうが安定して動作します。
参考: Expect マニュアルページ(man7.org)
“A return character is denoted \r.”
(復帰文字は \r で表される)
https://man7.org/linux/man-pages/man1/expect.1.html
expect を使った SSH 自動ログインスクリプト
インフラ運用で需要の高い SSH 接続の自動化を例に、具体的なスクリプトの作成手順を解説します。
SSH 自動接続スクリプトの作成例
リモートサーバーに SSH 接続し、パスワード入力を自動で行ったうえで、そのままターミナル操作を続行できるスクリプト(auto_ssh.sh)の例です。
#!/usr/bin/expect
# 変数の定義(環境に合わせて変更してください)
set HOST "192.168.1.100"
set USER "admin"
set PASS "P@ssw0rd123"
# タイムアウトの設定(秒)
set timeout 10
# SSH 接続コマンドの起動
spawn ssh ${USER}@${HOST}
# システムからの応答を監視し、分岐処理を行う
expect {
# 初回接続時のホストキー確認(yes/no/[fingerprint])が出た場合
"Are you sure you want to continue connecting" {
send "yes\r"
exp_continue
}
# パスワード入力プロンプトが出た場合(大文字小文字を区別しない)
-nocase "password:" {
send "${PASS}\r"
}
# タイムアウトした場合のエラー処理
timeout {
puts "接続がタイムアウトしました。"
exit 1
}
}
# 自動ログイン完了後、ユーザーのキーボード操作に切り替える
interact
スクリプトの処理フローと変数展開
シェバン(#!/usr/bin/expect)は、このスクリプトが bash ではなく expect で実行されることを宣言します。
変数の定義(set)では、接続先の IP アドレス、ユーザー名、パスワードを変数として定義し、後続処理で ${変数名} として展開します。接続先が変わってもスクリプトの修正が容易になります。
分岐処理(expect {})では、初回接続時の確認プロンプトと通常の password: プロンプトの両方に対応できるよう、波括弧内でパターンマッチングを行います。exp_continue は、マッチ後に再度 expect の監視を継続させるためのコマンドです。
旧来の記述からの変更点は次の通りです。
- 送信文字列の改行を
\nから\rに統一し、端末相手での安定性を高めています。 - ホストキー確認のパターンを
Are you sure you want to continue connectingまでに短縮し、現行 OpenSSH の(yes/no/[fingerprint])形式でも前方一致で拾えるようにしています。 - パスワードのパターンに
-nocaseを付与し、Password:とpassword:の表記差を吸収しています。
手動操作への移行(interact)は、パスワード送信後にログインした状態で制御を人間に戻します。このコマンドがないと、ログイン成功と同時にスクリプトが終了し、接続が切断されます。
ホストキー確認を簡素化する別解
初回接続時の yes/no 分岐をスクリプトから省きたい場合、OpenSSH 7.6 以降で使える StrictHostKeyChecking=accept-new を spawn の ssh オプションに付与する方法があります。
# 未知のホストは known_hosts に追加し、yes/no プロンプトを出さない
spawn ssh -o StrictHostKeyChecking=accept-new ${USER}@${HOST}このオプションは、未知のホスト鍵を自動で受け入れて known_hosts に追加する一方、既知ホストの鍵が変化した場合は接続を拒否します。StrictHostKeyChecking=no のようにすべての検証を無効化するわけではないため、自動化と最低限の安全性を両立しやすい選択肢です。ただし初回接続時の中間者攻撃を完全に防ぐものではないため、信頼できるネットワーク内での利用にとどめることをおすすめします。
参考: OpenSSH ssh_config マニュアル
“accept-new” mode automatically adds new host keys to known_hosts.
(accept-new は新規ホスト鍵を自動的に known_hosts へ追加する挙動)
https://man.openbsd.org/ssh_config
expect 利用時の制約とハマりポイント
expect は強力ですが、対話の自動化という性質上、いくつか押さえておきたい制約があります。実務でつまずきやすい点を整理します。
パターンマッチは既定で glob 方式
expect のパターンマッチは、既定でワイルドカード(glob)方式です。* や ?、[ ] が特殊文字として扱われます。正規表現でマッチさせたい場合は -re、文字列の完全一致で判定したい場合は -ex を指定します。プロンプト文字列に記号が含まれる場合は、意図しないマッチを避けるため明示的なフラグ指定を検討します。
参考: Expect マニュアルページ(man7.org)
“new users may find it easier to start by reading the descriptions of spawn, send, expect”
(新規ユーザーは spawn、send、expect の説明から読むとよい)
https://man7.org/linux/man-pages/man1/expect.1.html
大文字小文字と改行コードの差異
password: と Password: のように、プロンプトの表記は接続先によって異なります。-nocase を付与すると大文字小文字の差を吸収できます。また送信文字列の改行は、端末(pty)相手では \n よりも \r のほうが安定します。スクリプトが「プロンプトは出ているのに応答が送られない」という挙動を示す場合、改行コードが原因のことがあります。
タイムアウトと平文パスワードの課題
set timeout で指定した秒数を超えると、expect はタイムアウトします。上記の例では 10 秒に設定しており、ネットワーク遅延が大きい環境では延長を検討します。timeout ブロックでのエラー処理を用意しておくと、想定外のプロンプト変化で無限待機する事態を避けられます。
そして expect 最大の留意点は、スクリプト内にパスワードを平文で保持せざるを得ない点です。 expect は「対話の自動応答」を担うツールであり、認証情報の安全な管理そのものは解決しません。この課題への対処は、次のセクションの代替手段との使い分けで整理します。
SSH 自動ログインの代替手段と使い分け
expect は対話処理全般に使える汎用ツールですが、用途が SSH のパスワード自動化に限られる場合は、より適した手段があります。本番運用ではセキュリティ要件に応じて使い分けます。
パスワードを平文で保存するリスク
expect スクリプトで認証処理を自動化する場合、ファイル内にパスワードを平文(クリアテキスト)で記述するか、外部ファイルから読み込ませる必要があります。第三者にスクリプトを閲覧されると、システムへの不正アクセスにつながりかねません。最低限の対策として、スクリプトファイルのパーミッションを 600 や 700 に設定し、所有者以外が読み取れないよう制限することをおすすめします。
SSH 公開鍵認証(推奨される標準手法)
サーバー間の SSH 接続や rsync によるファイル同期を自動化したい場合は、expect ではなく SSH 公開鍵認証(パスフレーズなしの鍵ペア)を利用するのが、インフラ運用の標準的な手法です。公開鍵認証なら、パスワードをスクリプトに保存せずに自動ログインを構成できます。詳細は関連記事『SSH 公開鍵認証の設定手順』を参照してください。
sshpass(SSH 限定の簡易手段)
SSH のパスワード認証だけを手早く自動化したい場合は、sshpass という選択肢もあります。Ubuntu では sudo apt install sshpass で導入でき、sshpass -p 'パスワード' ssh user@host の形で利用します。sshpass は専用の擬似端末で ssh を実行し、対話入力が来たかのように見せかける仕組みです。
ただし -p でコマンドラインにパスワードを渡すと、ps コマンドで同一ホストの他ユーザーにパスワードが見えてしまうため、ファイル渡し(-f)や環境変数渡し(-e)が比較的安全です。多くのディストリビューションが sshpass を既定で同梱しないのも、平文パスワードの取り扱いに対する安全側の判断です。
参考: sshpass マニュアルページ(Ubuntu)
“sshpass runs ssh in a dedicated tty, fooling it”
(sshpass は専用の tty で ssh を実行し、対話入力に見せかける)
https://manpages.ubuntu.com/manpages/jammy/man1/sshpass.1.html
比較表と選定基準
| 手段 | 認証方式 | 向くケース | 主なリスク・留意点 |
|---|---|---|---|
| SSH 公開鍵認証 | 鍵ペア | サーバー間自動化の標準 | 秘密鍵の管理・漏洩対策 |
| expect | 対話の自動応答 | 鍵非対応のレガシー機器、複数プロンプトの制御 | スクリプト内の平文パスワード |
| sshpass | パスワードの非対話投入 | SSH 限定の簡易・一時的な自動化 | ps でのパスワード露出 |
| Ansible 等 | 鍵+Vault 等 | 多数ホストの継続的な構成管理 | 学習コスト、初期設計 |
選定の目安は次の通りです。
- 自分が管理するサーバー間の自動化 → SSH 公開鍵認証
- 鍵を登録できない古いルーターやスイッチ → expect
- SSH 単発・簡易の自動化(信頼できる環境のみ)→ sshpass
- 多数ホストを継続的に運用 → Ansible 等の構成管理ツール
まとめ
expect は、システムの出力を監視して定義済みの文字列を自動送信することで、SSH 接続などの対話処理をスクリプト化するツールです。導入と基本構文はシンプルですが、平文パスワードを扱う性質上、用途に応じた代替手段との使い分けが現実的です。要点を以下にまとめます。
- expect はシステム出力を監視し定義済み文字列を自動送信する仕組み
- Ubuntu では
sudo apt install expectで導入可能 - spawn・expect・send・interact の 4 コマンドによる対話制御
- 送信文字列の改行は
\r、パスワードは-nocaseで取りこぼし防止 - ホストキー確認は
accept-newでプロンプト省略が可能 - 平文パスワードのリスクから鍵認証や Vault との併用が現実的
- サーバー間は鍵認証、レガシー機器は expect という使い分け
以上、最後までお読みいただきありがとうございました。
