第十五章 计划任务(crontab)
15.2 什么是计划任务
定时提醒,或符合条件就提醒。
15.1.1 Linux计划任务的种类:at、cron
- 例行性的:每隔一定的周期要办的事项;
- 突发性的:这次做完以后就没有
计划任务的种类:
at
:可以处理仅执行一次就结束的命令。执行at时,要有atd这个服务的支持才行。crontab
:这个命令所设置的任务将会循环执行下去,可循环的时间为分钟、小时、每周、每月或每年等。crontab除了可以使用命令执行外,还可以编辑/etc/crontab
来支持,至于让crontab可以生效的服务则是crond
。
15.1.2 CentOS Linux系统上常见的例行性任务
- 执行日志文件的轮询(
logrotate
):系统一直记录系统内发生的各种信息,日志文件越来越大。适时挪动日志文件,让就数据与新数据分别存放,可以更有效记录这些事件信息。 - 日志文件分析
logwatch
的任务:如果系统发生了软件问题、硬件错误、信息安全问题等,会被记录到日志中,因此,系统管理员的重要任务之一是分析日志文件。但不可能手动通过vim软件查看日志文件,因为数据过于复杂。利用系统自带的logwatch
主动分析登录信息。 - 建立
locate
的数据库:该命令通过已经存在的文件名数据库来执行文件名的查询。文件名数据库放置在/var/lib/locate
中,系统主动执行updatedb
来更新数据库。 - RPM软件日志文件的建立
- 删除缓存
- 与网络有关的分析操作:如果安装了类似网站服务器的软件(如apache),那么Linux就会主动分析该软件的日志文件。同时某些凭证与任重的网络信息是否过期的问题,Linux系统也会友好地帮忙执行自动检查。
15.2 仅执行一次的计划任务
15.2.1 atd的启动与at运行的方式
[root@study ~] systemctl restart atd 重启atd服务
[root@study ~] systemctl enable atd 让这个服务开机就自动启动
[root@study ~] systemctl status atd 查看atd目前的状态
● atd.service - Job spooling tools
Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled; vendor preset: enabled)
Active: active (running) since 四 2020-06-11 20:28:20 CST; 31s ago
Main PID: 6665 (atd)
CGroup: /system.slice/atd.service
└─6665 /usr/sbin/atd -f
6月 11 20:28:20 study.centos.vbird systemd[1]: Started Job spooling tools.
使用at
这个命令产生所要运行的任务,并将这个任务以文本文件的方式写入/var/spool/at/
目录内,该任务便能等待atd
这个服务的使用与执行了。
管控at
:通过/etc/at.allow
和/etc/at.deny
这两个文件实现对at
的限制。
- 白名单:先找到
/etc/at.allow
文件,写在这个文件中的用户才能使用at
,没有在这个文件中的用户则不能使用at
(即使没有写在at.deny
中) - 黑名单:如果
/etc/at.allow
文件不存在,查找/etc/at.deny
文件,写在这个文件中的用户不能使用at
,没有在这个文件中的用户则可以使用at
。 - 无名单:如果两个文件都不存在,只有
root
可以使用at
。
15.2.2 实际运行单一计划任务
5分钟后,把 /root/.bashrc 这个文件的内容发给root用户
[root@study ~] at now +5 minutes
at> /bin/mail -s "testing at job" root < /root/.bashrc
at> <EOT>
job 1 at Thu Jun 11 20:48:00 2020
列出任务1内容看看:
root@study ~] at -c 1
#!/bin/sh
# atrun uid=0 gid=0
# mail root 0
umask 22
XDG_VTNR=1; export XDG_VTNR
SSH_AGENT_PID=2039; export SSH_AGENT_PID
XDG_SESSION_ID=1; export XDG_SESSION_ID
HOSTNAME=study.centos.vbird; export HOSTNAME
IMSETTINGS_INTEGRATE_DESKTOP=yes; export IMSETTINGS_INTEGRATE_DESKTOP
VTE_VERSION=5202; export VTE_VERSION
SHELL=/bin/bash; export SHELL
XDG_MENU_PREFIX=gnome-; export XDG_MENU_PREFIX
HISTSIZE=1000; export HISTSIZE
GNOME_TERMINAL_SCREEN=/org/gnome/Terminal/screen/5c2e0ba9_bff1_4e82_b9e0_c5abd2611194; export GNOME_TERMINAL_SCREEN
IMSETTINGS_MODULE=none; export IMSETTINGS_MODULE
USER=root; export USER
LS_COLORS=rs=0:di=38\;5\;27:ln=38\;5\;51:mh=44\;38\;5\;15:pi=40\;38\;5\;11:so=38\;5\;13:do=38\;5\;5:bd=48\;5\;232\;38\;5\;11:cd=48\;5\;232\;38\;5\;3:or=48\;5\;232\;38\;5\;9:mi=05\;48\;5\;232\;38\;5\;15:su=48\;5\;196\;38\;5\;15:sg=48\;5\;11\;38\;5\;16:ca=48\;5\;196\;38\;5\;226:tw=48\;5\;10\;38\;5\;16:ow=48\;5\;10\;38\;5\;21:st=48\;5\;21\;38\;5\;15:ex=38\;5\;34:\*.tar=38\;5\;9:\*.tgz=38\;5\;9:\*.arc=38\;5\;9:\*.arj=38\;5\;9:\*.taz=38\;5\;9:\*.lha=38\;5\;9:\*.lz4=38\;5\;9:\*.lzh=38\;5\;9:\*.lzma=38\;5\;9:\*.tlz=38\;5\;9:\*.txz=38\;5\;9:\*.tzo=38\;5\;9:\*.t7z=38\;5\;9:\*.zip=38\;5\;9:\*.z=38\;5\;9:\*.Z=38\;5\;9:\*.dz=38\;5\;9:\*.gz=38\;5\;9:\*.lrz=38\;5\;9:\*.lz=38\;5\;9:\*.lzo=38\;5\;9:\*.xz=38\;5\;9:\*.bz2=38\;5\;9:\*.bz=38\;5\;9:\*.tbz=38\;5\;9:\*.tbz2=38\;5\;9:\*.tz=38\;5\;9:\*.deb=38\;5\;9:\*.rpm=38\;5\;9:\*.jar=38\;5\;9:\*.war=38\;5\;9:\*.ear=38\;5\;9:\*.sar=38\;5\;9:\*.rar=38\;5\;9:\*.alz=38\;5\;9:\*.ace=38\;5\;9:\*.zoo=38\;5\;9:\*.cpio=38\;5\;9:\*.7z=38\;5\;9:\*.rz=38\;5\;9:\*.cab=38\;5\;9:\*.jpg=38\;5\;13:\*.jpeg=38\;5\;13:\*.gif=38\;5\;13:\*.bmp=38\;5\;13:\*.pbm=38\;5\;13:\*.pgm=38\;5\;13:\*.ppm=38\;5\;13:\*.tga=38\;5\;13:\*.xbm=38\;5\;13:\*.xpm=38\;5\;13:\*.tif=38\;5\;13:\*.tiff=38\;5\;13:\*.png=38\;5\;13:\*.svg=38\;5\;13:\*.svgz=38\;5\;13:\*.mng=38\;5\;13:\*.pcx=38\;5\;13:\*.mov=38\;5\;13:\*.mpg=38\;5\;13:\*.mpeg=38\;5\;13:\*.m2v=38\;5\;13:\*.mkv=38\;5\;13:\*.webm=38\;5\;13:\*.ogm=38\;5\;13:\*.mp4=38\;5\;13:\*.m4v=38\;5\;13:\*.mp4v=38\;5\;13:\*.vob=38\;5\;13:\*.qt=38\;5\;13:\*.nuv=38\;5\;13:\*.wmv=38\;5\;13:\*.asf=38\;5\;13:\*.rm=38\;5\;13:\*.rmvb=38\;5\;13:\*.flc=38\;5\;13:\*.avi=38\;5\;13:\*.fli=38\;5\;13:\*.flv=38\;5\;13:\*.gl=38\;5\;13:\*.dl=38\;5\;13:\*.xcf=38\;5\;13:\*.xwd=38\;5\;13:\*.yuv=38\;5\;13:\*.cgm=38\;5\;13:\*.emf=38\;5\;13:\*.axv=38\;5\;13:\*.anx=38\;5\;13:\*.ogv=38\;5\;13:\*.ogx=38\;5\;13:\*.aac=38\;5\;45:\*.au=38\;5\;45:\*.flac=38\;5\;45:\*.mid=38\;5\;45:\*.midi=38\;5\;45:\*.mka=38\;5\;45:\*.mp3=38\;5\;45:\*.mpc=38\;5\;45:\*.ogg=38\;5\;45:\*.ra=38\;5\;45:\*.wav=38\;5\;45:\*.axa=38\;5\;45:\*.oga=38\;5\;45:\*.spx=38\;5\;45:\*.xspf=38\;5\;45:; export LS_COLORS
GNOME_TERMINAL_SERVICE=:1.112; export GNOME_TERMINAL_SERVICE
SSH_AUTH_SOCK=/run/user/0/keyring/ssh; export SSH_AUTH_SOCK
USERNAME=root; export USERNAME
SESSION_MANAGER=local/unix:@/tmp/.ICE-unix/1888,unix/unix:/tmp/.ICE-unix/1888; export SESSION_MANAGER
GNOME_SHELL_SESSION_MODE=classic; export GNOME_SHELL_SESSION_MODE
PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/root/bin; export PATH
MAIL=/var/spool/mail/root; export MAIL
DESKTOP_SESSION=gnome-classic; export DESKTOP_SESSION
QT_IM_MODULE=ibus; export QT_IM_MODULE
XDG_SESSION_TYPE=x11; export XDG_SESSION_TYPE
PWD=/root; export PWD
XMODIFIERS=@im=ibus; export XMODIFIERS
LANG=zh_CN.UTF-8; export LANG
GDM_LANG=zh_CN.UTF-8; export GDM_LANG
GDMSESSION=gnome-classic; export GDMSESSION
HISTCONTROL=ignoredups; export HISTCONTROL
XDG_SEAT=seat0; export XDG_SEAT
HOME=/root; export HOME
SHLVL=2; export SHLVL
GNOME_DESKTOP_SESSION_ID=this-is-deprecated; export GNOME_DESKTOP_SESSION_ID
XDG_SESSION_DESKTOP=gnome-classic; export XDG_SESSION_DESKTOP
LOGNAME=root; export LOGNAME
XDG_DATA_DIRS=/root/.local/share/flatpak/exports/share/:/var/lib/flatpak/exports/share/:/usr/local/share/:/usr/share/; export XDG_DATA_DIRS
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-kYEJyFgt75,guid=1d143d87b68f769ced9acc6f5ee1c64a; export DBUS_SESSION_BUS_ADDRESS
LESSOPEN=\|\|/usr/bin/lesspipe.sh\ %s; export LESSOPEN
WINDOWPATH=1; export WINDOWPATH
XDG_RUNTIME_DIR=/run/user/0; export XDG_RUNTIME_DIR
XDG_CURRENT_DESKTOP=GNOME-Classic:GNOME; export XDG_CURRENT_DESKTOP
COLORTERM=truecolor; export COLORTERM
XAUTHORITY=/run/gdm/auth-for-root-XbAWvZ/database; export XAUTHORITY
cd /root || {
echo 'Execution directory inaccessible' >&2
exit 1
}
${SHELL:-/bin/sh} << 'marcinDELIMITER4b4fafbb'
/bin/mail -s "testing at job" root < /root/.bashrc 这句最重要
marcinDELIMITER4b4fafbb
定时关机功能
可以在一个任务中输入多个命令:
[root@study ~] at 23:00 2020-06-11
at> /bin/sync
at> /bin/sync
at> /sbin/shutdown -h now
at> <EOT>
job 2 at Thu Jun 11 23:00:00 2020
在终端显示内容:
echo "hello" > /dev/tty1
而通过下面这句无法显示到屏幕上,所有标准输出和标准错误输出都会发送到执行者的mailbox中,终端看不到信息
echo "hello"
at能实现【后台执行】的功能,就是脱机继续执行的任务。由于at计划任务的使用,系统会将该项at任务独立出你的bash环境,直接交给系统的atd程序来接管。因此,当你执行了at的任务后就可以立刻脱机了,剩下的工作就完全交给Linux管理。所以,有长时间的网络任务时,使用at可以免除网络断线后的困扰。
取消一个at命令,执行后发现命令有错
atq 查询有多少的at计划任务
atrm 2 删除这个任务2
系统有空时才执行后台任务,当CPU的任务负载小于0.8的时候,才执行这个任务。此处负载不是CPU使用率,二是CPU在单一时间点所负责的任务数量。
[root@study ~] echo "scale=100000;4*a(1)" | bc -lq & 让系统超忙
[1] 7161
[root@study ~] echo "scale=100000;4*a(1)" | bc -lq & 让系统超忙
[2] 7171
[root@study ~] echo "scale=100000;4*a(1)" | bc -lq & 让系统超忙
[3] 7179
[root@study ~] echo "scale=100000;4*a(1)" | bc -lq & 让系统超忙
[4] 7187
[root@study ~] uptime
21:01:39 up 5:50, 2 users, load average: 1.07, 0.26, 0.12
[root@study ~] batch 布置一个等闲的时候再执行的任务
at> /usr/bin/updatedb
at> <EOT>
job 3 at Thu Jun 11 21:01:00 2020
[root@study ~] date;atq 此时任务还没有被执行掉,因为系统正忙
2020年 06月 11日 星期四 21:02:11 CST
3 Thu Jun 11 21:01:00 2020 b root
[root@study ~] jobs 系统中的任务
[1] 运行中 echo "scale=100000;4*a(1)" | bc -lq &
[2] 运行中 echo "scale=100000;4*a(1)" | bc -lq &
[3]- 运行中 echo "scale=100000;4*a(1)" | bc -lq &
[4]+ 运行中 echo "scale=100000;4*a(1)" | bc -lq &
[root@study ~] kill -9 %1 %2 %3 %4 杀掉这些任务
[1] 已杀死 echo "scale=100000;4*a(1)" | bc -lq
[2] 已杀死 echo "scale=100000;4*a(1)" | bc -lq
[3]- 已杀死 echo "scale=100000;4*a(1)" | bc -lq
[4]+ 已杀死 echo "scale=100000;4*a(1)" | bc -lq
[root@study ~] uptime;atq 查询发现还没执行,负载降低需要时间
21:03:32 up 5:52, 2 users, load average: 2.06, 1.11, 0.46
3 Thu Jun 11 21:01:00 2020 b root
[root@study ~] uptime;atq 过了一会再查就已经被执行掉了
21:09:26 up 5:58, 2 users, load average: 0.02, 0.41, 0.36
整分钟时间,每分钟检查一次,任务是在整分时执行的,此时秒数为0。
15.3 循环执行的计划任务
循环执行的计划任务是由cron
这个系统服务来控制的。是开机默认启动的,因为Linux本身有很多的例行性计划任务。
15.3.1 用户的设置
管控cron
:通过/etc/cron.allow
和/etc/cron.deny
这两个文件实现对cron
的限制。
- 白名单:先找到
/etc/cron.allow
文件,写在这个文件中的用户才能使用cron
,没有在这个文件中的用户则不能使用cron
(即使没有写在cron.deny
中) - 黑名单:如果
/etc/cron.allow
文件不存在,查找/etc/cron.deny
文件,写在这个文件中的用户不能使用cron
,没有在这个文件中的用户则可以使用cron
。
用户dj
使用crontab
命令建立计划任务后,该项任务就会被记录到/var/spool/cron/dj
中。不要用vi直接编辑该文件可能由于输入语法错误,会导致无法执行cron。cron执行的每一项任务都会被记录到/var/log/cron
这个日志文件中,所以,通过查找/var/log/cron
恩建可以看看Linux有没有被植入木马。
利用dj的身份,每天12点发信给自己:
[dj@study ~]$ crontab -e 编辑任务,编辑完成后保存退出
no crontab for dj - using an empty one
crontab: installing new crontab
[dj@study ~]$ crontab -l 查看当前用户dj有哪些任务
0 12 * * * mail -s "at 12:00" dj < /home/dj/.bashrc
59 11 22 8 * mail gaogao < /home/dj/.bashrc
*/5 * * * * /home/dj/test.sh
30 16 * * 5 mail friend@his.server.name </home/dj/friend.txt
[dj@study ~]$ crontab -r 删除所有任务
[dj@study ~]$ crontab -l
no crontab for dj
如果想删除单条任务,可以使用-e
进入编辑文档中删除即可。文档中的内容就是-l
列出来的那些。
15.3.2 系统的配置文件:/etc/crontab、/etc/cron.d/*
crontab -e
是针对用户cron设计的,而要执行系统的例行性任务,可以编辑/etc/crontab
文件。
crontab -e
中的crontab
其实是/usr/bin/crontab
这个可执行文件;但是/etc/crontab
是个纯文本文件。可用root身份编辑它。
编辑好后,cron这个服务的最低检测限度是【分钟】,所以cron每分钟会去读取一次/etc/crontab
和/var/spool/cron
中的内容,只要编辑完保存好,cron的设置就自动会执行了。
登出
[root@study ~] cat /etc/crontab 看一下文件内容
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# 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
分 时 日 月 周 身份 命令
除了/etc/crontab外,另一个与系统运行相关的配置文件是/etc/cron.d:
[root@study ~] ls -l /etc/cron.d
总用量 12
-rw-r--r--. 1 root root 128 8月 9 2019 0hourly
-rw-r--r--. 1 root root 108 8月 6 2019 raid-check
-rw-------. 1 root root 235 8月 9 2019 sysstat
[root@study ~] cat /etc/cron.d/0hourly
# Run the hourly jobs
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
01 * * * * root run-parts /etc/cron.hourly 这里有学问
run-parts /etc/cron.hourly
命令解读:run-part
脚本会在大约5
分钟内随机选一个时间执行/etc/cron.hourly
目录下的所有执行文件,因此放在这个文件夹下的必须是可以被直接执行的命令脚本。
除了通过修改配置文件外,还可以直接将命令放置到(或链接到)/etc/cron.hourly/
文件夹下,让系统每小时的第1分钟开始后的5分钟内,随机选一个时间点执行,无需手动指定分、时、日、月、周。
15.3.3 一些注意事项
大量使用crontab时,总会有问题发生。最严重的问题是【系统资源分配不均】。
检测主机流量信息:
- 流量
- 区域内其他PC的流量监测
- CPU使用率
- RAM使用率
- 在线人数实时监测
需要注意:
- 【资源分配不均问题】:同时启动的话,系统某个时段会相当繁忙,可以通过分流,把任务列表中的不同的任务设置到不同的时间点。
- 【取消不要的输出选项】:如果执行成果或是执行的选项中有输出数据时,该数据会一直mail给指定账号,可以通过【数据流重定向】将结果输出到垃圾桶
/dev/null
中。 - 【安全的检验】:很多时候,木马都是以计划任务的方式植入的,可以借由检查
/var/log/cron
的内容来观察是否有【非您设置的cron被执行了】,这个时候要小心一些。 - 【周与日月不可同时并存】
15.4 可唤醒停机期间的工作任务
anacron
可以主动帮你执行【因某些原因,时间到了但却没有执行的计划任务】。
15.4.1 什么是anacron
anacron
也是每小时被crond
执行一次,然后anacron
再去检测相关的计划任务有没有被执行,如果有超过期限的任务在,就执行该任务,执行完毕或无需执行任何任务时,anacron
就停止。
anacron
默认会以一天、七天、一个月为期去检测系统未执行的crontab
任务。
anacron
会读取时间记录文件(timestamps),分析【现在的时间】与【时间记录文件所记载的上次执行anacron
的时间】,两者比较后若有差异,那就是在某些时刻没有执行crontab
,此时anacron
会开始执行未执行的crontab
任务。
15.4.2 anacron与/etc/anacrontab
anacron
是一个程序而非一个服务,这个程序已经进入crontab列表,每小时被执行一次。
[root@study ~]# cat /etc/cron.hourly/0anacron
#!/bin/sh
# Check whether 0anacron was run today already
if test -r /var/spool/anacron/cron.daily; then 检查上次执行anacron的时间戳
day=`cat /var/spool/anacron/cron.daily`
fi
if [ `date +%Y%m%d` = "$day" ]; then
exit 0;
fi
# Do not run jobs when on battery power
if test -x /usr/bin/on_ac_power; then
/usr/bin/on_ac_power >/dev/null 2>&1
if test $? -eq 1; then
exit 0
fi
fi
/usr/sbin/anacron -s 其实就是执行anacron -s命令
anacron 的配置文件:
[root@study ~] cat /etc/anacrontab
# /etc/anacrontab: configuration file for anacron
# See anacron(8) and anacrontab(5) for details.
SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# the maximal random delay added to the base delay of the jobs
RANDOM_DELAY=45
# the jobs will be started during the following hours only
START_HOURS_RANGE=3-22
#period in days delay in minutes job-identifier command
1 5 cron.daily nice run-parts /etc/cron.daily
7 25 cron.weekly nice run-parts /etc/cron.weekly
@monthly 45 cron.monthly nice run-parts /etc/cron.monthly
[root@study ~] more /var/spool/anacron/*
::::::::::::::
/var/spool/anacron/cron.daily
::::::::::::::
20200611
::::::::::::::
/var/spool/anacron/cron.monthly
::::::::::::::
20200530
::::::::::::::
/var/spool/anacron/cron.weekly
::::::::::::::
20200606