シェルスクリプトでfor文のコマンド出力をパイプでつないだ時のコマンド実行順序


以下シェルスクリプトがあるとします。

[code]

    for i in `seq 5`
    do
      echo ${i} # cmd1
    done | cat # cmd2
    
[/code]

このとき、パイプでつながれたcatコマンドはforのループが終了してから起動されるのでしょうか？  
それとも、ループと並行して起動し、echoの出力が都度送り込まれるような動きになるのでしょうか？




スクリプト名を `test.sh` として、strace コマンドで処理を追跡してみます。これを見て考えてみて下さい。

[code]

    $ strace -tt -f -e dup2,execve,write ./test.sh
    17:59:49.438629 execve("./test.sh", ["./test.sh"], 0x7ffddf147b30 /* 81 vars */) = 0
    17:59:49.440768 dup2(3, 255)            = 255
    strace: Process 145782 attached
    strace: Process 145783 attached
    [pid 145783] 17:59:49.441452 dup2(3, 0) = 0
    [pid 145782] 17:59:49.441493 dup2(4, 1) = 1
    strace: Process 145784 attached
    [pid 145784] 17:59:49.441858 dup2(4, 1) = 1
    [pid 145783] 17:59:49.442112 execve("/usr/bin/cat", ["cat"], 0x560ddec53970 /* 81 vars */) = 0
    [pid 145784] 17:59:49.442490 execve("/usr/bin/seq", ["seq", "5"], 0x560ddec53970 /* 81 vars */) = 0
    [pid 145784] 17:59:49.443350 write(1, "1\n2\n3\n4\n5\n", 10) = 10
    [pid 145784] 17:59:49.443487 +++ exited with 0 +++
    [pid 145782] 17:59:49.443526 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=145784, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
    [pid 145782] 17:59:49.443638 write(1, "1\n", 2) = 2
    [pid 145783] 17:59:49.443667 write(1, "1\n", 21
     <unfinished ...>
    [pid 145782] 17:59:49.443684 write(1, "2\n", 2 <unfinished ...>
    [pid 145783] 17:59:49.443701 <... write resumed>) = 2
    [pid 145782] 17:59:49.443709 <... write resumed>) = 2
    [pid 145782] 17:59:49.443729 write(1, "3\n", 2 <unfinished ...>
    [pid 145783] 17:59:49.443742 write(1, "2\n", 22
     <unfinished ...>
    [pid 145782] 17:59:49.443754 <... write resumed>) = 2
    [pid 145783] 17:59:49.443775 <... write resumed>) = 2
    [pid 145782] 17:59:49.443808 write(1, "4\n", 2) = 2
    [pid 145782] 17:59:49.443870 write(1, "5\n", 2 <unfinished ...>
    [pid 145783] 17:59:49.443891 write(1, "3\n4\n", 4 <unfinished ...>
    3
    4
    [pid 145782] 17:59:49.443902 <... write resumed>) = 2
    [pid 145783] 17:59:49.443911 <... write resumed>) = 4
    [pid 145783] 17:59:49.443937 write(1, "5\n", 25
    ) = 2
    [pid 145782] 17:59:49.444017 +++ exited with 0 +++
    [pid 145783] 17:59:49.444158 +++ exited with 0 +++
    17:59:49.444622 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=145782, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
    17:59:49.444817 +++ exited with 0 +++
    
[/code]




スクリプト名を `test.sh` として、strace コマンドで処理を追跡してみます。これを見て考えてみて下さい。

[code]

    $ strace -tt -f -e dup2,execve,write ./test.sh
    17:59:49.438629 execve("./test.sh", ["./test.sh"], 0x7ffddf147b30 /* 81 vars */) = 0
    17:59:49.440768 dup2(3, 255)            = 255
    strace: Process 145782 attached
    strace: Process 145783 attached
    [pid 145783] 17:59:49.441452 dup2(3, 0) = 0
    [pid 145782] 17:59:49.441493 dup2(4, 1) = 1
    strace: Process 145784 attached
    [pid 145784] 17:59:49.441858 dup2(4, 1) = 1
    [pid 145783] 17:59:49.442112 execve("/usr/bin/cat", ["cat"], 0x560ddec53970 /* 81 vars */) = 0
    [pid 145784] 17:59:49.442490 execve("/usr/bin/seq", ["seq", "5"], 0x560ddec53970 /* 81 vars */) = 0
    [pid 145784] 17:59:49.443350 write(1, "1\n2\n3\n4\n5\n", 10) = 10
    [pid 145784] 17:59:49.443487 +++ exited with 0 +++
    [pid 145782] 17:59:49.443526 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=145784, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
    [pid 145782] 17:59:49.443638 write(1, "1\n", 2) = 2
    [pid 145783] 17:59:49.443667 write(1, "1\n", 21
     <unfinished ...>
    [pid 145782] 17:59:49.443684 write(1, "2\n", 2 <unfinished ...>
    [pid 145783] 17:59:49.443701 <... write resumed>) = 2
    [pid 145782] 17:59:49.443709 <... write resumed>) = 2
    [pid 145782] 17:59:49.443729 write(1, "3\n", 2 <unfinished ...>
    [pid 145783] 17:59:49.443742 write(1, "2\n", 22
     <unfinished ...>
    [pid 145782] 17:59:49.443754 <... write resumed>) = 2
    [pid 145783] 17:59:49.443775 <... write resumed>) = 2
    [pid 145782] 17:59:49.443808 write(1, "4\n", 2) = 2
    [pid 145782] 17:59:49.443870 write(1, "5\n", 2 <unfinished ...>
    [pid 145783] 17:59:49.443891 write(1, "3\n4\n", 4 <unfinished ...>
    3
    4
    [pid 145782] 17:59:49.443902 <... write resumed>) = 2
    [pid 145783] 17:59:49.443911 <... write resumed>) = 4
    [pid 145783] 17:59:49.443937 write(1, "5\n", 25
    ) = 2
    [pid 145782] 17:59:49.444017 +++ exited with 0 +++
    [pid 145783] 17:59:49.444158 +++ exited with 0 +++
    17:59:49.444622 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=145782, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
    17:59:49.444817 +++ exited with 0 +++
    
[/code]

