Einführung
Ich versuche zu erfassen, welche Prozesse über einen begrenzten Zeitraum gestartet wurden.
Ich habe ein Skript erstellt (ps-suspects.sh
) wobei:
- Ich starte
ps-suspects.sh
vom Terminal. - Ich starte und schließe eine Anwendung, sagen wir den Desktop-Rechner.
- Ich drücke Strg +C um
ps-suspects.sh
zu beenden - Ich möchte wissen, wie der Prozessname für den Rechner lautet
- Ich möchte nicht, dass alle anderen Prozessnamen aufgelistet werden, die während des gesamten Zeitraums des Snapshots ausgeführt werden.
Das Problem
Ich habe ein Code-Snippet, das einer Feinabstimmung bedarf:
$ sort -k15 ~/pid.log | uniq -f14 -c
Folgendes wird erzeugt:
$ head ~/pid.tmp
1 /mnt/e/bin/ps-suspects.sh Possible suspects causing problems
63 1 S root 127 2 0 60 -20 - 0 - Sep08 ? 00:00:00 [acpi_thermal_pm]
63 1 S root 75 2 0 60 -20 - 0 - Sep08 ? 00:00:00 [ata_sff]
63 1 S root 447 2 0 60 -20 - 0 - Sep08 ? 00:00:00 [ath10k_aux_wq]
63 1 S root 446 2 0 60 -20 - 0 - Sep08 ? 00:00:00 [ath10k_wq]
63 1 S avahi 922 910 0 80 0 - 11195 - Sep08 ? 00:00:00 avahi-daemon: chroot helper
63 4 S avahi 910 1 0 80 0 - 11228 - Sep08 ? 00:00:00 avahi-daemon: running [alien.local]
126 0 S rick 2902 2867 0 80 0 - 7409 wait_w Sep08 pts/18 00:00:00 bash
63 0 S rick 25894 5775 0 80 0 - 4908 wait 10:43 pts/2 00:00:00 /bin/bash /mnt/e/bin/ps-suspects.sh
63 0 S root 980 976 0 80 0 - 4921 - Sep08 ? 00:00:01 /bin/bash /usr/local/bin/display-auto-brightness
Ich möchte alle Zeilen entfernen, die 63
vorkommen oder mehrmals.
Gewünschte Ausgabe
$ ps-suspects.sh
20 times / second ps -elf is captured to /home/rick/pid.log
Type Ctrl+C when done capturing
~/pid.log is sorted and uniq counted on column 15
which is full path and program name.
Then all matches with same unique count (the headings)
are stripped and only new processes started are printed.
This function can help you trace down what processes are
causing you grief for lid close events, hot plugging, etc.
^C
wc of ~/pid.log : 17288 343162 2717102 /home/rick/pid.log
HighCnt: 63
1 /mnt/e/bin/ps-suspects.sh Possible suspects causing problems
26 0 R rick 25976 2051 0 80 0 - 120676 - 10:43 ? 00:00:00 gnome-calculator
62 0 S root 22561 980 0 80 0 - 3589 - 10:42 ? 00:00:00 sleep 60
Frage
In diesem Beispiel 63
erscheint auf 90 % bis 99 % der Zeilen in Spalte 1, und diese Zeilen müssen entfernt werden. Alle Vorkommen von 126
könnte auch entfernt werden. Also irgendetwas das Auftretendste und Größte kann entfernt werden.
Kann jemand das fehlende awk
finden und/oder uniq
und/oder grep
um die Aufgabe zu beenden?
Akzeptierte Antwort:
Python zur Rettung:
python3 -c 'import sys,collections;l=[(int(L.split(None,1)[0]),L)for L in sys.stdin.readlines()];m=collections.Counter(x[0]for x in l).most_common(1)[0][0];print(*[x[1]for x in l if x[0]<m],sep="",end="")'
Alternative, unkomprimierte Version zur Verwendung als Skriptdatei:
#!/usr/bin/env python3
import sys
import collections
# read lines from stdin (with trailing \n) and extract the number in their first column
items = [(int(line.split(None, 1)[0]), line) for line in sys.stdin]
# find the most common number from the first column
most_common = collections.Counter(item[0] for item in items).most_common()[0][0]
# print input lines in order, but only those with their number lower than the most common
print(*[item[1] for item in items if item[0] < most_common], sep="", end="")
Die einzige Annahme, die dieses Skript in Bezug auf seine Eingabe macht, von der erwartet wird, dass sie in stdin geleitet wird, ist, dass jede Zeile eine gültige Ganzzahl in ihrer ersten durch Leerzeichen getrennten Spalte enthält. Die Zeilen müssen in keiner Form sortiert sein.
Verwandte:Welcher Hash-Algorithmus wird für Passwörter verwendet, die in 11.10 im Schatten gespeichert sind?Hinweis: Wenn es in der ersten Spalte mehrere verschiedene häufigste Zahlen mit derselben Anzahl gibt, ist es willkürlich, welche der beiden ausgewählt wird, sollte aber für dieselbe Eingabe konstant sein. Falls dies nicht erwünscht ist, müssten Sie stattdessen die Zeile, die den häufigsten Wert findet, durch etwas in der Art ersetzen, um den höchsten häufigsten Wert zu finden:
most_common = sorted(collections.Counter(item[0] for item in items).most_common(),
key=lambda x:x[::-1])[-1][0]
Beispieleingabe:
1 foo
3 bar
2 baz
3 apple
3 banana
2 cherry
4 beep
Beispielausgabe:
1 foo
2 baz
2 cherry