#前言#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
便可,異曲同工。