预期中的错误处理?

mun*_*ish 5 linux shell-script expect

我只是在改进我的问题,因为到目前为止我已经做到了:

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
Run Code Online (Sandbox Code Playgroud)

我希望我是正确的,但是如何获取本地记录的命令的输出 errlogs 和成功日志,其中 command 是诸如 ls、ls -lrt 之类的命令列表

此外,当我把这个:

 spawn ssh -q -o StrictHostKeyChecking=no $username@$hostname {ls -lrt;df -h}
Run Code Online (Sandbox Code Playgroud)

它登录并执行,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)
Run Code Online (Sandbox Code Playgroud)

命令变量包含一个由分号分隔的命令列表,如下所示:

   command 1; command 2;command 3(=$command)
Run Code Online (Sandbox Code Playgroud)

我不知道如何在 expect 脚本中一一执行它,因此我可以执行以下操作,而不是将命令放在 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
Run Code Online (Sandbox Code Playgroud)

我只是使用了 unix 语法和 expect 语法结合起来,只是为了让您了解我想要做什么。

use*_*471 8

Expect 的交互模型不包括 stdout 和 stderr 流的分离。当您生成一个进程时,您会创建一个新的伪 TTY,它的行为与用户在其终端中看到的几乎相同,并且用户通常无法区分这两者。尝试一下:

$ echo "This is stdout"
This is stdout
$ echo "This is stderr" 1>&2
This is stderr
Run Code Online (Sandbox Code Playgroud)

如果不做一些标记差异的事情,Expect 无法区分它们(就像命令行上的用户一样)。因此,对于您需要做的事情,Expect 可能是错误的工具。

现在,在不确切知道您为什么需要它的情况下,很难为您找到替代方法。对于您所需要的,您似乎可以使用单个 ssh 命令来完成此操作:

ssh -q -o StrictHostKeyChecking=no $username@$hostname "ls -lrt; df -h" 1>>successlog 2>>errorlog
Run Code Online (Sandbox Code Playgroud)

对于另一种内置支持生成子进程并分别获取其 stdout 和 stderr 的脚本语言,请尝试使用 Python 及其子进程模块。

ssh -q -o StrictHostKeyChecking=no $username@$hostname "ls -lrt; df -h" 1>>successlog 2>>errorlog
Run Code Online (Sandbox Code Playgroud)

但是,如果您真的,真的想在 Expect 中执行此操作,我认为最好的方法可能是检查最后一个进程的退出值,并在它不为零时写入您的错误日志文件。这是一个类似的例子:

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
Run Code Online (Sandbox Code Playgroud)