argonsputter
Anmeldungsdatum: 15. April 2016
Beiträge: Zähle...
|
Hallo, ich versuche mich jetzt schon den ganzen Tag damit, einen awk Befehl in eine Variable zu speichern und diese dann später aufzurufen. Da ich viele Anführungszeichen (in diesem Beispiel gekürzt) im awk Befehl habe, bekomme ich immer wieder Fehlermeldungen. | wochentag=`date | awk '{print $2,$3}'`
awk_cmd="awk '/'"$wochentag"'/ {print}'"
Finaler_Befehl=`cat /tmp/logdatei | $awk_cmd`
|
Das verpackte awk wird irgendwie falsch interpretiert. Hat jemand eine Idee?
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11250
Wohnort: München
|
Wenn du awk selbst in einer Variable halten willst, musst du eval auspacken (oder eine Subshell starten): http://wiki.bash-hackers.org/commands/builtin/eval Man könnte das aber auch anders lösen - zumindest für das verkürzte Beispiel passt das leicht in eine Zeile:
| resultat=$(awk "/$(date +"%d. %b")/ {print}" /tmp/logdatei)
|
Wobei ich zumindest bei dem kurzen Beispiel keinen Vorteil von awk gegenüber (f)grep sehe:
| resultat=$(fgrep "$(date +"%d. %b")" /tmp/logdatei"
|
Edit: Falsche Formatierungssequenz im date-Befehl ersetzt, du scheinst den abgekürzten Monat ("%b") haben zu wollen, nicht den abgekürzten Wochentag ("%a")
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17604
Wohnort: Berlin
|
argonsputter schrieb: | wochentag=`date | awk '{print $2,$3}'`
awk_cmd="awk '/'"$wochentag"'/ {print}'"
Finaler_Befehl=`cat /tmp/logdatei | $awk_cmd`
|
Backticks solltest Du Dir gar nicht erst angewöhnen. Schlecht lesbar, nicht vernünftig zu schachteln, nicht portabel. | wochentag=$(date | awk '{print $2,$3}')
|
lässt sich aber auch als
schreiben, oder was spricht dagegen?
| Finaler_Befehl=`cat /tmp/logdatei | $awk_cmd`
|
Useless use of cat, oder?
| Finaler_Befehl=$($awk_cmd /tmp/logdatei)
|
Und das ist eine seltsame Maskierung:
| awk_cmd="awk '/'"$wochentag"'/ {print}'"
|
Meine Umschreibung sieht so aus:
| awk_cmd="awk /$wochentag/ {print}"
|
Es wird jedenfalls einen zusammenhängenden String ergeben, und die Leerstelle wird dann als Teil des Programmnamens interpretiert, der Slash folglich als Pfadtrenner, $wochentag als Unterverzeichnis, und " {print}" als schließlich auszuführende Datei (alle Zeichen sind valide im Dateinamen, außer dem Pfadtrenner Slash und der binären 0. Dem kann man mit einem Array begegnen:
| awk_cmd=(awk "/$wochentag/ {print}")
|
Mal nachschauen, was das wird:
| echo ${awk_cmd[*]}
awk /Jan 10/ {print}
|
(Ich habe den Wochentag umformatiert, um in einer Logdatei auch was zu finden).
Schreiten wir zur feierlichen Eröffnung und lassen die Cat weiter schlafen:
| res=$(${awk_cmd[*]} /var/log/auth.log)
|
Wieso das Literal "awk" aber überhaupt in eine Variable gepackt wird müsstest Du noch erklären.
| res=$(awk "/$wochentag/ {print}" /var/log/auth.log)
# oder
awk_befehl="/$wochentag/ {print}"
res=$(awk "$awk_befehl" /var/log/auth.log)
# oder
res=$(awk /$(date +"%b %d")/" "{print} /var/log/auth.log)
|
ist vielleicht in ein paar Monaten besser verständlich. Und insgesamt verständlicher und kürzer ist auch seahawks Greplösung, aber dass das weitgehend identisch ist, mit dem was ich habe, ist mir erst aufgefallen, nachdem ich mich selbst auf die Lösungssuche gemacht habe. Da ich meine 2, 3 Erklärungen loswerden wollte und die Ermahnung, Backticks zu meiden, wollte ich den Rest nicht löschen o. umsonst probiert haben.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 13176
|
argonsputter schrieb:
ich versuche mich jetzt schon den ganzen Tag damit, einen awk Befehl in eine Variable zu speichern und diese dann später aufzurufen. Da ich viele Anführungszeichen (in diesem Beispiel gekürzt) im awk Befehl habe, bekomme ich immer wieder Fehlermeldungen.
Wozu? Warum packst Du das nicht in eine Shell-Funktion? Edit: zum Beispiel so: | fun() {
awk "/$(date | awk '{print $2,$3}')/ {print}" "$@"
}
|
Und dann Der cat ist überflüssig. Edit 2: In diesem Fall muss man auch nicht awk nehmen: | fun() {
fgrep -w "$(date | awk '{print $2,$3}')" "$@"
}
|
|
track
Anmeldungsdatum: 26. Juni 2008
Beiträge: 7174
Wohnort: Wolfen (S-A)
|
Meine Vorredner haben es ja auch schon auf ihre Weise gesagt: einen Befehl in eine Variable zu packen (den man dann mit eval ausführen muss !) ist eine Unart, und allerhöchstens mal in einem äußerst speziellen Sonderfall sinnvoll. (Beachte: es ist zudem ein Sicherheitsleck, wenn ein Variableninhalt ausgeführt werden darf !) Was hast Du eigentlich konkret vor, dass Du solche Konstruktionen brauchst ? Denn sonst würde ich sagen, dass nicht nur date selber hübsch formatiert ausgeben kann, sondern genauso gut auch awk : track@track:~$ awk 'BEGIN { print strftime("%d. %b") }'
11. Jan Wie gesagt: verrat uns doch einfach mal, was Du genau erreichen willst. LG, track
|
argonsputter
(Themenstarter)
Anmeldungsdatum: 15. April 2016
Beiträge: 17
|
Danke erstmal für eure Antworten. Ich möchte einfach nur rausfinden, wie lange der Benutzer eingeloggt war. D.h. Ich mache ein Dort sehe ich dann hh:mm der jeweiligen Session. Diese zerstückel ich mir dann mit awk. Und genau diesen langen awk Befehl wollte ich in eine Variable packen, weil ich ihn öfters aufrufe.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 13176
|
argonsputter schrieb:
Ich möchte einfach nur rausfinden, wie lange der Benutzer eingeloggt war. D.h. Ich mache ein Dort sehe ich dann hh:mm der jeweiligen Session. Diese zerstückel ich mir dann mit awk.
Was bedeutet denn das? Was genau willst Du erreichen? Willst Du auch überlappende Logins desselben Benutzers auswerten? Willst Du Zeiten aufsummieren? etc.
Und genau diesen langen awk Befehl wollte ich in eine Variable packen, weil ich ihn öfters aufrufe.
Wie gesagt, nimm mindestens eine Funktion.
|
argonsputter
(Themenstarter)
Anmeldungsdatum: 15. April 2016
Beiträge: 17
|
Was bedeutet denn das? Was genau willst Du erreichen? Willst Du auch überlappende Logins desselben Benutzers auswerten? Willst Du Zeiten aufsummieren? etc.
Ich möchte einfach nur sehen, wie lange die Benutzer auf dem System waren. Egal wer. Ich sammel nur die hh und mm... einfach eine Zusammenfassung. Ich summiere dann auch via awk die Stunden. ☺
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 13176
|
argonsputter schrieb:
Ich möchte einfach nur sehen, wie lange die Benutzer auf dem System waren. Egal wer. Ich sammel nur die hh und mm... einfach eine Zusammenfassung. Ich summiere dann auch via awk die Stunden. ☺
Also, bei mir zeigt last -dwan 10 bereits die Dauer jedes einzelnen Logins. Was willst Du darüber hinaus noch?
|
argonsputter
(Themenstarter)
Anmeldungsdatum: 15. April 2016
Beiträge: 17
|
Das mit der Funktion hat gut geklappt! Aber jetzt ist mir aufgefallen, dass die Zeit ja für jedes pts einzeln gezählt wird. So errechne ich ja mehr als 24h an Stunden für einen Tag. Ich könnte dies zwar rausfiltern, indem ich alle pts ignoriere und nur nach lokalen Anmeldungen ( :0 ) schaue, aber wenn ich via ssh eine Verbindung aufgebaut habe, dann habe ich wieder Überlappungen. Mist!
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 13176
|
Wie gesagt: ich würde damit anfangen festzulegen, was Du eigentlich erreichen willst. Wenn man das Ziel kennt, kann man deutlich effektiver darauf zusteuern.
|
argonsputter
(Themenstarter)
Anmeldungsdatum: 15. April 2016
Beiträge: 17
|
rklm schrieb: Wie gesagt: ich würde damit anfangen festzulegen, was Du eigentlich erreichen willst. Wenn man das Ziel kennt, kann man deutlich effektiver darauf zusteuern.
Ja, ich gebe dir recht ☺ Ich will herausfinden, wie lange der Benutzer am System war, also die Stunden zählen. Mir ist erst später bewusst geworden, dass mir "last" die Zeiten überlappend anzeigt. Du hast das sogar auch in einem Post darüber geschrieben, was ich geschickt überlesen habe. Und das ist jetzt genau mein Problem. Der Benutzer kann ja mehrere pts offen haben. Nur das rauszufiltern würde das Script doch sprengen. Ich überlege jetzt auch gerade, ob ich mit who die einzelnen Benutzer minütlich im cronjob abfrage und dann eigene Logfiles schreibe. Dann natürlich auch minütlich das logfile vergleichen, ob der Benutzer noch da ist und falls nicht, eine Uhrzeit eintragen.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 13176
|
argonsputter schrieb:
Ich will herausfinden, wie lange der Benutzer am System war, also die Stunden zählen. Mir ist erst später bewusst geworden, dass mir "last" die Zeiten überlappend anzeigt. Du hast das sogar auch in einem Post darüber geschrieben, was ich geschickt überlesen habe. Und das ist jetzt genau mein Problem. Der Benutzer kann ja mehrere pts offen haben. Nur das rauszufiltern würde das Script doch sprengen.
Es sollte nicht zu schwer sein. Ansatz könnte ungefähr so aussehen: Zeilenweise die Ausgabe von last lesen. Anfang und Ende in einen vergleichbaren Zeitstempel umwandeln. In einer Map (assoziatives Array in awk ) den letzten Anfang und Ende des aktuellen Benutzers (Schlüssel der Map) auslesen. Falls Werte gefunden wurden und es eine Überlappung gibt (also falls Anfang(letzter) < Ende(aktuell) < Ende(letzter)) führt man die beiden zusammen, indem man Anfang(letzter) := Anfang(aktuell) setzt. Falls keine Werte gefunden oder keine Überlappung, gib den letzten Zeitraum aus und merke Anfang(aktuell) und Ende(aktuell).
Am Ende gehe einmal durch die Map und gebe alle Zeiträume aus.
Das geht vermutlich mit awk - ich würde lieber Ruby dafür nehmen.
Ich überlege jetzt auch gerade, ob ich mit who die einzelnen Benutzer minütlich im cronjob abfrage und dann eigene Logfiles schreibe. Dann natürlich auch minütlich das logfile vergleichen, ob der Benutzer noch da ist und falls nicht, eine Uhrzeit eintragen.
Das erscheint mir dann doch zu ressourcenverschwenderisch. ☺
|
argonsputter
(Themenstarter)
Anmeldungsdatum: 15. April 2016
Beiträge: 17
|
Der Zeitvergleich ist noch etwas zu hoch für mich. Ich hatte eben auch noch die idee, dass ich in /etc/.bashrc für alle Benutzer im Login eine Datei anlege mit Zeitangabe. Und beim logout wird in der Logdatei auch ein Eintrag vorgenommen. Natürlich würde ich noch eine Abfrage einbauen, um sicher zu gehen, dass der Benutzer keine weitere Sessions hat.
|
curly
Anmeldungsdatum: 2. Mai 2010
Beiträge: 268
|
Hier ebenfalls zwei interessante Ansätze: http://www.linuxquestions.org/questions/linux-newbie-8/total-login-time-of-each-user-in-last-940715/ Das Skript im letzten Post läuft zumindest, inwieweit das korrekt ist und die Ausgabe brauchbar, darfst du gerne selbst rausfinden ☺ . Hier noch ein Tool, das zumindest pro User die Daten bereitstellt, wird mit apt installiert: http://www.ihaveapc.com/2011/03/how-to-find-out-total-log-in-time-of-users-in-linux-mint-ubuntu/ Vielleicht kannst du das ja verwenden. Gruß
Dirk
|