mail auf unix funktioniert nicht richtig

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
patmaster
User
Beiträge: 106
Registriert: Donnerstag 3. Februar 2011, 17:21

Hi,

Da bei uns ständig die Server den Geist aufgeben und es keiner mitbekommt, dachte ich mir ich schreibe ein kleines Script, das uns darüber in Kenntnis setzt:
hostnames ist eine Liste aus Paaren, die aus IP und Servername bestehen, die ich hier mal zensiert habe ;)

Code: Alles auswählen

import subprocess
hostnames = [("xx.xx.xx.xx","XXXXXXXX" ), ....]

for host in hostnames:    
    ret = subprocess.call("ping -c 1 %s" % host[0], shell=True, stdout=open("/dev/null", "w"),stderr=subprocess.STDOUT)
    if ret == 0:
        print "%s is alive" % host[1]
        mailstring = "%s is alive" % host[1]
        cmd = ["mail -s 'Test' test.test@test.at"]
        subprocess.call(cmd,shell=True)
    else:
        print "%s is dead" % host[1]
Mein Problem ist nun, dass beim senden der Mail das Script anscheinend hängen bleibt. Sobald ich das Script aber kille, bekomme ich die Mail.
Ich bin noch Anfänger und verwende vermutlich subprocess falsch.
Kann mich bitte jemand aufklähren ?!
Zuletzt geändert von patmaster am Mittwoch 20. März 2013, 14:36, insgesamt 1-mal geändert.
deets

Du koennstest schonmal damit anfangen, deine Postings in den dafuer vorgesehenen Unterforen zu machen. Oder entgeht mir hier die Verbindung zu Grafikprogrammierung?

Danach wuerde ich dir mal empfehlen, statt suprocess zum Versand von mails lieber die Python-eigene smtplib zu verwenden. Da gibt es genug Beispiele.

Dann benutzt du subprocess eher...ungewoehnlich. Entweder ist cmd ein String, oder eine Liste - wenn letzteres, dann aber mit den einzelnen Komponenten, also

["mail", "-s", ...]

Ich bin mir im Moment nicht sicher, ob dann shell-expansion noch funktioniert, aber ich sehe auch keinen Grund dafuer, warum du shell=True uberehaupt verwendest.

Last but not least: mail nimmt den Mail-Body ueber die Standardeingabe entgegen, du gibst ihm aber nichts. Das koennte dein Verhalten erklaeren.
patmaster
User
Beiträge: 106
Registriert: Donnerstag 3. Februar 2011, 17:21

sry, das mit dem Forum war nen versehen -.-
Danke für die Tipps !
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Was spricht dagegen Standardsoftware wie z.b. Nagios zu nutzen? Das ist jetzt nun wirklich kein aussergewoehnliches Problem, dass das selbst schreiben rechtfertigt ;)

Zur Benutzung von `subprocess` gibt es in der Doku und auch hier im Forum jede Menge Beispiele.
Drache
User
Beiträge: 51
Registriert: Montag 29. November 2010, 21:51
Wohnort: Berlin
Kontaktdaten:

Mmmh, hilft dir der (ungetestete) Code Fetzen weiter ?

Code: Alles auswählen

import email
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.Utils import formatdate
if deine_bedinung == True:
            oNachricht = MIMEMultipart()
            oNachricht['From'] = 'deine_mail@dein_email_account.de'
            oNachricht['To'] = 'seine_mail@dein_email_account.de'
            oNachricht['Date'] = formatdate(localtime= True)
            oNachricht['Subject'] = "oh Oh"
            server = smtplib.SMTP('mail.dein_email_account.de')
            server.ehlo()
            server.login('deine_mail','topsecret')
            server.starttls()
            server.ehlo()
            server.sendmail(oNachricht['From'], oNachricht['To'],oNachricht.as_string())
            server.quit()
            print("email  versendet\n ")
Drache
patmaster
User
Beiträge: 106
Registriert: Donnerstag 3. Februar 2011, 17:21

Danke Drache, aber ich hab das mittlerweile mit mail von Linux hinbekommen:

Code: Alles auswählen

#imports
import subprocess, time 

#variables
hostnames = [("xx.xx.xx.xx","XXXXXXXXX" ), ....]
recips = ["xx.xx@xx.xx",...]
logstring = ""
mail = 0

#for all hosts
for host in hostnames:
    #certain hosts need diffrent treatment (nmap instead of ping)    
    #ping
    if host[0] != "xx.xx.xx.xx":
        ret = subprocess.call("ping -c 1 %s" % host[0], shell=True, stdout=open("/dev/null", "w"),stderr=subprocess.STDOUT)
        if ret == 0:
            logstring += "%s seems to be alive \n" % host[1]        
        else:
            logstring += "%s seems to be dead !!! \n" % host[1]        
            mail += 1            
    #nmap
    else:
        ret = subprocess.Popen("nmap -p 8000 %s" % host[0],shell=True,stdout=subprocess.PIPE)
        if "8000/tcp open" in ret.communicate()[0]:
            logstring += "%s seems to be alive \n" % host[1]
        else:
            logstring += "%s seems to be dead !!! \n" % host[1]
            mail +=1
#send a mail if we los a Server
if mail > 0:            
    for recip in recips:
        subprocess.call("echo '%s' | mail -s 'Serverstatus' %s" % (logstring,recip), shell=True)

#write log anyway
with open("/home/technik/windowsmount/Produktion/Serverstatus/pinger_log.txt", "w") as log:
    lt = time.localtime()
    jahr, monat, tag, stunde, minute, sekunde = lt[0:6]
    log.write("Checked Serverstatus at %02i.%02i.%04i - %02i:%02i:%02i  \n" % (tag,monat,jahr,stunde,minute,sekunde))
    log.write("-------------------------------------------------------- \n")
    log.write(logstring)
Bin dankbar für konstruktives feedback.
Ich nehme an es gibt ne bessere möglichkeit die mail an mehrere Leute zu versenden, aber auf die schnelle habe ich die richtige Syntax nicht gefunden...
deets

Mindestens mal solltest du dir subprocess nochmal anschauen, und statt "call" "Popen" verwenden - da kannst du naemlich die standardeingabe von mail einfach mit einem String beschicken, via Popen.stdin.write(message).

Aber noch besser ist die von mir & Drache vorgeschlagene Moeglichkeit, mails direkt zu versenden, und die "Syntax" dafuer wurde dir ja schon praesentiert.
patmaster
User
Beiträge: 106
Registriert: Donnerstag 3. Februar 2011, 17:21

alles klar, werde mir das ganze per Gelegenheit noch mal ansehen.
Vlt. kommt ja davon auch noch was in dem Python-Buch das ich gerade lese :)
Benutzeravatar
Whitie
User
Beiträge: 216
Registriert: Sonntag 4. Juni 2006, 12:39
Wohnort: Schulzendorf

Hallo patmaster,
evtl. könnte man für das ganze Skript auch das logging Modul verwenden. Ein FileHandler und ein SMTPHandler.

Gruß Whitie

Edit: Hier mal ein kleines (ungetestetes) Beispiel

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import logging
import os
import subprocess

from logging.handlers import RotatingFileHandler, SMTPHandler


HOSTS = (('xx.xx.xx.xx', 'XXXX'), ('yy.yy.yy.yy', 'YYYYY'))
RECIPIENTS = ['admin1(at)example.org', 'admin2(at)example.org']


def create_logger():
    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)
    file_handler = RotatingFileHandler('/path/to/logfile.log',
        maxBytes=1000*1000, backupCount=7)
    smtp_handler = SMTPHandler('smtp.example.org', 'sender(at)example.org',
        RECIPIENTS, 'Serverstatus')
    smtp_handler.setLevel(logging.ERROR)
    formatter = logging.Formatter('[%(asctime)s] %(levelname)s: %(message)s',
        '%d.%m.%Y - %H:%M:%S')
    file_handler.setFormatter(formatter)
    smtp_handler.setFormatter(formatter)
    logger.addHandler(file_handler)
    logger.addHandler(smtp_handler)
    return logger


def main():
    log = create_logger()
    for ip, name in HOSTS:
        try:
            subprocess.check_call(['ping', '-c', '3', ip],
                stdout=open(os.devnull, 'w'), stderr=subprocess.STDOUT)
            log.info('%s seems to be alive', name)
        except subprocess.CalledProcessError:
            log.error('%s seems to be dead!', name)


if __name__ == '__main__':
    main()
Antworten