如何比較正在運行的進程的輸出?

如何比較正在運行的進程的輸出?

我正在運行基準測試gem5模擬器,它在運行時不斷將輸出列印到終端。我已經將相同基準測試的樣本運行儲存在文字檔案

所以現在我想將打印到控制台的輸出流與之前黃金運行的文本文件進行比較。如果輸出與文字檔案相比存在差異,則模擬應自動終止。

基準測試需要大量時間來運行。我只對當前運行中的第一個錯誤感興趣,這樣我就可以節省等待執行完成來比較兩個輸出的時間。

答案1

我忍不住想進一步尋找一種比較 a 的輸出的正確方法。運行過程(在終端機中)針對“黃金運行”文件,正如您所提到的。

如何捕捉正在運行的進程的輸出

我使用script帶有-f選項的命令。這會將目前(文字)終端內容寫入檔案;此-f選項是在每次寫入事件到終端時更新輸出檔案。腳本命令用於記錄終端機視窗中發生的所有情況。
下面的腳本定期導入此輸出。

這個腳本的作用

如果您在終端機窗口中執行該腳本,它將打開第二個終端窗口,並使用該script -f命令啟動。在這個(第二個)終端機視窗中,您應該執行命令來啟動基準測試過程。雖然此基準測試過程會產生結果,但這些結果會定期(每 2 秒)與您的「黃金運行」進行比較。如果發生差異,則不同的輸出將顯示在「主」(第一個)終端機中,並且腳本終止。出現一行,格式如下:

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

explanation:

error: (<golden_run_result>, <current_differing_output>)

在此輸出之後,您可以安全地關閉第二個窗口,並執行測試。

如何使用

  • 將下面的腳本複製到一個空文件中。
    當您查看“黃金運行”文件時,第一部分(在實際測試開始之前)是無關緊要的,並且在不同的系統上可能會有所不同。因此,您需要定義實際輸出開始的行。在你的情況下我將其設定為:

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

    如有必要,請更改它。

  • 設定“golden run”檔案的路徑。
  • 將腳本儲存為compare.py,透過命令運行:

    python3 /path/to/compare.py
    

    `

  • 第二個視窗打開,顯示Script started, the file is named </path/to/file>
  • 在第二個視窗中,執行基準測試,第一個不同的結果出現在第一個視窗:

在此輸入影像描述

我是如何測試的

我創建了一個小程序,可以逐一列印您的黃金運行編輯版本的台詞。我讓腳本將其與原始的“golden run”文件進行比較。

劇本:

#!/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)

答案2

您可以使用diffutil.

假設你有你的金色文件,以及其他我改變了。

我沒有運行你的程序,所以我寫了這個模擬:

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

它讀取自其他文件(bad_file),每秒逐行輸出。

現在運行此腳本,並將其輸出重定向到log檔案。

$ simulate > log &

我還寫了檢查腳本:

#!/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

不要忘記使其可執行chmod +x checker.sh

該腳本有兩個參數。第一個參數是黃金檔案的路徑,第二個參數是日誌檔案的路徑。

$ ./checker.sh path_to_golden path_to_log

此檢查器會計算文件中目前的行數log,並將其與golden_file.

每秒運行檢查器,並在需要時執行kill命令

checker.sh如果你願意,你可以寫 bash 函數每秒執行一次:

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

之前關於 diff 的部分答案

您可以將它們作為文本文件逐行比較

man 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

如果我們比較我們的文件:

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

我們將看到這樣的輸出:

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

它顯示了不同的線

這是最終命令,我假設您不想檢查前 15 行:

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

它將向您顯示兩列中的所有差異。如果您只想知道有什麼區別,請使用:

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

如果文件相同,它不會列印任何內容

答案3

我不知道您的輸入資料有多複雜,但您可以使用類似的方法awk讀取輸入的每一行並將其與已知值進行比較。

$ 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

在這種情況下,我輸入一個延時數字流,並awk一直運行,直到輸入中的第一個變數(僅有的此處的變數)等於 2,然後退出並在此過程中停止串流。

相關內容