# 練習 17:任務調度:`cron`,`at`
> 原文:[Exercise 17. Job schedulers: cron, at](https://archive.fo/TRJCB)
> 譯者:[飛龍](https://github.com/wizardforcel)
> 協議:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/)
> 自豪地采用[谷歌翻譯](https://translate.google.cn/)
通常我們需要按計劃執行程序。例如,讓我們想象一下,你需要在每天的半夜備份你的作品。為了在 Linux 中完成它,有一個叫`cron`的特殊程序。這是一個惡魔,這意味著,當計算機啟動后,它就是啟動了,并在后臺默默等待,在時機到來時為你執行其他程序。`cron`具有多個配置文件,系統級的,或者用戶級的。默認情況下,用戶沒有`crontab`,因為沒有為它們安排任何東西。這是`cron`配置文件的位置:
`/etc/crontab` - 系統級`cron`配置文件。
`/var/spool/cron/crontabs/` - 用于存儲用戶配置文件的目錄。
現在我們來談談`cron`配置文件的格式。如果你運行`cat /etc/crontab`,你將看到:
```
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# m h dom mon dow user command
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#
```
它的語法足夠簡單,讓我們選取一行:
```
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly
```
然后拆開:
```
17 # 每個小時的第 17 個分鐘
* # 月中的每一天
* # 年中的每一月
* # 每個星期
root # 作為 root 用戶
cd / # 執行命令 'cd /'
&& # 如果 'cd /' 執行成功,那么
run-parts --report /etc/cron.hourly # 執行命令 'run-parts --report /etc/cron.hourly'
```
現在我總結`cron`的格式:
```
* * * * * <用戶> <要執行的命令>
T T T T T (僅僅用于系統
| | | | | 的 crontab)
| | | | |
| | | | +----- 星期幾 (0 - 6) (0 是星期天, 或者使用名稱)
| | | +---------- 月份 (1 - 12)
| | +--------------- 天 (1 - 31)
| +-------------------- 小時 (0 - 23)
+------------------------- 分鐘 (0 - 59)
```
這是時間格式中,可能的字符的縮略列表:
+ 星號(`*`) - 字段中的所有值,例如 分鐘的`*`表示每分鐘。
+ 斜線(`/`) - 定義范圍的增量。例如,`30-40/3`意味著在第 30 分鐘運行程序,每 3 分鐘一次,直到第 40 分鐘。
+ 百分比(`%`) - 在命令字段中,百分比后的所有數據將作為標準輸入發送到命令。現在不要糾結這個。
+ 逗號(`,`) - 指定列表,例如分鐘字段的`30,40`表示第 30 和 40 `分鐘。
+ 連字(`-`) - 范圍。例如,分鐘字段的`30-40`意味著每分鐘在30到40分鐘之間。
+ `L` - 指定最后一個東西,例如它允許你指定一個月的最后一天。
現在我會給你一些例子:
```
# m h dom mon dow user command
# (每月每天每小時)每分鐘
* * * * * root /bin/false
# (每月每天)每小時的第 30~40 分鐘中的每分鐘
30-40 * * * * root /bin/false
# (每月每天)每小時的第 30~40 分鐘中的每五分鐘
30-40/5 * * * * root /bin/false
# (每月每天每小時)每五分鐘
*/5 * * * * user command to be executed
# 每月的最后一天的每小時每分鐘
* * L * * root /bin/false
# 每月的星期天和星期三的每小時每分鐘
* * * * 0,3 root /bin/false
```
好的,但是如何加載`crontab`?這是`cron`命令的列表:
+ `crontab -l` - 打印出當前的`crontab`。
+ `crontab -e` - 為當前用戶編輯`crontab`。
+ `crontab -r` - 刪除當前用戶的`crontab`。
+ `crontab /path/to/file` - 為當前用戶加載`crontab`,覆蓋過程中的現有項。
+ `crontab > /path/to/file` - 將`crontab`保存到文件中。
這就是如何使用`cron`系統守護進程。但是還有一個可以調度程序執行的選項。它就是`at`工具。它們之間的區別是,`cron`為重復運行任務而設計,而且是很多次,并且`at`為調度一次性的任務而設計。這是相關的命令:
+ `at` - 在指定的時間執行命令。
+ `atq` - 列出待處理的任務。
+ `atrm` - 刪除任務。
+ `batch` - 執行命令,然后系統空轉。
這個信息轉儲似乎不夠,現在我會給你用于`at`的,時間規范表格,取自 <http://content.hccfl.edu/pollock/unix/atdemo.htm>。在下面的例子中,假定的當前日期和時間是 2001 年 9 月 18 日星期二上午 10:00。
| 示例 | 含義 |
| --- | --- |
| at noon | 2001 年 9 月 18 日星期二下午 12:00 |
| at midnight | 2001 年 9 月 18 日星期二上午 12:00 |
| at teatime | 2001 年 9 月 18 日星期二下午 4:00 |
| at tomorrow | 2001 年 9 月 19 日星期二上午 10:00 |
| at noon tomorrow | 2001 年 9 月 19 日星期二下午 12:00 |
| at next week | 2001 年 9 月 25 日星期二上午 10:00 |
| at next monday | 2001 年 9 月 24 日星期二上午 10:00 |
| at fri | 2001 年 9 月 21 日星期二上午 10:00 |
| at OCT | 2001 年 10 月 18 日星期二上午 10:00 |
| at 9:00 AM | 2001 年 9 月 18 日星期二上午 9:00 |
| at 2:30 PM | 2001 年 9 月 18 日星期二下午 2:30 |
| at 1430 | 2001 年 9 月 18 日星期二下午 2:30 |
| at 2:30 PM tomorrow | 2001 年 9 月 19 日星期二下午 2:30 |
| at 2:30 PM next month | 2001 年 10 月 18 日星期二下午 2:00 |
| at 2:30 PM Fri | 2001 年 9 月 21 日星期二下午 2:30 |
| at 2:30 PM 9/21 | 2001 年 9 月 21 日星期二下午 2:30 |
| at 2:30 PM Sept 21 | 2001 年 9 月 21 日星期二下午 2:30 |
| at 2:30 PM 9/21/2010 | 2001 年 9 月 21 日星期二下午 2:30 |
| at 2:30 PM 9.21.10 | 2001 年 9 月 21 日星期二下午 2:30 |
| at now + 30 minutes | 2001 年 9 月 18 日星期二上午 10:30 |
| at now + 1 hour | 2001 年 9 月 18 日星期二上午 11:00 |
| at now + 2 days | 2001 年 9 月 20 日星期二上午 10:00 |
| at 4 PM + 2 days | 2001 年 9 月 20 日星期二下午 4:00 |
| at now + 3 weeks | 2001 年 10 月 9 日星期二上午 10:00 |
| at now + 4 months | 2002 年 1 月 18 日星期二上午 10:00 |
| at now + 5 years | 2007 年 9 月 18 日星期二上午 10:00 |
現在你將學習如何添加、查看和移除`at`和`crontab`任務。
## 這樣做
```
1: echo 'echo Here I am, sitting in ur at, staring at ur date: $(date) | write user1' | at now + 1 minutes
2: atq
```
等待你的消息出現,按下`<ENTER>`并輸入更多東西:
```
3: echo '* * * * * echo Here I am, sitting in ur crontab, staring at ur date: $(date) | write user1' > ~/crontab.tmp
4: crontab -l
5: crontab ~/crontab.tmp
6: crontab -l
```
現在等待這個消息出現并移除它。
```
7: crontab -r
8: crontab -l
```
## 你會看到什么
```
user1@vm1:~$ echo 'echo Here I am, sitting in ur at, staring at ur date: $(date) | write user1' | at now + 1 minutes
warning: commands will be executed using /bin/sh
job 13 at Thu Jun 28 14:43:00 2012
user1@vm1:~$ atq
14 Thu Jun 28 14:45:00 2012 a user1
user1@vm1:~$
Message from user1@vm1 on (none) at 14:43 ...
Here I am, sitting in ur at, staring at ur date: Thu Jun 28 14:43:00 MSK 2012
EOF
user1@vm1:~$ crontab -l
no crontab for user1
user1@vm1:~$ echo '* * * * * echo Here I am, sitting in ur crontab, staring at ur date: $(date) | write user1' > ~/crontab.tmp
user1@vm1:~$ crontab -l
* * * * * echo Here I am, sitting in ur crontab, staring at ur date: $(date) | write user1
user1@vm1:~$
Message from user1@vm1 on (none) at 14:47 ...
Here I am, sitting in ur crontab, staring at ur date: Thu Jun 28 14:47:01 MSK 2012
EOF
user1@vm1:~$ crontab -r
user1@vm1:~$ crontab -l
no crontab for user1
user1@vm1:~$
```
## 解釋
1. 讓`at`在下一分鐘執行命令`echo Here I am, sitting in ur at, staring at ur date: $(date) | write user1`。
1. 打印`at`的任務隊列。
1. 將`echo '* * * * * echo Here I am, sitting in ur crontab, staring at ur date: $(date) | write user1 `寫入你的主目錄中的`crontab.tmp`。
1. 打印你當前的`crontab`,但目前沒有東西,所以它只是把這個告訴你。
1. 將`crontab.tmp`的內容加載到你的個人`crontab`文件。
1. 打印你當前的`crontab`。現在有一些東西。
1. 刪除你當前的`crontab`。
1. 告訴你,你再次沒有了`crontab`。
## 附加題
+ 閱讀`man crontab`, `man at`, `man write`。
+ 讓你的系統每 5 分鐘告訴你當前時間。
+ 讓你的系統在每小時的開始告訴你當前時間。
- 笨辦法學 Linux 中文版
- 練習 0:起步
- 練習 1:文本編輯器,vim
- 練習 2:文本瀏覽器,少即是多
- 練習 3:Bash:Shell、.profile、.bashrc、.bash_history
- 練習 4:Bash:處理文件,pwd,ls,cp,mv,rm,touch
- 練習 5:Bash:環境變量,env,set,export
- 練習 6:Bash:語言設置,LANG,locale,dpkg-reconfigure locales
- 練習 7:Bash:重定向,stdin,stdout,stderr,<,>,>>,|,tee,pv
- 練習 8:更多的重定向和過濾:head,tail,awk,grep,sed
- 練習 9:Bash:任務控制,jobs,fg
- 練習 10:Bash:程序退出代碼(返回狀態)
- 練習 11:總結
- 練習 12:文檔:man,info
- 練習 13:文檔:Google
- 練習 14:包管理:Debian 包管理工具aptitude
- 練習 15:系統啟動:運行級別,/etc/init.d,rcconf,update-rc.d
- 練習 16:處理進程,ps,kill
- 練習 17:任務調度:cron,at
- 練習 18:日志:/var/log,rsyslog,logger
- 練習 19:文件系統:掛載,mount,/etc/fstab
- 練習 20:文件系統:修改和創建文件系統,tune2fs,mkfs
- 練習 21:文件系統:修改根目錄,chroot
- 練習 22:文件系統:移動數據,tar,dd
- 練習 23:文件系統:權限,chown,chmod,umask
- 練習 24:接口配置,ifconfig,netstat,iproute2,ss,route
- 練習 25:網絡:配置文件,/etc/network/interfaces
- 練習 26:網絡:封包過濾配置,iptables
- 練習 27:安全 Shell,ssh,sshd,scp
- 練習 28:性能:獲取性能情況,uptime,free,top
- 練習 29:內核:內核消息,dmesg
- 練習 30:打磨、洗練、重復:總復習
- 下一步做什么
- Debian 手動安裝