bash

What is the best practice to redirect all original (only) stderr outputs to /dev/null in a bash function?


Is there any best practice to:

  1. Not have to follow each command with 2> /dev/null
  2. Not lose own >&2 outputs of the function
  3. Have a simple flag allowing to temporarily disable (1) above, or to custom collect it in e.g. logfile

IMPORTANT Only the ORIGINAL stderr output is meant to be suppressed/redirected, NOT ALL.

It is quite tedious to be redirecting every single command's error output to /dev/null, it is much easier to redirect a { ...; } block, or a function. But it's impossible then to have that function produce own >&2 outputs - unless sent to stdout instead, which is undesirable.

Example:

func() {
    ping 1.1.1.1 2>/dev/null || echo "DNS unreachable." >&2

    [[ -n $GVAR ]] || echo "Environment not set." >&2

    stat /tmp/a_secret_file 2>/dev/null || echo "Cannot stat secret file." >&2
}

Whatever produced by ping and stat should be suppressed, but own echo messages shown.


Solution

  • You can redirect the whole function, but use a different file handle for its "own" standard error.

    An example:

    #!/bin/bash
    func() {
        ping 1.1.1.1 || echo DNS unreachable >&3
        ...
    } 3>&2 2>/dev/null
    
    func
    

    To change the behaviour, you can have two different functions wrapping the actual one with different redirections:

    #!/bin/bash
    func() {
        echo This goes nowhere >&2
        echo This goes to stderr >&3
    }
    
    f1 () {
        func
    } 3>&2 2>/dev/null
    
    f2 () {
        func
    } 3>&2
    
    echo f1
    f1
    
    echo f2
    f2  # The message "This goes nowhere" appears on stderr.