Joe*_*lav 7 bash ssh rsync shell-script quoting
我有一系列命令,例如:
ssh -i key 10.10.10.10 mkdir -p "${DEST_PATH}/subdir1" "${DEST_PATH}/subdir2"
rsync "${SOURCE_PATH}" "$DEST_HOST:${DEST_PATH}/subdir1"
...
Run Code Online (Sandbox Code Playgroud)
这些被馈送变量为
DEST_PATH=$( myfun "foo" )
SOURCE_PATH=$( myfun "bar" )
Run Code Online (Sandbox Code Playgroud)
这反过来又被馈送为字符串
function myfun {
local VALUE=$( grep "$1" yadayada.txt | tail -1 | sed 's/someregex//' )
echo "$VALUE"
}
Run Code Online (Sandbox Code Playgroud)
你会如何处理$VALUE有一些空间..就像如果$VALUE是Hello World?我以为总是使用""可以解决所有问题,但我错了。其他几个问题建议转义或使用单引号,但我不确定最好的方法。
谢谢
如果你知道远程系统有一个xargs支持-0选项的命令,你可以这样做:
printf '%s\0' "$DEST_PATH/subdir1" "$DEST_PATH/subdir2" |
ssh -i key 10.10.10.10 'xargs -0 mkdir -p --'
Run Code Online (Sandbox Code Playgroud)
这xargs -0 mkdir -p --一块的shell代码将由所有炮弹解释相同的(记得sshd在远程机器上运行的远程用户的登录shell来解释给的代码ssh可能是任何东西)。
的参数列表mkdir通过远程 shell 的标准输入以 NUL 分隔,由xargs.
这种方法的另一个优点是您可以传递任意数量的参数。如果需要,xargs将打破该列表并运行几次调用mkdir -p -- dirn dirn+1...以绕过参数+环境列表的大小限制,甚至可能在为非常大的列表传输完整列表之前开始创建目录。
请参阅如何在不知道远程用户的登录 shell 的情况下通过 ssh 执行任意简单命令?对于其他方法。
rsync默认情况下,它本身具有相同的问题,因为它将远程文件/目录的名称作为远程 shell 命令行的一部分传递给同步自/至同步,而更好的解决方案是使用-s/--protect-args它不是在 shell 代码中传递文件/目录名称,而是在rsync服务器的标准输入上传递它。
所以:
rsync -s -- "$SOURCE_PATH" "$DEST_HOST:$DEST_PATH/subdir1/"
Run Code Online (Sandbox Code Playgroud)
引用rsync手册页:
如果您需要传输包含空格的文件名,您可以指定
--protect-args(-s) 选项,或者您需要以远程 shell 能够理解的方式转义空格。例如:Run Code Online (Sandbox Code Playgroud)rsync -av host:'file\ name\ with\ spaces' /dest
$ rsync --rsync-path='set -x; rsync' /etc/issue localhost:'1 2'
+zsh:1> rsync --server -e.LsfxC . 1 2
$ rsync --rsync-path='set -x; rsync' /etc/issue localhost:'1;uname>&2'
+zsh:1> rsync --server -e.LsfxC . 1
+zsh:1> uname
Linux
Run Code Online (Sandbox Code Playgroud)
查看如何将文件名解释为 shell 代码。
与-s:
~$ rsync -s --rsync-path='set -x; rsync' /etc/issue localhost:'1;uname>&2'
+zsh:1> rsync --server -se.LsfxC
Run Code Online (Sandbox Code Playgroud)
远程 shell 命令行上没有文件名的踪迹。
~$ cat '1;uname>&2'
Ubuntu 20.04.1 LTS \n \l
Run Code Online (Sandbox Code Playgroud)