rsync命令变量,bash脚本

Rsync command variable, bash script

RSYNC="rsync -avzhe 'ssh -i /path/to/deploy_keys/id_rsa' --delete "

# Files
$RSYNC deploy@ip:/var/www/path1 /var/www/path1
$RSYNC deploy@ip:/var/www/path2 /var/www/path2

我想引入这个 RSYNC 变量更紧凑,但它会抛出一个错误:

Unexpected remote arg: deploy@ip:/var/www/path1

如果我只在双引号内使用 rsync,它工作正常。为了可读性,我将它们分开命令调用。

如果您想将命令字符串存储到一个变量中并稍后对其求值,您可以使用 eval 或更安全的替代技术:

#!/bin/bash

# Store the command into an array
RSYNC=(rsync -avzhe 'ssh -i /path/to/deploy_keys/id_rsa' --delete)
# Run the command
"${RSYNC[@]}" deploy@ip:/var/www/path1 /var/www/path1

Why eval should be avoided

将字符串分配给变量然后再次将其提交给 shell 后,它的标记化方式有所不同。考虑以下脚本

VAR="/bin/ls 'Test1 Test2'"
$VAR

它会抛出两个错误:

/bin/ls: cannot access 'Test1
/bin/ls: cannot access Test2'

您猜对了,撇号不再影响标记化。相反,当命令行参数被提供给 /bin/ls

时,它们被视为普通字符

虽然 eval 被正确地认为是邪恶的,但它是迄今为止获得脚本 运行 的最简单方法。它将所有参数拼接成一行并再次应用分词过程。

RSYNC="rsync -avzhe 'ssh -i /path/to/deploy_keys/id_rsa' --delete "

# Files
eval $RSYNC deploy@ip:/var/www/path1 /var/www/path1
eval $RSYNC deploy@ip:/var/www/path2 /var/www/path2

我同意 eval 是危险的。除了@Eugeniu Rosca 建议的数组方法外,您还可以使用 shell 函数:

my_rsync() {
    rsync -avzhe 'ssh -i /path/to/deploy_keys/id_rsa' --delete "$@"
}

my_rsync deploy@ip:/var/www/path1 /var/www/path1
my_rsync deploy@ip:/var/www/path2 /var/www/path2

顺便说一句,你应该阅读 BashFAQ #50: I'm trying to put a command in a variable, but the complex cases always fail!