≡ Menu

seq command

One our reader asks:

How do I generate a range of numbers under BASH for loop command? For example, I need to run particular command inside loop 100 or 500 times. Basically I want function that counts FROM and TO a range of numbers like 50-10.

To print a sequence of numbers use GNU seq command. In olden days we use our own shell script. But no more dirty shell script, just use good seq command.

This is quite handy when you want to writing shell scripts that requires loop-using range of numbers.

seq command syntax

seq LAST
seq FIRST LAST
seq FIRST INCREMENT LAST

If FIRST or INCREMENT is omitted, it defaults to 1. That is, an omitted INCREMENT defaults to 1 even when LAST is smaller than FIRST. FIRST, INCREMENT, and LAST are interpreted as floating point values. INCREMENT is usually positive if FIRST is smaller than LAST, and INCREMENT is usually negative if FIRST is greater than LAST.

Try out following examples:
$ seq 5
Output:

1
2
3
4
5

Few more examples:$ seq 5 10
$ seq 0 2 10
$ seq 5 -1 1

seq command and shell script (for loop)

You can use seq command in bash for loop as follows:

#!/bin/bash
for i in $(seq 5)
do
  echo "Welcome $i times"
done
 

Bash for loop to generate a sequence of numbers

You can also use bash for loop as follows:

#!/bin/bash
for ((a=1; a <= 5 ; a++))
do
   echo "Welcome $a times."
done

Real World Experience

#!/bin/bash
# Script to move topics from old shared hosting to new lighttpd vps server
#
U="http://forum.cyberciti.biz/viewtopic.php?t="
rdu=""
for n in $(seq 1 521)
do
  rdu="$(lynx --dump $U$n | egrep "vt([0-9]+)\.html$" | awk '{ print $2}' | uniq)"
  if [ "$rdu" == "" ]; then
    :
  else
    echo "$n => \"$rdu\","
  fi
  rdu=""
done

Above script generates a new php code (array) to match with variable t so that we can send 301 redirect. So anyone visiting old forum url http://www.cyberciti.biz/nixcraft/forum/viewtopic.php?t=513 will be redirected to new url :D
Next, I just need to copy and paste the array generated by shell script into viewtopic.php and all users are redirected to new url with 301 http code.

<?php
$URLS = array (
....
..
3 => "http://forum.cyberciti.biz/mysql-cluster-vt3.html",
4 => "http://forum.cyberciti.biz/nice-look-and-feel-vt4.html",
5 => "http://forum.cyberciti.biz/squid-monitoring-using-mrtg-vt5.html"
....
);
$top=$_GET['t'];
$u=$URLS[$top];
if ( isset($u)) {
  @include_once("../../include.genlib.php");
  movePage(301, "$u");
}
else
{
  @include_once("../../include.genlib.php");
  movePage(301, "http://forum.cyberciti.biz");
}
?>

Set a step value and generate a sequence number

In case, you are interested in my old (perhaps dirty) shell script ;)

#!/bin/bash
# Usage:
# ./script 1 5 +
# ./script 100 50 -
# where    START END +/-
FROM=$1
TO=$2
ACTION="$3"
if [ "$ACTION" == "+" ];
then
while [ $FROM -le $TO ]
do
  echo -n $FROM " "
  (( FROM++ ))
done
echo ""
else
while [ $FROM -ge $TO ]
do
  echo -n $FROM " "
  (( FROM-- ))
done
echo " "
fi

Run script as follows to set a step value and generate a sequence:
$ chmod +x script
$ ./script 5 10 +
$ ./script 20 10 -

You can simply monitor your remote system hosted some remote IDC. There may be tons of causes for which system goes out the network.

Understanding ping command

ping is one of the basic and nifty command to test network connection. For example you can send 4 ping request to cyberciti.biz with following command:
$ ping -c 4 cyberciti.biz
$ ping -c 4 router

Output:

PING router (192.168.1.254) 56(84) bytes of data.
64 bytes from router (192.168.1.254): icmp_seq=1 ttl=64 time=1.02 ms
64 bytes from router (192.168.1.254): icmp_seq=2 ttl=64 time=0.824 ms
64 bytes from router (192.168.1.254): icmp_seq=3 ttl=64 time=0.826 ms
64 bytes from router (192.168.1.254): icmp_seq=4 ttl=64 time=0.843 ms
--- router ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3012ms
rtt min/avg/max/mdev = 0.824/0.880/1.027/0.085 ms

Just see output '--- router ping statistics ---', 4 received is key to verify that 4 packets send and received successfully. You can extract 4 received with the following command:
$ ping -c4 router | grep 'received'
Output:

4 packets transmitted, 4 received, 0% packet loss, time 3012ms

Next logical step is to just get number 4 received using awk command:
$ ping -c4 router | grep 'received' | awk -F',' '{ print $4}'
Output:

4 received 

Last step is to just get 4 number and remove received word:
$ ping -c4 router | grep 'received' | awk -F',' '{ print $2}' | awk '{ print $1}'
Output:

4 

Shell script to system monitoring with ping command

Now you know how to obtained received packets, it is time to automate entire process with simple script. Here is sample script (download link):

#!/bin/bash
HOSTS="cyberciti.biz theos.in router"
COUNT=4
for myHost in $HOSTS
do
  count=$(ping -c $COUNT $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
  if [ $count -eq 0 ]; then
    # 100% failed 
    echo "Host : $myHost is down (ping failed) at $(date)"
  fi
done

You can download complete working script which sends an email alert here.

Setup Cron job

In order to run this script every 30 minutes (or as per your requirements), you need to install a script as cron job:
$ chmod +x /path/to/monitorHost
Install the monitorHost script as crontab using the editor:
$ crontab -e
Append the following cronjob entry:
# Monitor remote host every 30 minutes using monitorHost
30 * * * * /home/vivek/bin/monitorHost

Save and close the file.