Оболочка не перенаправляет вывод tar в файл.

Я предполагаю, что это простая проблема, но мне не с кем перепроверить свою работу.

Вот мой bash скрипт

#!/bin/bash

# установить формат даты и имя дампа
DATE=$(date +"%Y%m%d-%H%M")
DUMPFILE=$DATE.dump

# путь к каталогу логов и имя выходного лог-файла
LOGDIR=/opt/mongodb/backups/logs
DBLOG=$DATE-dump.log

# сделать резервное копирование базы данных и вывести в файл дампа, перенаправить вывод в лог
docker exec -i mongodb sh -c "mongodump --archive" > $DUMPFILE 2> $LOGDIR/$DBLOG

# архивировать файл дампа и загрузки файлов
ARCHIVENAME=$DATE.tgz
ARCHIVELOG=$DATE-archive.log
tar -czvf $ARCHIVENAME /opt/mongodb/$DUMPFILE /opt/mongodb/files &> $LOGDIR/$ARCHIVELOG

Где я застрял, скрипт правильно выводит лог дампа. Однако, когда доходит до конца, я получаю

./backup.sh: line 20: /opt/mongodb/backups/logs/20250328-0942-archive.log: No such file or directory

Я попытался использовать абсолютный путь вместо переменной:

tar -czvf $ARCHIVENAME /opt/mongodb/$DUMPFILE /opt/mongodb/files &> /opt/mongodb/backups/logs/$ARCHIVENAME

Но я получаю ту же ошибку. Я полагаю, что это либо мое плохое понимание перенаправлений, tar, либо синтаксическая ошибка. Любая помощь будет оценена.

РЕДАКТИРОВАТЬ: Каждый раз, когда я запускаю скрипт, создается файл с именем “‘ ‘”. Если запустить

cat ‘ ‘

Я вижу, что файл содержит лог, так что вывод действительно перенаправляется в файл, просто не в желаемой манере.

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

Строка, продолжающаяся на следующей строке с помощью обратного слэша, не должна содержать ничего после обратного слэша, даже пробел.

Так как у вас есть пробел после обратного слэша, пробел цитируется, так что вы, по сути, говорите

some-command &> ‘ ‘

Следующая строка после этого пытается запустить несуществующий лог-файл как команду. Это и генерирует сообщение об ошибке “No such file or directory”.

Я предполагаю, что вы или ваш редактор добавили пробел после в строке, из-за чего происходит перенаправление в (‘ ‘) вместо файла.

.

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

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

Теория: Понимание перенаправления ввода/вывода в Shell

Перенаправление потоков ввода/вывода в командной оболочке Bash является одной из ключевых операций, позволяющей управлять тем, куда отправляется вывод команд и откуда эти команды получают свои данные. Символы > и 2> используются для перенаправления стандартного вывода и стандартного вывода ошибок соответственно. Например, 2> используется для того, чтобы перенаправить поток ошибок в другой файл.

Когда вы используете &> (или сокращенное &>) в Bash, это символ означает объединение стандартного вывода и вывода ошибок в одно место. Но наиболее важно здесь то, что перенаправление требует, чтобы за символами перенаправления следовал корректный целевой файл или поток, в противном случае может возникнуть ошибка.

Пример: Рассмотрение ошибки в вашем коде

В предоставленном коде мы имеем следующий фрагмент:

tar -czvf $ARCHIVENAME /opt/mongodb/$DUMPFILE /opt/mongodb/files &> $LOGDIR/$ARCHIVELOG

До этой строки возникает ошибка: ./backup.sh: line 20: /opt/mongodb/backups/logs/20250328-0942-archive.log: No such file or directory.

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

Применение: Исправление и отладка проблемы

Для корректного выполнения вашего сценария избегайте пробелов после обратного слэша. Обновите ваш код, убрав пробелы следующим образом:

tar -czvf $ARCHIVENAME /opt/mongodb/$DUMPFILE /opt/mongodb/files &> $LOGDIR/$ARCHIVELOG

Кроме того, убедитесь, что все каталоги, включая $LOGDIR, существуют и имеют правильные права доступа для записи. Вы можете добавить в ваше скрипт предусловия для автоматического создания каталогов, если они не существуют:

#!/bin/bash

# Установка форматов даты и имен файлов
DATE=$(date +"%Y%m%d-%H%M")
DUMPFILE=$DATE.dump

# Директория логов и имя файла вывода логов
LOGDIR=/opt/mongodb/backups/logs

# Создаем директорию логов, если она не существует
mkdir -p $LOGDIRDBLOG=$DATE-dump.log

# Делаем бэкап базы данных и выводим в dump-файл, перенаправляем вывод в лог
docker exec -i mongodb sh -c "mongodump --archive" > $DUMPFILE 2> $LOGDIR/$DBLOG

# Архивируем dump-файл и файлы загрузок
ARCHIVENAME=$DATE.tgz
ARCHIVELOG=$DATE-archive.log
tar -czvf $ARCHIVENAME /opt/mongodb/$DUMPFILE /opt/mongodb/files &> $LOGDIR/$ARCHIVELOG

Заключение

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

Друзья помогите этому контенту стать доступнее в социальных сетях.

Не проходи мимо жмакни по кнопке возможно кому то еще он будет полезен!