Linux

期望中的錯誤處理?

  • September 11, 2016

我只是在改進我的問題,因為到目前為止我已經做到了這一點:

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
   }
}

引用自:https://unix.stackexchange.com/questions/66520