Bash脚本手动运行,但在crontab上失败

我是shell脚本的新手。 我写了一个shell脚本来做MySQL数据库的增量备份。脚本是可执行的格式,手动执行时运行成功,但通过crontab执行时失败。
Crontab条目是这样的:* / 1 * * * * /home/db-backup/mysqlbackup.sh
下面是shell脚本代码 –

#!/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上计划它不显示任何错误。 我怎样才能知道脚本是否在运行?
  • 其次,在crontab中执行shell脚本的正确方法是什么?
  • 有些博客build议改变环境variables。 什么是最好的解决scheme

从crontab运行脚本并不总是有相同的环境variables,你通常会被授予…做到这一点:

更改

  #!/bin/sh 

  #!/bin/sh -x 

与-x,你可以尝试手动设置PATH,甚至踢开/ etc / profile,如果一切都失败。

 #!/bin/sh -x PATH=/bin:/sbin:/usr/bin:/usr/sbin /bin/sh /etc/profile 

shell的/ bin / sh版本不像$(…)结构。 你最好的办法是做下面的其中一个:
1.将shebang行更改为#!/ bin / bash
2.将crontab命令更改为* / 1 * * * * / bin / bash /home/db-backup/mysqlbackup.sh
3. 1和2。

尝试导出path和variables,在crontabspath必须指定,你执行的方式很好,有很多post在StackO和serverfault,你可以find答案这个问题

为了快速排除故障,可以用echo将自己的脚本放在输出文件中。 就像在顶端放一个:

 #!/bin/bash LOGFILE=/tmp/myoutput.log echo "Starting" > $LOGFILE 

等等。 然后,您可以在脚本应该运行后查看输出文件,也许可以看到它失败的位置。 如果完全没有输出的话,甚至可能还没有运行,我们还没有确定。 然后您可以进一步排除故障。

脚本从cron运行时,可能不会设置所需的环境variables。 尝试:

 */1 * * * * . /etc/profile; /home/db-backup/mysqlbackup.sh >>/tmp/mysqlbackup.log 2>&1 

这意味着首先通过在实际备份之前运行默认configuration文件脚本来设置环境。 此外在最后还有STDOUT和STDERRredirect到一个日志文件。

寻找/ var / log / cron或类似的。 根据您的* nix风味,日志可能也在… / messages或… / syslog中。 在/etc/syslog.conf确切configuration中寻找cron

希望这有助于:-)

简短的措辞解决scheme:在/ etc / crontab文件中注释HOME = /指令

现在解释:

我发现这个话题是因为我的mysql备份脚本flushing bin-logs,交互性很好,但在cron时失败。 但是事情发生了,我的设置和Rudra的设置稍有不同,所以根本的原因和解决办法也是如此,但是我仍然可以把它放在这里给其他人使用和我一样的设置。

好的,与Rudra的设置不同的是,我不会将脚本中的用户名和密码传递给mysqladmin。 相反,我按照“6.1.2.1”的build议安装。 MySQL文档( http://dev.mysql.com/doc/refman/5.5/en/password-security-user.html )的密码安全最终用户指南“,即在〜/ .my的[client]部分根的.cnf文件。

Linuxparsing成HOME环境variables的值。 cron守护进程(按照man 5 crontab)“几个环境variables由cron(8)守护进程自动设置。 SHELL设置为/ bin / sh,LOGNAME和HOME设置在crontab的所有者的/ etc / passwd行中。 HOME和SHELL可能会被crontab中的设置覆盖“

所以,使用这个设置“mysqladmin flush-logs”应该可以正常工作,而不需要将密码作为命令行parameter passing就好了,但是没有。 原因是(无论出于何种原因),默认的/ etc / crontab文件(至less在CenOS 6.2中)有一个指令HOME = /,覆盖man中描述的一个设置。

所以,在你的/ etc / crontab中注释一下,看看对你有帮助!

干杯,罗马。

我在AIX 7.1上遇到了与crontab相同的问题。

为此,我replace了configuration文件shell的命令/bin/sh 。 另外,在命令shell中添加file.sh . ~/.profile在第一行。 之后,这个命令工作正常。

这是我使用的crontab上的行:

 mm hh * * * d . ~/.profile;/Directory/Command.sh > /LOG/logfile_command.log.`date | awk '{print $3$2$6}'` 2>&1 

其中mm:分钟,hh:小时,d:日(0-6)

无论何时在脚本中使用DataBase查询,都需要导出path。 以下是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