Bash-скриптинг, проверка на ошибки, логирование - PullRequest
7 голосов
/ 02 марта 2010

Вот один из них для магов Баш-Фу. Нет, вообще-то, я просто шучу, вы, наверное, все это знаете, кроме меня ..

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

Вот что у меня есть:

01: #!/bin/bash
02: 
03: ROOTDIR="/data/www"
04: 
05: TAR="${ROOTDIR}/log/svg_out_xml/export_out_ack_$(date +%Y-%m-%d).tar"
06: cd ${ROOTDIR}/exchange/export/out_ack/
07: find . -mtime +7 -type f -print0 | xargs -0 tar -cf "${TAR}"
08: gzip ${TAR}
09: find . -mtime +7 -type f -print0 | xargs -0 rm -f

По сути, мне нужно проверить, все ли хорошо в строках 7 и 8, и если это так, выполнить 9.

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

Ответы [ 4 ]

12 голосов
/ 02 марта 2010

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

# Save standard output and standard error
exec 3>&1 4>&2
# Redirect standard output to a log file
exec 1>/tmp/stdout.log
# Redirect standard error to a log file
exec 2>/tmp/stderr.log

# Now the output of all commands goes to the log files
echo "This goes to /tmp/stdout.log"
echo "This goes to /tmp/stderr.log" 1>&2
...

# Print a message to the original standard output (e.g. terminal)
echo "This goes to the original stdout" 1>&3

# Restore original stdout/stderr
exec 1>&3 2>&4
# Close the unused descriptors
exec 3>&- 4>&-

# Now the output of all commands goes to the original standard output & error
...

Чтобы выполнить команду только в случае успеха предыдущей, вы можете связать их с помощью следующих условий:

# Execute command2 only if command1 succeeds, and command3 only if both succeed:
command1 && command2 && command3

# Execute command2 only if command1 fails
command1 || command2

так что вы можете делать такие вещи, как

{ find . -mtime +7 -type f -print0 | xargs -0 tar -cf "${TAR}" &&
  gzip ${TAR} && 
  find . -mtime +7 -type f -print0 | xargs -0 rm -f } || 
    { echo "Something failed" 1>&2; exit 1 }

или укажите подробности в журнале:

find . -mtime +7 -type f -print0 | xargs -0 tar -cf "${TAR}" || 
  { echo "find failed!!" 1>&2; exit 1 }
gzip ${TAR} || 
  { echo "gzip failed!!" 1>&2; exit 1 }
find . -mtime +7 -type f -print0 | xargs -0 rm -f || 
  { echo "cleanup failed!!" 1>&2; exit 1}
7 голосов
/ 02 марта 2010

Для ведения журнала вы можете заключить разделы вашего скрипта в фигурные скобки и перенаправить стандартный вывод в файл журнала:

{
    script_command_1
    script_command_2
    script_command_3
} >> /path/to/log_file
6 голосов
/ 02 марта 2010

Простой выход, но без явного сообщения об ошибке добавьте -e к шебангу, то есть #!/bin/sh -e, что приведет к выходу оболочки в случае сбоя команды.

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

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

3 голосов
/ 02 марта 2010

GNU tar имеет --remove-files, который удалит файлы после их добавления в архив. v приведет к выводу списка файлов по мере их добавления. z пропустит смолу через gzip на лету.

Ваше решение find является колоритным; файл может соответствовать критериям между вызовами, поэтому он удаляется, но не резервируется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...