Как улучшить скрипт с помощью rsync

Вопрос или проблема

У меня есть следующий скрипт, использующий rsync для резервного копирования и синхронизации моих файлов.

Как я могу сделать этот скрипт более компактным, быстрым и с лучшей обработкой ошибок?

#!/bin/sh
  
errors=""

sudo rsync -avh --delete --no-o --no-g /home/xralf/audio /media/extdevice/rsync_backups/
if [ "$?" -eq "0" ]
then
  echo "нет ошибок в аудио"
else
  errors="${errors}ошибка в аудио\n"
fi

sudo rsync -avh --delete --no-o --no-g /home/xralf/books /media/extdevice/rsync_backups/
if [ "$?" -eq "0" ]
then
  echo "нет ошибок в книгах"
else
  errors="${errors}ошибка в книгах\n"
fi

sudo rsync -avh --delete --no-o --no-g /home/xralf/source_code /media/extdevice/rsync_backups/
if [ "$?" -eq "0" ]
then
  echo "нет ошибок в исходном коде"
else
  errors="${errors}ошибка в исходном коде\n"
fi

# больше таких каталогов с этой кодовой структурой

echo ${errors}

Позже я планирую не следить за выполнением скрипта, так что я хотел бы видеть только результат и верить, что все прошло хорошо.
Я запустил скрипт, но в итоге единственная информация, которую я получил, это ошибка в исходном коде, и я не могу понять, в чем именно ошибка (какой файл ее вызвал).

Если ваш приоритет — быть компактным и быстрым (т.е. минимизируя количество процессов, но в этом случае вы ограничены вводом-выводом диска, а не ЦП или памятью):

#!/bin/bash
sudo rsync -a --delete --no-o --no-g \
       /home/xralf/{audio,books,source_code} \
       /media/extdevice/rsync_backups/ &&
    echo "rsync выполнен успешно" 1>&2 || echo "rsync завершился с ошибками" 1>&2

Удаление опции -v сделает вывод менее шумным, так что вы сможете сосредоточиться на явных ошибках, если они есть. Перенаправление 1>&2 отправляет STDOUT в STDERR, так что сообщения об ошибках отправляются туда, где ожидаются. Если выполнять без наблюдения, следующие альтернативы могут оказаться лучшими вариантами, чем встроенная echo, за счет одного дополнительного процесса:

  1. сервер может использовать logger для отправки сообщения в syslog для централизованной обработки. Точная синтаксис будет зависеть от конфигурации сервера.

  2. использование date для добавления временной информации, с последней строкой скрипта:

date +"[%Y/%m/%d %H:%M:%S] rsync выполнен успешно" 1>&2 || \
date +"[%Y/%m/%d %H:%M:%S] rsync завершился с ошибками" 1>&2

для вывода чего-то вроде [2022/12/05 14:37:27] rsync выполнен успешно

Если вы не обязаны использовать sh, но можете использовать более сложный оболочку, такой как bash, вы можете сделать что-то вроде этого:

#!/bin/bash

dirs=( "audio" "books" "source_code" );
errors=()
for dir in "${dirs[@]}"; do
  sudo rsync \
       -avh --delete --no-o --no-g \
       /home/xralf/"$dir" \
       /media/extdevice/rsync_backups/ &&
    echo "нет ошибок в $dir" ||
      errors+=("ошибка в $dir\n")
done

printf '%s\n' "${errors[@]}"

Вы, вероятно, также хотите захватить stderr, но это делает то же самое, что и ваш скрипт.

Команда rsync принимает параметр --log-file=FILE. Вы можете проверить его на наличие ошибок, когда резервное копирование завершено.

Для повышения эффективности она также принимает --exclude-from=FILE и --include-from=FILE. Вы можете создать текстовые файлы, содержащие список всего, что вы хотите и не хотите резервировать, и вызывать их из одной команды rsync вместо нескольких.

Смотрите man rsync или онлайн-страницу man.

Создайте файл с именем module.sh и дайте ему следующий текст:

#!/usr/bin/env bash                                                                                                                     

# -A=Архив. Используйте рекурсию и сохраняйте почти все.
# -V=Подробно.
# -H=Сохранять жесткие ссылки.
# -Z=Сжимать.
# --Delete=
#     Если узел в каталоге 'from' удаляется,
#     удалить его в каталоге 'to'.
# --No-o=Нет владельца. 
# --No-g=Нет группы.
# Опции --No частично отменяют опцию Архив.

sync_dir(){
    local from="${1}";
    local to="${2}";

    rsync               \
        -avhz           \
        --delete        \
        --no-o          \
        --no-g          \
            "${from}/"  \
            "${to}"     \
        1>/dev/null     \
        ;

    # Сохраните результат синхронизации.
    local sync_result="${?}";

    # Имя проекта — это последний каталог из строки from.
    local project_name=$(grep -oE '[^/]*$' <<<"${from}");

    local error="Нет ошибок в: ${project_name}";
    if [ "${sync_result}" -ne "0" ]; then
        error="Ошибка в: ${project_name}\n";
        fi  
    printf "${error}\n";
    };

Затем вы создаете другой файл и подключаете модуль оттуда:

#!/usr/bin/env bash
                                                                       
. ./module.sh;

sync_dir '/home/xralf/audio' '/media/extdevice/rsync_backups/';
# Больше каталогов синхронизации здесь.

Обратите внимание на другой Shebang, этот соответствует POSIX.

Я также добавил опцию -z для Rsync. Она сжимает данные по пути.

Ответ или решение

Оптимизация скрипта для rsync: Быстрее, компактнее и с лучшей обработкой ошибок

Введение

Параметры резервного копирования и синхронизации данных играют ключевую роль в администрировании систем. Программа rsync – мощный инструмент для данной задачи, однако к скрипту, который использует этот инструмент, следует подходить с осторожностью, чтобы он был как можно более эффективным и надежным. В данной статье мы рассмотрим, как улучшить ваш скрипт на основе rsync, сделать его более компактным, быстрым и с лучшей обработкой ошибок.

Проблема

Ваш текущий скрипт обрабатывает несколько директорий по очереди и сохраняет ошибки в отдельной переменной. Однако, если в процессе синхронизации возникает ошибка, вы не получаете полной информации о том, что именно пошло не так, и это затрудняет процесс диагностики. Кроме того, повторяющийся код делает ваш скрипт более тяжелым и менее понятным.

Оптимизированный подход

1. Использование массивов

Первый шаг к сокращению кода и улучшению его читаемости – использование массивов для хранения директорий. Это позволит вам избавиться от повторяющегося кода.

#!/bin/bash

dirs=( "audio" "books" "source_code" )
errors=()

for dir in "${dirs[@]}"; do
    if sudo rsync -avh --delete --no-o --no-g "/home/xralf/$dir" "/media/extdevice/rsync_backups/"; then
        echo "Без ошибок в директории $dir."
    else
        errors+=("Ошибка в директории $dir.")
    fi
done

# Вывод всех ошибок в конце
if [ ${#errors[@]} -gt 0 ]; then
    printf '%s\n' "${errors[@]}"
else
    echo "Все директории успешно синхронизированы."
fi
2. Логирование операций

Для более удобного анализа ошибок целесообразно использовать логирование команд rsync. Вы можете записывать вывод в файл, чтобы позже проанализировать, что именно пошло не так.

rsync ... --log-file=/path/to/logfile.log
3. Использование параметра –exclude-from и –include-from

Если ваши операции резервного копирования затрагивают множество файлов, рекомендуется использовать файлы для исключений и включений. Это поможет избежать повторения однотипного кода и сделает его более управляемым.

4. Добавление временных меток

Для повышения информативности логов можете добавлять временные метки к выводимым сообщениям. Это также упростит отладку в будущем:

date +"[%Y/%m/%d %H:%M:%S] Без ошибок в директории $dir." >> /path/to/logfile.log
5. Обработка ошибок

Оптимизировав обработку ошибок, мы можем дополнительно выводить информацию о конкретных ошибках:

if ! rsync ...; then
    echo "Ошибка при синхронизации $dir. Проверяйте логи." >> /path/to/logfile.log
fi

Заключение

Используя указанные методы, вы сможете создать более компактный, быстрый и информативный скрипт для rsync. Оптимизация скрипта является не только улучшением его производительности, но и упрощением процесса диагностики ошибок, что, в свою очередь, ведет к более надежной работе резервного копирования. Не забывайте также проверять актуальность документации rsync и применять новые возможности по мере их появления.

Оцените материал
Добавить комментарий

Капча загружается...