cat tmpfile | mailx -s "Test Mail" [email protected]
cat tmpfile >>YourLog
将这三句放到一个脚本里,在crontab执行这个脚本
我开始老想着用一条很长的脚本直接放到crontab里执行实现我想要的功能,很傻
另外推荐给大家一个邮件客户端小工具sendEmail,我在linux、aix、solaris下都能直接用,不需要安装的绿色软件,也不用鼓捣什么sendmail了
crontab有一个邮件发送的机制,如果crontab执行脚本时,stdout有输出时,会以邮件的形式发送到crontab当前用户,使用mail
命令即可查看邮件。这些信息经常很有用,往往携带了错误信息,可以帮助管理员排错,因此管理员对于mail不可不关注。
注意:
想要看到crontab报警邮件需要有邮件服务器,在centos/RHEL,ubuntu/Debian等主流发行版都会有一个
mailutils
软件包,这个软件包就二选一依赖于邮件服务端软件postfix
/sendmail
和客户端软件(早一些的发行版,如centos/RHEL5 优先依赖的是sendmail,centos6,ubuntu12.04等新一些的发行版,优先依赖的是postfix)
安装
mailutils
之后,默认配置即可收到crontab的邮件,使用mail命令即可看到邮件详情。
但当服务器比较多时,一台台ssh上去敲mail
命令显然不合适,有没有方法能让crontab把邮件发送到管理员的邮箱呢?crontab已经有这种设定了。
研究了一天,google了一天老外的资料,眼睛都花了(希望自己动手解决的可以google一下各种关于crontab smtp之类的关键字,老外提到的基本集中在几个点),加上自己的各种尝试,总结方法如下:
MAILTO变量
首先值得关注的是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
中定义的[email protected]
并不会影响到crontab -e
!依然需要在crontab -e
中重新写上[email protected]
,再加上系统中有各种拆散的crontab(如/etc/cron.d/,/etc/cron.daily等等)。
但是对于MAILTO
这个变量问题,有一个变通的解决方案。
还记得在msmtp配置中提到的aliases /etc/aliases
这个配置段吗?根据msmtp的man手册,这个代表使用指定文件定义aliases,默认为空。
/etc/aliases
这个文件是sendmail的邮件别名,如果之前安装过postfix/sendmail的话,是存在这个文件的,指明了如果发到哪个用户的邮件,自动使用别名命名成别的地址。
这个文件的格式也很简单user: email_address
即可,如root: [email protected]
,这样的话发到root的邮件就会自动被别名替换而发送到[email protected]
。
我的配置: default: [email protected]
,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的。希望有知道的朋友不吝赐教!
CentOS5.1里oracle用户的crontab:
00-59/2 * * * * /backupGZGA.sh 1>>/tmp/gzgaCronLog.log 2>>/tmp/gzgaCronLog.log;cat /tmp/gzgaCronLog.log|sendmail [email protected] "GZGA Backup Mission Finished!"
我欲实现功能:1.脚本/backupGZGA.sh被CRON自动调用执行完成后把整个执行过程中终端中产生的日志及提示信息输入到\gzgaCronLog.log文件中去,向[email protected]发个邮件标题为"GZGA Mission Finished."并发送附件gzgaCronLog.log.
var/spool/mail的内容:
rom [email protected] Tue Oct 7 17:32:13 2008
Return-Path: <[email protected]>
Received: from localhost.localdomain (localhost.localdomain [127.0.0.1])
by localhost.localdomain (8.13.8/8.13.8) with ESMTP id m979WDOf004744
for <[email protected]>; Tue, 7 Oct 2008 17:32:13 +0800
Received: (from oracle@localhost)
by localhost.localdomain (8.13.8/8.13.8/Submit) id m979WCW3004743;
Tue, 7 Oct 2008 17:32:12 +0800
Date: Tue, 7 Oct 2008 17:32:12 +0800
Message-Id: <[email protected]>
From: [email protected] (Cron Daemon)
To: [email protected]
Subject: Cron <oracle@localhost> /backupGZGA.sh 1>>/tmp/gzgaCronLog.log 2>>/tmp/gzgaCronLog.log;cat /tmp/gzgaCronLog.log|sendmail [email protected] "GZGA Backup Mission Finished!"
Content-Type: text/plain; charset=UTF-8
Auto-Submitted: auto-generated
X-Cron-Env: <SHELL=/bin/sh>
X-Cron-Env: <HOME=/home/oracle>
X-Cron-Env: <PATH=/usr/bin:/bin>
X-Cron-Env: <LOGNAME=oracle>
X-Cron-Env: <USER=oracle>
/bin/sh: sendmail: command not found
请教上述错误信息什么原因?如何调整和修改才能实现我的预期功能1?
功能2:脚本被CRON自动调用执行完成后向终端中发送提示信息:"XXXX年XX月XX日XX时XX分XX秒 GZGA Mission Finished Pls check ur mail",当前用户没有打开终端就自动开启一个终端发送粗体提示信息:"XXXX年XX月XX日XX时XX分XX秒 GZGA Mission Finished" ,提示信息最好在终端的正中央!
在不影响功能1的情况下具体如何修改ORACLE用户的crontab语句才能实现功能2?
非常感谢!
------Solutions------
上述crontab语句执行过程中CentOS的sendmail服务正在运行
在/var/log/cron里的内容:Oct 7 17:42:01 localhost crond[5200]: (oracle) CMD (/backupGZGA.sh 1>>/tmp/gzgaCronLog.log 2>>/tmp/gzgaCronLog.log;cat /tmp/gzgaCronLog.log|sendmail [email protected] "GZGA Backup Mission Finished!")
Oct 7 17:44:01 localhost crond[5280]: (oracle) CMD (/backupGZGA.sh 1>>/tmp/gzgaCronLog.log 2>>/tmp/gzgaCronLog.log;cat /tmp/gzgaCronLog.log|sendmail [email protected] "GZGA Backup Mission Finished!")
Oct 7 17:46:02 localhost crond[5358]: (oracle) CMD (/backupGZGA.sh 1>>/tmp/gzgaCronLog.log 2>>/tmp/gzgaCronLog.log;cat /tmp/gzgaCronLog.log|sendmail [email protected] "GZGA Backup Mission Finished!")
Oct 7 17:48:01 localhost crond[5437]: (oracle) CMD (/backupGZGA.sh 1>>/tmp/gzgaCronLog.log 2>>/tmp/gzgaCronLog.log;cat /tmp/gzgaCronLog.log|sendmail [email protected] "GZGA Backup Mission Finished!")
------Solutions------
XXXX年XX月XX日XX时XX分XX秒为oracle用户的crontab语句执行完成后CentOS的当前时间。
------Solutions------
用mail 试试!
------Solutions------
另外,用service sendmail status 看看sendmail服务是否启动?
GOOD LUCK!
------Solutions------
to bshawk :非常感谢你的帮助!
用mail试过可以发送,但我的sendmail一直是启动状态啊,是不是路径的问题啊!
00-59/1 * * * * /backupGZGA.sh 1>>/tmp/gzgaCronLog.log 2>>/tmp/gzgaCronLog.log;cat /tmp/gzgaCronLog.log|mail -s "GZGA backup finished!" [email protected]
用上述语句可以实现给[email protected]发送标题为"GZGA backup finished!",内容为/tmp/gzgaCronLog.log中的内容!
我想实现的功能为:1.给[email protected]发送标题为"XXXX年XX月XX日XX时XX分XX秒GZGA backup finished!",附件为/tmp/gzgaCronLog.log中最后一百行的内容!XXXX年XX月XX日XX时XX分XX秒为oracle用户的crontab语句mail执行时CentOS的当前时间。
2:脚本被CRON自动调用执行完成后向oracle终端中发送提示信息:"XXXX年XX月XX日XX时XX分XX秒 GZGA Mission Finished Pls check ur mail",当前用户没有打开终端就自动开启一个终端发送粗体提示信息:"XXXX年XX月XX日XX时XX分XX秒 GZGA Mission Finished" ,提示信息最好在终端的正中央!
请教具体如何修改上述crontab语句?
------Solutions------
up
------Solutions------
up
------Solutions------
oracle用户 crontab -l如下:
00-59/1 * * * * /backupGZGA.sh 1>>/tmp/gzgaCronLog.log 2>>/tmp/gzgaCronLog.log;cat /tmp/gzgaCronLog.log|mutt -s "GZGA backup finished!" -a /tmp/gzgaCronLog.log [email protected]
已实现每隔一分钟向[email protected]发标题为"GZGA backup finished!"的邮件并附件功能!怎样修改上述语句才能实现给[email protected]发送标题为"XXXX年XX月XX日XX时XX分XX秒GZGA backup finished!",附件为/tmp/gzgaCronLog.log中最后一百行的内容!XXXX年XX月XX日XX时XX分XX秒为oracle用户的crontab语句mutt执行时CentOS的当前时间。
2:脚本被CRON自动调用执行完成后向oracle终端中发送提示信息:"XXXX年XX月XX日XX时XX分XX秒 GZGA Mission Finished Pls check ur mail",当前用户没有打开终端就自动开启一个终端发送粗体提示信息:"XXXX年XX月XX日XX时XX分XX秒 GZGA Mission Finished" ,提示信息最好在终端的正中央!
实现在不行拆分成两个crontab语句也可以!
------Solutions------
up
------Solutions------
oracle用户 crontab -l如下:
00-59/1 * * * * /backupGZGA.sh 1>>/tmp/gzgaCronLog.log 2>>/tmp/gzgaCronLog.log;curdate=`date +%y%m%d`;cat /tmp/gzgaCronLog.log|mutt -s GZGABackupFinished${curdate} -a /tmp/gzgaCronLog.log
/var/spool/mail/oracle:
From [email protected] Sat Oct 11 15:49:02 2008
Return-Path: <[email protected]>
Received: from localhost.localdomain (localhost.localdomain [127.0.0.1])
by localhost.localdomain (8.13.8/8.13.8) with ESMTP id m9B7n1Eb018900
for <[email protected]>; Sat, 11 Oct 2008 15:49:01 +0800
Received: (from oracle@localhost)
by localhost.localdomain (8.13.8/8.13.8/Submit) id m9B7n1L2018899;
Sat, 11 Oct 2008 15:49:01 +0800
Date: Sat, 11 Oct 2008 15:49:01 +0800
Message-Id: <[email protected]>
From: [email protected] (Cron Daemon)
To: [email protected]
Subject: Cron <oracle@localhost> /backupGZGA.sh 1>>/tmp/gzgaCronLog.log 2>>/tmp/gzgaCronLog.log;curdate=`date +
Content-Type: text/plain; charset=UTF-8
Auto-Submitted: auto-generated
X-Cron-Env: <SHELL=/bin/sh>
X-Cron-Env: <HOME=/home/oracle>
X-Cron-Env: <PATH=/usr/bin:/bin>
X-Cron-Env: <LOGNAME=oracle>
X-Cron-Env: <USER=oracle>
/bin/sh: -c: line 0: unexpected EOF while looking for matching ``'
/bin/sh: -c: line 1: syntax error: unexpected end of file
还是不行啊,错误信息如上,请教如何解决?
------Solutions------
oracle用户 crontab -l如下:
00-59/1 * * * * /backupGZGA.sh 1>>/tmp/gzgaCronLog.log 2>>/tmp/gzgaCronLog.log;/mailme.sh
/mailme.sh源码如下:
curdate=`date +%y%m%d_%H%M%S`;
tail -n 100 /tmp/gzgaCronLog.log > /tmp/gzgaCronLog.log.1;
cat /tmp/gzgaCronLog.log.1 |mutt -s GZGABackupFinised${curdate} -a /tmp/gzgaCronLog.log.1 [email protected];wall "${curdate}GZGA Backup Mission Finised Pls check u guys' mail!!"
************************************************************************************
上述语句已实现了:给[email protected]发送标题为"XXXX年XX月XX日XX时XX分XX秒GZGA backup finished!", 附件为/tmp/gzgaCronLog.log中最后一百行的内容!XXXX年XX月XX日XX时XX分XX秒为oracle用户的crontab语句mutt执行时CentOS的当前时间。
2:脚本被CRON自动调用执行完成后向当前所有已打开终端中发送提示信息:"XXXX年XX月XX日XX时XX分XX秒 GZGA Mission Finished Pls check ur mail",
现在的问题是:
感觉mutt有时不能正常按设定的时间来发送邮件,有时能.而且怎么设置能让mutt支持中文?CentOS5.1的服务端在没有终端开启的情况下,wall "${curdate}GZGA Backup Mission Finised Pls check u guys' mail!!" 语句不能实现自动开启一个终端并在其中持续显示粗体"${curdate}GZGA Backup Mission Finised Pls check u guys' mail!!"
------Solutions------
up
------Solutions------
XP客户机的虚拟机内CentOS5.1下oracle用户 crontab -l如下:
00-59/1 * * * * /backupGZGA.sh 1>>/tmp/gzgaCronLog.log 2>>/tmp/gzgaCronLog.log;/mailme.sh
*****************************************************************************************
/mailme.sh源码如下:
curdate=`date +%y%m%d_%H%M%S`;
tail -n 100 /tmp/gzgaCronLog.log > /tmp/gzgaCronLog.log.1;
cat /tmp/gzgaCronLog.log.1 |mutt -s GZGABackupFinised${curdate} -a /tmp/gzgaCronLog.log.1 [email protected];wall "${curdate}GZGA Backup Mission Finised Pls check u guys' mail!!"
************************************************************************************
上述语句已实现了:每隔一分钟执行脚本backupGZGA.sh,给[email protected]发送标题为"XXXX年XX月XX日XX时XX分XX秒GZGA backup finished!", 附件为/tmp/gzgaCronLog.log中最后一百行的内容的邮件!XXXX年XX月XX日XX时XX分XX秒为oracle用户的crontab语句mutt执行时CentOS的当前时间。
2:脚本被CRON自动调用执行完成后向当前服务端所有已打开终端中发送提示信息:"XXXX年XX月XX日XX时XX分XX秒 GZGA Mission Finished Pls check ur mail",
现在的我欲实现的需求功能是:
1.CentOS5.1的服务端在没有终端开启的情况下,实现自动开启一个终端(黑色背景白色字体)并在其中持续显示粗体信息为:"${curdate}GZGA Backup Mission Finised Pls check u guys' mail!!"
2.crontab语句中/mailme.sh执行后自动向已连接的和指定的Win XP客户端(192.168.0.102/AFLRED01)发送弹出式消息内容为粗体"${curdate}GZGA Backup Mission Finised Pls check u guys' mail!!"
Win XP客户端包括以WINSCP或FLASHXP连接CentOS5.1的,我已下载了samba-3.2.4.tar.gz 到/usr/local下解压完
请教实现上述功能在我原有代码基础上该如何修改crontab表语句及相关脚本,用到xterm samba该如何切换用户及配置?或请高人提供详细地更好的解决方案,非常感激!
补充一下 功能1:如果CentOS5.1的服务端有已开启的终端那就用wall "${curdate}GZGA Backup Mission Finised Pls check u guys' mail!!" 来发送提示信息!
------Solutions------
[root:/root]#crontab -l
00-59/1 * * * * /testG.sh
根目录下testG.sh 源码:
export DISPLAY=:0;
pid=`ps -e | grep -E 'gnome-terminal' | awk '{print $1}'`
echo "$pid";
if [ "$pid" != "" ] ; then
gnome-terminal &
fi
**************************************************************************************
上述crontab语句和shell脚本总是每隔一分钟就通过gnome-terminal弹出一个可交互式终端(由gnome-terminal命令开启并可接受wall广播信息),怎样通过修改上述代码实现:服务端没有终端打开时开启一个可交互式终端并保证其不自动关闭,当已有一个可交互式终端存在时就不再重复开启新的可交互式终端.
谢谢!
------Solutions------
up
------Solutions------
请教CentS5.1下,在SMB服务启动的情况下,如何用smbclient命令向已连接服务端的以及指定的windows客户端发送弹出式提示消息?具体如何配置SMB服务?