1、背景2、问题
2.1 问题描述2.2 问题原因 3、解决方案4、参考文献 1、背景
在使用腾讯云的EMR-3.2.1时,客户有个需求,需要每周定时执行balance。
balance的脚本内容如下:
#!/bin/bash# It does not allow to run more than 1 Balancer process at the same time on a same hdfs-cluster.count=0log_file=/opt/balancer/logs/balancer-out.logerr_outfile=/opt/balancer/logs/balancer-debug.logfunction my_balancer(){ if [ ! -f ${log_file} ]; then touch ${log_file} elif [ ! -f ${err_outfile} ]; then touch ${err_outfile} fi jps | grep Balancer # if no Balancer running, then "$?" is 1、then good to start "hdfs balancer" if [ $? -ne 0 ]; then echo "No other Balancer process, go on to run this balancer job" nohup hdfs balancer -Ddfs.balancer.movedWinWidth=5400000 -Ddfs.balancer.moverThreads=1000 -Ddfs.balancer.dispatcherThreads=200 -Ddfs.datanode.balance.bandwidthPerSec=20971520 -Ddfs.balancer.max-size-to-move=10737418240 -threshold 5 1>${log_file} 2>${err_outfile} &if [ $? -eq 0 ]; then echo "successfully started running balancer as Daemon at" `date +'%Y-%m-%d_%H:%M:%S'` #count=$((${count}+1)) # TODO: to run next balancer loop, need to clean corresponding log then re-run. else echo "failed started balancer at" `date +'%Y-%m-%d_%H:%M:%S'` fi fi}# run the Balancermy_balancer
测试定时任务时使用的crontab 如下:
*/1 * * * * sh /home/hadoop/auto_balance.sh
2、问题 2.1 问题描述在测试时发现定时任务没有正常执行,因为在上述脚本中的日志文件中没有得到正常的输出,且报错内容也看不到。
修改该crontab 如下,以便查看定时任务在执行时有何报错:
*/1 * * * * sh /home/hadoop/auto_balance.sh > /home/hadoop/1.log 2>/home/hadoop/2.log
然后在/home/hadoop/2.log中看到了报错如下:
nohup: failed to run command ‘hdfs’: No such file or directory
2.2 问题原因从/home/hadoop/2.log中的报错,可以确定是crontab的环境变量问题。crontab没有获取到正确的环境变量。这是因为crontab有自己的环境变量,在/etc/crontab中。
SHELL=/bin/bashPATH=/sbin:/bin:/usr/sbin:/usr/binMAILTO=rootHOME=/# For details see man 4 crontabs# Example of job definition:# .---------------- minute (0 - 59)# | .------------- hour (0 - 23)# | | .---------- day of month (1 - 31)# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat# | | | | |# * * * * * user-name command to be executed
配置解释:
前四行是用来配置crond任务运行的环境变量
第一行SHELL变量指定了系统要使用哪个shell,这里是bash;
第二行PATH变量指定了系统执行命令的路径;
第三行MAILTO变量指定了crond的任务执行信息将通过电子邮件发送给root用户,如果MAILTO变量的值为空,则表示不发送任务执行信息给用户;
第四行的HOME变量指定了在执行命令或者脚本时使用的主目录。
手动执行的执行环境是当前账户的配置文件~/.bash_profile
注意:手动执行成功的命令/脚本,放到crontab中不一定能够正常执行。
3、解决方案有两种解决方案:
非系统自带的命令,使用绝对路径,如hdfs命令改为/usr/local/service/hadoop/bin/hdfs。在balance脚本中#!/bin/bash下加上一行source /etc/profile 或 、/etc/profile,这样crontab就能获取到正确的环境变量了。或者直接通过绝对路径来使用非系统自带的命令。在/etc/crontab中添加环境变量即可在PATH属性后面添加,也可以在执行对应的命令之前,加入一条命令,使得环境变量生效,例如:
0 * * * * 、/etc/profile;/bin/sh /var/www/java/audit_no_count/bin/restart_audit.sh
注意:在corntab 中执行多条语句时,用分号;隔开。故以上例子就是先执行、/etc/profile;这条命令,然后再运行sh脚本。这样,crontab在执行脚本的时候,就能够读到用户的环境变量参数 4、参考文献
[1] Crontab内环境变量与Shell环境变量的关系及解决问题的办法
[2] Linux中crontab的坑爹环境变量问题