3

I have written a command that output a list of hostnames, e.g. :

clab148node11
clab148node12
clab148node15
clab148node16

Now, I would like to remove those nodes that do not respond to ping. For now I have something like this :

for node in $nodes
do
         result=$(ping -c 1 $node; echo $?)
done

Now how do I remove nodes that have the $result different than 0 ?

2
  • 2
    Is it a requirement to remove from the list? I prefer to build a new list instead: error=(); for node in $nodes; do ping -c 1 $node || error+=($node); done
    – manatwork
    Commented Feb 5, 2013 at 10:28
  • @manatwork Well it's also a solution but if it's possible to be done without then I would like to see it as well.
    – Patryk
    Commented Feb 5, 2013 at 10:33

3 Answers 3

4

I'd prefer to build a new list and replace an old one with a new:

nodes="127.0.0.1 1.2.3.4 1.2.3.4 "
nodes_out=
for node in $nodes
do 
    ping -c 1 $node >/dev/null 2>&1 && nodes_out+=$node
done
nodes=$nodes_out
2

like @manatwork said, it looks simpler and safer to build a new list with the valid nodes.

However, as "$nodes" is evaluated before the first iteration of the for loop, it should be possible to change it during that same loop:

$ nodes="127.0.0.1 1.2.3.4 1.2.3.4 "
$ for node in $nodes; do
      result=$(ping -c 1 $node >/dev/null 2>/dev/null; echo $?);
      if [ "$result" -ne 0 ]; 
      then    nodes=$(echo $nodes | sed -e "s/ *$node */ /"); 
      fi;
      echo result=$result node=$node nodes=$nodes ;    
  done ;

Notice : my sed replace [space]$node[space] or $node[space] or [space]$node to work in all cases depending on the position of $node in the $nodes list (If its in the middle, or the first or the last element, space(s) before and after it will be either present or not). And it only replace 1 occurence at a time, but you could add a final /g to get rid of all occurences at once.

This outputs:

result=0 node=127.0.0.1 nodes=127.0.0.1 1.2.3.4 1.2.3.4
result=1 node=1.2.3.4 nodes=127.0.0.1 1.2.3.4
result=1 node=1.2.3.4 nodes=127.0.0.1
1
  • you can use nodes=${nodes/$node} instead expression with sed in bash, ksh, etc. spaces don't matter in such list.
    – rush
    Commented Feb 5, 2013 at 11:43
0

Another option is to simply use an inverse grep to find all occurrences in the list not matching the host:

for node in $nodes
do
    if ! `ping -c 1 $node > /dev/null 2>&1`; then 
        nodes="`echo \"$nodes\" | grep -v \"$node\"`"
    fi
done

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .