Linux 嵌入式expect脚本向bash返回成功或失败
我在bash脚本中嵌入了一个expect脚本,以便在服务器上放置一些ftp文件。 我试图让expect脚本向bash进程返回一个成功或失败的输出值,这样我就可以执行它,但我失败得很惨。 脚本如下所示:Linux 嵌入式expect脚本向bash返回成功或失败,linux,bash,tcl,expect,Linux,Bash,Tcl,Expect,我在bash脚本中嵌入了一个expect脚本,以便在服务器上放置一些ftp文件。 我试图让expect脚本向bash进程返回一个成功或失败的输出值,这样我就可以执行它,但我失败得很惨。 脚本如下所示: sftper() { local filename="$1" local user="user" local password="password" local host="ftpserver" local in=1 IFS= read -r -d
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"
}
sftper()
{
本地文件名=“$1”
本地用户=“用户”
本地密码=“密码”
本地主机=“ftpserver”
本地输入=1
IFS=read-r-d''expect_命令脚本中最令人惊讶的事情是调用interact
,这是一个expect命令,允许用户直接连接到生成的程序。但是,在向sftp发送bye
命令后,它不太可能有用;aclose;exit
sequence w我们的期望值更高(关闭控制虚拟终端并退出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脚本包装器变得简单得多:
sftper()
{
expect /path/to/do_sftp_put.exp "$1"
return $?
}
这里不需要太多花哨的引用;这就是设计工作的方式。是的,expect脚本需要仔细的保护,这样只有您才能读取它,因为它包含实时凭据,但是您以前在shell代码中遇到过这个问题,所以这不是什么新鲜事
[编辑]:当然,这仍然无法检测错误。为此,您需要一个更复杂的脚本。最常见的错误之一是密码错误(或与用户不匹配)。要解决此问题,我们采用以下方法:
# 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,我将尝试配置SSH标识,以便使用基于密钥的身份验证而不是基于密码的身份验证,因为这在实践中在多个方面更安全。然而,这是对您的操作的重大更改因此,这显然超出了问题的范围。脚本中最令人惊讶的一点是,您调用了interact
,这是一个Expect命令,允许用户直接连接到生成的程序。但是,在您向sftp发送bye
命令后,close;退出
序列更符合预期(关闭控制虚拟终端并退出预期脚本)
因此,我希望有更多类似于:
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脚本包装器变得简单得多:
sftper()
{
expect /path/to/do_sftp_put.exp "$1"
return $?
}
这里不需要太多花哨的引用;这就是设计工作的方式。是的,expect脚本需要仔细的保护,这样只有您才能读取它,因为它包含实时凭据,但是您以前在shell代码中遇到过这个问题,所以这不是什么新鲜事
[编辑]:当然,这仍然无法检测错误。为此,您需要一个更复杂的脚本。最常见的错误之一是密码错误(或与用户不匹配)。要解决此问题,我们采用以下方法:
# 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,我将尝试配置SSH标识,以便使用基于密钥的身份验证而不是基于密码的身份验证,因为这在实践中在多个方面更安全。然而,这是对您的操作的重大更改因此,它肯定超出了问题的范围。非常感谢。我会尝试一下。脚本按设计工作,但在上传失败时无法识别。我故意尝试了一个错误的密码和一个错误的文件名,但每次expect都返回0
:`user@host的密码:权限被拒绝,请重试我又犯错误了。user@host's password:+return 0 sftp>put bad_file stat bad_file:没有这样的文件或目录sftp>+return 0`Right。您需要使用expect
命令的多子句版本(在expect脚本中)来检测故障并处理它(通过调用exit 1
以及其他方法,因为这会向上发送错误)。谢谢。你有任何链接我可以签出来做这件事吗?找到了一些有趣的东西。再次感谢你的帮助!非常感谢你的帮助。我会尝试一下。脚本按设计工作,但在上传失败时无法识别。我故意尝试了错误的密码和错误的文件名,但每次expect返回0
: ` user@host的密码:权限被拒绝,请重试。user@host's password:+return 0 sftp>put bad_file stat bad_file:没有这样的文件或目录sftp>+return 0`Right。您需要使用多子句版本的expect
命令(在expect脚本中)检测故障并进行处理(通过调用退出1
以及其他方法,因为这会向上发送错误)。非常感谢。您有任何链接我可以查看以执行此操作吗?找到一些有趣的内容。再次感谢您的帮助!