Linux

如何將控制台輸出儲存到文件中

  • May 25, 2022

我正在執行嵌入式 Linux,我的命令行有 console=/dev/ttyO0,….

我有連接到這個 UART 的終端程序,可以看到系統產生的一切。現在,在現場執行時,我想將所有這些輸出儲存在文件中(我已連接媒體)。但是我使用 syslogd、klogd、logger 和 Co. 所做的所有努力都沒有給我想要的結果——有些消息被儲存了,但有些沒有——通常是最重要的。

例如,如果我執行:

#myapplication.sh | logger        

我在 syslog 中看到的“echo”命令,也可以從應用程序列印,也可以列印一些驅動程序消息。但是,如果應用程序因分段錯誤而崩潰,則不會記錄此資訊。但這是最有價值的!

所以,最好和最需要的是將 ttyO0 重定向到一個文件,但是怎麼做呢?

我找到了這樣一個建議:

(stty raw; cat > received.txt) < /dev/ttyO0

但這不起作用:我可以鍵入命令 fe ifconfig,但回复既不會出現在文件中,也不會出現在控制台上。甚至沒有創建文件…:-(

如果可以同時擁有-文件和串列控制台-那就太好了。但是文件具有更高的優先級。

非常感謝您的幫助!

更新:我找到了答案——見最後一個。

你似乎錯過了一個相當基本的事實。每個可管道程序都依賴於這樣一個事實,即它從任何呼叫它的程序中獲取三個處於預打開狀態的標准文件描述符。在涉及管道的大多數情況下,呼叫程序將是命令外殼。

這三個文件描述符是:

  • 文件描述符#0:標準輸入流,或stdin簡稱。
  • 文件描述符#1:標準輸出流,或stdout簡稱。
  • 文件描述符#2:標準錯誤輸出流,或stderr簡稱。

當程序沒有通過管道或重定向來讀/寫文件時,所有這三個文件描述符通常都指向目前登錄會話正在執行的 TTY 設備。如果故意將程序作為守護程序或後台/非互動式程序啟動,則所有這些都可能被定向到文件或/dev/null,或者可能定向到某種日誌記錄工具。

錯誤消息通常會輸出到stderr流中,以便它們不會與可能的管道數據輸出混在一起。但是在像您這樣的情況下,當您希望擷取所有輸出時,您需要明確告訴系統抓取兩個流。

如果您想將您的所有輸出傳遞myapplication.sh到管道中,您可能必須執行以下操作:

myapplication.sh 2>&1 | logger

上面寫著“將2>&1文件描述符 #2 重定向到 #1 要去的同一個地方”,然後你可以同時對它們進行管道傳輸。

您可以使用如下的小腳本自行測試:

#!/bin/sh
echo "this is stdout"
echo "this is stderr" >&2

>&2意思是“獲取此命令的標準輸出並將其發送到標準錯誤流中” 。stderr這可能是在腳本中生成輸出的最簡單方法。

現在,如果您執行此腳本./test.sh | od -t x1z以獲取十六進制轉儲形式的輸出,您將得到:

$ ./test.sh | od -t x1z
this is stderr
0000000 74 68 69 73 20 69 73 20 73 74 64 6f 75 74 0a     >this is stdout.<
0000017

所以只有stdout輸出被od命令處理。

如果您添加2>&1以合併兩個流,您將改為:

$ ./test.sh 2>&1 | od -t x1z
0000000 74 68 69 73 20 69 73 20 73 74 64 6f 75 74 0a 74  >this is stdout.t<
0000020 68 69 73 20 69 73 20 73 74 64 65 72 72 0a        >his is stderr.<
0000036

現在兩個輸出都被發送到管道中,這就是您在使用| logger.


您的第二個命令行正在擷取您的嵌入式設備從終端程序接收的任何內容,而不是嵌入式設備發送到終端的內容:

(stty raw; cat > received.txt) < /dev/ttyO0

您說您正在開發使用核心參數的嵌入式系統console=/dev/ttyO0,因此本質/dev/console上將是一個串列埠,而不是圖形顯示(甚至可能不存在於嵌入式設備中)。

如果您在嵌入式設備上執行該命令,括號內的命令將使用分配stdin/dev/ttyO0. 但是,如果您通過連接到 的串列線路輸入該命令,則ttyO0預設情況下可能會是這樣,因此此輸入重定向可能只是在重新執行這種情況。

/dev/ttyO0設備是連接到另一台電腦上的終端程序的 UART 的直接表示。當您從中讀取時,您只會得到您在終端程序中輸入的內容:無法讀取之前發送到終端程序中的任何輸出。寫入其中的任何內容都直接進入串列電纜末端的終端程序。

串列埠上的 Unix 命令行通常根據遠端回顯原理工作:為了查看您在終端程序上寫的內容,嵌入式系統上的 TTY 驅動程序必須將您鍵入的每個字元的副本發送回終端程序。這種行為不是對稱的:終端程序也不會通過串列埠連接發送回它接收到的任何內容的副本。

TTY 驅動程序是一件複雜的事情,因為 Unix 傳統要求它能夠做很多事情——遠端回顯功能只是其中之一。

當您使用 時stty raw,您實際上關閉了 TTY 驅動程序的所有通常有用的功能,包括遠端回顯功能。因此,從那時起,除非有什麼明確地讀取/dev/ttyS0並立即將其寫入其中,否則您將看不到您在終端程序上寫入的內容。

一旦stty raw命令退出,來自終端程序的任何輸入都將進入cat命令,當不帶參數呼叫時,它會按原樣將其傳遞到其標準輸出中。但是它的標準輸出現在已經被重定向到一個文件中,received.txt. 所以發生的情況是,只有您在終端程序上鍵入的內容才會寫入文件,直到cat命令結束 - 並且只有在獲得文件結尾字元(通常是Control+D)時才會結束。

(由於執行重定向的 shell 可能會進行任何緩衝,因此可能沒有輸出到received.txt文件中,除非您以文件結尾字元結束輸入,和/或輸入多於一行的文本。)

因此,除了關閉 TTY 驅動程序功能之外,(stty raw; cat > received.txt) < /dev/ttyO0嵌入式系統上的 根本不做任何事情來擷取正在寫入的任何輸出/dev/ttyO0。此命令的唯一用途是在您對串列埠連接進行故障排除時:如果您懷疑您的終端程序以某種方式破壞了您發送的字元,這是擷取終端程序發送到的任何內容的方法最原始形式的嵌入式設備。


如果您想絕對記錄通過 UART 連接發生的所有事情,包括核心恐慌消息,那麼最好的方法可能是告訴另一台電腦上的終端程序記錄所有流量。許多終端程序都內置了此功能。

這是因為如果核心出現問題,實際上可能無法再將任何內容寫入磁碟文件。僅從 UART 發送錯誤消息文本並相信接收它的人會擷取它要簡單得多。

嘗試使用 picocom 而不是 console=/dev/ttyS0。還有其他工具,但 picocom 聽起來最簡單。

如果您使用其中一種工具,您可以在輸出端使用管道和三通。

picocom /dev/ttyS0 -b 115200 -l | tee my.log

https://askubuntu.com/q/1010232

引用自:https://unix.stackexchange.com/questions/604572