stdbuf サブプロセスの仮定動作

stdbuf サブプロセスの仮定動作

次の項目について正確に何も見つかりませんでした。マニュアルページ。子プロセスで想定される動作が生成されたプロセス自体でどのように発生するかstdbuf

たとえば、

stdbuf -oL myprog

~からパスワード、私はそれが設定されていることを知っていますLD_PRELOAD、私が知っている限り、すべての環境変数はすべての子プロセスから継承されます。

fork();私とサブプロセスの両方に興味がありますfork(); execv();。 (これが変化をもたらすかどうかはわかりません。)

fork();行動がまったく変わってはいけません。execv()同じものLD_PRELOAD(そしてenvに保存されているstdbuf設定)が使用されるため、同じ動作が適用されます(たとえば、stdoutはラインバッファリングされています)。

正しいですか?

答え1

strace(環境を使用execve)とwriteシステムコールは何が起こっているのかを理解するのに役立ちます。

ここではstdbufGNU coreutils 8.25が使用されます。私はFreeBSDが同様に動作すると信じていますstdbuf

フォークなしで実行:

$ 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に渡されますenvwrite()出力が端末に送信されない場合でも、これら2つのシステムコールは出力がバッファリングされていないことを確認します。

フォークと実行:

$ 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,

同じ状況。

したがって、yesは実行されるコマンドとすべての子に適用されます(動的リンカーまたはlibcがsetuid / setgid ...アプリケーションに対して実行するように環境をクリーンアップしない場合stdbuf)。LD_PRELOAD

答え2

timeout次のテストコードに示すように、バッファリングはfork / execを介して継承されます。

bash-4.1$ cat isbuffed.c 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
    printf("should not appear if buffered");
    sleep(999);
    exit(EXIT_SUCCESS);
}
bash-4.1$ make isbuffed
cc     isbuffed.c   -o isbuffed
bash-4.1$ timeout 3 ./isbuffed
bash-4.1$ stdbuf -o0 timeout 3 ./isbuffed
should not appear if bufferedbash-4.1$ 

関連情報