Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to use ping in a script

Tags:

bash

ssh

ping

I want a bash script that'll do:

for c in computers:
do
   ping $c
   if ping is sucessfull:
      ssh $c 'check something'
done

If I only do ssh and the computer is iresponsive, it takes forever for the timeout. So I was thinking of using the output of ping to see if the computer is alive or not. How do I do that? Other ideas will be great also

like image 218
Guy Avatar asked Nov 13 '09 08:11

Guy


1 Answers

I wrote such a script in 1997 and used it heavily for some years: sshall.

It is simplistic and not very versatile. On the other hand, it supports some checks you probably don't need.

Once I started using ssh in more varied ways, I stopped using or updating this script; I now either write shell loops directly or use Ansible adhoc commands.

The script:

#!/bin/sh
#
# $Id: sshall 1259 2017-06-26 16:59:42Z rp $

# sshall: ssh to multiple hosts, *last* arg is command
# with -i, also accepts input ... I'd rather dup stdin or so, but how?

PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/usr/etc; export PATH
tmpfile=/tmp/sshall-$$

# error handling
trap 'rm -f $tmpfile; exit' 1 2 3 4 13 15

#--- cmdline parsing ---#
#

Puke()
{
  if [ -n "$*" ]; then echo Fatal error: $* 1>&2; fi
  cat <<ZZ 1>&2

Usage:
  $0 [-v] [-i] [-e] [-b] [-u user] [-H] [-Y] [-P] host1 [host2 [...]] "command"

  to issue "ssh host command" for every host

  use -i flag to supply input, -e to redirect stderr to stdout,
    -v for progress messages, -b to start in the background,
    -u user to connect as the given user,
    -H to check the hostnames with 'host',
    -Y to check them with 'ypmatch',
    -P to check them with 'ping',
    -o text to pass the given option through to ssh

  note: the effect of -i is to call ssh without the -n flag
  take care: -b may fill up your process table if used on many hosts

ZZ

  exit 1
}

input=
hostlist=
verbose=
bg=
check_w_host=
check_w_ypmatch=
check_w_ping=
user_prefix=

while :
do
  case "$1" in
    -h|-help|\?*) Puke;;
    -b) bg=1
    if [ -n "$command" ]; then Puke "options must precede arguments"; fi;;
    -i) input=1
    if [ -n "$command" ]; then Puke "options must precede arguments"; fi;;
    -v) verbose=1
    if [ -n "$command" ]; then Puke "options must precede arguments"; fi;;
    -e) errtoout=1
    if [ -n "$command" ]; then Puke "options must precede arguments"; fi;;
    -o)
  if [ -n "$o_opt" ]; then Puke "specify only one -o option"; fi
       shift; o_opt="$1"
    if [ -n "$command" ]; then Puke "options must precede arguments"; fi;;
    -u) shift; user_prefix="$1@"
    if [ -n "$command" ]; then Puke "options must precede arguments"; fi;;
    -H) check_w_host=1
    if [ -n "$command" ]; then Puke "options must precede arguments"; fi;;
    -Y) check_w_ypmatch=1
    if [ -n "$command" ]; then Puke "options must precede arguments"; fi;;
    -P) check_w_ping=1
    if [ -n "$command" ]; then Puke "options must precede arguments"; fi;;
    -*) Puke "$1 is not a valid option" ;;
    "") break;;
    *) hostlist="$hostlist $command"; command=$1;;
  esac
  shift
done

if [ -z "$command" ]
then
  Puke "no command supplied"
fi

if [ -z "$hostlist" ]
then
  Puke "no host(s) supplied"
fi

case "$user_prefix" in
-*)
  Puke "no -u argument supplied" ;;
esac

if [ -n "$check_w_host" ]
then
  for h in $hostlist
  do
    if host 2>&1 >/dev/null
    then
      Puke "host cannot find '$h'"
    fi
  done
fi

if [ -n "$check_w_ypmatch" ]
then
  for h in $hostlist
  do
    if ypmatch hosts 2>&1 >/dev/null
    then
      Puke "ypmatch cannot find '$h'"
    fi
  done
fi


#--  OK, start doing useful things ---#
#

if [ -n "$input" ]
then
  # read input!
  cat >$tmpfile
  # we can do away with the $tmpfile, with a fork for every host ...
fi

Ssh()
{
  case "$errtoout" in
    "") ssh "$@" | sed "s/^/$h: /" ;;
    *)  ssh "$@" 2>&1 | sed "s/^/$h: /" ;;
  esac
}

Ssh_o()
{
  case "$o_opt" in
  "") Ssh "$@";;
  *)  Ssh -o "$o_opt" "$@";;
  esac
}

Ssh_w_tmp()
{
  if [ -f "$tmpfile" ]
  then
    cat $tmpfile | Ssh_o "$@"
  else
    Ssh_o -n "$@"
  fi
}

for h in $hostlist
do
  if [ -z "$check_w_ping" ] || ping $h 2 >/dev/null  # note: "2 >"
  # host is active
  then
    #if [ -z "`finger @$h 2>&1 | grep 'Connection refused$'`" ]
    # host accepts finger - very crude check to see if ssh will work
    # however, finger has been disabled since, where I live
    if true
    then
      if [ -n "$verbose" ]
      then
        echo "executing '$command' on '$h'" 1>&2
      fi

      case "$bg" in
      "")
          Ssh_w_tmp $user_prefix$h "$command" ;;
      *)
          Ssh_w_tmp $user_prefix$h "$command" & ;;
        esac
    fi
    fi
done

rm -f $tmpfile
like image 98
reinierpost Avatar answered Sep 24 '22 16:09

reinierpost