Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save sagespidy/d260115b7779bda617c7ffd71b5ff7a7 to your computer and use it in GitHub Desktop.
Save sagespidy/d260115b7779bda617c7ffd71b5ff7a7 to your computer and use it in GitHub Desktop.

A shebang/hashbang is the first line of an executable script that starts with #!.

Example for an executable shell script:

#!/bin/sh

And here is what I propose to use instead:

#!/usr/bin/env time bash -ex

Why?

The advantages of this approach:

  1. Using bash instead of sh makes your script not POSIX-compliant. However, if you anyway use any of nice bash features, for example [[ instead of [, it ensures that your script would still work on systems which have some other shell as default, such as Ubuntu.

  2. Setting -ex flags ensures that script will exit on error and all executed commands will be printed to stderr.

  3. The most interesting part: prefixing bash invocation by time command.

    Some shell scripts take long time to complete, especially those related to processing large data files. When they are finished, it is always interesting to see how long time did they take to run. But before launching them it easy to forget to prepend the time command to the script invocation.

    When it is in the script itself, its execution time would always be measured.

How?

It can be illustrated using a single script named test.sh

#!/usr/bin/env time bash -ex                                                                                                                  
                                                                                                                                              
sleep 1                                                                                                                                       
false                                                                                                                                         
echo "this place should never be reached"                                                                                                               

As usually, it has to be made executable at first:

chmod +x test.sh

and then it can be launched:

$ ./test.sh 
+ sleep 1
+ false
        1.00 real         0.00 user         0.00 sys

The commands and elapsed time are printed, the code after command that returned non-zero exit code was not executed.

It is easy to check that both commands and time are printed to stderr, so they would not interfere with pipes:

$ ./test.sh 2>/dev/null

prints nothing.

And?

If you like the benefits listed above, you can set #!/usr/bin/env time bash -ex as a template for new files with .sh extension.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment