bash to automate input file daily + ping test - bash

I'm running a ping test for 100 IP's daily, every day the input file IP will get updated becauses its dynamic. And I'm specifying input(100 IP list) as first argument. As the below script will ran for every 10 mins
Note:- I'm using different IP's everyday, so need to change the input file every day at 12AM
Running script as background at Apr 1 at 12AM
sh ping.sh IPlist_apr1.txt &
on second day my secondary script(which will create updated IP's) will choose other set of IP's in this file format 'IPlist_apr2.txt'
On third day - IPlist_apr3.txt ... and it will log $1.log every day on the CWD.
likewise this process continue, What I'm actually looking my ping script should handle the list day by day as first argument.
Snippet of my actual script.
t=10m
ip=$1 #### specify the file having IP's
while sleep $t
do
if ping -c1 $ip >/dev/null 2>&1; then
echo "`date +%H:%M`: $ip is up";
else
echo "`date +%H:%M`: $ip is down";
fi >>$1.log;
done

You need to read the IP addresses from the file named by the argument.
while IFS= read -r ipaddr; do
if ping -c1 "$ipaddr"; then
status=up
else
status=down
fi
printf '%s: %s is %s\n' "$(date +%H:%M)" "$ipaddr" "$status"
done < "$1"
Note that this runs one batch of pings, then exits. The caller should be responsible for sleeping 10 minutes and specifying the correct file name for the input.

Related

Creating a shell script to check network connectivity

I'm making a simple shell script that runs an infinite loop, then if the output of the ping command contains "time" (indicating that it pinged successfully) it should echo "Connected!", sleep 1, and clear. However, I get no output from my script.
#!/bin/bash
while :
do
if [[ $(ping google.com) == *time* ]];
then
echo -en '\E[47;32m'"\033[1mS\033[0m"
echo "Connected!"
else
echo -en '\E[47;31m'"\033[1mZ\033[0m"
echo "Not Connected!"
fi
clear
sleep 1
done
Your script is not giving output because ping never terminates. To get ping to test your connectivity, you'll want to give it a run count (-c) and a response timeout (-W), and then check its return code:
#!/bin/bash
while true
do
if ping -c 1 -W 5 google.com 1>/dev/null 2>&1
then
echo "Connected!"
break
else
echo "Not Connected!"
sleep 1
fi
done
ping will return 0 if it is able to ping the given hostname successfully, and nonzero otherwise.
It's also worth noting that an iteration of this loop will run for a different period of time depending on whether ping succeeds quickly or fails, for example due to no network connection. You may want to keep the iterations to a constant length of time -- like 15 seconds -- using time and sleep.

Network monitoring ping

i am reading from a txt file several hundred ip addresses, want to ping the list to the end of the file. would like this to run in a loop instead, read to the end of the file, then start at the first address again.
trap 'echo ****Interrupted****; exit'INT
echo -n "Enter the file name with the ip addresses"
read file
echo -n "Enter the file name for the log file"
read log
while read line
do
echo "pinging: "$line
echo -e "">>$log
echo -n "NEXT PING: ">>$log
echo -n "$line" : " >>$log
$ping -c 3 -W 2 $line >>$log
done <"$file"
Use fping.
http://fping.org/
From the fping man page:
DESCRIPTION
fping is a program like ping(8) which uses the Internet Control Message
Protocol (ICMP) echo request to determine if a target host is responding.
fping differs from ping in that you can specify any number of targets on the
command line, or specify a file containing the lists of targets to ping.
Instead of sending to one target until it times out or replies, fping will
send out a ping packet and move on to the next target in a round-robin
fashion.

bash. while loop with xargs kill -9

I have a list of IP addresses and I have to run a command for every single IP address.
I did it with this code:
array=($(</tmp/ip-addresses.txt))
for i in "${array[#]}"; do
./command start $i &
done
Now, the list of IP addresses is constantly refreshed every 2 minutes and I need to kill every command that is no longer with the new IP addresses.
Practically, the command needs to be executed again every 2 minutes with the refreshed IP addresses and all the another old IP needs to be killed.
How can I do that?
A simple workaround: (Not tested)
sleep_delay=120 # 2 mins
while true; do
(
array=($(</tmp/ip-addresses.txt))
for i in "${array[#]}"; do
./command start $i &
done
sleep $(( sleep_delay + 2 )) # 2 can be any number >0
) & PPID=$!
sleep $sleep_delay
pkill -9 -p $PPID
done
Note: I have not optimized your code, just added a wrapper around your code.
EDIT:
Edited code to satisfy requirement that the old processes should not be killed, if the IP is still same.
NOTE: I haven't tested the code myself, so be careful while using the kill command. You can test by putting echo before the kill statement. If it works well, you can use the script...
declare -A pid_array
while true; do
array=($(</tmp/ip-addresses.txt))
for i in `printf "%s\n" ${!pid_array[#]} | grep -v -f <(printf "%s\n" ${array[#]})`; do
kill -9 ${pid_array[$i]} # please try to use better signal to kill, than SIGKILL
unset pid_array[$i]
done
for i in "${array[#]}"; do
if [ -z "${pid_array[$i]}" ]; then
./command start $i & pid_array[$i]=$!
fi
done
sleep 120
done
Your script would be changed like:
#!/bin/bash
GAP=120
while :
do
#Do your stuff here
sleep $GAP
done
exit 0
After two minutes it would read from refreshed file

Modify shell script to monitor/ping multiple ip addresses

Alright so I need to constantly monitor multiple routers and computers, to make sure they remain online. I have found a great script here that will notify me via growl(so i can get instant notifications on my phone) if a single ip cannot be pinged. I have been attempting to modify the script to ping multiple addresses, with little luck. I'm having trouble trying to figure out how to ping a down server while the script keeps watching the online servers. any help would be greatly appreciated. I haven't done much shell scripting so this is quite new to me.
Thanks
#!/bin/sh
#Growl my Router alive!
#2010 by zionthelion73 [at] gmail . com
#use it for free
#redistribute or modify but keep these comments
#not for commercial purposes
iconpath="/path/to/router/icon/file/internet.png"
# path must be absolute or in "./path" form but relative to growlnotify position
# document icon is used, not document content
# Put the IP address of your router here
localip=192.168.1.1
clear
echo 'Router avaiability notification with Growl'
#variable
avaiable=false
com="################"
#comment prefix for logging porpouse
while true;
do
if $avaiable
then
echo "$com 1) $localip avaiable $com"
echo "1"
while ping -c 1 -t 2 $localip
do
sleep 5
done
growlnotify -s -I $iconpath -m "$localip is offline"
avaiable=false
else
echo "$com 2) $localip not avaiable $com"
#try to ping the router untill it come back and notify it
while !(ping -c 1 -t 2 $localip)
do
echo "$com trying.... $com"
sleep 5
done
echo "$com found $localip $com"
growlnotify -s -I $iconpath -m "$localip is online"
avaiable=true
fi
sleep 5
done
The simplest approach is to wrap this script with another one that creates N processes. Assume your script is called "watchip", then put into another script the text
watchip 10.0.1.1 &
watchip 10.0.1.2 &
watchip 10.0.1.3 &
etc
and set localip to $1 inside watchip.
I don't think it's necessary to run multiple scripts. Here is a general script to monitor a list of IP addresses and note changes in ping success...
#!/bin/bash
set 10.0.0.1 10.0.0.2 # etc
trap exit 2
while true; do
i=1
for ipnumber in "$#"; do
statusname=up$i
laststatus=${!statusname:-0}
ping -c 1 -t 2 $ipnumber > /dev/null
ok=$?
eval $statusname=$ok
if [ ${!statusname} -ne $laststatus ]; then
echo status changed for $ipnumber
if [ $ok -eq 0 ]; then
echo now it is up
else
echo now it is down
fi
fi
i=$(($i + 1))
done
sleep 5
done
Change localip=192.168.1.1 to:
localip=$1
This allows the IP address to be passed in as a command-line argument. Then you can run multiple copies of the script passing in different IP addresses. You could then create a master script to run multiple copies of the monitoring script. Assuming the script you posted is monitor.sh:
#!/bin/sh
monitor.sh 192.168.1.1 &
monitor.sh 192.168.2.2 &
monitor.sh 192.168.3.3 &
wait
Keep two arrays. One with available IPs; the other with unavailable ones. When their status changes, move them to the other array. No need for multiple background processes.
I've omitted the logging stuff. You can add it back in. This is untested code.
available=(192.168.1.1 192.168.1.2 192.168.1.3 192.168.1.4)
unavailable=()
while true
do
for index in ${!available[#]}
do
if ! ping -c 1 -t 2 ${available[index]}
then
growlnotify -s -I $iconpath -m "${available[index]} is offline"
unavailable+=(${available[index]})
unset "available[index]"
fi
done
for index in ${!unavailable[#]}
do
if ping -c 1 -t 2 ${unavailable[index]}
then
growlnotify -s -I $iconpath -m "${unavailable[index]} is back online"
available+=(${unavailable[index]})
unset "unavailable[index]"
fi
done
done

Making bash script to check connectivity and change connection if necessary. Help me improve it?

My connection is flaky, however I have a backup one. I made some bash script to check for connectivity and change connection if the present one is dead. Please help me improve them.
The scripts almost works, except for not waiting long enough to receive an IP (it cycles to next step in the until loop too quick). Here goes:
#!/bin/bash
# Invoke this script with paths to your connection specific scripts, for example
# ./gotnet.sh ./connection.sh ./connection2.sh
until [ -z "$1" ] # Try different connections until we are online...
do
if eval "ping -c 1 google.com"
then
echo "we are online!" && break
else
$1 # Runs (next) connection-script.
echo
fi
shift
done
echo # Extra line feed.
exit 0
And here is an example of the slave scripts:
#!/bin/bash
ifconfig wlan0 down
ifconfig wlan0 up
iwconfig wlan0 key 1234567890
iwconfig wlan0 essid example
sleep 1
dhclient -1 -nw wlan0
sleep 3
exit 0
Here's one way to do it:
#!/bin/bash
while true; do
if ! [ "`ping -c 1 google.com; echo $?`" ]; then #if ping exits nonzero...
./connection_script1.sh #run the first script
sleep 10 #give it a few seconds to complete
fi
if ! [ "`ping -c 1 google.com; echo $?`" ]; then #if ping *still* exits nonzero...
./connection_script2.sh #run the second script
sleep 10 #give it a few seconds to complete
fi
sleep 300 #check again in five minutes
done
Adjust the sleep times and ping count to your preference. This script never exits so you would most likely want to run it with the following command:
./connection_daemon.sh 2>&1 > /dev/null & disown
Have you tried omitting the -nw option from the dhclient command?
Also, remove the eval and quotes from your if they aren't necessary. Do it like this:
if ping -c 1 google.com > /dev/null 2>&1
Trying using ConnectTimeout ${timeout} somewhere.

Resources