Wie vergleicht man die Ausgabe eines laufenden Prozesses?

Wie vergleicht man die Ausgabe eines laufenden Prozesses?

Ich führe einen Benchmark durch aufGem5-Simulator, das während der Ausführung die Ausgabe auf dem Terminal ausgibt. Ich habe bereits einen Probedurchlauf desselben Benchmarks in einemTextdatei.

Jetzt möchte ich den Ausgabestream, der auf der Konsole gedruckt wird, mit der Textdatei des vorherigen Golden Runs vergleichen. Wenn es einen Unterschied zwischen der Ausgabe und der Textdatei gibt, sollte die Simulation automatisch beendet werden.

Der Benchmark benötigt viel Zeit. Mich interessiert nur der erste Fehler im aktuellen Lauf, damit ich die Wartezeit bis zum Abschluss der Ausführung einsparen und beide Ergebnisse vergleichen kann.

Antwort1

Ich konnte nicht widerstehen, noch ein wenig weiter zu rätseln, um einen geeigneten Weg zu finden, die Ausgabe einesLaufender Prozess(im Terminal) gegen eine „Golden Run“-Datei, wie Sie es erwähnen.

So erfassen Sie die Ausgabe des laufenden Prozesses

Ich habe den scriptBefehl mit der -fOption verwendet. Dadurch wird der aktuelle (textuelle) Terminalinhalt in eine Datei geschrieben; die -fOption besteht darin, die Ausgabedatei bei jedem Schreibvorgang im Terminal zu aktualisieren. Der Skriptbefehl dient dazu, alles aufzuzeichnen, was in einem Terminalfenster geschieht.
Das folgende Skript importiert diese Ausgabe regelmäßig.

Was dieses Skript macht

Wenn Sie das Skript in einem Terminalfenster ausführen, wird ein zweites Terminalfenster geöffnet, das mit dem script -fBefehl gestartet wird. In diesem (zweiten) Terminalfenster sollten Sie Ihren Befehl ausführen, um den Benchmark-Prozess zu starten. Während dieser Benchmark-Prozess seine Ergebnisse erzeugt, werden diese Ergebnisse regelmäßig (alle 2 Sekunden) mit Ihrem „Golden Run“ verglichen. Wenn ein Unterschied aufgetreten ist, wird die abweichende Ausgabe im „Hauptterminal“ (ersten Terminal) angezeigt und das Skript wird beendet. Es erscheint eine Zeile im Format:

error: ('Solutions: 13.811084', 'Solutions: 13.811084 aap noot mies')

explanation:

error: (<golden_run_result>, <current_differing_output>)

Nach dieser Ausgabe können Sie das zweite Fenster sicher schließen und Ihre Tests ausführen.

Wie benutzt man

  • Kopieren Sie das folgende Skript in eine leere Datei.
    Wenn Sie sich Ihre „Golden Run“-Datei ansehen, ist der erste Abschnitt (vor dem eigentlichen Test) irrelevant und kann auf verschiedenen Systemen unterschiedlich sein. Daher müssen Sie die Zeile definieren, in der die eigentliche Ausgabe beginnt. In Ihrem Fall habe ich sie wie folgt festgelegt:

    first_line = "**** REAL SIMULATION ****"
    

    ändern Sie es bei Bedarf.

  • Legen Sie den Pfad zu Ihrer „Golden Run“-Datei fest.
  • Speichern Sie das Skript unter und compare.pyführen Sie es mit dem folgenden Befehl aus:

    python3 /path/to/compare.py
    

    `

  • ein zweites Fenster öffnet sich mitScript started, the file is named </path/to/file>
  • Führen Sie in diesem zweiten Fenster Ihren Benchmarktest durch. Das erste abweichende Ergebnis wird im ersten Fenster angezeigt:

Bildbeschreibung hier eingeben

So habe ich getestet

Ich habe ein kleines Programm erstellt, das die Zeilen einer bearbeiteten Version Ihres Golden Runs nacheinander ausgibt. Ich habe das Skript so konfiguriert, dass es sie mit der ursprünglichen „Golden Run“-Datei vergleicht.

Das Skript:

#!/usr/bin/env python3

import subprocess
import os
import time

home = os.environ["HOME"]

# files / first_line; edit if necessaary
golden_run = "/home/jacob/Bureaublad/log_example"
first_line = "**** REAL SIMULATION ****"

# don't change anything below
typescript_outputfile = home+"/"+"scriptlog.txt"
# commands
startup_command = "gnome-terminal -x script -f "+typescript_outputfile
clean_textcommand = "col -bp <"+typescript_outputfile+" | less -R"
# remove old outputfile
try:
    os.remove(typescript_outputfile)
except Exception:
    pass
# initiate typescript
subprocess.Popen(["/bin/bash", "-c", startup_command])
time.sleep(1)
# read golden run
with open(golden_run) as src:
    original = src.read()
orig_section = original[original.find(first_line):]
# read last output of current results so far
def get_last():
    read = subprocess.check_output(["/bin/bash", "-c", clean_textcommand]).decode("utf-8")
    if not first_line+"\n" in read:
        return "Waiting for first line"
    else:
        return read[read.find(first_line):]
    with open(typescript_outputfile, "wt") as clear:
        clear.write("\n")
# loop
while True:
    current = get_last()
    if current == "\n":
        pass
    else:
        if not current in orig_section and current != "Waiting for first line":
            orig = orig_section.split("\n")
            breakpoint = current.split("\n")
            diff = [(orig[i], breakpoint[i]) for i in range(len(breakpoint)) \
                    if not orig[i] == breakpoint[i]]
            print("error: "+str(diff[0]))
            break
        else:
            pass
    time.sleep(5)

Antwort2

Sie können diffutil verwenden.

Angenommen, Sie habendeingoldene Feile undein andererdass ich mich geändert habe.

Ich habe Ihr Programm nicht ausgeführt, deshalb habe ich diese Simulation geschrieben:

#!/bin/bash
    while read -r line; do
        echo "$line";
        sleep 1;
    done < bad_file

Es lautet ausein andererDatei (bad_file) und Ausgabe zeilenweise jede Sekunde.

Führen Sie jetzt dieses Skript aus und leiten Sie seine Ausgabe in logeine Datei um.

$ simulate > log &

Außerdem habe ich ein Prüfskript geschrieben:

#!/bin/bash

helper(){
    echo "This script takes two file pathes as arguments."
    echo "$0 path/to/file1 path/to/file2"
}

validate_input(){
    if [[ $# != 2 ]]; then 
        helper
        exit 1
    fi

    if [[ ! -f "$1" ]]; then
        echo "$1" file is not exist.
        helper
        exit 1
    fi
    if [[ ! -f "$2" ]]; then
        echo "$2" file is not exist.
        helper
        exit 1
    fi
}

diff_files(){
# As input takes two file and check
# difference between files. Only checks
# number of lines you have right now in
# your $2 file, and compare it with exactly
# the same number of lines in $1
    diff -q -a -w <(tail -n+"$ULINES" $1 | head -n "$CURR_LINE") <(tail -n+"$ULINES" $2 | head -n "$CURR_LINE")
}

get_curr_lines(){
# count of lines currenly have minus ULINES
    echo "$[$(cat $1 | wc -l) - $ULINES]"
}

print_diff_lines(){
    diff -a -w --unchanged-line-format="" --new-line-format=":%dn: %L" "$1" "$2" | grep -o ":[0-9]*:" | tr -d ":"
}

ULINES=15 # count of first unused lines. How many first lines to ignore

validate_input "$1" "$2"
CURR_LINE=$(get_curr_lines "$2") # count of lines currenly have minus ULINES

if [[ $CURR_LINE < 0 ]];then
    exit 0
fi

IS_DIFF=$(diff_files "$1" "$2")
if [[ -z "$IS_DIFF" ]];then
    echo "Do nothing if they are the same"
else
    echo "Do something if files already different"
    echo "Line number: " `print_diff_lines "$1" "$2"`
fi

Vergessen Sie nicht, es ausführbar zu machen chmod +x checker.sh.

Dieses Skript benötigt zwei Argumente. Das erste Argument ist der Pfad zu Ihrer Golden-Datei, das zweite Argument der Pfad zu Ihrer Protokolldatei.

$ ./checker.sh path_to_golden path_to_log

Dieser Prüfer zählt die Anzahl der Zeilen, die sich derzeit in Ihrer logDatei befinden, und vergleicht sie mit der exakt gleichen Anzahl von Zeilen in golden_file.

Sie führen den Checker jede Sekunde aus und führen bei Bedarf den Kill-Befehl aus

Wenn Sie möchten, können Sie eine Bash-Funktion schreiben, die checker.shjede Sekunde ausgeführt wird:

$ chk_every() { while true; do ./checker.sh $1 $2; sleep 1; done; }

Teil der vorherigen Antwort zum Thema Diff

Sie können sie Zeile für Zeile als Textdatei vergleichen

Ausman diff

NAME
   diff - compare files line by line

   -a, --text
          treat all files as text

   -q, --brief
          report only when files differ

   -y, --side-by-side
          output in two columns

Wenn wir unsere Dateien vergleichen:

$ diff -a <(tail -n+15 file1) <(tail -n+15 file2)

Wir werden diese Ausgabe sehen:

2905c2905
< Solutions: 0.686669
---
> Solutions: 0.686670
2959c2959
< Solutions: 0.279124
---
> Solutions: 0.279125
3030c3030
< Solutions: 0.539016
---
> Solutions: 0.539017
3068c3068
< Solutions: 0.308278
---
> Solutions: 0.308279

Es zeigt die Linie, die sich unterscheidet

Und hier ist der letzte Befehl. Ich gehe davon aus, dass Sie die ersten 15 Zeilen nicht überprüfen möchten:

$ diff -y -a <(tail -n+15 file1) <(tail -n+15 file2)

Es werden Ihnen alle Unterschiede in zwei Spalten angezeigt. Wenn Sie nur wissen möchten, ob es Unterschiede gibt, verwenden Sie Folgendes:

$ diff -q -a <(tail -n+15 file1) <(tail -n+15 file2)

Es wird nichts gedruckt, wenn die Dateien gleich sind

Antwort3

Ich habe keine Ahnung, wie kompliziert Ihre Eingabedaten sind, aber Sie könnten so etwas verwenden, awkum jede Zeile beim Eintreffen zu lesen und mit einem bekannten Wert zu vergleichen.

$ for i in 1 2 3 4 5; do echo $i; sleep 1; done | \
  awk '{print "Out:", $0; fflush(); if ($1==2) exit(0)}'
Out: 1
Out: 2

In diesem Fall füge ich einen zeitverzögerten Strom von Zahlen ein und dieser awkläuft, bis die erste Variable in der Eingabe (dienurVariable hier) gleich 2 ist, wird dann beendet und hält dabei den Stream an.

verwandte Informationen