Linux
期望中的錯誤處理?
我只是在改進我的問題,因為到目前為止我已經做到了這一點:
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 mike@10.38.164.103 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)
我不知道如何在期望腳本中一一執行它,因此我可以執行以下操作,而不是將命令放在 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 的互動模型不包括 stdout 和 stderr 流的分離。當你生成一個程序時,你會創建一個新的偽 TTY,它的行為幾乎與使用者在其終端中看到的相同,並且使用者通常無法區分兩者。嘗試一下:
$ 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 } }