私はこれまでに達成した結果のために私の質問を具体化しています。
set username [lindex $argv 0]
set password [lindex $argv 1]
set hostname [lindex $argv 2]
if {[llength $argv] == 0} {
send_user "Usage: scriptname username \'password\' hostname\n"
exit 1
}
send_user "\n#####\n# $hostname\n#####\n"
spawn ssh -q -o StrictHostKeyChecking=no $username@$hostname
expect {
timeout { send_user "\nFailed to get password prompt\n"; exit 1 }
eof { send_user "\nSSH failure for $hostname\n"; exit 1 }
"Password: "
}
send "$password\r"
expect {
timeout { send_user "\nLogin failed. Password incorrect.\n"; exit 1}
"{severname:mike} "
}
send "ls -lrt\n"
expect {
"{severname:mike} " {
send "uname\n"
}
}
expect {
"{severname:mike} " }
send "exit\r"
close
私は正しいと思いますが、コマンドがls、ls -lrtなどのコマンドのリストであるローカルに記録されたコマンドの出力エラーログと成功ログをどのように取得できますか?
さらに、私がこう言うとき:
spawn ssh -q -o StrictHostKeyChecking=no $username@$hostname {ls -lrt;df -h}
ログインして実行しますls -lrt;df -h
が、デバッグオプションを使用するとエラーが発生します。コマンドがsshの範囲内で実行されたため、接続が閉じられている可能性があります。
[root@testgfs2 final]# ./workingscript.exp mike bar01 10.38.164.103
#####
# 10.38.164.103
#####
spawn ssh -q -o StrictHostKeyChecking=no [email protected] ls -lrt
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {19901}
expect: does "" (spawn_id exp6) match glob pattern "Password: "? no
Password:
expect: does "Password: " (spawn_id exp6) match glob pattern "Password: "? yes
expect: set expect_out(0,string) "Password: "
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "Password: "
send: sending "bar01\r" to { exp6 }
expect: does "" (spawn_id exp6) match glob pattern "{severname:mike} "? no
expect: does "\r\n" (spawn_id exp6) match glob pattern "{severname:mike} "? no
total 6
-rw-r--r-- 1 mike other 136 Feb 26 08:39 local.cshrc
-rw-r--r-- 1 mike other 157 Feb 26 08:39 local.login
-rw-r--r-- 1 mike other 174 Feb 26 08:39 local.profile
expect: does "\r\ntotal 6\r\n-rw-r--r-- 1 mike other 136 Feb 26 08:39 local.cshrc\r\n-rw-r--r-- 1 mike other 157 Feb 26 08:39 local.login\r\n-rw-r--r-- 1 mike other 174 Feb 26 08:39 local.profile\r\n" (spawn_id exp6) match glob pattern "{severname:mike} "? no
expect: read eof
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "\r\ntotal 6\r\n-rw-r--r-- 1 mike other 136 Feb 26 08:39 local.cshrc\r\n-rw-r--r-- 1 mike other 157 Feb 26 08:39 local.login\r\n-rw-r--r-- 1 mike other 174 Feb 26 08:39 local.profile\r\n"
write() failed to write anything - will sleep(1) and retry...
send: sending "ls -lrt\n" to { exp6 send: spawn id exp6 not open
while executing
"send "ls -lrt\n""
(file "./workingscript.exp" line 30)
コマンド変数には、次のようにセミコロンで区切られたコマンドのリストが含まれています。
command 1; command 2;command 3(=$command)
Expectスクリプトで1つずつ実行する方法がわからないため、sshスコープにコマンドを配置する代わりに、次のことができます。
spawn ssh -q -o StrictHostKeyChecking=no $username@$hostname
IFS=';'
for i in $command
do
expect {
"{severname:mike} " {
send "$i\n"
} 2>> errorlog 1>> succeslog
}
done
私は単に私がやろうとしていることのアイデアを提供するためにUnix構文とExpect構文の組み合わせを使用しています。
答え1
Expect の相互作用モデルには、stdout ストリームと stderr ストリーム分離は含まれません。プロセスを作成すると、ユーザーが端末で見たものとほぼ同じように動作する新しい疑似TTYを作成しますが、ユーザーは2つの違いを区別できないことがよくあります。試してみてください:
$ echo "This is stdout"
This is stdout
$ echo "This is stderr" 1>&2
This is stderr
しないでください何違いを示すために、Expectはそれを区別する方法はありません(コマンドラインのユーザーと同じように)。したがって、Expectはおそらくあなたがしなければならないことのための間違ったツールです。
今、なぜこれが必要なのかを正確に知らない場合は、選択肢を見つけるのは難しいです。必要に応じて、単一のsshコマンドを使用してこれを実行できるようです。
ssh -q -o StrictHostKeyChecking=no $username@$hostname "ls -lrt; df -h" 1>>successlog 2>>errorlog
サブプロセスの作成とstdoutとstderrのインポートをデフォルトでサポートする他のスクリプト言語の場合は、Pythonとそのサブプロセスモジュールを試してください。
import shlex
from subprocess import Popen, PIPE
cmd = Popen(shlex.split('ssh -q -o StrictHostKeyChecking=no $username@$hostname "ls -lrt; df -h"'), stdout=PIPE, stderr=PIPE)
cmd.wait() # Wait for the command to complete
success_output = cmd.stdout
error_output = cmd.stderr
しかし、もしあなたが本当に本物Expectでこれを行うには、最後のプロセスの終了値を確認し、その値がゼロ以外の場合はエラーログファイルに書き込むのが最善の方法だと思います。同様の例は次のとおりです。
spawn ssh -q -o StrictHostKeyChecking=no $username@$hostname
# Receive password prompt and send the password here...
expect {
-ex $prompt { send "ls -lrt\r" }
timeout {
send_user "Everything is terrible forever.\n"
exit 1
}
}
expect {
-ex $prompt {
set output $expect_out(buffer)
send {echo RETVAL::$?::}
send "\r"
}
timeout {
send_user "Everything is terrible forever.\n"
exit 1
}
}
expect {
-ex {RETVAL::0::} {
set fp [open successlog a]
puts $fp $output
close $fp
}
-re {RETVAL::[1-9][0-9]*::} {
set fp [open errorlog a]
puts $fp $output
close $fp
}
timeout {
send_user "Everything is terrible forever.\n"
exit 1
}
}