我编写了一个使用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
空格”?
答案 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 ...