如何将输出重定向数据处理到电子邮件中,将其附加到列表

时间:2017-05-18 04:30:51

标签: python email

如何将python列表数据处理成MIME的邮件功能。下面是查找" sshd"在系统上进行处理并根据应用的条件,如果它运行超过30分钟,然后通过电子邮件报告。

我正在使用" cStringIO"用于重定向目的的模块因此数据可以保存在data_stream变量上,我可以将其调用到邮件发送功能中。因此,当我运行脚本时,它正确地在控制台上运行,但是它发送到不同部分的电子邮件,我在脚本代码后很快引用了下面的示例..

  

问题摘要:

如下面的测试示例,当我运行脚本时,它在命令控制台上运行正常,但是当它通过电子邮件处理时,它会发送这4个不同的电子邮件备注..

#!/usr/bin/python
from subprocess import Popen, PIPE
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import subprocess
import socket
import sys
import cStringIO
import re
mylist = list()

hst_name = (socket.gethostname())
def checK_ps():
    ps = subprocess.Popen(['ps', '-eo' 'pid,user,args,etime='], stdout=subprocess.PIPE)
    output = ps.communicate()[0]
    for line in output.splitlines():
         result = re.search(".*[\/\s]+(sshd:)\s+", line)
         if result:
             time_items = re.split('-|:',(line.split(' ')[-1]))
             time_len = len(time_items)
             mystdout = sys.stdout
             data_stream = cStringIO.StringIO()
             sys.stdout = data_stream

             if  time_len == 4:
                 print "Alert sshd: is running longer on the host",hst_name,time_items[0],"days:" #  "-->",line.strip()

             elif time_len == 3:
                 print "Alert sshd: is running longer on the host",hst_name,time_items[-3],"hours:" # "-->",line.strip()

             elif time_len == 2 and int(time_items[-2]) >= 30:
                 print "Alert sshd: is running longer on the host",hst_name,time_items[-2],"minutes:" #, "-->",line.strip()

             sys.stdout = mystdout
             variable_data = data_stream.getvalue()
             xxx = variable_data + line.strip() + "\n\n"
             mylist.append(xxx)
             mailp = Popen(["/usr/sbin/sendmail", "-t", "-oi"], stdin=PIPE)
             msg = MIMEMultipart('alternative')
             msg['To'] = "karn@example.com"
             msg['Subject'] = "Daily PS Check Report"
             msg['From'] = "systemHealth@example.com"
             msg1 = MIMEText(xxx,  'text')
             msg.attach(msg1)
             mailp.communicate(msg.as_string())
    print "".join([str(x) for x in mylist] )
checK_ps()
  

示例:脚本的测试运行:

     

主要问题是以下所有"警报"正在进入4个不同的电子邮件,这些电子邮件应该是同一个系统中的所有进程。

$ ./testps.py     警报sshd:在主机root-karn 01小时运行更长时间:     4536 root sshd:karn [priv] 01:03:21

Alert sshd: is running longer on the host root-karn 01 hours:
4621 karn     sshd: karn@pts/1               01:03:11

Alert sshd: is running longer on the host root-karn 20 hours:
20124 root     sshd: niraj [priv]             20:16:06

Alert sshd: is running longer on the host root-karn 20 hours:
20130 niraj    sshd: niraj@pts/2              20:16:05

现在,我已尝试附加列表并对其进行处理,但上面看起来相同,我很想知道它如何处理成单个电子邮件。

  

要求:   在单个服务器运行时从单个服务器获取单个电子邮件并捕获该过程。

欣赏任何组织和建议。

2 个答案:

答案 0 :(得分:0)

您必须将脚本拆分为不同的部分,每个部分都有专门的任务。

进口

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import subprocess
import socket
import re

收集事件

def _read_ps()
    with subprocess.Popen(['ps', '-eo' 'pid,user,args,etime='], stdout=subprocess.PIPE) as ps:
        messages = list()
        for line in output.splitlines():
            if re.search(".*[\/\s]+(sshd:)\s+", line):
                time_items = re.split('-|:',(line.split(' ')[-1]))
                time_len = len(time_items)

                message = ""
                if time_len in (3, 4,) or (time_len == 2 & int(time_items[0] >= 30)):
                    message = "Alert sshd: is running longer on the host %s %s days:" % hst_name,time_items[0]
                messages.append("".join(message, line.strip, '\n\n'))
    return messages

lst[-3]如果len(lst) == 3lst[0]相同,那么该部分可以简化

您重定向sys.stdout以打印邮件,但使用print >> buffer, message比使用现在的方式更容易,甚至该方法也不像字符串格式化那么简单你用它的目的

编译邮件消息

上一个方法的结果是要发送的消息列表。如果有任何消息,此方法会将其编译为一封电子邮件。我不熟悉在Python上编译电子邮件,所以这可能需要一些工作。

def _construct_message(messages):
    if not messages: # no messages to send
        return None
    msg = MIMEMultipart('alternative')
    msg['To'] = "karn@example.com"
    msg['Subject'] = "Daily PS Check Report"
    msg['From'] = "systemHealth@example.com"
    for message in messages:
        msg.attach(MIMEText(message, 'text')
    return msg

您可以使用以下内容替换最后3行代替for循环:

return msg.attach(MIMEText'\n'.join(messages), 'text')

但我对电子邮件不太熟悉

发送电子邮件

编译完电子邮件后,您需要发送

def _send_mail(mail_message):
    with Popen(["/usr/sbin/sendmail", "-t", "-oi"], stdin=subprocess.PIPE) as mailp:
        mailp.communicate(mail_message.as_string())

将它们绑在一起

def check_ps():
    messages = _read_ps()
    mail_message = _construct_message(messages)
    if mail_message:
        _send_mail(mail_message)

将工作分成小部分的优点是,您可以更轻松地调试和测试每个单独的方法

上下文管理器

Popen可以使用with语句用作上下文管理器。这样,即使出现问题,连接也会正确关闭

答案 1 :(得分:0)

感谢大家在帖子上灌输您的想法和观点,如果有的话,我以不同的方式工作并获得我的解决方案!

from subprocess import Popen, PIPE
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import subprocess
import socket
import sys
import os
import re

hst_name = (socket.gethostname())
def checK_ps():
    ps = subprocess.Popen(['ps', '-eo' 'pid,user,args,etime='], stdout=subprocess.PIPE)
    output = ps.communicate()[0]
    for line in output.splitlines():
         #if len(re.findall('\\b'+line+'\\b', "rm", flags=re.IGNORECASE))>0:
         result = re.search(".*[\/\s]+(rm)\s+", line)
         #result = re.search(".*[\/|\s]+(rm)\s+", line)
         if result:
             time_items = re.split('-|:',(line.split(' ')[-1]))
             time_len = len(time_items)
             print_stdout = sys.stdout
             print_output = open('/tmp/ps_msg', 'a')
             sys.stdout = print_output
             if  time_len == 4:
                 print "Alert rm is running longer on the host",hst_name,time_items[0],"days:" + "\n" + line.strip()
                 print ""

             #elif time_len == 3:
             elif time_len == 3 and int(time_items[-3]) >= 02:
                 print "Alert rm is running longer on the host",hst_name,time_items[-3],"hours:" + "\n" +  line.strip()
                 print ""

             elif time_len == 2 and int(time_items[-2]) >= 05:
                 print "Alert rm is running longer on the host",hst_name,time_items[-2],"minutes:" + "\n" + line.strip()
                 print ""

             sys.stdout = print_stdout
             print_output.close()
checK_ps()

############ Process capturing part done above #################
############ File comparison & sendmail part starts here ########

def ps_Mail():
    filename = "/tmp/ps_msg"
    f = file(filename)
    if os.path.exists(filename) and os.path.getsize(filename) > 0:
        mailp = Popen(["/usr/sbin/sendmail", "-t", "-oi"], stdin=PIPE)
        msg = MIMEMultipart('alternative')
        msg['To'] = "karn@example.com"
        msg['Subject'] = "Uhh!! Unsafe rm process Seen"
        msg['From'] = "psCheck@example.com"
        msg1 = MIMEText(f.read(),  'text')
        msg.attach(msg1)
        mailp.communicate(msg.as_string())
ps_Mail()

###########  Clean the file after Sending an E-mail  ############
os.unlink("/tmp/ps_msg")