通过在 bash 脚本中使用 ping 检查主机可用性

我想写一个脚本,这将不断检查,如果任何设备在网络上,这应该是在线一整天,是真的在线。我试过用 ping 但是

if [ "`ping -c 1 some_ip_here`" ]
then
echo 1
else
echo 0
fi

1无论我输入有效或无效的 IP 地址。如何检查某个特定地址(或 IP 地址列表中的任何设备)是否脱机?

328321 次浏览

Ping returns different exit codes depending on the type of error.

ping 256.256.256.256 ; echo $?
# 68


ping -c 1 127.0.0.1 ; echo $?
# 0


ping -c 1 192.168.1.5 ; echo $?
# 2

0 means host reachable

2 means unreachable

You don't need the backticks in the if statement. You can use this check

if ping -c 1 some_ip_here &> /dev/null
then
echo 1
else
echo 0
fi

The if command checks the exit code of the following command (the ping). If the exit code is zero (which means that the command exited successfully) the then block will be executed. If it return a non-zero exit code, then the else block will be executed.

There is advanced version of ping - "fping", which gives possibility to define the timeout in milliseconds.

#!/bin/bash
IP='192.168.1.1'
fping -c1 -t300 $IP 2>/dev/null 1>/dev/null
if [ "$?" = 0 ]
then
echo "Host found"
else
echo "Host not found"
fi

FYI, I just did some test using the method above and if we use multi ping (10 requests)

ping -c10 8.8.8.8 &> /dev/null ; echo $?

the result of multi ping command will be "0" if at least one of ping result reachable, and "1" in case where all ping requests are unreachable.

I can think of a one liner like this to run

ping -c 1 127.0.0.1 &> /dev/null && echo success || echo fail

Replace 127.0.0.1 with IP or hostname, replace echo commands with what needs to be done in either case.

Code above will succeed, maybe try with an IP or hostname you know that is not accessible.

Like this:

ping -c 1 google.com &> /dev/null && echo success || echo fail

and this

ping -c 1 lolcatz.ninja &> /dev/null && echo success || echo fail
up=`fping -r 1 $1 `
if [ -z "${up}" ]; then
printf "Host $1 not responding to ping   \n"
else
printf "Host $1 responding to ping  \n"
fi

This seems to work moderately well in a terminal emulator window. It loops until there's a connection then stops.

#!/bin/bash


# ping in a loop until the net is up


declare -i s=0
declare -i m=0
while ! ping -c1 -w2 8.8.8.8 &> /dev/null ;
do
echo "down" $m:$s
sleep 10
s=s+10
if test $s -ge 60; then
s=0
m=m+1;
fi
done
echo -e "--------->>  UP! (connect a speaker) <<--------" \\a

The \a at the end is trying to get a bel char on connect. I've been trying to do this in LXDE/lxpanel but everything halts until I have a network connection again. Having a time started out as a progress indicator because if you look at a window with just "down" on every line you can't even tell it's moving.

for i in `cat Hostlist`
do
ping -c1 -w2 $i | grep "PING" | awk '{print $2,$3}'
done

I liked the idea of checking a list like:

for i in `cat Hostlist`
do
ping -c1 -w2 $i | grep "PING" | awk '{print $2,$3}'
done

but that snippet doesn't care if a host is unreachable, so is not a great answer IMHO.

I ran with it and wrote

for i in `cat Hostlist`
do
ping -c1 -w2 $i >/dev/null 2>&1 ; echo $i $?
done

And I can then handle each accordingly.

This is a complete bash script which pings target every 5 seconds and logs errors to a file.

Enjoy!

#!/bin/bash
        

FILE=errors.txt
TARGET=192.168.0.1


touch $FILE
while true;
do
DATE=$(date '+%d/%m/%Y %H:%M:%S')
ping -c 1 $TARGET &> /dev/null
if [[ $? -ne 0 ]]; then
echo "ERROR "$DATE
echo $DATE >> $FILE
else
echo "OK "$DATE
fi
sleep 5
done

check host every one second and send message when host is reach

while :;do ping -c 1 -w 1 -q 8.8.8.8 &>/dev/null && /root/telegram-send.sh "Host reacheble now" && break || sleep 1;done