Stdout

子程序的 stdbuf 假定行為

  • April 19, 2020

我在手冊頁中沒有完全找到關於以下內容的內容。子程序中的假定行為是如何由本身產生的程序產生的stdbuf

例如:

stdbuf -oL myprog

程式碼中,我知道它設置了LD_PRELOAD,據我所知,所有環境變數都是在任何子程序中繼承的。

我對這兩個fork();fork(); execv();子流程都感興趣。(不確定這是否會有所作為。)

fork();根本不應該改變行為。execv()將使用相同的LD_PRELOAD(以及也儲存在 env 中的 stdbuf 設置)並因此應用相同的行為(來自範例:stdout 是行緩衝的)。

對?

strace使用execve(with environ) 和write系統呼叫可以幫助了解發生了什麼:

這裡使用stdbufGNU 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… 應用程序)。

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