可直接执行的脚本放到crontab中就不执行了

iamlaosong文

前面文章曾提到过的定时检测压缩包并完成解压、修改文件名和导入到数据库的脚本(检测压缩包并处理的Linux脚本(解压、批量修改文件名、导入)),后来发现放到crontab中就无法执行了,费了很大劲,一步步找问题,首先是脚本肯定执行了,后来在脚本中增加一些其他命令如pwd、echo等都执行了,最后发现是导入程序没有执行,其实也不是没有执行,而是执行后退出来了。

下面是找问题的过程:

首先,crond服务未启动,这个可以排除,因为还有其他定时任务在做,简单测试一下就可以发现脚本执行了。

第二,权限问题,比如没有执行权限,这个也不存在,因为直接执行是正常的。

第三、路径问题,任务命令是绝对路径,脚本中加了pwd语句显示路径是对的,再说直接执行也没问题。

第四、时差问题,因为服务器与客户端时差问题,所以crontab的时间以服务器时间为准,这个也没问题。

第五、变量问题,有时候命令中含有变量,但crontab执行时却没有,也会造成执行失败,这个也没问题。

上面五点只是解决crontab不能正常执行的问题,现在是脚本执行了,只是关键的导入命令没有执行,于是我想到了环境变量的问题,因为导入程序是需要和oracle打交道的,需要很多环境变量,原以为定时任务是在oracle用户下建立的,应该具有这个用户的环境变量,其实不然,定时任务执行时根本没有加载这些环境变量。oracle用户下建立的定时任务,只有其权限,没有环境变量。

找到问题,解决也很简单,只需将.bash_profile执行一下就行了。可以在当前脚本中执行,也可以在其调用的脚本jsimp.sh中执行。下面是部分脚本:

#import data beginning
. /home/oracle/.bash_profile
cd ${BINDIR}
for dd in ${SYFDAT}
do
  ./jsimp.sh ${dd} SYF
done
for dd in ${BCFDAT}
do
  ./jsimp.sh ${dd} BCF
done
#end import

代码中. /home/oracle/.bash_profile前面的点(注意后面有个空格)表示脚本在同一个shell中执行, 所调用的脚本中声明的变量和环境变量都可以在主脚本中得到和使用。在Linux平台上开发,经常会在一个shell脚本中(或者控制台)调用另外一个shell脚本文件,在一个脚本中调用另外一个脚本有三种方法:

1、fork  ( /directory/script.sh)
    fork是最普通的, 就是直接调用,即在脚本里面用/directory/script.sh来调用script.sh这个脚本。运行的时候开一个sub-shell执行调用的脚本,sub-shell执行的时候,parent-shell还在,sub-shell执行完毕后返回parent-shell。sub-shell从parent-shell继承环境变量,但是sub-shell中的环境变量不会带回parent-shell中。

2、exec (exec /directory/script.sh)
    调用时脚本名称前加上exec四个字符。exec与fork不同,不需要新开一个sub-shell来执行被调用的脚本,被调用的脚本与父脚本在同一个shell内执行。但是使用exec调用一个新脚本以后,父脚本中exec行之后的内容就不会再执行了。
这是exec和source的区别。

3、source (source /directory/script.sh)
    调用时前面加上source六个字符或者用一个“.”代替source。与fork的区别是不新开一个sub-shell来执行被调用的脚本,而是在同一个shell中执行。所以被调用的脚本中声明的变量和环境变量都可以在主脚本中得到和使用。

简单的说,fork相当于出国旅游了一趟,啥也没带回来;exec相当于直接出国定居了,再也不回来了;而source则是把外国的景点搬到国内,风景都留下来了。对应这三种方法,上面jsimp.sh脚本的调用写法如下:

#fork
./jsimp.sh
#exec
exec ./jsimp.sh
#source
. ./jsimp.sh

最后,想说一下,环境变量这个坑,已经有无数的人掉下去了,今后,还将有无数的人前赴后继,继续跳进去,祝那些掉坑里的坑友们好运。


你可能感兴趣的:(Linux应用)