#前言#shell
crontab有一个邮件发送的机制,若是crontab执行脚本时,stdout有输出时,会以邮件的形式发送到crontab当前用户,使用mail
命令便可查看邮件。这些信息常常颇有用,每每携带了错误信息,能够帮助管理员排错,所以管理员对于mail不可不关注。ubuntu
注意:vim
想要看到crontab报警邮件须要有邮件服务器,在centos/RHEL,ubuntu/Debian等主流发行版都会有一个
mailutils
软件包,这个软件包就二选一依赖于邮件服务端软件postfix
/sendmail
和客户端软件(早一些的发行版,如centos/RHEL5 优先依赖的是sendmail,centos6,ubuntu12.04等新一些的发行版,优先依赖的是postfix)服务器
安装
mailutils
以后,默认配置便可收到crontab的邮件,使用mail命令便可看到邮件详情。dom
但当服务器比较多时,一台台ssh上去敲mail
命令显然不合适,有没有方法能让crontab把邮件发送到管理员的邮箱呢?crontab已经有这种设定了。ssh
研究了一天,google了一天老外的资料,眼睛都花了(但愿本身动手解决的能够google一下各类关于crontab smtp之类的关键字,老外提到的基本集中在几个点),加上本身的各类尝试,总结方法以下:ide
#MAILTO变量#post
首先值得关注的是MAILTO
这个变量,这个在crontab的man手册写的也很清楚:测试
In addition to LOGNAME, HOME, and SHELL, cron(8) will look at MAILTO if it has any reason to send mail as a result of running commands in ``this'' crontab. If MAILTO is defined (and non-empty), mail is sent to the user so named. MAILTO may also be used to direct mail to multiple recipients by separating recipient users with a comma. If MAILTO is defined but empty (MAILTO=""), no mail will be sent. Otherwise mail is sent to the owner of the crontab.
也就是说,定义了MAILTO
这个变量,那么crontab会将stdout的内容以邮件的形式发送到MAILTO定义的邮箱中。
测试一下,编辑/etc/crontab
,增长两行:
MAILTO=myuser@mydomain.com * * * * * root echo "mail test"
若是没什么问题的话,__有可能__会在一分钟之后收到cron的邮件。
#smtp#
若是上面的方案能起做用的话,那么恭喜你,你省了不少麻烦。下面我要说的就是我折腾了一天后才搞定的玩意——smtp!
上面说有可能会收到邮件,是由于邮件发送机制决定的,如下表述可能不许确,是按照我本身的理解来讲的,可能会误导。邮件的发送方和接收方须要有域名,能够被DNS正确解析的。若是你的服务器有域名,那么恭喜你,只需挂上本身的域名,配置一下postfix/sendmail容许向外发送邮件便可。若是没有域名,或者服务器在内网的话,这种方式就行不通了(这里可能有误,我有一台服务器在域名那里直接写的是主机IP,能够发送出去。可是另外一台这样作就不行,猜想是否跟IP能反解析有关)
下面介绍的是一种更通用的形式——smtp协议!
首先须要装smtp客户端,老外推荐更多的是msmtp
这个smtp客户端,个人系统是ubuntu-server 12.04,如下命令所有都是ubuntu 12.04上能够用的命令,若是是其余发行版,作相应变动便可
使用smtp发送邮件的话,那么postfix/sendmail就再也不须要了,能够卸载掉
apt-get purge postfix #完全卸载postfix(若是以前使用的服务端是sendmail的话就改为sendmail) apt-get purge mailutils #完全卸载mailutils,mail都发送到外部邮箱去了,所以mail命令也没用了,若是还想在本地发送邮件的话,保留也能够 apt-get auto-remove #清理掉再也不使用的依赖项
##安装msmtp## 以后安装msmtp,注意的是有两个软件包都要装:
apt-get install msmtp-mta #只装这一个就能够了,由于这个软件包依赖于msmtp,会自动安装。msmtp-mta这个软件包会将/usr/sbin/sendmail --> /usr/bin/msmtp作一个软链接,也就是会将原来使用sendmail发送邮件的程序改成使用msmtp发送。
若是此时安装mailutils
(可选),会发现因为存在/usr/sbin/sendmail,因此既不会安装sendmail也不会安装postfix。
##配置msmtp## msmtp安装完毕并不存在全局配置文件,须要时能够本身创建一个。具体的命令行语法就很少介绍了,看--help
帮助就能够了。
msmtp支持全局配置/etc/msmtprc
和用户个性配置~/.msmtprc
,须要全部用户使用一样的msmtp配置的话,只创建/etc/msmtprc
就能够了,如下是个人配置
vim /etc/msmtprc
defaults logfile /var/log/msmtp.log #注意权限,普通用户可能没有写入这个文件的权限,能够管理员受权 syslog on #这个选项是记录到syslog的,能够去掉这一行,默认是off aliases /etc/aliases #先看看这个文件是否存在,若是不存在就不要加这一行,这一行的做用后面再说 account default host smtp.ym.163.com from user@domain.com user user@domain.com password mypass auth on tls on tls_certcheck off
个人配置,使用网易企业邮箱的smtp服务器发送邮件的,开启了tls。这里根据须要本身调整,若是使用QQ邮箱或是gmail等其余邮箱,请参考邮箱帮助文档配置smtp。
配置完毕以后测试一下
msmtp -Sd
看一下输出,检测一下变量,看看有没有问题,发送一封邮件试试echo -e "Subject: Test Mail\r\n\r\nThis is a test mail" |msmtp --debug -t youremail@domain
,看一下输出,若是能收到邮件的话,那么msmtp的配置就结束了。
##使用msmtp替换sendmail,成为crontab发送邮件的客户端##
只需安装msmtp-mta
这个软件包便可,会自动作软链接,上面提到过,若是没装的话,也能够手工软链接/usr/lib/sendmail
和/usr/sbin/sendmail
两个文件到/usr/bin/msmtp
,以后若是crontab发送邮件的时候,就会使用msmtp了。
##遇到的问题## 1:CRON[28742]: (root) MAIL (mailed 1 byte of output; but got status 0x004e, #012)
这是因为已经使用了smtp代替了sendmail/postfix,已经链接到了smtp服务器上,smtp服务器可不识别root、mail这样的用户名做为邮件地址,因此报错了。配合开始提到的
MAILTO
变量,在crontab中写入MAILTO
这个变量,强制指定将邮件发送到目标邮箱中便可。
2:中文乱码,效果以下:
������ english ls: ������������/asldkfjasdf: ��������������������������� LANG=zh_CN.UTF-8 LANGUAGE=zh_CN:zh LC_CTYPE="zh_CN.UTF-8" LC_NUMERIC="zh_CN.UTF-8" LC_TIME="zh_CN.UTF-8" LC_COLLATE="zh_CN.UTF-8" LC_MONETARY="zh_CN.UTF-8" LC_MESSAGES="zh_CN.UTF-8" LC_PAPER="zh_CN.UTF-8" LC_NAME="zh_CN.UTF-8" LC_ADDRESS="zh_CN.UTF-8" LC_TELEPHONE="zh_CN.UTF-8" LC_MEASUREMENT="zh_CN.UTF-8" LC_IDENTIFICATION="zh_CN.UTF-8" LC_ALL=zh_CN.UTF-8
记得邮件有
content type
这个属性吗?设置为text/plain; charset=utf-8
就能够搞定了。crontab有一个CONTENT_TYPE
变量(详见man 5 crontab
,搜索charset
这个关键字便可找到相关内容),在crontab中定义CONTENT_TYPE=text/plain; charset=utf-8
就能够了
#依旧没解决的问题#
##crontab全局变量问题##
试了不少次,发现全部的crontab文件的环境变量都是独立的,也就是说在/etc/crontab
中定义的MAILTO=yourmail@domain.com
并不会影响到crontab -e
!依然须要在crontab -e
中从新写上MAILTO=yourmail@domain.com
,再加上系统中有各类拆散的crontab(如/etc/cron.d/,/etc/cron.daily等等)。
可是对于MAILTO
这个变量问题,有一个变通的解决方案。
还记得在msmtp配置中提到的aliases /etc/aliases
这个配置段吗?根据msmtp的man手册,这个表明使用指定文件定义aliases,默认为空。
/etc/aliases
这个文件是sendmail的邮件别名,若是以前安装过postfix/sendmail的话,是存在这个文件的,指明了若是发到哪一个用户的邮件,自动使用别名命名成别的地址。
这个文件的格式也很简单user: email_address
便可,如root: myemail@qq.com
,这样的话发到root的邮件就会自动被别名替换而发送到myemail@qq.com
。
个人配置: default: myemail@163.com
,default表明缺省,即不指定的话,全部发送到用户的邮件都将被这个别名替换,这样就不须要全部的crontab去指定MAILTO
这个变量了,缺省会发送到crontab用户中,而后被别名替换。
可是对于CONTENT_TYPE
这个变量我真的没有什么好办法了,但愿有朋友支招,只能一个个写了……
所幸的是基本上只有本身写的脚本才有中文输出,系统命令大可能是英文的,因此暂时只把这个变量加到了crontab -e
中,之后若是哪一个出现中文乱码了再在哪一个crontab中加吧。
google到老外的一种解决方案,就是给
cron
守护进程传递参数,让cron启动的时候初始化环境变量,就会成为crontab中全局变量,我看ubuntu的crontab的man手册,也提到了自定义变量写在/etc/default/corn中,可是打开这个文件,提示这个文件已经再也不支持了,若是有自定义变量的需求,写入/etc/init/cron.conf
或/etc/init/cron.override
,而后我就不会搞了,也没google到别人怎么写cron.override的。但愿有知道的朋友不吝赐教!
好了,就这么多了,困得不行了,睡觉先……
2016-09-07: 感谢回复的朋友,其实理论上只要存在/usr/sbin/sendmail
便可,因此能够本身写一个shell脚本伪形成/usr/sbin/sendmail
便可,异曲同工。