Stdout
子程序的 stdbuf 假定行為
我在手冊頁中沒有完全找到關於以下內容的內容。子程序中的假定行為是如何由本身產生的程序產生的
stdbuf
?例如:
stdbuf -oL myprog
從程式碼中,我知道它設置了
LD_PRELOAD
,據我所知,所有環境變數都是在任何子程序中繼承的。我對這兩個
fork();
和fork(); execv();
子流程都感興趣。(不確定這是否會有所作為。)
fork();
根本不應該改變行為。execv()
將使用相同的LD_PRELOAD
(以及也儲存在 env 中的 stdbuf 設置)並因此應用相同的行為(來自範例:stdout 是行緩衝的)。對?
strace
使用execve
(with environ) 和write
系統呼叫可以幫助了解發生了什麼:這裡使用
stdbuf
GNU coreutils 8.25。我相信 FreeBSD 的stdbuf
工作方式類似:exec 並且沒有分叉:
$ env -i strace -s200 -vfe execve,write /usr/bin/stdbuf -o0 /usr/bin/env /usr/bin/env > /dev/null execve("/usr/bin/stdbuf", ["/usr/bin/stdbuf", "-o0", "/usr/bin/env", "/usr/bin/env"], []) = 0 execve("/usr/bin/env", ["/usr/bin/env", "/usr/bin/env"], ["_STDBUF_O=0", "LD_PRELOAD=/usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so"]) = 0 execve("/usr/bin/env", ["/usr/bin/env"], ["_STDBUF_O=0", "LD_PRELOAD=/usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so"]) = 0 write(1, "_STDBUF_O=0\n", 12) = 12 write(1, "LD_PRELOAD=/usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so\n", 60) = 60 +++ exited with 0 +++
LD_PRELOAD
並將配置_STDBUF_O
傳遞給兩個env
命令。write()
即使輸出沒有到達終端,這兩個系統呼叫也會確認輸出沒有被緩衝。分叉和執行:
$ env -i strace -s200 -vfe execve,write /usr/bin/stdbuf -o0 /bin/sh -c '/usr/bin/env; :' > /dev/null execve("/usr/bin/stdbuf", ["/usr/bin/stdbuf", "-o0", "/bin/sh", "-c", "/usr/bin/env; :"], []) = 0 execve("/bin/sh", ["/bin/sh", "-c", "/usr/bin/env; :"], ["_STDBUF_O=0", "LD_PRELOAD=/usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so"]) = 0 Process 16809 attached [pid 16809] execve("/usr/bin/env", ["/usr/bin/env"], ["_STDBUF_O=0", "LD_PRELOAD=/usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so", "PWD=/home/stephane"]) = 0 [pid 16809] write(1, "_STDBUF_O=0\n", 12) = 12 [pid 16809] write(1, "LD_PRELOAD=/usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so\n", 60) = 60 [pid 16809] write(1, "PWD=/home/stephane\n", 19) = 19 [pid 16809] +++ exited with 0 +++ --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED,
同樣的情況。
所以是
stdbuf
的,適用於它執行的命令及其所有後代(前提是它們不像動態連結器或 libc 那樣清理環境,LD_PRELOAD
用於 setuid/setgid… 應用程序)。