bashpingsigkilloutput-redirect

Bash: capture ping's intermediary statistics on SIGQUIT to variable


I have this:

 ping -q xxx.xxx.xxx.xxx & disown; pingpid=$!
 for run in {1..3}; do
 sleep 5
 stats+=$(kill -SIGQUIT $pingpid)
 done
 kill $pingpid

So basically I launch ping in background with -q option (to show just stats), get its PID and then execute a for loop in which I want to store the intermediary stats of ping on each kill -SIGQUIT $pingpid in a variable... that's 3 lines of stats, 5 seconds apart.

I can see the intermediary stats being printed to stdout but when I check the $stats variable, I find it empty. I also tried with stderr redirection to stdout but I still can't get the variable to have the stats stored in it.


Solution

  • The output that you're trying to capture is coming from the ping process (on its standard error to be precise), not the kill process. You need to capture its output with a redirection when you launch it. Try this:

    stats=""
    {
            read pingpid
            for run in {1..3}; do
                    sleep 5
                    kill -quit $pingpid
                    read line
                    stats+="$line"$'\n'
            done
    } < <(ping -q xx.xx.xx.xx 2>&1 >/dev/null & echo $!)
    
    kill $pingpid
    stats=${stats%$'\n'}  # Remove the extra newline
    echo "$stats"
    

    The ordering of the redirection in the ping command, 2>&1 >/dev/null, redirects standard out to /dev/null while standard error is redirected to the input of the loop.