设置 Ubuntu 16.04 需要脚本
在下面的简单脚本中,目标是使用 ssh 在远程计算机上的目录中简单地查找最旧的 .zip 文件。
然后使用 scp 将此文件下载到本地“workingBuild”目录中。
当前脚本
#!/usr/bin/expect
set user "hidden"
set pass "hidden"
set sourceDir "/opt/tomcat/someDirectoryName/"
set workingDir "/home/someUser/workingBuild"
spawn sh -c "ssh $user@www ls -t $sourceDir | head -1"
expect "password:"
send "$pass\r"
expect -re ".*\.zip"
set sourceFile $expect_out(0,string)
spawn sh -c "echo 'bob'$sourceFile'bob2'"
spawn sh -c "scp $user@www:$sourceDir$sourceFile $workingDir"
expect {
password: {send "$pass\r"; exp_continue}
}
问题
看来我在存储的文件名前面的 $sourceFile 变量中填充了一个隐藏的回车符 (\r)。这反过来又导致 scp 命令出现问题,因为它将文件名和目标目录放在新行上。导致无效命令:
spawn sh -c scp meliudaj@www:/opt/tomcat/someDirectoryName/
build_0.0.1.zip /home/meliudaj/workingBuild
上面代码中的以下调试行也演示了这一点:
spawn sh -c "echo 'bob'$sourceFile'bob2'"
$sourceFile'bob2' 始终位于 'bob' 下面的新行
期望的结果将是这样的:
spawn sh -c scp meliudaj@www:/opt/tomcat/someDirectoryName/ build_0.0.1.zip /home/meliudaj/workingBuild
问题
如何从 $sourceFile 变量中删除 \r,或者如何以不同方式填充 $sourceFile 变量以防止 (\r) 首先出现。
PS 我已经尝试了许多不同的尝试来使用 sed、awk 和 tr 但我尝试过的似乎都没有帮助。
答案1
发送密码并“按 Enter”后,ssh 所做的第一件事就是发出换行符。您在从 Expect_out 缓冲区中提取的文本中没有考虑到这一点。另请注意,expect 使用 CRNL 来表示换行符,我理解这是为了与某些网络协议标准保持一致。
这个交互式预期会话几乎重现了该问题。最后,我将变量的内容发送到外部命令od
以准确查看其中的内容:
expect1.1> spawn sh -c {read password; ls -t | head -1}
spawn sh -c read password; ls -t | head -1
42945
expect1.2> send "\r"
expect1.3> expect "*.zip"
somefile.zip
expect1.4> set sourceFile $expect_out(0,string)
somefile.zip
expect1.5> exec od -c << $sourceFile
0000000 \r \n s o m e f i l e . z i p
0000016
您想要做的是捕获发生的以“.zip”结尾的文本最后一个换行符之后。使用正则表达式相当简单:
expect1.1> spawn sh -c {read password; ls -t | head -1}
spawn sh -c read password; ls -t | head -1
42992
expect1.2> send "\r"
expect1.3> expect -re {.*\r\n(.*\.zip)}
somefile.zip
expect1.4> set sourceFile $expect_out(1,string)
somefile.zip
expect1.5> exec od -c << $sourceFile
0000000 s o m e f i l e . z i p
0000014
请注意使用(1,string)
来获取第一组括号捕获的文本。