一个引号引起的crontab bug

对于crontab调用的程序,我们要一定要注意引号和相对路径,不然会给你导致无穷的问题。 阿健同学写了cron程序,部署在所有的服务器上,但是在一台服务器上怎么都会报一个错误,导致结果失败。 可所有的程序都是一模一样的。   主要代码如下, 脚本其实很简单.

1
2
3
4
5
6
7
8
9
10
11
 TEST_SIZE=`ls -l /opt/buffer/ | grep test* | awk '{print $5}'`
TEST_DATE=`ls -l /opt/buffer/ | grep test* | awk '{print $6, $7, $8}'`
if [ $TEST_SIZE -ge 0 ];
then
echo $TEST_SIZE > /mnt/log/88/TEST_SIZE.log
echo $TEST_DATE > /mnt/log/88/TEST_DATE.log
echo $TEST_DATE > /mnt/log/88/TEST_ORI.log
else
echo "null" > /mnt/log/fluentd/88/TEST_SIZE.log
more /mnt/log/88/TEST_ORI.log > /mnt/log/88/TEST_DATE.log
fi

看着也没有什么大错,虽然有点挫吧,但是该有的判断也都有的. 于是用set -x打开shell的调试,发现了一个错误

1
[: -ge: unary operator expected 

这个很明显是一边没有获得到值导致的错误.于是再往上看,发现在grep的时候, 程序里写的是 grep test*, 可在这里变成了 grep test_abc.log . 用find找了一下,果然在/root目录下发现了test_abc.log 这个问题,  而这个crontab是运行在root账户下. 我们在脚本里加上export看它是在哪个目录中执行的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
declare -x CVS_RSH="ssh"
declare -x G_BROKEN_FILENAMES="1"
declare -x HISTSIZE="1000"
declare -x HOME="/root"
declare -x HOSTNAME="tk04.tk.hk"
declare -x INPUTRC="/etc/inputrc"
declare -x LANG="en_US.UTF-8"
declare -x LESSOPEN="|/usr/bin/lesspipe.sh %s"
declare -x LOGNAME="root"
declare -x LS_COLORS=""
declare -x MAIL="/var/spool/mail/root"
declare -x OLDPWD
declare -x PATH="/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/ruby/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/bin:/bin"
declare -x PWD="/root"
declare -x SHELL="/bin/sh"
declare -x SHLVL="2"
declare -x USER="root"

那就很明白了.   原来当前目录就是/root啊。而你在 test* 的时候因为/root目录下只有test_abc.log, 所以自动补全成(这应该是一个典型的bug)test_abc.log 了。 而如果 /root 还有别的如 test_def.log 那理论上应该不会自动补全了。   至于bash为什么要做这样的处理,我们只能参考源码了。 而且我们得小心不同版本之间的区别。 所以实际经验就是加引号。 单引号和双引号在这里是没有区别的,但是大部分场合是有很大区别的。 以及``和$() 之间的区别也要清楚,这些就放到以后再说吧。