Linux Crontab 拾遗笔记

介绍

Crontab 是一个用于设置周期性被执行任务(即计划任务)的工具。

  • 被周期性执行的任务:Cron Job
  • 周期性执行的任务列表:Cron Table

安装

# 主程序
yum install vixie-cron -y

# 用来安装、卸装、列举用来驱动 cron 守护进程的表格的程序
yum install crontabs -y

# 启动 crond 服务
service crond start|stop|status|try-restart|reload

检测服务状态

+ 方法1:crontab -l
+ 方法2:ps -elf | grep crond | grep -v "grep"
+ 方法3:service crond status

Crond 是什么?

Crond 是一个守护进程,每分钟会从配置文件中刷新并执行定时任务。 每分钟不仅要读一次 /var/spool/cron 内的所有文件,还需要读一次 /etc/crontab。

系统级计划任务 /etc/crontab

分 时 日 月 周 `用户名` /root/do.sh

用户级的计划任务 /var/spool/cron/用户名

# 编辑指定用户的任务表
# -u 缺省不写就代表当前用户
crontab -e [-u 用户名]

# 列举指定用户的任务表
crontab -l [-u 用户名]

# 清除指定用户的任务表
crontab -r [-u 用户名]

补充几点说明:

  1. 执行 crontab -e 实际上是修改文件 vi /var/spool/cron/用户名
  2. 执行 crontab 文件名 时,是直接导入覆盖任务表到 /var/spool/cron/用户名 中。
  3. /etc/cron.d/ 目录里的文件,可以认为是对系统配置的补充文件,会在 crond 运行时自动加载

使用者权限

  • 文件 /etc/cron.deny 中所列用户不允许使用 crontab 命令
  • 文件 /etc/cron.allow 中所列用户允许使用 crontab 命令

配置格式

# 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

有趣的配置示例

# 奇数分钟执行
1-59/2 * * * * /root/do.sh

# 偶数分钟执行
*/2 * * * * /root/do.sh

# 表示第 1,3,5,7,9 分钟会执行,第11分钟不会执行
# 即先要满足条件 1~10,再满足逢 2
1-10/2 * * * * /root/do.sh

执行日志

可以通过看日志来知道任务有没有运行 tail -f /var/log/cron

ls /var/log/cron*

- cron(最新的日志文件)
- cron-20161030(截止到10月30日的日志文件)
- cron-20161106
- cron-20161113
- cron-20161120

容易犯错的点

1、环境变量读取

Crontab 执行任务调度时,不会加载任何环境变量,所以请在执行脚本中自己用 source 命令引入环境变量。

另外执行脚本中涉及文件路径时必须写绝对路径。

2、第3个参数(日)和第五个参数(周)是逻辑或的关系

# 四月的第一个星期日0点59分运行
# 注意 %w 百分号要用斜杠转义,因为 % 本身在 Crontab 里是换行的意思
59 0 1-7 4 * test `date +\%w` -eq 0 && /root/do.sh

# 错误的写法:
# 四月的 1~7 号或星期日0点59分运行
59 0 1-7 4 0 /root/do.sh

# 比较(0 真,1 假)
test 1 = 1

# 输出上一条命令的结果
echo $?

3、如何执行周期小于1分钟的任务?

# 每半分钟执行一次
# 写两遍:第1遍每分钟的0秒执行,第2遍虽然也是0秒开始,但会先睡30秒再真正执行脚本
*/1 * * * * /root/do.sh
*/1 * * * * sleep 30s; /root/do.sh

注意清理系统用户的邮件日志

每条任务调度执行完毕,系统都会将任务输出信息通过 mail 形式发送给当前系统用户 /var/spool/mail/用户名,日积月累,日志会很大,因此,将每条任务进行重定向忽略输出:

0 */3 * * * /root/do.sh >/dev/null 2>&1

如何选择 HTTPS/SSL 证书?

通常考虑的因素:

  • 是否支持多域名、泛域名
  • 价格
  • 信息泄露的保额
  • 厂商是国内还是国外
  • 证书在浏览器上显示的小图标样式

SSL证书分为四大类:

  • DV 证书
  • OV 证书
  • EV 证书
  • 自签名证书

自签名证书很少被部署到正式的网站上,一般是被用在内部的测试环境中,这里就不做介绍。

DV 证书

DV 证书即 Domain Validation Certificate。

用于验证一个或多个域名的所有权,无需递交纸质文件,仅验证域名管理权(即 whois 信息中的管理员邮箱验证),无需人工验证申请单位真实身份。

OV 证书

OV 证书即 Organization Validation CErtificate。 OV 证书用于验证此域名由特定组织或单位所拥有的域名,在 DV 证书的基础上,增加了企业认证信息。

申请此类证书,通过证书颁发机构审查网站企业身份和域名所有权以证明申请单位是一个合法存在的真实实体,CA 机构将在人工核实后签发证书。

DV 证书和 OV 证书在浏览器上显示的图标为:

EV 证书

EV 证书即 Extended Validation Certificate EV 证书是目前最高信任级别的证书,通过极其严格、苛刻的审查来验证网站企业身份和域名所有权,确保网站身份的真实可靠。一般会要求提供纸质材料。

例如 GitHub 采用的是 EV 证书,所以浏览器地址栏显示了企业名,并采用了目前最推荐的安全加密算法套件:TLS1.2(协议版本)+ ECDHE_RSA(密钥协商交换)+ AES_128_GCM(对称加密)。

EV 证书在浏览器上显示的图标为:

除了认证等级和显示图标的区别,三类证书在域名的支持性、价格、赔偿费用上也是不相同的。

总结下:

  • 如果是个人网站或初期的企业网站,可以选择 DV 证书
  • 如果是综合性的企业门户网站,可以选择 OV 证书
  • 如果是金融类的企业网站,域名需求没有那么多,可以选择 EV 证书

哪个SSL证书厂商是可以被信赖的?

SSL证书的厂商非常多,也没有绝对的好与坏之分。不过我们也可以从行业内影响力、历史安全问题、市场占有率等角度来评判。

这也是目前行业中比较公认的可信任厂商,可以看到前六名分别是:

  • Comodo
  • Symantec
  • Godaddy
  • GlobalSign
  • IdenTrust
  • DigiCert

个人博客网站,可以考虑以下免费 SSL 证书:

  • 阿里云 Symantec 免费证书(云盾-HTTPS证书)
  • 腾讯云 GeoTrust 免费证书 http://www.laozuo.org/8681.html
  • StartSSL
  • Let’s Encrypt
  • Namecheap

参考文章:

Linux sed 的日常用法

sed 全名 StreamEditor(流编辑器)用程序的方式来编辑文本,基本上就是正则匹配。

http://coolshell.cn/articles/9104.html

Linux 启动流程和脚本加载顺序

http://www.ruanyifeng.com/blog/2013/08/linux_boot_process.html

Mac 下通过 launchctl 管理自启动程序和计划任务

Mac 下的计划任务和服务是通过 plist 来管理,类似于 CentOS 的 crontab。

首先进入到 ~/Library/LaunchAgents 下新建一个 plist 文件

vi ~/Library/LaunchAgents/com.TASK_NAME.launchctl.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>com.TASK_NAME.launchctl.plist</string>
  <key>ProgramArguments</key>
  <array>
    <string>/Users/silverd/AutoMakeLog.sh</string>
  </array>
  <key>StartCalendarInterval</key>
  <dict>
    <key>Minute</key>
    <integer>4</integer>
    <key>Hour</key>
    <integer>13</integer>
  </dict>
  <key>StandardOutPath</key>
  <string>/var/log/AutoMakeLog.log</string>
  <key>StandardErrorPath</key>
  <string>/var/log/AutoMakeLog.err</string>
</dict>
</plist>

我翻译成 JSON 格式会更加直观些:

{
  Label: 'com.TASK_NAME.launchctl.plist',
  ProgramArguments: [
    '/Users/silverd/AutoMakeLog.sh'
  ],
  StartCalendarInterval: {
    Minute: 4,
    Hour: 13
  },
  StandardOutPath: '/var/log/AutoMakeLog.log',
  StandardErrorPath: '/var/log/AutoMakeLog.err',
}

Label 就是这个任务的名字,这里一般取 plist 的文件名,这个名字不能和其它的 plist 重复

# 载入任务(Permanently enabling a job)
launchctl load -w com.TASK_NAME.launchctl.plist

# 去除任务(Permanently disabling a job)
launchctl unload -w com.TASK_NAME.launchctl.plist

# 立即执行,不管时间到了没有
# 注意:手动执行任务前必须先载入
launchctl start com.TASK_NAME.launchctl.plist

# 停止执行任务
launchctl stop com.TASK_NAME.launchctl.plist

# 列出当前所有任务
launchctl list

重要的参数说明:

-w Overrides the Disabled key and sets it to false or true for the load and unload subcommands respectively.
-F Force the loading or unloading of the plist. Ignore the Disabled key

Launchd 脚本存储在以下位置:

~/Library/LaunchAgents              -- For a specific user
/Library/LaunchAgents               -- For all users  
/Library/LaunchDaemons              -- For system boot
/System/Library/LaunchAgents        -- For OS X use only
/System/Library/LaunchDaemons       -- For OS X native processes only

LaunchDaemons 的拥有者必须是 root:wheel,权限是 644(rw-r-r)

LaunchAgents 除了 ~/Library/LaunchAgents 的拥有者是登录用户 (silverd)本身外,其余目录下的也应该是 root:wheel

不建议把脚本放到 /System/Library/LaunchDaemons/ 和 /System/Library/LaunchAgents/ 中,因为每次系统更新都会清空该目录。

LaunchAgents 和 LaunchDaemon 的区别

LaunchAgents: 是用户登陆后启动的服务

LaunchDaemon: 是用户未登陆前就启动的服务

参考文章

Redis Server 连接端口-随手记

安装完 redis server 后,发现 telnet 127.0.0.1 6379 报 connetion failed 错误,也无法提供外网访问。查看 redis.conf 里的确实 bind 127.0.0.1 没错呀。

其实是防火墙的原因,测试服的话,可以直接关闭:

/etc/init.d/iptables stop 或 service iptables stop

输入 /usr/local/redis/bin/redis-cli 即可连上。

如果不想这么粗鲁,那么可以打开指定端口:

iptables -I INPUT -p tcp --dport 6379 -j ACCEPT

# 查看当前防火墙状态:
/etc/init.d/iptables status

# 记得改完要保存,否则重启了就无效
/etc/init.d/iptables save

# 重启防火墙策略
/etc/init.d/iptables restart

如果执行 redis-cli 时看到以下错误:

Could not connect to Redis at 127.0.0.1:6379: Connection refused

那一定是 redis server 忘记启动了 =_=!

/etc/init.d/redis start

Memcached Server 一样的道理,端口变成 11211,可以用 telnet 绑定IP 11211 来测试通不通。

附上:在 CentOS 自建 Redis/Memcached Server 的一些注意事项:

Redis

# 修改绑定的IP(默认127.0.0.1)为内网IP,如:10.117.38.193
vi /usr/local/redis/etc/redis.conf

Memcached

# 修改绑定的IP(默认127.0.0.1)为内网IP,如:10.117.38.193
# 以及调整缓存大小(默认64M)
vi /etc/init.d/memcached

设置开机启动

vi /etc/rc.local

# 加入以下两行
/etc/init.d/memcached start
/etc/init.d/redis start