Я новичок в написании сценариев оболочки. Я написал сценарий оболочки для инкрементного резервного копирования базы данных MySQL. Сценарий имеет исполняемый формат и успешно работает при выполнении вручную, но не работает при выполнении через crontab.
Запись в crontab выглядит так: * / 1 * * * * /home/db-backup/mysqlbackup.sh
Ниже приведен код сценария оболочки -
#!/bin/sh
MyUSER="root" # USERNAME
MyPASS="password" # PASSWORD
MyHOST="localhost" # Hostname
Password="" #Linux Password
MYSQL="$(which mysql)"
if [ -z "$MYSQL" ]; then
echo "Error: MYSQL not found"
exit 1
fi
MYSQLADMIN="$(which mysqladmin)"
if [ -z "$MYSQLADMIN" ]; then
echo "Error: MYSQLADMIN not found"
exit 1
fi
CHOWN="$(which chown)"
if [ -z "$CHOWN" ]; then
echo "Error: CHOWN not found"
exit 1
fi
CHMOD="$(which chmod)"
if [ -z "$CHMOD" ]; then
echo "Error: CHMOD not found"
exit 1
fi
GZIP="$(which gzip)"
if [ -z "$GZIP" ]; then
echo "Error: GZIP not found"
exit 1
fi
CP="$(which cp)"
if [ -z "$CP" ]; then
echo "Error: CP not found"
exit 1
fi
MV="$(which mv)"
if [ -z "$MV" ]; then
echo "Error: MV not found"
exit 1
fi
RM="$(which rm)"
if [ -z "$RM" ]; then
echo "Error: RM not found"
exit 1
fi
RSYNC="$(which rsync)"
if [ -z "$RSYNC" ]; then
echo "Error: RSYNC not found"
exit 1
fi
MYSQLBINLOG="$(which mysqlbinlog)"
if [ -z "$MYSQLBINLOG" ]; then
echo "Error: MYSQLBINLOG not found"
exit 1
fi
# Get data in dd-mm-yyyy format
NOW="$(date +"%d-%m-%Y-%T")"
DEST="/home/db-backup"
mkdir $DEST/Increment_backup.$NOW
LATEST=$DEST/Increment_backup.$NOW
$MYSQLADMIN -u$MyUSER -p$MyPASS flush-logs
newestlog=`ls -d /usr/local/mysql/data/mysql-bin.?????? | sed 's/^.*\.//' | sort -g | tail -n 1`
echo $newestlog
for file in `ls /usr/local/mysql/data/mysql-bin.??????`
do
if [ "/usr/local/mysql/data/mysql-bin.$newestlog" != "$file" ]; then
echo $file
$CP "$file" $LATEST
fi
done
for file1 in `ls $LATEST/mysql-bin.??????`
do
$MYSQLBINLOG $file1>$file1.$NOW.sql
$GZIP -9 "$file1.$NOW.sql"
$RM "$file1"
done
$RSYNC -avz $LATEST /home/rsync-back
Сценарии, запускаемые из crontab, не всегда имеют те же переменные среды, которые вы обычно принимаете как должное ... Сделайте следующее:
+ Изменить
#!/bin/sh
к
#!/bin/sh -x
с -x вы можете попробовать установить PATH вручную и даже отключить / etc / profile, если ничего не помогает.
#!/bin/sh -x
PATH=/bin:/sbin:/usr/bin:/usr/sbin
/bin/sh /etc/profile
попробуйте экспортировать пути и переменные, в crontabs пути должны быть указаны, способ, которым вы выполняете, в порядке, есть много сообщений на StackO и serverfault, где вы можете найти ответ на эту проблему
Версия оболочки / bin / sh не любит конструкцию $ (...). Лучше всего сделать одно из следующих:
1. Измените строку shebang на #! / Bin / bash
2. Измените команду crontab на * / 1 * * * * / bin / bash /home/db-backup/mysqlbackup.sh
3. И 1, и 2.
Для быстрого устранения неполадок обильно посыпьте свой сценарий эхом в выходной файл. Как поставить одну вверху:
#!/bin/bash
LOGFILE=/tmp/myoutput.log
echo "Starting" > $LOGFILE
и так далее. Затем вы можете посмотреть выходной файл после того, как сценарий должен был запуститься, и, возможно, увидеть, где он не работает. Если вывода вообще нет, возможно, он даже не работает, что мы еще не определили. Тогда вы сможете продолжить устранение неполадок.
Необходимые переменные среды, вероятно, не будут установлены при запуске скрипта из cron. Пытаться:
*/1 * * * * . /etc/profile; /home/db-backup/mysqlbackup.sh >>/tmp/mysqlbackup.log 2>&1
Это означает, что сначала настройте среду, запустив сценарий профиля по умолчанию перед фактическим резервным копированием. Дополнительно в конце есть перенаправление STDOUT и STDERR в файл журнала.
Найдите / var / log / cron или аналогичный. В зависимости от вашего вкуса * nix журнал также может находиться в ... / messages или ... / syslog. Искать cron
в /etc/syslog.conf точный конфиг.
Надеюсь, это поможет :-)
Краткое решение: комментарий директивы HOME = / в вашем файле / etc / crontab
Теперь объяснение:
Я нашел эту тему, потому что мой сценарий резервного копирования mysql, очищающий bin-logs, отлично работал в интерактивном режиме, но не работал, когда cron. Но случилось так, что моя установка немного отличалась от установки Рудры, поэтому основная причина и решение тоже, но все же позвольте мне опубликовать это здесь для других с той же настройкой, что и у меня.
Хорошо, мое отличие от настройки Rudra в том, что я не передаю имя пользователя и пароль mysqladmin в скрипте. Вместо этого я настраиваю, как предложено в «6.1.2.1. Руководство для конечных пользователей по защите паролем »документации MySQL (http://dev.mysql.com/doc/refman/5.5/en/password-security-user.html ), т.е. в разделе [client] файла ~ / .my.cnf root.
Linux разрешает ~ в значения переменной окружения HOME. cron daemon (согласно man 5 crontab) «Некоторые переменные среды устанавливаются автоматически демоном cron (8). SHELL устанавливается в / bin / sh, а LOGNAME и HOME устанавливаются из строки / etc / passwd владельца crontab. HOME и SHELL могут быть отменены настройками в crontab »
Итак, с такой настройкой mysqladmin flush-logs должен работать нормально, без передачи пароля в качестве параметра командной строки, но это НЕ сработало. Причина этого заключалась в том, что (по любой причине) файл / etc / crontab по умолчанию (по крайней мере, в CenOS 6.2) имеет директиву HOME = /, перезаписывающую одну настройку, как описано в man.
Так что прокомментируйте его в своем / etc / crontab и убедитесь, что это вам поможет!
Ура, Роман.
У меня была такая же проблема с crontab в AIX 7.1.
Для этого я заменил команду /bin/sh
с профильной оболочкой. Также в командной оболочке file.sh
добавлено . ~/.profile
в первой строке. После этого команда заработала нормально.
Это строка в crontab, которую я использовал:
mm hh * * * d . ~/.profile;/Directory/Command.sh > /LOG/logfile_command.log.`date | awk '{print $3$2$6}'` 2>&1
где мм: минуты, чч: час, д: день (0-6)
Каждый раз, когда вы используете запрос базы данных в скрипте, вам необходимо экспортировать путь. Ниже приводится экспорт базы данных Oracle:
ORACLE_HOME=/u01/app/oracle/product/11.2.0/db_1
LD_LIBRARY_PATH=$ORACLE_HOME/lib
PATH=$ORACLE_HOME/bin:$PATH
export PATH
export ORACLE_HOME
export ORACLE_SID
export LD_LIBRARY_PATH