15

I'm trying to write a simple script to monitor my network status, without all of ping's output:

ping -q -c 1 google.com > /dev/null && echo online || echo offline

The problem is that when I'm not connected, I'm still getting an error message in my output:

ping: unknown host google.com
offline

How can I keep this error message out of my output?

Braiam
  • 35,991
operalala
  • 371

3 Answers3

28

When you run:

ping -q -c 1 google.com > /dev/null && echo online || echo offline

You are essentially only redirecting the output of Stream 1 (i.e. stdout) to /dev/null.

This is fine when you want to redirect the output that is produced by the normal execution of a program. However, in case you also wish to redirect the output caused by all the errors, warnings or failures, you should also redirect the stderr or Standard Error stream to /dev/null.

One way of doing this is prepending the number of the stream you wish to redirect to the redirection operator, > like this: Command 2> /dev/null

Hence, your command would look like:

ping -q -c 1 google.com > /dev/null 2> /dev/null && echo online || echo offline

But, notice that we have already redirected one stream to /dev/null. Why not simply piggyback on the same redirection? Bash allows us to do this by specifying the stream number to which to redirect to. 2>&1.

Notice the & character after the redirection operator. This tells the shell that what appears next is not a filename, but an identifier for the output stream.

ping -q -c 1 google.com > /dev/null 2>&1  echo online || echo offline

Be careful with the redirection operators, their order matters a lot. If you were to redirect in the wrong order, you'll end up with unexpected results.

Another way in which you can attain complete silence is by redirecting all output streams to /dev/null using this shortcut: &>/dev/null (or redirect to a log file with &>/path/to/file.log).

Hence, write your command as:

ping -q -c 1 google.com &> /dev/null && echo online || echo offline
crisron
  • 499
darnir
  • 4,489
9

You need to redirect both standard output (> or 1>) and standard error (2>):

ping -q -c 1 google.com > /dev/null 2>/dev/null && echo online || echo offline

or, redirect one to the other:

ping -q -c 1 google.com > /dev/null 2>&1 && echo online || echo offline
terdon
  • 242,166
8
$ ping -q -c 1 google.com > /dev/null 2>&1 && echo online || echo offline

Examples

$ ping -q -c 1 google.com > /dev/null 2>&1 && echo online || echo offline
online

$ ping -q -c 1 googleadf.com > /dev/null 2>&1 && echo online || echo offline
offline

Speeding up ping

Depending on your ping implementation you may be limited to a single count -c 1. Some implementations will let you go below this, but you're essentially having to wait for bad lookups to timeout. So instead of using ping you might want to use fing instead.

slowness of ping failing

$ date; ping -q -c 1 google.com > /dev/null 2>&1 && echo online || echo offline; date
Tue Jan 28 13:51:10 EST 2014
online
Tue Jan 28 13:51:10 EST 2014

$ date; ping -q -c 1 googleadf.com > /dev/null 2>&1 && echo online || echo offline; date
Tue Jan 28 13:51:15 EST 2014
offline
Tue Jan 28 13:51:25 EST 2014

fing is much faster to fail

$ date; fing -p google.com > /dev/null 2>&1 && echo online || echo offline; date
Tue Jan 28 13:49:21 EST 2014
online
Tue Jan 28 13:49:22 EST 2014

$ date; fing -p googleadf.com > /dev/null 2>&1 && echo online || echo offline; date
Tue Jan 28 13:49:35 EST 2014
online
Tue Jan 28 13:49:38 EST 2014
slm
  • 369,824
  • 1
    I'd rather use time command than manually computing time difference with date: time { fing -p googleadf.com > /dev/null 2>&1 && echo online || echo offline; } – Ruslan Jan 29 '14 at 11:44
  • @Ruslan - thanks, I did it this way b/c I wanted the output of date. It's easier, IMO, for someone else to read the output generated. – slm Jan 29 '14 at 13:22