関数内の関数は、要求された場合に複数回呼び出されませんか?

関数内の関数は、要求された場合に複数回呼び出されませんか?
> cat b.txt 
function first
    {
    sleep 1
    echo $(echo $$)
    }

function second
    {
    openssl enc -aes-256-cbc -k "$(first)"
    }

echo nyi | second | second | second
> 
> time sh -x b.txt 
+ echo nyi
+ second
+ second
+ second
++ first
++ sleep 1
++ first
++ sleep 1
++ first
++ sleep 1
+++ echo 32383
+++ echo 32383
++ echo 32383
++ echo 32383
+ openssl enc -aes-256-cbc -k 32383
+++ echo 32383
+ openssl enc -aes-256-cbc -k 32383
++ echo 32383
+ openssl enc -aes-256-cbc -k 32383
ɚ��2;��<�Vp��H�����F�q�AHO��Sܽd��d4��X��#}
real    0m1.026s
user    0m0.016s
sys 0m0.025s
> 

質問: このスクリプトが少なくとも 3 秒間実行されないのはなぜですか?

最初の関数には「sleep 1」があり、2 番目の関数では 3 回呼び出される必要があります。

「実際の 0m1.026s」によると、スリープは 1 回だけ実行されるようです。または、並列 (??) の場合、どうすれば線形にできますか?

答え1

パイプラインの各部分はほぼ同時に開始されます。

の3つの呼び出しはsecondすべて同時に開始されます。これにより発生する3つのサブシェルはfirst展開を呼び出し"$(first)"、3つのsleep 1呼び出しは同時に発生します(トレース出力で確認できます)。する起こる)。

パイプラインをシリアル化するのは I/O だけです。つまり、パイプライン内の 1 つのプロセスが前のプロセスからの入力を待機するか、次のプロセスによって出力が読み取られるのを待機します。

パイプラインのビットを順番に開始、実行、終了するには、次のようにします。

echo nyi | second >out1
second <out1 >out2
second <out2

つまり、それらを個別に実行し、中間結果をファイルに保存します。

関連情報