Seite 1 von 1

Stringbearbeitung und subprocess

Verfasst: Mittwoch 30. März 2011, 10:52
von peddy
Hallo,

ich möchte ein kleines Programm schreiben, welches über SSH eine Abfrage startet und mir die installierten Xen-VMs ausgibt. Das ist mein Sourcecode:

Code: Alles auswählen

#!/usr/bin/env python
# -*- encoding: utf-8; py-indent-offset: 4 -*-

import subprocess

hosts = ( 
    'xen01',
    'xen02',
    'xen03',
    'xen05'
)

def get_vmlist():
    host_out = []
    for i in range(0, len(hosts)):
        output = subprocess.Popen(['ssh','-l','root',str(hosts[i]),'xe','vm-list|grep','name-label'], stdout=subprocess.PIPE)
        host_out.append(output.stdout.read())
    return host_out

vms = get_vmlist()
print vms[0]
Die Ausgabe von vms[0] sieht dann so aus:
name-label ( RW): CAG1
name-label ( RW): CLS01
name-label ( RW): Mail-3
name-label ( RW): RSA01
name-label ( RW): Control domain on host: xen01
name-label ( RW): Web01
name-label ( RW): Monitoring01
name-label ( RW): MX1
name-label ( RW): Mail-1
Wie man unschwer erkennen kann, bekomme ich neben dem Rechnernamen noch einige überflüssige Informationen, die ich gerne wegfiltern möchte.

Habt ihr eine Idee wie das anstellen kann? Kann ich die Ausgabe von subprocess.Popen auch zeilenweise in eine Liste schreiben? Das würde die Sache glaube ich vereinfachen.

Re: Stringbearbeitung und subprocess

Verfasst: Mittwoch 30. März 2011, 11:22
von BlackJack
@peddy: Dateiobjekte sind "iterable" und zwar sind sie Iteratoren über die Zeilen. Also kann man eine Liste mit Zeilen ganz einfach mit der `list()`-Funktion bekommen.

Bitte werde das `i` in der Schleife los. Das und der `str()`-Aufruf auf das jeweilige `hosts`-Element sind beide total überflüssig. Man kann bei den Sequenztypen in Python *direkt* über die Elemente iterieren und muss keinen Umweg über einen Index machen. Also ``for host in hosts:``…

Ansonsten sieht mir das wirklich nach grundlegender Zeichenkettenverarbeitung aus. Schau doch einfach mal was Zeichenketten so an Methoden und Indexmöglichkeiten (Stichwort "slicing") bieten.

Re: Stringbearbeitung und subprocess

Verfasst: Mittwoch 30. März 2011, 12:59
von peddy
Danke für deine Denkanstöße, dass hat mich einen guten Schritt weiter gebracht. Ich habe mein Script überdacht und etwas umgebaut. Mein Programm wird dadurch hoffentlich etwas flexibler und schöner lesbar.

Code: Alles auswählen

#!/usr/bin/env python
# -*- encoding: utf-8; py-indent-offset: 4 -*-

import subprocess

hosts = (
    'xen01',
    'xen02',
    'xen03',
    'xen05'
)

def get_vms(hostname):
    output = subprocess.Popen(['ssh','-l','root',hostname,'xe','vm-list|grep','name-label'], stdout=subprocess.PIPE)
    vm_liste = output.stdout.read()
    return vm_liste

for hostname in hosts:
    print get_vms(hostname)
Ich blicke jedoch noch nicht, wie ich die Ausgabe zeilenweise in eine Liste schreiben kann. print list(get_vms(hostname)) liefert mir so was:
[' ', ' ', ' ', ' ', ' ', 'n', 'a', 'm', 'e', '-', 'l', 'a', 'b', 'e', 'l', ' ', '(', ' ', 'R', 'W', ')', ':', ' ', 'C', 'A', 'G', '1', '\n', ' ', ' ', ' ', ' ', ' ', 'n', 'a', 'm', 'e', '-', 'l', 'a', 'b', 'e', 'l', ' ', '(', ' ', 'R', 'W', ')', ':', ' ', 'C', 'L', 'S', '0', '1', '\n', ' ', ' ', ' ', ' ', ' ', 'n', 'a', 'm', 'e', '-', 'l', 'a', 'b', 'e', 'l', ' ', '(', ' ', 'R', 'W', ')', ':', ' ', 'M', 'a', 'i', 'l', '-', '3', '\n', ' ', ' ', ' ', ' ', ' ', 'n', 'a', 'm', 'e', '-', 'l', 'a', 'b', 'e', 'l', ' ', '(', ' ', 'R', 'W', ')', ':', ' ', 'R', 'S', 'A', '0', '1', '\n', ' ', ' ', ' ', ' ', ' ', 'n', 'a', 'm', 'e', '-', 'l', 'a', 'b', 'e', 'l', ' ', '(', ' ', 'R', 'W', ')', ':', ' ', 'C', 'o', 'n', 't', 'r', 'o', 'l', ' ', 'd', 'o', 'm', 'a', 'i', 'n', ' ', 'o', 'n', ' ', 'h', 'o', 's', 't', ':', ' ', 'x', 'e', 'n', '0', '1', '\n', ' ', ' ', ' ', ' ', ' ', 'n', 'a', 'm', 'e', '-', 'l', 'a', 'b', 'e', 'l', ' ', '(', ' ', 'R', 'W', ')', ':', ' ', 'W', 'e', 'b', '0', '1', '\n', ' ', ' ', ' ', ' ', ' ', 'n', 'a', 'm', 'e', '-', 'l', 'a', 'b', 'e', 'l', ' ', '(', ' ', 'R', 'W', ')', ':', ' ', 'M', 'o', 'n', 'i', 't', 'o', 'r', 'i', 'n', 'g', '0', '1', '\n', ' ', ' ', ' ', ' ', ' ', 'n', 'a', 'm', 'e', '-', 'l', 'a', 'b', 'e', 'l', ' ', '(', ' ', 'R', 'W', ')', ':', ' ', 'M', 'X', '1', '\n', ' ', ' ', ' ', ' ', ' ', 'n', 'a', 'm', 'e', '-', 'l', 'a', 'b', 'e', 'l', ' ', '(', ' ', 'R', 'W', ')', ':', ' ', 'M', 'a', 'i', 'l', '-', '1', '\n']

Re: Stringbearbeitung und subprocess

Verfasst: Mittwoch 30. März 2011, 13:05
von EyDu
Suchst du

Code: Alles auswählen

print get_vms(hostname).split("\n")
?

Re: Stringbearbeitung und subprocess

Verfasst: Mittwoch 30. März 2011, 13:14
von peddy
EyDu hat geschrieben:Suchst du

Code: Alles auswählen

print get_vms(hostname).split("\n")
?
Danke, das geht.

Re: Stringbearbeitung und subprocess

Verfasst: Mittwoch 30. März 2011, 13:38
von Rebecca

Code: Alles auswählen

>>> "hallo\nwelt".splitlines()
['hallo', 'welt']
finde ich da noch etwas schoener.

Re: Stringbearbeitung und subprocess

Verfasst: Donnerstag 31. März 2011, 12:50
von peddy
Hallo,

könnt ihr mal meinen Code überfliegen und mir sagen was ein Profi optimieren würde?

Code: Alles auswählen

#!/usr/bin/env python
# -*- encoding: utf-8; py-indent-offset: 4 -*-

import subprocess

hosts = (
    'xen01',
    'xen02',
    'xen03',
    'xen05'
)

def get_vms(hostname):
    vm_liste = []
    output = subprocess.Popen(['ssh','-l','root',hostname,'xe','vm-list|grep','name-label'], stdout=subprocess.PIPE)
    vms_unformatiert = output.stdout.read()
    for line in vms_unformatiert.splitlines():
        if hostname not in line:
            vm_liste.append(line.replace('name-label ( RW):','').strip())
    return vm_liste

for host in hosts:
    print get_vms(host)
Output:
['CAG1', 'CLS01', 'Mail-3', 'RSA01', 'Web01', 'Monitoring01', 'MX1', 'Mail-1']
['FTPS01', 'DC02', 'RSA02', 'PS3', 'CLS02', 'MX2', 'Mail-2', 'SQL04']
...
...

Re: Stringbearbeitung und subprocess

Verfasst: Donnerstag 31. März 2011, 13:00
von peddy
So hab jetzt selber noch ein paar Sachen gefunden:

Code: Alles auswählen

def get_vms(hostname):
    vm_liste = []
    output = subprocess.Popen(['ssh','-l','root',hostname,'xe','vm-list|grep','name-label'], stdout=subprocess.PIPE)
    for line in output.stdout.read().splitlines():
        if hostname not in line:
            vm_liste.append(line.replace('name-label ( RW):','').strip())
    return vm_liste

Re: Stringbearbeitung und subprocess

Verfasst: Donnerstag 31. März 2011, 13:04
von deets
peddy hat geschrieben:Hallo,

könnt ihr mal meinen Code überfliegen und mir sagen was ein Profi optimieren würde?
Ich wuerde noch ein

Code: Alles auswählen

# achtung, aussem kopp, schau nochmal in die doku
stdout, strerr = output.communicate()
reinwerfen. Und die variable dann auch nicht output nennen.

Der Grund ist, dass du sonst in eine race-condition kommen kannst. Wenn zB aufgrund von Netzwerk-Problemen der Aufbau der Verbindung verzoegert wird, dann liest dein Programm nix ein, und macht froehlich weiter. Daher solltest du auf jeden Fall auf's Ende des Prozesses warten.

Und im Grunde natuerlich auch noch Fehlerbehandlung betreiben...

Re: Stringbearbeitung und subprocess

Verfasst: Donnerstag 31. März 2011, 13:12
von BlackJack
@peddy: Dateien sind wie schon gesagt "iterable". Und zwar liefern sie die Zeilen in der Datei eine nach der anderen. Es ist also unnötig die Daten von `output.stdout` erst komplett zu lesen und dann in Zeilen aufzuteilen.

@deets: Die race condition sehe ich nicht!? Das lesen hört doch erst auf wenn die Gegenseite Datei geschlossen hat, nicht wenn es blockiert weil die Gegenseite noch nichts geschrieben hat.

Re: Stringbearbeitung und subprocess

Verfasst: Donnerstag 31. März 2011, 13:52
von peddy
BlackJack hat geschrieben:@peddy: Dateien sind wie schon gesagt "iterable". Und zwar liefern sie die Zeilen in der Datei eine nach der anderen. Es ist also unnötig die Daten von `output.stdout` erst komplett zu lesen und dann in Zeilen aufzuteilen.
Ich glaube zu wissen was du meinst, aber ich kann es nicht umsetzten. Kannst du mir noch einen Tipp geben, wie die Syntax aussehen müsste?

Re: Stringbearbeitung und subprocess

Verfasst: Donnerstag 31. März 2011, 13:58
von BlackJack
@peddy: ``for line in output.stdout:``

Re: Stringbearbeitung und subprocess

Verfasst: Donnerstag 31. März 2011, 19:53
von deets
BlackJack hat geschrieben: @deets: Die race condition sehe ich nicht!? Das lesen hört doch erst auf wenn die Gegenseite Datei geschlossen hat, nicht wenn es blockiert weil die Gegenseite noch nichts geschrieben hat.
Wo du recht hast.. Ich nehme alles zurueck und behaupte das Gegenteil!