將 stdin 和 stdout 重新導向到文件

將 stdin 和 stdout 重新導向到文件

所以我有一個程序,它接受用戶輸入並根據輸入輸出文字。

EDIT2:我想建立一個運行 C 執行檔的腳本,該腳本從檔案提供 C 程式輸入並將輸出重定向到另一個檔案。但是,每當為輸入列印輸出時,我也想列印輸入,基本上將輸入和輸出組合/合併在一起。因此,我在文件中逐行輸入輸入,然後將每個輸入的輸出列印到文件中,並且我繼續這樣做。我不想重新運行該程序,我希望該程序仍然運行,直到它到達輸入文件的末尾或直到我從腳本向它發送終止信號。 (我正在嘗試為班級製作一個評分腳本。學生提交他們的程序,我運行這個腳本,並向他們的程序提供輸入,但我想一起跟踪輸入+輸出,這樣我就可以更輕鬆地跟踪每個輸出的輸入)我可以弄清楚如何自己創建腳本的其餘部分,但我只是堅持將輸入+輸出組合在一起。

Edit3:我認為expect不會起作用,因為我無法知道程式會輸出什麼。我只知道它應該接受什麼。

(注意:我將有許多不同的可執行文件,它們具有不同的格式,但都應該要求相同數量的輸入)

例如,可執行檔之一可能是這樣的:

"Enter a number: " (Wait for user input)
"Give another: "  (Wait for user input
"Total: " (Output based on input)
"Do you want to run again? "(Wait for user input)

編輯:我的腳本的主要目標是運行程序,逐行從文件中獲取輸入。例如,對於這個程序,我希望它將文件“輸入”作為標準輸入,但我也想追蹤與標準輸出合併的標準輸入。

所以我知道./a.out<input>output會輸出

Enter a number: 
Give another:  
Total:  15
Do you want to run again? 

然而,它缺少我想要包含的輸入,因此我只需查看輸出檔案就可以根據輸出判斷輸入是什麼,因為輸入可能是 7 8 N 或 5 10 N 或類似的東西。

答案1

如果我理解正確,您想要檢測何時a.out從標準輸入讀取數據,以及何時發送該數據並將該數據寫入同一個日誌文件 stdout 被重定向到以在echo交互運行時模擬本地終端?

那麼也許解決方案(bash 語法)會是這樣的:

mkfifo strace.fifo
{
  while read -d, trace; do
    if [[ $trace = *"read(0" ]]; then
      IFS= read -rn1 answer <&3 || break
      answer=${answer:-$'\n'}
      printf %s "$answer" >&2
      printf %s "$answer"
    fi
  done < strace.fifo 3< answers.txt |
    strace -o strace.fifo -e read ./a.out
} > log 2>&1

這個想法是使用strace(假設您使用的是 Linux)來追蹤read系統調用,並且只要檔案描述符 0 存在read,就從 開始一次輸入一個字元answers.txt

編輯:如果程式使用 stdio 或類似的東西。當輸出被重定向到常規檔案並且不再是終端時,可能發生的情況是它輸出的所有提示都被緩衝,並且僅在程式退出時才會刷新。

解決方法是使用stdbuf: 替換./a.outstdbuf -oL ./a.out。這將告訴應用程式(假設它是動態連結的應用程式並且緩衝是由於 stdio)在 stdout 上進行行緩衝,就像它是終端一樣。然而,它仍然不會做的是在從 stdin 讀取 stdio 時刷新 stdout,如果 stdin/stdout 是終端,它通常會這樣做。例如,在明確fflush或最終寫入換行符號之前,不會顯示未以換行符號終止的提示。因此最好的方法可能是stdbuf -o0完全停用緩衝。

如果a.out可以分叉進程或線程,請將-f選項新增至strace.

如果應用程式在select實際poll執行read.非阻塞 I/O 也可能導致我們發送資料過快。

正如評論中所提到的。expect是模擬使用者互動的工具,它使用偽終端,所以你會自動獲得輸入回顯並且不會有緩衝輸出問題。作為 的替代方案stdbuf,您可以使用它unbuffer附帶的腳本來包裝a.out偽終端。在這種情況下,您可能需要在檢測讀取和發送答案之間添加一點延遲,以便expect在其標準輸出上重現提示。

答案2

用於script此。這正是它的用途。

script /tmp/logfile -c 'your command here'

例如:

>> script /tmp/log -c 'read -p "Value: " value; echo "value=$value"'
Script started, file is /tmp/log
Value: foo
value=foo
Script done, file is /tmp/log

>> cat /tmp/log
Script started on Wed 01 May 2013 01:16:34 PM EDT
Value: foo
value=foo

Script done on Wed 01 May 2013 01:16:35 PM EDT

相關內容