2017-05-18 9 views
1

pythonリストデータをMIMEのメール機能にどのように処理するか。以下は、システム上の "sshd"プロセスを検索し、30分以上実行してから電子メールで報告する場合のような条件に基づいたスクリプトです。出力リダイレクトデータを電子メールに処理してリストに追加する方法

私はリダイレクト目的で "cStringIO"モジュールを使用していますので、データはメール送信機能に呼び出すことができるdata_stream変数に保持することができます。私は、それは別の部分に送信し、それが正しく、コンソール上で動作するスクリプトが、電子メールを実行したときので、私はすぐにスクリプトコードの後に​​以下の例を引用しています。..

問題の概要:

#!/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'] = "[email protected]" 
      msg['Subject'] = "Daily PS Check Report" 
      msg['From'] = "[email protected]" 
      msg1 = MIMEText(xxx, 'text') 
      msg.attach(msg1) 
      mailp.communicate(msg.as_string()) 
    print "".join([str(x) for x in mylist]) 
checK_ps() 

..私は、スクリプトを実行したとき、それはコマンドコンソールで大丈夫実行されますが、それは、電子メールを介して処理するとき、それは、これらの4つの異なる電子メールのメモを送信する以下の試験例のように例:テスト

主な問題は、「アラート」以下のすべてが同じシステムからのすべてのプロセスとして1つの4つの異なる電子メールに送られることです。

$ ./testps.py アラートsshdは:ホストルート・カーンに長く実行されている01時間: 4536ルートのsshd:今すぐカーン[PRIV]一時03分21秒

Alert sshd: is running longer on the host root-karn 01 hours: 
4621 karn  sshd: [email protected]/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: [email protected]/2    20:16:05 

私はリストを追加してそれを処理しようとしましたが、上記と同じように見えますが、どのように処理して1つの電子メールにすることができるのか不思議です。

要件: 1つのサーバーから1つの電子メールを受信し、そのプロセスをキャッチします。

ヒストリと提案を参考にしてください。

+0

@私は本当に上のポストに専門家のアドバイスをしたいと思います。 – rockypy17

+0

あなたは結果を見つけるたびに電子メールを送信します。あなたは 'for'ループの外に送信 –

+0

一つの方法は、2つの方法の間で機能を分割するだろう取る必要があります。開いているプロセスをチェックし、結果を転送するために選択した 'list'、' dict'、またはwhather coolctionを返します。このコレクションをとり、電子メールを組み立てて送信するもう1つの方法です。 MaartenFabré@ –

答えて

0

スクリプトを別々のセクションに分割する必要があります。それぞれに専用のタスクがあります。その部分が

を簡略化することができるようlen(lst) == 3は、lst[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]イベントの収集あなたは、メッセージを印刷するsys.stdoutをリダイレクトしかし、これはあなたが今やっているやり方よりもprint >> buffer, messageで簡単だったかもしれません。 Dも、その方法は、メール・メッセージに

をコンパイルし、それを

を使用目的の書式文字列のように単純ではない従来の方法の結果は、送信するメッセージのリストです。このメソッドは、メッセージがあればこれを1つの電子メールにコンパイルします。私はPythonで電子メールをコンパイルすることに慣れていないので、これにはいくつかの作業が必要な場合があります。

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

しかし、私は、電子を送信する電子メール

とあまり慣れていないんだ。その代わり、ループのために、あなたがこのような何かとの最後の3行を置き換えることができますの

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

電子メールメッセージがコンパイルされると

-mail、あなたはそれを

def _send_mail(mail_message): 
    with Popen(["/usr/sbin/sendmail", "-t", "-oi"], stdin=subprocess.PIPE) as mailp: 
     mailp.communicate(mail_message.as_string()) 
を送信する必要があります

小さな破片に作業を分割することの利点は、あなたがより簡単にデバッグできると

Popenを使用することができます

コンテキストマネージャ個々の各メソッドをテストすることで、一緒

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

それを結びつけますコンテキストマネージャーとしてwithステートメントを使用します。この方法であなたは、正しく接続を閉じます何かが

+0

あなたの貴重な時間と回避策を投稿してくれてありがとう、私はファイルオブジェクトの作成でそれを達成しましたが、多くのありがとう。申し訳ありませんが、私はあなたの答えを投票する権限があまりありません。 – rockypy17

+0

ファイル作成で何を達成しましたか?それがうまくいくなら、あなたはそれを受け入れることができます。それが動作しない場合、私はさらに –

+0

、それを改善するために助けることができる場所を私に知らせて、私は解決策を自分で持って、私は以下のコード全体を掲載しました。私はあなたの答えをまだ確認していない、私は確認し、動作する場合は同意します。マールテン・ファーブル@ – rockypy17

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'] = "[email protected]" 
     msg['Subject'] = "Uhh!! Unsafe rm process Seen" 
     msg['From'] = "[email protected]" 
     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") 
関連する問題