3
> 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
> 

Question: why doesn this script runs for at least 3 seconds?

There is a "sleep 1" in the first function and it should be called 3 times in the second function.

According to the "real 0m1.026s" it seems that the sleep is only executed once. Or if it is parallel (??) then how can I make it linear?

  • As I can see first is called 3 times, as expected. – ctrl-alt-delor Apr 14 '17 at 19:49
3

The parts of a pipeline are started (close to) simultaneously.

All three invocations of second will start at the same time. The three subshells that this gives rise to will invoke first to expand "$(first)" and the three sleep 1 calls will happen concurrently (you can see in the trace output that they do happen).

It's only the I/O that serializes a pipeline, i.e. one process in the pipeline waiting for input from the previous, or waiting to have its output read by the next.

To have the bits of the pipeline start, run and exit in sequence:

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

That is, run them separatedly and store the intermediate results in files.

  • wow, Thanks!, but how can I make it linear instead of concurrent? I don't understand how could it be concurrent if it is a pipe that should listen to the input and when it gets the input it can run, strange – pepite Apr 14 '17 at 20:31
  • @pepite But the point is, it doesn't listen for input when the shell is running the first function. In fact, at that point, the associated openssl command hasn't even been started yet. – Kusalananda Apr 14 '17 at 20:37
  • @pepite: A UNIX (or, for that matter, also Windows) pipeline works by starting up both ends concurrently and connecting the output of the left-hand end to the input of the right-hand end. If you write program1 | program2 | program3 all the three programs start concurrently and work in parallel, with program2 reading its input from the output of program1 (and of course waiting if necessary for program1 to produce some output) and program3 reading its input from the output of program2 (and of course waiting if necessary for program2 to produce some output). – AlexP Apr 14 '17 at 21:26
  • any other solution to avoid disk write? Thanks! – pepite Apr 15 '17 at 9:38
  • @pepite You could try something like echo nyi | { sleep 1; second } | { sleep 2; second } | { sleep 3; second }. – Kusalananda Apr 15 '17 at 16:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.