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
    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 Feb 5 '13 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 Feb 5 '13 at 10:33
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
| improve this answer | |
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
| improve this answer | |
  • you can use nodes=${nodes/$node} instead expression with sed in bash, ksh, etc. spaces don't matter in such list. – rush Feb 5 '13 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
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.