26551


以下の`diff <(ps -e) <(ps -e)`の実行結果を見ると、ひとつのコマンド呼び出し中のプロセス置換の実行順序は決まってないように思われます。

[code]

    $ diff <(ps -e) <(ps -e)
    $ diff <(ps -e) <(ps -e)
    232d231
    < 18157 pts/1    00:00:00 bash
    236d234
    < 18161 pts/1    00:00:00 ps
    $ diff <(ps -e) <(ps -e)
    232a233
    > 18163 pts/1    00:00:00 bash
    234a236
    > 18166 pts/1    00:00:00 ps
    
    <略>
    
    $ diff <(ps -e) <(ps -e)
    234c234
    < 20740 pts/1    00:00:00 bash
    ---
    > 20740 pts/1    00:00:00 bash <defunct>
    236d235
    < 20742 pts/1    00:00:00 ps
    
[/code]

プロセス置換を直列に実行させる、もしくは順序を定めて実行させる方法はありますか？


CC BY-SA 3.0
2016-06-07T11:13:30.970
26542
2016-06-08T23:09:56.390
13199
question
bash
プロセス置換の実行順序について


質問文にある結果を見る限り、実行順序の問題ではなく、マルチプロセス環境で複数プロセスをほぼ並行して実行したときのタイミングの問題ではないでしょうか。

直列に実行させるには、直列に実行することになるかと。

[code]

    $ ps -e > out1
    $ ps -e > out2
    $ diff out1 out2
    
[/code]


CC BY-SA 3.0
2016-06-07T16:12:24.487
26547
2016-06-07T16:12:24.487
4010
26542
answer


[process substition -
bash](https://www.gnu.org/software/bash/manual/html_node/Process-
Substitution.html) によれば、 process substitution は FIFO (ないし、 `/def/fd`)
でもって実装される想定だと記述されています。

FIFO は、基本的にその in と out を並列に走らせる想定の機構だと思っています。なので bash も、基本的には substitute
されるプロセスを親プロセスと並列で走らせる設計なのではないでしょうか。

もし、本気で 2つの(子)プロセスに関して直列に実行するなどの同期をとりたいのだとしたら、それは例えば `&`
で非同期実行した２つのプロセスの実行順序を制御したいのだ、という欲求に近いものになると思っています。(そしてそれをどう実装するのかを想像すると、多分子プロセス自体がお互いになんらかの同期処理を行わないといけないのだろうな、と想像しています)

それをやるんだったら、素直に一旦ファイルに吐き出した方がいいのでは、と思っています。


CC BY-SA 3.0
2016-06-07T17:37:39.623
26548
2016-06-07T17:48:09.557
2016-06-07T17:48:09.557
754
754
26542
answer


まぁ、Linux であれば `flock(1)` を使って `process substitution` の処理を直列に実行させる事は可能です。

**subst.sh**

[code]

    #!/bin/bash
    diff <(ps -e) <(ps -e)
    
    # Process trace
    $ strace -tt -e execve -f ./subst.sh 2>&1 | grep -E 'execve\("/bin/ps"|exited with 0'
    [pid 28373] 11:46:32.822097 execve("/bin/ps", ["ps", "-e"], [/* 64 vars */]) = 0
    [pid 28375] 11:46:32.830374 execve("/bin/ps", ["ps", "-e"], [/* 64 vars */]) = 0
    [pid 28373] 11:46:33.076616 +++ exited with 0 +++
    [pid 28375] 11:46:33.099348 +++ exited with 0 +++
    
[/code]

**subst_with_flock.sh**

[code]

    #!/bin/bash
    lock=$0
    diff <(flock "$lock" ps -e) <(flock "$lock" ps -e)
    
    # Process trace
    $ strace -tt -e execve -f ./subst_with_flock.sh 2>&1 | grep -E 'execve\("/bin/ps"|exited with 0'
    [pid 28404] 11:47:51.611734 execve("/bin/ps", ["ps", "-e"], [/* 64 vars */]) = 0
    [pid 28404] 11:47:51.791915 +++ exited with 0 +++
    [pid 28405] 11:47:51.796736 execve("/bin/ps", ["ps", "-e"], [/* 64 vars */]) = 0
    [pid 28405] 11:47:51.966822 +++ exited with 0 +++
    
[/code]

ただし、実行順序は不定です。

**date.sh**

[code]

    #!/bin/bash
    lock=$0
    cat <(flock "$lock" date +'1 %M:%S.%N') \
        <(flock "$lock" date +'2 %M:%S.%N') \
        <(flock "$lock" date +'3 %M:%S.%N') \
        <(flock "$lock" date +'4 %M:%S.%N') \
        <(flock "$lock" date +'5 %M:%S.%N')
    
    # Process trace
    $ strace -tt -e execve -f ./date.sh 2>&1 >trace | grep -E 'execve\("/bin/date"|exited with 0'
    [pid 30031] 12:37:12.780454 execve("/bin/date", ["date", "+4 %M:%S.%N"], [/* 64 vars */]) = 0
    [pid 30031] 12:37:12.793103 +++ exited with 0 +++
    [pid 30034] 12:37:12.798596 execve("/bin/date", ["date", "+3 %M:%S.%N"], [/* 64 vars */]) = 0
    [pid 30034] 12:37:12.803944 +++ exited with 0 +++
    [pid 30035] 12:37:12.811373 execve("/bin/date", ["date", "+2 %M:%S.%N"], [/* 64 vars */]) = 0
    [pid 30035] 12:37:12.819125 +++ exited with 0 +++
    [pid 30036] 12:37:12.824015 execve("/bin/date", ["date", "+5 %M:%S.%N"], [/* 64 vars */]) = 0
    [pid 30036] 12:37:12.831424 +++ exited with 0 +++
    [pid 30037] 12:37:12.836361 execve("/bin/date", ["date", "+1 %M:%S.%N"], [/* 64 vars */]) = 0
    [pid 30037] 12:37:12.842358 +++ exited with 0 +++
    
[/code]


CC BY-SA 3.0
2016-06-08T04:10:27.290
26551
2016-06-08T23:09:56.390
2016-06-08T23:09:56.390
26542
answer