Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

terminate a shell script without waiting for early parts of pipeline

Tags:

bash

pipe

Consider the following script:

#!/bin/bash
function long_running {
    for i in $(seq 1 10); do
        echo foo
        sleep 100
    done
}

long_running | head -n 1

This produces the expected output (one line "foo") but sleeps (for the specified 100 seconds) before terminating. I would like the script to terminate immediately when head does. How can I force bash to actually quit immediately? Even changing the last line to

long_running | (head -n 1; exit)

or similar doesn't work; I can't get set -e, another common suggestion, to work even if I force a failure with, say, (head -n 1; false) or the like.

(This is a simplified version of my real code (obviously) which doesn't sleep; just creates a fairly complex set of nested pipelines searching for various solutions to a constraint problem; as I only need one and don't care which I get, I'd like to be able to make the script terminate by adding head -n 1 to the invocation...)

like image 925
Andrew H. Hunter Avatar asked Dec 24 '11 23:12

Andrew H. Hunter


People also ask

How do you terminate a shell script?

To end a shell script and set its exit status, use the exit command. Give exit the exit status that your script should have. If it has no explicit status, it will exit with the status of the last command run.

How do you exit a pipe pipe quote?

How to escape quotes and pipe? Capturing the output of the command (using backquotes) and then echo ing that is an antipattern. Just run the command directly, and let its output go to the usual place.

How do you exit a script if command fails?

Exit When Any Command Fails This can actually be done with a single line using the set builtin command with the -e option. Putting this at the top of a bash script will cause the script to exit if any commands return a non-zero exit code.

What is bash Pipestatus?

The PIPESTATUS environment variable in Bash comes to our rescue for getting the exit status of each command in a pipeline. $ PIPESTATUS is an array. It stores the exit status of each command in the pipeline: $ hello_world.sh 5 | grep "Hello World" | grep "Hello Universe" $ echo ${PIPESTATUS[@]} 5 0 1.


1 Answers

How about sending the function to head like this -

#!/bin/bash
function long_running {
    for i in $(seq 1 10); do
        echo foo
        sleep 100
    done
}

head -n 1 <(long_running)

Obviously if you will increase the -n to a greater number, the sleep would kick in but would exit once head is completed.

like image 166
jaypal singh Avatar answered Oct 22 '22 20:10

jaypal singh