Jade Dungeon

cron

全局配置

/etc/crontab文件包括环境变量与任务的配置:

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=""HOME=/
# run-parts
51 * * * * root run-parts /etc/cron.hourly
24 7 * * * root run-parts /etc/cron.daily
22 4 * * 0 root run-parts /etc/cron.weekly
42 4 1 * * root run-parts /etc/cron.monthly
  • 第一行SHELL变量指定了系统要使用哪个shell,这里是bash
  • 第二行PATH变量指定了系统执行命令的路径
  • 第三行MAILTO变量指定了crond的任务执行信息将通过电子邮件发送给root用户, 如果MAILTO变量的值为空,则表示不发送任务执行信息给用户,
  • 第四行的HOME变量指定了在执行命令或者脚本时使用的主目录。
  • 第六至九行定义了定时任务

crontab

  • *:代表所有可能的值,例如month字段如果是星号, 则表示在满足其它字段的制约条件后每月都执行该命令操作。
  • ,:可以用逗号隔开的值指定一个列表范围,例如,1,2,5,7,8,9
  • -:可以用整数之间的中杠表示一个整数范围,例如2-6表示2,3,4,5,6
  • /:可以用正斜线指定时间的间隔频率,例如0-23/2表示每两小时执行一次。 同时正斜线可以和星号一起使用,例如*/10,如果用在minute字段,表示每十分钟执行一次。

所有用户定义的crontab文件都被保存在/var/spool/cron目录中。 其文件名与用户名一致。

权限配置:

  • /etc/cron.deny:该文件中所列用户不允许使用crontab命令
  • /etc/cron.allow:该文件中所列用户允许使用crontab命令
  • /var/spool/cron/:所有用户crontab文件存放的目录,以用户名命名

需要注意的问题

今天遇见一个问题,crontab的定时任务不能自动执行,但是手动执行脚本一直能成功。 查到最后,发现是脚本里用了系统的环境变量。下面开始解释:

1.crontab与环境变量

不要假定cron知道所需要的特殊环境,它其实并不知道。 所以你要保证在shelll脚本中提供所有必要的路径和环境变量, 除了一些自动设置的全局变量。所以注意如下3点:

1)脚本中涉及文件路径时写全局路径;

2)脚本执行要用到java或其他环境变量时,通过source命令引入环境变量,如:

cat start_cbp.sh
#!/bin/sh
source /etc/profile
export RUN_CONF=/home/d139/conf/platform/cbp/cbp_jboss.conf
/usr/local/jboss-4.0.5/bin/run.sh -c mev &

3)当手动执行脚本OK,但是crontab死活不执行时。这时必须大胆怀疑是环境变量惹的祸, 并可以尝试在crontab中直接引入环境变量解决问题。如:

0 * * * * . /etc/profile;/bin/sh /var/www/java/audit_no_count/bin/restart_audit.sh

2.其他应该注意的问题

1)新创建的cron job,不会马上执行,至少要过2分钟才执行。如果重启cron则马上执行。

2)每条 JOB 执行完毕之后,系统会自动将输出发送邮件给当前系统用户。日积月累, 非常的多,甚至会撑爆整个系统。所以每条 JOB 命令后面进行重定向处理是非常必要的: >/dev/null 2>&1。前提是对 Job 中的命令需要正常输出已经作了一定的处理, 比如追加到某个特定日志文件。

3)当crontab突然失效时,可以尝试/etc/init.d/crond restart解决问题。 或者查看日志看某个job有没有执行/报错tail -f /var/log/cron

4)千万别乱运行crontab -r。它从Crontab目录(/var/spool/cron)中删除用户的Crontab文件。 删除了该用户的所有crontab都没了。

5)在crontab中%是有特殊含义的,表示换行的意思。如果要用的话必须进行转义\%, 如经常用的date '+%Y%m%d'在crontab里是不会执行的,应该换成date '+\%Y\%m\%d'

3.crontab中的输出配置

crontab中经常配置运行脚本输出为:>/dev/null 2>&1,来避免crontab运行中有内容输出。

4.登录对环境变量与配置的影响

Linux 中定时任务不生效的问题屡见不鲜, 本质原因是: 登录式 shell & 非登录式 shell.

登录式 shell 有:

  • su - <username>
  • Login: username / password

非登录式 shell

  • su <username>
  • 图形界面
  • 脚本执行




 

Bash 配置文件

全局配置文件

  • /etc/profile
  • /etc/profile.d/*.sh
  • /etc/bashrc

用户配置文件

  • ~/.bash_profile
  • ~/.bashrc

profile 类文件主要用途

  • 设定环境变量
  • 运行命令和脚本

bashrc 类文件主要用途

  • 设定本地变量
  • 定义命令别名

shell 读取配置文件顺序

登录式 shell

/etc/profile --> /etc/profile.d --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc

非登录式 shell

~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh

由以上信息可知, 因为定时任务是「非登录式 shell」, 故而很多环境变量不会被加载, 其中包括PATH.

我自己写定时任务脚本的时候, 会在脚本的开头写:

#!/bin/sh
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/local/zookeeper/bin:/root/bin

5.PAM权限问题

首先确定脚本可以手动执行,然后查看定时任务的日志/var/log/cron, 发现日志中报错如下(程序名) FAILED to authorize user with PAM (Module is unknown)

解决方法:修改/etc/pam.d/crond,把把所有required改成sufficient,这个对非root用户管用

account    sufficient pam_access.so
account    include    password-auth
session    sufficient pam_loginuid.so
session    include    password-auth
auth       include    password-auth

配置修改后,使用/etc/init.d/crond restart重启crontab使之生效(Centos7使用命令systemctl restart crond重启)

这样可以解决非root用户crontab定时任务无法执行问题