English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

expectコマンドを使用してShellの自動化インタラクションを実現する方法の詳細

背景

linuxのスクリプトでは、リモート操作を行う多くのシーンがあります。例えば、リモートログインssh、リモートコピーscp、ファイル転送sftpなどです。これらのコマンドでは、セキュリティパスワードの入力が必要で、通常の使用では、パスワードを手動で入力し、セキュリティ認証を受け入れる必要があります。リモート操作の自動化を実現するために、expectの機能を利用することができます。

expectは無料のプログラミング言語で、自動およびインタラクティブなタスクの通信を実現し、人的な介入なしで使用できます。expectは進化し続けており、時間が経つにつれて機能が強化され、システム管理者の強力なアシスタントとして人気があります。expectはTclプログラミング言語のサポートが必要であり、expectを実行するにはまずTclをインストールする必要があります。

expectのインストール

expectはTclの上に構築されたため、expectをインストールする前にまずTclをインストールする必要があります。

(一)Tcl インストール

ホームページ: http://www.tcl.tk

ダウンロード先: http://www.tcl.tk/software/tcltk/downloadnow84.tml

1.ソースコードパッケージのダウンロード

wget http://nchc.dl.sourceforge.net/sourceforge/tcl/tcl8.4.11-src.tar.gz 

2.ソースコードパッケージの解凍

tar xfvz tcl8.4.11-src.tar.gz 

3.インストール設定

cd tcl8.4.11/unix 
./configure --prefix=/usr/tcl --enable-shared 
make 
make install 

注意:

1、インストールが完了した後、tclのソースコードのルートディレクトリに移動し、サブディレクトリunixの下のtclUnixPort.hをサブディレクトリgenericにコピーします。

2、一時的にtclのソースコードを削除しないでください。なぜなら、expectのインストールプロセスではそれが必要になるからです。

(二)expect インストール(Tclのライブラリが必要)

ホームページ: http://expect.nist.gov/

1.ソースコードパッケージのダウンロード

wget http://sourceforge.net/projects/expect/files/Expect/5.45/expect5.45.tar.gz/download 

2.ソースコードパッケージの解凍

tar xzvf expect5.45.tar.gz 

3.インストール設定

cd expect5.45 
./configure --prefix=/usr/expect --with-tcl=/usr/tcl/lib --with-tclinclude=../tcl8.4.11/generic 
make 
make install 
ln -s /usr/tcl/bin/expect /usr/expect/bin/expect 

expect

expectの核心はspawn、expect、send、setです。

spawn 実行するコマンドを呼び出します

  • expect コマンド提示情報の出現を待ち、つまりユーザーが入力する提示をキャッチします:
  • send 必要なインタラクティブ値を送信し、ユーザーが手動で入力する内容を置き換えます
  • set 変数の値を設定します
  • interact 実行完了後にインタラクティブ状態を維持し、コントロール権をコンソールに渡します。この時点で手動で操作することができます。この行がないと、ログインが完了した後、リモート端末に残らず退出します。
  • expect eofは必ず追加してください。spawnと対応して、ターミナル出力情報の終了をキャッチします。if....endifに似ています

expectスクリプトはinteractまたはexpect eofで終了する必要があります。自動化タスクを実行する場合、通常expect eofで十分です。

他の設定

  • expectは常にタイムアウトを設定しないように設定します set timeout -1
  • expectを設定 300秒超時、超過すると300 expectの内容が見つからない場合、set timeoutを終了します 300

expectの構文

expectはTcl構文を使用しています

  • Tclコマンドはスペースで区切られたワードで構成されています。そのうち、最初のワードはコマンド名で、残りはコマンドのパラメータです
    cmd arg arg arg
  • $シンボルは変数の値を表します。この例では、変数名はfooです。
    $foo
  • 角括弧はネストされたコマンドを実行します。例えば、コマンドの結果を別のコマンドのパラメータとして渡したい場合、このシンボルを使用します
    [cmd arg]
  • ダブルクォートは単語群をコマンドのパラメータとしてマークします。"$"シンボルおよび角括弧はダブルクォート内で解釈されます
    "some stuff"
  • 大括弧は単語群をコマンドのパラメータとしてマークします。ただし、大括弧内の他のシンボルは解釈されません
    {some stuff}
  • 反スラッシュシンボルは特殊シンボルを参照するために使用されます。例えば:nは改行を表します。反スラッシュシンボルは"$"シンボル、引用符、角括弧、および大括弧の特殊意味を閉じるためにも使用されます


login.expはリモートログイン専用で、簡単な使用方法:login.exp "exclude" "${remote_ip}" "${remote_user}" "${remote_passwd}" "${remote_command}"

#!/usr/bin/expect -f
##########################################################
#SSHを通じてログインしてコマンドを実行
#パラメータ:1.Use_Type [check/execute]
#  2.SSHServerIp
#  3.SSHUser
#  4.SSHPassword
#  5.CommandList [複数のコマンド間で;で区切る]
#返り値:
# 0 成功
#  1 パラメータの数が正しくありません
#  2 SSHサーバーサービスが開いていません
#  3 SSHユーザーパスワードが不正です
#  4 SSHサーバー接続タイムアウト
##########################################################
proc usage {} {
 regsub ".*/" $::argv0 "" name
 send_user "Usage:\n"
 send_user " $name Use_Type SSHServerIp SSHUser SSHPassword CommandList\n"
 exit 1
} 
## 引数の個数を確認
if {[llength $argv] != 5}
 usage
}
#変数の設定
Use_Typeを[argvの0番目]に設定
SSHServerIpを[argvのlindex]に設定 1]
SSHUserを[argvのlindex]に設定 2]
SSHPasswordを[argvのlindex]に設定 3]
CommandListを[argvのlindex]に設定 4]
#spawn ping ${SSHServerIp} -w 5
#expect {
# -nocase -接続拒否"10パケット損失0%" {
#  send_error "Ping ${SSHServerIp}は到達不能です、IPアドレスを確認してください。\n"
#  exit 1
# }
#}
タイムアウトを設定 360
ressshを0に設定
#ssh接続時にyesを確認するかどうかを示す変数の定義
inputYesを0に設定
ok_stringをLOGIN_SUCCESSに設定
if {$Use_Type=="check"} {
 #ssh接続をアクティブにする場合、yesを入力して確認が必要な場合は、yesを入力し、inputYesを設定1、それともSSHパスワードを入力
 ssh ${SSHUser}@${SSHServerIp} "echo $ok_string"
} else {   
 ssh ${SSHUser}@${SSHServerIp} "$CommandList"をスパン
}
expect {
 -nocase -yes/no" {
  send -- yes\n
  inputYesを設定 1
 }
 -nocase -re "assword: " {
  send -- "${SSHPassword}\n"
  set resssh 1
 }
 #-nocase -接続拒否" { 
 #  send -- "${CommandList}\n"
 #}
 $ok_string {}
 -nocase -接続拒否" {
  SSHサービスが${SSHServerIp}でアクティブではありません。\nsend_error "
  exit 2
 }
 timeout {}}
  send_error "Connect to SSH server ${SSHUser}@${SSHServerIp} timeout(10s).\n"
  exit 4
 }
}
#「yes」を確認した場合、SSH パスワードを入力します。
if {$inputYes==1}
 expect {
  -nocase -re "assword: " {
   send -- "${SSHPassword}\n"
   set resssh 1
  }
 }
}
#もし「try again」または「password:」の表示があれば、ユーザー名とパスワードが間違っていることを示しています。直接退出します。
if {$resssh==1}
 expect {
  -nocase -re "try again" {
   send_error "SSH user:${SSHUser} passwd error.\n"
   exit 3
  }
  -nocase -re "assword:" {
   send_error "SSH user:${SSHUser} passwd error.\n"
   exit 3
  }
  eof {}
 }
}
send_error -- "$expect_out(buffer)"
#-nocase -re "No such user" {
#  send_error "No such user.\n"
#  exit 5
# }
#exit

まとめ

これでこの記事のすべての内容が終わりました。この記事の内容が皆さんの学習や仕事に参考になることを願っています。疑問がある場合は、コメントを残して交流してください。皆様の「呐喊教程」へのサポートに感謝します。

声明:この記事の内容はインターネットから取得しており、著作権者に帰属します。インターネットユーザーが自発的に貢献し、自己でアップロードしたものであり、このサイトは所有権を持ちません。人工的に編集されていないため、関連する法的責任を負いません。著作権侵害の疑いがある場合は、以下のメールアドレスまでご連絡ください:notice#oldtoolbag.com(メールを送信する際、#を@に変更してください。報告を行い、関連する証拠を提供してください。一旦確認がついたら、このサイトは即座に侵害疑いのコンテンツを削除します。)

おすすめ