当变量"$exclude_list"
被调用为参数时,rsync 会忽略双引号并以某种方式包含主文件夹,即使脚本中没有提到。我尝试将其包装起来"${exclude_list}"
,但这也无济于事。
在与 结合使用之前显示变量的内容rsync
,表明它是正确的。
另一件奇怪的事情是,当我这样做时echo rsync ...
输出是正确的并且没有错误。
有问题的 Bash 脚本的一部分:
echo "$exclude_list"
rsync -av --dry-run "$exclude_list" "$src" "$dest" >> /var/log/rsync.log || {
sendmail "Error: rsync failed for folder $src."; exit 1; }
输出:
--exclude=lost+found
rsync: [sender] link_stat "/home/user/ --exclude=lost+found" failed: No such file or
directory (2)
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at
main.c(1333) [sender=3.2.3]
这是 MCVE:
#!/bin/bash
# List of source folders
SRC_FOLDERS=(
[0]="/mnt/load-1/"
[1]="/mnt/load-2/"
)
# List of backup folders
DEST_FOLDERS=(
[0]="/mnt/load-1-b/"
[1]="/mnt/load-2-b/"
)
# List of folders to exclude during backup
EXCLUDE_FOLDERS=(
"lost+found"
"lost-found"
)
# Form the exclude list for rsync
for exclude_folder in "${EXCLUDE_FOLDERS[@]}"; do
exclude_list="$exclude_list --exclude=$exclude_folder"
done
# Loop through each folder pair
for i in "${!SRC_FOLDERS[@]}"; do
src=${SRC_FOLDERS[$i]}
dest=${DEST_FOLDERS[$i]}
rsync -av --dry-run "$exclude_list" "$src" "$dest"
done
答案1
问题在于
for exclude_folder in "${EXCLUDE_FOLDERS[@]}"; do exclude_list="$exclude_list --exclude=$exclude_folder" done
你迭代一个数组EXCLUDE_FOLDERS
并从中创建一个非数组变量exclude_list
。当它稍后被引用时"$exclude_list"
,shell 会将其扩展为一个单词。
for
在循环为空之前exclude_list
。循环内的第一个赋值使变量以 开头--exclude…
。注意前导空格。由于这个空格,rsync
它不会将此词识别为选项;它将其识别为相对路径。我认为您当前的工作目录是/home/user/
。绝对路径是,因此/home/user/ --exclude=…
,该文件不存在,这就是错误所指出的。
即使前导空格不存在并exclude_list
以某种方式创建--exclude=… --exclude=…
,它仍然是错误的。"$exclude_list"
总是扩展为一个单词。您希望每个--exclude=…
都是 的单独参数rsync
。
不引用$exclude_list
可能会有点用,但这是一个糟糕的解决方案;例如EXCLUDE_FOLDERS
如果元素包含空格、制表符或换行符(或触发通配符),它将(或可能)失败。
请阅读我们如何运行存储在变量中的命令?在 Bash 中,最好使用数组。创建exclude_list
一个数组:
for exclude_folder in "${EXCLUDE_FOLDERS[@]}"; do
exclude_list+=("--exclude=$exclude_folder")
done
然后在调用中rsync
使用"${exclude_list[@]}"
。