shellstdincapture

Make sh Commands Stream to Capture Stdin


Having script.sh

#!/bin/sh
sh <<EOF
cat | xargs -n 1 echo captured
echo first
echo second
EOF

Running this would output

captured echo
captured first
captured echo
captured second

So that the second and the third (echo) commands were not executed but instead the cat just captures and exhausts all the upcoming commands stream and puts down to its pipe

Besides calling

echo input | script.sh

would have the very same effect.

Having the very same three commands as a plain script file script-plain.sh

#!/bin/sh
cat | xargs -n 1 echo captured
echo first
echo second

would behave differently and

echo input | script.sh

would output

input
first
second

So how to achieve having streaming pipeline e.g.

curl some-streaming-endpoint

that outputs continuously something like

echo ping 1
cat
echo ping 2
echo ping 3
....
echo ping n

the behavior of executing them as a plain script and the subject commands to capture the shell stdin it self (if any) instead of commands source one

so that how to make a script executor.sh similar to

#!/bin/sh
curl some-streaming-endpoint | sh

that with the invocation like

echo "data 1\n$data 2" | ./executor.sh

would produce the output

ping 1
data 1
data 2
ping 2
ping 3
...
ping n

P.S. without temporary piping command into a file i.e.

curl some-source > ~/tmp/source.sh
~/tmp/source.sh

since a stream might be continuous


Solution

  • It's not entirely clear what you intend.

    If you have bash, perhaps:

    #!/bin/bash
    sh <(curl url)
    

    Otherwise, you could make a fifo by hand:

    #!/bin/sh
    mkfifo input
    curl url >input &
    sh input
    wait
    rm input