【Linux】expect コマンドの使い方 | SSH 接続や対話処理を自動化するスクリプト例

  • URLをコピーしました!
目次

はじめに

Linux 環境の運用において、コマンド実行中にパスワードの入力を求められたり、確認プロンプト(Yes/No)で処理が一時停止したりする「対話処理」は、バッチスクリプトなどによる自動化の大きな障壁となります。

この対話型のコマンド操作を、スクリプト内で自動応答させるためのツールが「expect」です。本記事では、Ubuntu 環境における expect の基本的な使い方から、実務で頻出する「SSH 接続の自動化(自動ログイン)」を想定した実践的なスクリプト例までを解説します。

この記事でわかること
  • expect コマンドが対話処理を自動化する仕組み
  • Ubuntu へのインストール手順と4つの主要コマンド
  • SSH 自動ログインスクリプトの作成例と処理フロー
  • 運用時のセキュリティリスクと代替手段の検討

expect コマンドとは?対話処理を自動化する仕組み

Linux の標準的なシェルスクリプト(bash など)は、記述されたコマンドを上から順に実行していく直列的な処理を得意とします。しかし、途中でユーザーからの入力を待機する処理(プロンプト)が発生すると、そこで処理がブロックされてしまいます。

コマンドラインにおける「対話(プロンプト待機)」の課題

例えば、ssh コマンドでリモートサーバーに接続する際や、sudo コマンドを実行する際、システムはパスワード入力を求めて一時停止します。これらのコマンドは、標準入力(パイプやリダイレクト)からパスワードを受け付けない仕様になっていることが多いため、単純なシェルスクリプトでは自動化が困難です。

expect が自動応答を実現する仕組み

expect は、このような対話処理を自動化するために設計されたプログラムです。

その仕組みは非常にシンプルで、「システムから出力される文字列を監視(expect)」し、あらかじめ設定した特定の文字列(「password:」など)を検知すると、「事前に定義した文字列を送信(send)」します。

この「出力の監視」と「入力の送信」を組み合わせることで、人間がキーボードを叩いて応答しているかのように、システムとの対話処理をスクリプト上で完結させることが可能になります。

expect のインストールと基本構文

Ubuntu / Debian 系 Linux では、標準のパッケージマネージャ(apt)から簡単に expect をインストールできます。

Ubuntu / Debian 環境へのインストール手順

# パッケージリストの更新
sudo apt update

# expect のインストール
sudo apt install expect

インストール後、expect -v コマンドでバージョン情報が表示されれば準備完了です。

必須となる4つの主要コマンド

expect スクリプトを記述する上で、中核となるコマンドは以下の4つです。これらを組み合わせることで、ほとんどの対話処理を自動化できます。

  • spawn: 自動化したいコマンド(ssh や ftp など)を、expect の管理下で子プロセスとして起動します。
  • expect: システムからの出力(プロンプトなど)を監視し、指定した文字列にマッチするまで待機します。
  • send: マッチした文字列に対して、応答として文字列(パスワードなど)を送信します。
  • interact: expect による自動処理を終了し、人間による手動操作(キーボード入力)に制御を戻します。

send の文末には必ず改行(\n\r)を含めます。

【実践】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)が出た場合
    "Are you sure you want to continue connecting (yes/no" {
        send "yes\n"
        exp_continue
    }
    # パスワード入力プロンプトが出た場合
    "password:" {
        send "${PASS}\n"
    }
    # タイムアウトした場合のエラー処理
    timeout {
        puts "接続がタイムアウトしました。"
        exit 1
    }
}

# 自動ログイン完了後、ユーザーのキーボード操作に切り替える
interact

スクリプト内の処理フローと変数展開の解説

シェバン(#!/usr/bin/expect

このスクリプトが bash ではなく expect で実行されることを宣言します。

変数の定義(set

接続先の IP アドレス、ユーザー名、パスワードを変数として定義し、後続の処理で ${変数名} として展開します。これにより、接続先が変わってもスクリプトの修正が容易になります。

分岐処理(expect {}

初回接続時に発生する yes/no の確認プロンプトと、通常の password: プロンプトの両方に対応できるよう、波括弧内でパターンマッチングを行っています。exp_continue は、マッチ後に再度 expect 処理(監視)を継続させるためのコマンドです。

手動操作への移行(interact

パスワード送信後、システムにログインした状態で制御を人間に戻します。このコマンドがないと、ログイン成功と同時にスクリプトが終了し、接続が切断されてしまいます。

運用時のセキュリティリスクと推奨される代替手段

expect は対話処理を自動化する強力なツールですが、本番環境で運用する際にはセキュリティ上のリスクを正しく理解し、適切な代替手段と比較検討する必要があります。

パスワードを平文で保存するリスクについて

expect スクリプトの性質上、認証が必要な処理を自動化する場合、スクリプトファイル内にパスワードを平文(クリアテキスト)で直接記述するか、外部ファイルから読み込ませる必要があります。

もし悪意のある第三者や他のユーザーにスクリプトを閲覧された場合、システムへの不正アクセスを容易に許してしまう重大なインシデントに繋がります。最低限の対策として、スクリプトファイルのパーミッションを 600700 に厳格に設定し、所有者以外が読み取れないように制限をかけることが必須です。

SSH 公開鍵認証(パスフレーズなし)との適切な使い分け

Linux サーバー間の SSH 接続や rsync によるファイル同期を自動化したい場合、expect ではなく「SSH 公開鍵認証(パスフレーズなしの鍵ペア)」を利用するのが、インフラ運用の標準的なベストプラクティスです。

公開鍵認証を利用すれば、パスワードをスクリプトに保存することなく、安全に自動ログインが可能です。expect コマンドは、「公開鍵認証をサポートしていない古いネットワーク機器(ルーターやスイッチ)へのログイン」や「パスワード入力が必須なレガシーシステムの対話型バッチ実行」など、標準的な手法で回避できないケースに限定して活用することを推奨します。

まとめ

本記事では、Linux 環境における expect コマンドの基本と、SSH 自動ログインスクリプトの作成手順について解説しました。

  • expect はシステムの出力を監視し、事前に定義した文字列による自動応答を実現する。
  • Ubuntu 環境では標準のパッケージマネージャから容易にインストールできる。
  • spawn、expect、send、interact の 4 つの基本コマンドで高度な対話処理を構築できる。
  • パスワードの平文保存にはリスクが伴うため、可能であれば SSH 公開鍵認証を優先する。

以上、最後までお読みいただきありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!

この記事を書いた人

主にインフラを得意とするエンジニアです。日々の業務で得た実践的なノウハウや、最新の脆弱性ニュースなどを備忘録を兼ねて発信しています。
同じエンジニアの方々の課題解決のヒントになれば嬉しいです。

[ Certs ] CCIE Lifetime Emeritus / VCAP-DCA ✒️ [ Life ] 技術書・ビジネス書愛好家📖 / 小・中学校で卓球コーチ👟

目次