我将期望脚本嵌入bash脚本中,以便将一些ftp文件放置在服务器上。 我试图让期望脚本向bash进程返回成功或失败的输出值,以便我可以对其执行操作,但是我失败了。 脚本如下所示:
sftper()
{
local filename="$1"
local user="user"
local password="password"
local host="ftpserver"
local in=1
IFS= read -r -d '' expect_commands <<EOD >echo_log
spawn /usr/bin/sftp $user@$host
expect "*assword:"
send "$password\r"
expect "sftp>"
send "put $filename\r"
expect "sftp>"
send "bye\r"
interact
EOD
expect -c "${expect_commands//
/;}"
in="$?"
return "$in"
}
`
请,我在做错什么,该如何解决?
答案 0 :(得分:4)
脚本中最令人惊讶的一件事情是调用interact
,这是一个Expect命令,它允许用户直接连接到生成的程序。但是,将bye
命令发送到sftp后,它不太可能有用。 close; exit
序列会更令人期待(关闭控制虚拟终端并退出Expect脚本)。
因此,我希望有更多类似的东西:
IFS= read -r -d '' expect_commands <<EOD >echo_log
spawn /usr/bin/sftp $user@$host
expect "*assword:"
send "$password\r"
expect "sftp>"
send "put $filename\r"
expect "sftp>"
send "bye\r"
close
exit
EOD
更一般地说,您应该考虑如果发生问题(例如,密码已过期)会发生什么,并且编写一个完整的期望脚本而不是运行所有shell引用的方法可能会更容易。我添加了一些小的解释性注释……
# Assuming this is in a file called do_sftp_put.exp
# set up the variables; first line is how to get a command line argument
set filename [lindex $argv 0]
set user "user"
set password "password"
set host "ftpserver"
# launch sftp
spawn /usr/bin/sftp $user@$host
# login sequence
expect "*assword:"
send "$password\r"
expect "sftp>"
# send the file
send "put $filename\r"
expect "sftp>"
# Shut down
send "bye\r"
close
exit
然后,您的shell脚本包装器将变得更加简单:
sftper()
{
expect /path/to/do_sftp_put.exp "$1"
return $?
}
这里不需要太多花哨的报价;这就是一切设计的工作方式。是的,期望脚本需要仔细的保护,以便只有您才能读取它,因为它包含实时凭据,但是您在shell代码中曾遇到过这个问题,所以这并不是什么新鲜事。
[EDIT]:当然,这仍然无法检测到错误。为此,您需要一个更复杂的脚本。最常见的错误之一是密码错误(或与用户不匹配)。为了解决这个问题,我们采取以下措施:
# login sequence
expect "*assword:"
send "$password\r"
expect "sftp>"
并将其升级为:
# login sequence
expect "*assword:"
send "$password\r"
expect {
"password" {
# It's asking for the password *again*; must be wrong!
# Kill the sftp program and exit with an error code
close
exit 1
}
"sftp>"
}
弄清楚如何检测错误并不总是那么简单(您可以使用正则表达式等,并且您需要确切了解要针对的是什么),在某些情况下,最好备份并尝试完全是另一种方法。具体来说,对于sftp, I 将尝试配置SSH身份,以便我可以使用基于密钥的auth而不是基于密码的auth,因为在实践中,这在几种方面都更加安全。但是,这是对您的操作的重大更改,因此绝对不在问题范围内。