我正在尝试创建一个bash脚本,它将指定为命令行参数的目录同步到远程服务器(也由参数指定)。目前,我正在使用eval
,它解决了参数扩展问题,但由于某种原因导致rsync不保留远程文件的所有权(除了邪恶,我知道)。从命令提示符运行带有所有相同标志和参数的rsync命令可以正常工作。
我尝试使用$()
作为替代方案,但我陷入了变量扩展的真正混乱,并保护了需要保护远程rsync路径的位(需要引用和带空格的路径的反斜杠。)
所以 - 我想2个问题 - 是否有eval
阻止rsync
保留所有权的原因(bash脚本在源计算机上以root身份运行,ssh
以root身份进入远程计算机 - 仅仅是为了现在)?有没有办法让$()
在这种情况下工作? (修剪过的)代码如下:
#!/bin/bash
RSYNC_CMD="/usr/bin/rsync"
RSYNC_FLAGS="-az --rsh=\"/usr/bin/ssh -i \${DST_KEY}\"" # Protect ${DST_KEY} until it is assigned later
SRC=${1} # Normally this is sense checked and processed to be a canonical path
# Logic for setting DST based on command line parameter snipped for clarity - just directly assign for testing
DST='root@some.server.com:'
DST_KEY='/path/to/sshKey.rsa'
TARG=${DST}${SRC//' '/'\ '} # Escape whitespace for target system
eval ${RSYNC_CMD} ${RSYNC_FLAGS} \"${SRC}\" \"${TARG}\" # Put quotes round the paths - even though ${TARG} is already escaped
# All synced OK - but ownership not preserved despite -a flag
我尝试将RSYNC_CMD
更改为sudo /usr/bin/rsync
,并将--rsync-path="sudo /usr/bin/rsync
添加到RSYNC_FLAGS
,但两者都没有任何区别。我只是看不到我错过的东西......
答案 0 :(得分:1)
执行此操作的正确方法是使用数组。 -a
应该已经暗示-o
。
RSYNC_CMD="/usr/bin/rsync"
DST='root@some.server.com:'
DST_KEY='/path/to/sshKey.rsa'
RSYNC_FLAGS=(-az --rsh="/usr/bin/ssh -i ${DST_KEY}")
SRC=${1}
TARG="${DST}$SRC"
${RSYNC_CMD} "${RSYNC_FLAGS[@]}" "${SRC}" "${TARG}"
使用RSYNC_RSH
代替--rsh
,您可以在设置其值之前导出变量。这至少可以让您将导出放在设置其余标志的同一区域。然后,您可以推迟完成其值,直到您拥有正确的身份文件。
RSYNC_CMD="/usr/bin/rsync"
export RSYNC_RSH="/usr/bin/ssh -i %s" # Use a placeholder for now; set it later
RSYNC_FLAGS=( -a -z )
# Later...
DST='root@some.server.com:'
DST_KEY='/path/to/sshKey.rsa'
RSYNC_RSH=$( printf "$RSYNC_RSH" "$DST_KEY" )
SRC=${1}
TARG="${DST}$SRC"
${RSYNC_CMD} "${RSYNC_FLAGS[@]}" "${SRC}" "${TARG}"