Ich versuche ein Shellscript zu schreiben was die gesamte Logginzeit eines Nutzers an einem Rechner ermittelt werden soll

Hinweis: In dem Thema Ich versuche ein Shellscript zu schreiben was die gesamte Logginzeit eines Nutzers an einem Rechner ermittelt werden soll gibt es 14 Antworten auf 2 Seiten. Der letzte Beitrag () befindet sich auf der letzten Seite.
  • Also ich danke euch schon mal für die Antworten =D :thumbup::thumbup:


    ich habe weiter dran gearbeitet, komme aber nicht zum Ergebnis.


    Also die wichtigen Informationen die ich vorenthalten habe sind wie folg.


    Das Skript soll als erstes den Rechnernamen und den Nutzernamen übernehmen
    also bsp.: ./logtime.sh MEINRECHNER MEINNAME
    also ist MEINRECHNER dann $1 und MEINNAME $2


    dann soll er prüfen ob der Rechner erreichbar ist und ob der Nutzer auf diesem Rechner existiert


    was ich ja mit ping und finger gemacht hatte. Wobei finger allein nicht ausreicht

    Code
    ssh $1 finger $2




    sollte dafür gehen.


    Anschließend möchte ich also die gesamte Loginzeit des Nutzers ermittel die er insgesamt auf diesen rechner verbracht hat
    diese sind ja im /var/log/wtmp* verzeichnissen gespeichert
    Das heist ich muss die da irgendwie auswerten und und zusammenrechnen.


    Dazu lege ich einen temp. Ordner an, den ich auf die Variable TMP speichere

    Code
    TMP=mktemp -d  $(basename $0)-temp-created-$(date +%Y-%m-%d_%H:%M:%S)_XXXXXXXXX

    dann hole ich mir mittels scp den die wtmp Dateien und entpacke sie mittels unxz :smilie_pc_011:


    Code
    scp $1:/var/log/wtmp* $TMP
    unxz $TMP/*.xz

    und jetzt komme ich an die Probleme. Wie kann ich jede wtmp Datei auswerten (also eine wtmp und mehrere bsp 14 auf dem Server wtmp-20170112).
    Dazu dachte ich



    Hier habe ich das Problem das er das last Kommando nicht erkannt wird, also wird dieser auch Falsch sein



    wie kann ich das besser realisieren? ?(?(

    Für den Inhalt des Beitrages 103583 haftet ausdrücklich der jeweilige Autor: Timmi0701

  • Was mir noch so einfällt:
    Du gehst ja eh mit ssh auf die Kiste. Also kannst du auch wirklich auf finger verzichten.
    Du müsstest den Output von finger ja auch erst filtern.
    Einfacher mag es sein für alle User einfach die Usernamen aus der /etc/passwd zu lesen.


    Bash
    # alle User
    awk -F: '{if ($3>999 && $3 < 60000){ print $1}}' /etc/passwd
    # da die UserIDs auf anderen Distris/Unices erheblich von openSUSE
    # abweichen können, oder vom root anders gesetzt sein können,
    # könnte man auch die tatsächlich gültigen Werte für 999 und 60000
    # einfach lesen:
    grep UID_MIN /etc/login.defs
    grep UID_MAX /etc/login.defs
  • Halöchen, :D


    also so sieht mein derzeitiger Forschungsstand aus


    Mein Problem ist jetzt wie man sieht, die Variable total auzugeben. Also ich denke mal so wie ich das jetzt zusammengeschrieben habe, mit total${count} hoffe ich das er die variable um eins Zählt also das es eine total1, total2, ...,totaln gibt
    Wie gebe ich diese aber wieder aus :smilie_pc_011:

    Für den Inhalt des Beitrages 103753 haftet ausdrücklich der jeweilige Autor: Timmi0701

  • Bash
    for var in $TMP/wtmp*
    	do 
    		LOGIN=$(last -F -f $var | grep $2 | cut -c 44-63)
    		LOGOUT=$(last -F -f $var | grep $2 | cut -c 71-90)

    Nimm für eigene Variablen keine durchgehende Großschreibung.


    Die ist eigentlich für Environmentvariablen und für reine Systemvariablen gedacht.
    Das ist schlechter Stil. Auch wenn im Internet noch so viele schlechte Beispiele dieser Unsitte folgen.
    Man kann damit leicht mal eine solche Variable versehentlich ändern. Die Resultate können verheerend sein.
    (Es gibt viel mehr solcher Variablen, als der gemeine Shellscripter kennt.)


    Die Logik mit der du diese verschachtelten Schleifen baust, ist schwer zu durchdringen.
    Guter Code ist von jedem Leser zu verstehen.
    Bei dir muss man ganz schön um die Ecke denken.
    Das ist später kaum mehr zu wartender Code. Den wird man lieber neu schreiben, als an veränderte Anforderungen anpassen zu wollen.
    Solche Sünden holen dich ein. Eher früher, als später.



    Bash
    echo $LOTIME
    		let total${count}=$LOTIME-$LITIME
    		echo "toal= $total$count" #Also bei der Variante kommt nichts gescheites raus
                    echo "total= $total"  #Hier kommt nichts (leeres Feld nach dem = )
                    echo "total= $total${count}"  #War ja klar dass das nicht Funktioniert
    		#Zähler um eins erhöhen
    		count=$((count + 1))
    done

    Das Leerzeichen nach dem Istgleich ist nicht dein Problem. Innerhalb des Strings, den echo ausgibt, ist da halt ein Leerzeichen.
    count=$((count + 1)) lässt sich kürzer schreiben: ((count++)) genügt. Der Dollar vor dem runden Klammerpaar bewirkt die Expansion. Der Ausdruck wird also zum Wert der Addition expandiert, den du dann wieder der Variablen zuweist. Es genügt einfach die Variable hochzuzählen. Der Inkrementoperator tut das ohne viel Tippen auch alleine. Und ohne Expansion und erneute Zuweisung.


    Das ist ganz, ganz schlechter Stil, der sehr fehlerträchtig ist: let total${count}=$LOTIME-$LITIME
    Das let ist alte Posix Shell Syntax. Die bash ist moderner und kennt leistungsfähigere und elegantere Konstrukte.
    Da du Bashisms schreibst, muss es bash sein. Es macht also wenig Sinn auf die alte umständliche Syntax zurückzugreifen.
    Noch schlimmer ist es, alte Syntax mit moderner zu vermischen. ${...} ist moderne Syntax.


    Und dann ist da ein ganz kapitaler Fehler drin: Du denkst, dass du der Reihe nach verschiedene Variablen names total<Ziffer> setzt. Das passiert auch. Nur kannst du dann darauf nicht mehr zugreifen. Denn das Konstrukt echo "total= $total${count}" wird nur einmal ausgewertet. Beim Parsen ersetzt die Bash $total mit nichts, weil eben die Variable total nirgends gesetzt worden ist. Erinnere dich: Du hattest Variablen, wie total12 oder total5 gesetzt, aber eben nicht total. Und ${count} hat halt den Wert, den count gerade hat. Mehr wird nicht ausgegeben. Deine gesetzten total-Variablen bleiben unbeachtet.


    Es gibt auch nur einen Weg, das auf diese Art zu lösen. Den schreibe ich aber nicht, weil eval evil ist. Das nimmt man nur, wenn man wirklich gute Gründe UND keine, und wirklich keine andere Möglichkeit mehr hat.
    Die Bash kennt aber Arrays und sogar assoziative Arrays. Die sind hier gefragt.
    Eine Übersicht über Arrays findet sich hier.
    Noch eleganter und effizienter wären hier assoziative Arrays. Der User wäre der Key, seine Gesamtzeit der Value.
    Über assoziative Arrays hier schmökern.


    Du hattest wohl die indirekte Expansion im Sinn.
    Die funktioniert aber nur anders rum:


    Bash
    red="rote Farbe"
    green="grüne Farbe"
    
    
    color=red
    echo ${!color}
    
    
    color=green
    echo ${!color}