首页 > 解决方案 > 运行远程脚本时,Expect 的结果不可靠

问题描述

因为我的公司坚持使用 sudo,所以我现在不得不废弃我为运行远程命令而构建的 ssh 系统。

我有一个将连接到服务器的脚本,sudo 进入 db2 inst 所有者帐户,然后运行一个脚本(之前交付到 /tmp)。也许 10 次中有 1 次会起作用(为我的测试输出“Hello world”)。

这是远程服务器上的 ksh 脚本 (/tmp/cwow/generic.ksh):

#!/usr/bin/ksh93
echo "Hello world"

[我也尝试添加 sleep 5 并等待混合结果,但它并没有解决问题]

我在本地运行的期望脚本是:

#!/usr/bin/expect

set spath /tmp/cwow/generic.ksh

set pass $env(MYEXPECTPASS)
set user $env(MYEXPECTUSER)

if { [llength $argv] != 2 } {
        send_user "USAGE: $argv0 host inst\n"
        exit
}
set host   [lindex $argv 0]
set inst   [lindex $argv 1]

set timeout 10
log_user 1
exp_internal 0

eval spawn /usr/bin/ssh -t $user@$host "sudo su - cwow"
expect {
        timeout { send_user "TimedOut"; exit }

        -glob "assword:" {
                send "$pass\r"
                expect {
                        -glob "assword:" {
                                send "$pass\r"
                                expect {
                                        -glob " " {
                                                send "/tmp/cwow/generic.ksh\r\n"
                                                expect {
                                                        -glob "world" {
                                                                send_user "Got it\r"
                                                        }
                                                }
                                        }
                                }
                        }
                }
        }
}

我还应该注意,我从来没有收到“知道了”的消息,但我真的不需要它来工作,只是好奇为什么它没有。我需要可靠地工作是让脚本运行,而且大多数时候,它似乎没有运行。

任何针对弱预期用户的想法将不胜感激。

标签: expect

解决方案


(不是答案,只是格式化的评论)

你不需要嵌套所有的期望命令:如果你期望一个没有动作主体的模式,脚本将继续执行下一个命令。这更具可读性,IMO:

expect {
    timeout { send_user "TimedOut"; exit }
    "assword:" 
}
send "$pass\r"
expect "assword:" 
send "$pass\r"
expect " "
send "/tmp/cwow/generic.ksh\r"
expect "world" 
send_user "Got it\n"

请注意,您应该使用“按 Enter”send来生成进程。\r\n用于send_user.


推荐阅读