讓crontab使用smtp服務器向管理員發送報錯郵件

#前言#shell


crontab有一個郵件發送的機制,若是crontab執行腳本時,stdout有輸出時,會以郵件的形式發送到crontab當前用戶,使用mail命令便可查看郵件。這些信息常常頗有用,每每攜帶了錯誤信息,能夠幫助管理員排錯,所以管理員對於mail不可不關注。ubuntu

注意:vim

想要看到crontab報警郵件須要有郵件服務器,在centos/RHEL,ubuntu/Debian等主流發行版都會有一個mailutils軟件包,這個軟件包就二選一依賴於郵件服務端軟件postfix/sendmail和客戶端軟件mailcentos

(早一些的發行版,如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便可,異曲同工。

相關文章
相關標籤/搜索