![Rsync игнорирует двойные кавычки в скрипте](https://rvso.com/image/1684445/Rsync%20%D0%B8%D0%B3%D0%BD%D0%BE%D1%80%D0%B8%D1%80%D1%83%D0%B5%D1%82%20%D0%B4%D0%B2%D0%BE%D0%B9%D0%BD%D1%8B%D0%B5%20%D0%BA%D0%B0%D0%B2%D1%8B%D1%87%D0%BA%D0%B8%20%D0%B2%20%D1%81%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%B5.png)
Когда переменная "$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"
, оболочка расширяет ее до одного слова.
До того, как 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[@]}"
.