期望脚本中的rsync-path

时间:2015-12-29 13:08:29

标签: tcl expect rsync

我编写了一个使用expect自动rsync的备份脚本。

为确保备份所有文件,我使用rsync的{​​{3}}选项。

#!/bin/bash
set -e

expect <<- DONE
    spawn rsync --rsync-path="sudo\\ rsync" -uav myuser@example.com:/home/myuser/ /backups/home/myuser
    expect ":"
    send -- "mypassword\r"
    expect eof
DONE

这不按预期工作。我收到以下错误消息:

bash: sudo rsync: command not found
rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
rsync error: error in rsync protocol data stream (code 12) at io.c(226) [Receiver=3.1.1]

我已经看到--rsync-path="sudo rsync"关于在rsync命令行中使用空格,并且在这里和那里添加了单引号,双引号和转义反斜杠,但还没有任何工作。

如何在--rsync-path脚本中使用“expect空格”?

2 个答案:

答案 0 :(得分:1)

问题在于你得到了这个:

--rsync-path="sudo\\ rsync"

Inside Expect / Tcl,这被视为:

--rsync-path="sudo rsync"

并且,因为Tcl的引用规则与bash相同,然后使用带有双引号的"sudo rsync" 作为发送到远程端的命令。这令人非常困惑。正确的解决方法是省略双引号; (反斜杠引用)反斜杠将确保它全部作为一个参数生成,并正确地发送到另一侧。

我真的不喜欢将HEREdocs与Tcl一起使用。当不同种类的引用相互作用时,太多事情会变得奇怪。在真正的目标语言中使用单个脚本要好得多,从那以后你可以使用变量来使事情变得更清晰:

#!/usr/bin/env expect

set remoteRsync "sudo rsync"
set from myuser@example.com:/home/myuser/
set to   /backups/home/myuser
set pass "mypassword"

spawn rsync --rsync-path=$remoteRsync -uav $from $to
expect ":"
send -- "$pass\r"
expect eof
exit

这使得代码的结构更容易查看,并且更容易调试。在开始时使用/usr/bin/env的位只是避免使用bash包装的一种方法。

不,这些变量在使用时不需要引用。 Tcl不是bash。

答案 1 :(得分:0)

您无法使用--rsync-path来执行此操作,因为您想要的是分词,即 shell 所做的事情。

那么如何通过指定单个路径名来运行运行命令的命令?

在远程系统上,编写执行susync的脚本包装器sudo(不要忘记chmod 755):

#!/bin/sh
exec /path/to/sudo /path/to/rsync "$@"

并使用

spawn rsync --rsync-path=/path/to/susync ...