查看stdin的內容
我正在嘗試調試一個可以通過標準輸入接收命令的 Linux 應用程序,能夠看到寫入標準輸入的所有內容非常有用。
我的第一種方法是執行
sudo cat /proc/$pid/fd/0
,但事實證明這是一種無效的方法,因為cat
我的程序和我的程序都在嘗試使用該文件描述符的內容,並且只有一個程序可以贏得比賽。另一種方法是使用tail,但由於此處列出的原因,這不起作用。
我可以輕鬆地將調試日誌記錄添加到我的應用程序中,這將解決問題,但我很想知道是否有我缺少的更通用的方法。
strace
?下面的例子。啟動一個 cat 程序,該程序正在讀取標準輸入並寫入 /tmp/foofile。找到pid,strace它。並且在原來的貓視窗中,輸入一些文字,嘿嘿。
# cat >/tmp/foofile # ps -ef|grep cat steve 2134 1801 0 22:25 pts/2 00:00:00 cat # strace -fp 2134 Process 2134 attached read(0, "test\n", 65536) = 5 write(1, "test\n", 5) = 5 read(0,
要從文件描述符 0 中提取讀取:
strace -fp 2134 -e trace=read -o "|grep read.0,"
在 linux 上,您可以將應用程序的文件描述符作為
/dev/fd/[0-9]
. 您絕對可以對命名文件和輸入流執行的操作是tee
對該文件和標準輸出的輸入。因此,當我發現自己處於您的情況時*(就像我經常做的那樣),我通常會做*的事情是tee
輸入到我的閱讀應用程序和/dev/fd/2
-stderr。像這樣:
seq 10 | tee /dev/fd/2 | wc -c 1 2 3 4 5 6 7 8 9 10 21
當然,即使你不在一個 linux 系統上,同樣的事情也可以便攜地完成——如果在某些情況下不太具體的話——只需做
...| tee /dev/tty | ...
如果您在說
stdin
*(如您的連結所示)*時談論的是終端,那麼您可能仍然會做同樣的事情,儘管由於核心的行緩衝,它可能會變得更加棘手。因此,在這種情況下,我會做的是tty
通過將我的命令包裝進去來記錄所有 i/luit
o——因為我發現它在兩者中更方便——儘管script
也可以以大致相同的方式工作。
luit
可能已經安裝在您的系統上 - 它通常與 / 打包xterm
- 它是一個非常簡單的 cli 工具,旨在進行 UTF-8 翻譯*(該功能可能完全通過 cli 開關禁用,但我從來沒有找到理由這樣做)*對於不理解它的終端應用程序。它的工作原理是在目前 tty 層下將自己的 pty(它擁有主 fd)分層並將所有 i/o 從目前會話複製到其子層,在那裡它執行您請求的應用程序。因為它擁有主端,所以它可以輕鬆地複制它在其他地方讀取/寫入的所有 i/o,並且它提供了一種方便的方法來要求它這樣做:
luit -olog /dev/fd/2 sh -c 'read var; echo "$var"' eecchhoo tthhiiss vvaarr?????? echo this var??? echo this var???
如您所見,將所有終端輸入
luit
記錄到其命名-olog
文件中。在這種情況下,使用
/dev/fd/2
幾乎沒有那麼有用——因為所有的 i/o 都會在同一個地方結束兩次。我通常更喜歡打開第二個終端,使用tty
命令查詢其名稱,並將該/dev/pts/[0-9]
名稱用作luit
/script
的命名輸出文件 - 這會將所有 i/o 同時復製到兩個終端 - 所以我可以在一個終端上閱讀/查看它,並與之互動。tee
在大多數情況下可以用來做同樣的事情,但它通常沒有 pty 的 master 端推薦它的優勢。如果您的目的正如您所說的那樣 - 複製所有流程的輸入以供您查看 - 那麼您可能最好專注於輸入。
strace
對很多事情都很有用,但是如果您想獲得典型行為的準確報告,那麼有理由認為您應該在收集報告時盡可能少地修改該行為。換句話說,如果你想要輸入,複製輸入,不要插入一個調試父程序,它會-TRAP
在每次進行系統呼叫時暫停你的程序。