为什么profile中设置的环境变量在crond中取不到?

环境: centos6

分析:

一般来讲,都是因为在某个环节把环境变量给清了:

  1. 要么是应用程序为了安全,自己清理了环境变量;这种情况多半在应用程序的配置中允许设置保留哪些环境变量(如:sudo程序)
  2. 要么是外部脚本启动应用程序时(使用env命令)把环境变量给清了;如: service命令启动服务(如: crond)时就使用env清理了环境变量:

    解决办法: 要么不清环境变量,要么添加自己期望保留的环境变量

根据上面的理论,修改了/sbin/service 添加了自己想保留的环境变量,如下:

(其实,如果直接使用/etc/init.d/crond start 来启动crond是和 /sbin/service 没有一毛钱关系的)

测试发现,在crond中启动的程序,依然获取不到想要的环境变量;根据上面理论,基本是crond把环境变量给清理了,那么这个该怎么办呢?

解决办法1: 给每个cron 任务写一个wrapper,在wrapper中设置自己需要的环境变量,wrapper.sh如下:

这样,只需要在每条cron的前面添加 wrapper.sh 就行了,如下:

cron执行log如下:

看起来还不错:)

但是,我有上百条cron,修改起来好是麻烦;其实通过写脚本来添加,还好;不过每次添加新的cron都要记着先写/tmp/wrapper.sh 有些繁琐,忘记了怎么办?

解决办法2:

据说cron会参考环境变量SHELL,而且可以在crontab中设置这个SHELL,你们crond应该就是用这个东西启动子进程的,否则要这个干啥?如果我在crontab中如下设置:

其不很方便?

测试发现并不如此简单,原因如下:

  1. 如果SHELL设置为/tmp/wrapper.sh 则crond是这么使用的:
    /tmp/wrapper.sh -c “/bin/echo 1 >/tmp/debug.txt”
    显然,我的wrapper.sh中没有处理-c选项; 简单,我也不关心这个,直接shift掉不就完了?wrapper.sh 修改如下:

    测试发现找不到/tmp/debug.txt;但是,在cron的邮件中找到了 “ 1 >/tmp/debug.txt”(这是cron任务的输出); 分析发现,我们的wrapper.sh 似乎并不认识 “>” ,难怪,我的wrapper.sh确实不是一个shell,不能解析 “>”, 但是如果为此写一个认识 “>” 的shell也不值当的呀!还是让bash自己来干吧
  2. 我们上面已经说了,crond使用了bash的-c选项,-c选项就是把字符串当做shell来执行,我何不学下呢?如下:

    嗯,就是这样子的

 

附录: vixiecron 的源码(src/do_command.c)中(函数: static int child_process(entry * e, char **jobenv); )是这么运行任务的:

man execle可以知道:

其中,最后一个参数是要执行的shell的环境变量,没有继承父进程的环境变量(虽然没有专门clear所有的环境变量)

 

其实,完全可以在crontab file的前面定义想要的环境变量的,这里定义的环境变量不会被清空

 

 

留下评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据