Bash 脚本手动运行,但在 crontab 上失败
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14612444/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Bash script runs manually, but fails on crontab
提问by Rudra
I'm a newbie to shell scripting. I have written a shell script to do incremental backup of MySQL database.The script is in executable format and runs successfully when executed manually but fails when executed through crontab.
我是 shell 脚本的新手。我写了一个shell脚本来做MySQL数据库的增量备份。脚本是可执行格式,手动执行时运行成功,但通过crontab执行时失败。
Crontab entry is like this :
Crontab 条目是这样的:
*/1 * * * * /home/db-backup/mysqlbackup.sh
Below is the shell script code -
下面是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
- First of all, when scheduled on crontab it is not showing any errors. How can I get to know whether the script is running or not?
- Secondly, what is the correct way to execute the shell script in a crontab. Some blogs suggest for change in environment variables. What would be the best solution
- 首先,在 crontab 上安排时,它没有显示任何错误。我怎样才能知道脚本是否正在运行?
- 其次,在 crontab 中执行 shell 脚本的正确方法是什么。一些博客建议更改环境变量。什么是最好的解决方案
When I did $echo PATH, I got this
当我执行 $echo PATH 时,我得到了这个
/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/mysql/bin:/opt/android-sdk-linux/tools:/opt/android-sdk-linux/platform-tools:~/usr/lib/jvm/jdk-6/bin
回答by amaurea
The problem is probably that your $PATH is different in the manual environment from that under which crontab runs. Hence, which
can't find your executables. To fix this, first print your path in the manual environment (echo $PATH
), and then manually set up PATH at the top of the script you run in crontab. Or just refer to the programs by their full path.
问题可能是您的 $PATH 在手动环境中与运行 crontab 的环境不同。因此,which
找不到您的可执行文件。要解决此问题,请首先在手动环境 ( echo $PATH
) 中打印您的路径,然后在您在 crontab 中运行的脚本的顶部手动设置 PATH。或者只是通过它们的完整路径来引用程序。
Edit: Add this near the top of your script, before all the which
calls:
编辑:在所有which
调用之前,将其添加到脚本顶部附近:
export PATH="/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/mysql/bin:/opt/android-sdk-linux/tools:/opt/android-sdk-linux/platform-tools:~/usr/lib/jvm/jdk-6/bin"
回答by JimR
Another more generic way is to have cron run the user's bash logon process. In addition to the PATH, this will also pick up any LD_LIBRARY_PATH, LANG settings, other environment variables, etc. To do this, code your crontab entry like:
另一种更通用的方法是让 cron 运行用户的 bash 登录过程。除了 PATH 之外,这还将获取任何 LD_LIBRARY_PATH、LANG 设置、其他环境变量等。为此,请对您的 crontab 条目进行编码,例如:
34 12 * * * bash -l /home/db-backup/mysqlbackup.sh
回答by blokeish
My Issue was that I set the cron job in /etc/cron.d (Centos 7). It seems that when doing so I need to specify the user who executes the script, unlike when a cronjob is entered at a user level.
我的问题是我在 /etc/cron.d (Centos 7) 中设置了 cron 作业。似乎这样做时我需要指定执行脚本的用户,这与在用户级别输入 cronjob 时不同。
All I had to do was
我所要做的就是
*/1 * * * * root perl /path/to/my/script.sh
*/5 * * * * root php /path/to/my/script.php
Where "root" states that I am running the script as root. Also need to make sure the following are defined at the top of the file. Your paths might be different. If you are not sure try the command "which perl", "which php".
其中“root”表示我以 root 身份运行脚本。还需要确保在文件顶部定义了以下内容。您的路径可能有所不同。如果您不确定,请尝试命令“which perl”、“which php”。
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
回答by Enio Marques Junior
Just import your user profile in the beginning of the script.
只需在脚本的开头导入您的用户配置文件。
i.e.:
IE:
. /home/user/.profile