Durchlaufen Sie die Server und führen Sie den Befehl aus

7

Ich habe eine Reihe von Servern in einer Textdatei namens network_list.txt. Wie kann ich die Server durchlaufen und den Befehl ausführen und das Ergebnis anzeigen? Ich habe folgendes versucht:

filename="network_list.txt"
service=httpd
while read -r line
do
    name="$line"
    ping -c 3 $name > /dev/null 2>&1;
    RETVAL=$?
        if [ $RETVAL -ne 0 ]
        then 
           echo "$name is down"
        else 
            echo "$name is up and running"
        fi
    http_status=$(ssh $name ps -ef | grep -v grep | grep $service | wc -l)
        if [ $http_status -ne 0 ]
        then
            echo "$service is up and running in $name"
        else
            echo "$service is down in $name"
        fi
done < "$filename"

Aber es stoppt nach dem ersten Server.

Vielen Dank :) .

KTM
quelle
Was ist das Format Ihrer Eingabedatei?
Jaroslav Kucera
es ist wie 192.168.1.101 192.168.1.102 192.168.1.103 - - - - - - Zeile für Zeile
KTM
6
Dies scheint mir der perfekte Anwendungsfall für Ansible oder ein anderes Konfigurationsmanagement-Tool zu sein.
GregL
1
Ich stimme Gregs Rat zu, Ansible zu verwenden. Früher hatte ich solche Skripte mit einer forSchleife. Jetzt füge ich diese Hostnamen in eine Ansible-Konfigurationsdatei ein und fordere Ansible an, auf jedem von ihnen ein Skript auszuführen. Ansible bietet Ihnen die Möglichkeit, das Skript lokal zu schreiben und zu testen und es dann auf jedem Server remote auszuführen. Die Hälfte der Dinge, die meine Skripte früher erledigt haben, werden von Ansible-Modulen erledigt, daher muss ich viel weniger warten. A + wird niemals zurückkehren.
Stephen Ostermiller
2
Salz würde auch dafür gut funktionieren. Es wäre im Grunde:salt \* cmd.run "systemctl is-active httpd"
Michael Hampton

Antworten:

7

Sie müssen den Befehl stdin of SSH in Ihrer Schleife nach nirgendwo umleiten, um zu verhindern, dass alle Ihre Zeilen gelesen werden. Dies sollte es tun:

http_status=$(ssh $name "ps -ef | grep -v grep | grep $service | wc -l" < /dev/null)
Khaled
quelle
ping_stat = $ (ping -c 4 -q $ name 2> & 1), Hallo, warum konnte ich nach diesem Befehl nicht $ name verwenden?
KTM
8

Es gibt eine Lösung mit -n -xParametern:

http_status=$(ssh -nx name ps -ef | grep -v grep | grep $service | wc -l)

Das -xdeaktiviert die X11-Weiterleitung, um mögliche X11 forwarding request failedNachrichten zu entfernen.

Das -nleitet stdin von / dev / null um (verhindert tatsächlich das Lesen von stdin).

Jaroslav Kucera
quelle
1

Während die Antwort, die akzeptiert wird, völlig funktioniert, möchte ich nur dieses Skript anbieten, das nützlich sein könnte, wenn jemand darauf stößt.

Verwendungszweck

Sie müssten also offensichtlich die Zeilen unter den Zeilen "Echo $ server $ serverIP" ändern, um die tatsächlichen Befehle wiederzugeben, die Sie verwenden möchten. $ 1 ist das erste, was Sie nach "./scriptname.sh" eingeben - z. B. ./scriptname.sh $ 1 $ 2 $ 3 ... - und so funktioniert das:

$ 1 sollte die Datei mit Ihren Hostnamen sein. $ 2 ist der Positionsparameter, den Sie an FunctionC weitergeben (der in diesem Beispielskript immer aufgerufen wird). Mit $ 2 und $ 3 können die anderen Funktionen (A / B) aufgerufen werden. Alternativ können Sie $ 3 und $ 4 am EOF durch "FunctionA" und "FunctionB" ersetzen, wenn Sie sie immer ausführen möchten.

Ich hoffe, dies hilft jemandem. Es war für mich von unschätzbarem Wert , wenn ich Pakete bereitstellte oder Dinge in der gesamten Domäne testete.

#! /bin/bash
SVRList=`ls ./$1`

#========[ FUNCTIONS ]===============

FunctionA () {
  for server in `cat $SVRList | grep -v ^#`  # Makes variable "server" from each line in $SVRlist that is not commented
do
  serverIP=$(nslookup $server | tail -2 | awk -F ":" '{print $2}')
  echo "============= $server | $serverIP ============="
  #command that you'd like to run locally
done
}

FunctionB () {
      for server in `cat $SVRList | grep -v ^#`
    do
      passedvar="192.16.${1}"
      serverIP=$(nslookup $server | tail -2 | awk -F ":" '{print $2}')
      echo "============= $server | $serverIP ============="
      ssh -q $serverIP '#command that you'd like to run remotely'
      ssh -q $serverIP '#second command, if you so fancy'
      ssh -q $serverIP "ping $passedvar"
      #^ is done just to show an example of what can be done
    done
    }

FunctionC () {
  for server in `cat $SVRList | grep -v ^#`
do
  passedvar="192.16.${1}"
  serverIP=$(nslookup $server | tail -2 | awk -F ":" '{print $2}')
  echo "============= $server | $serverIP ============="
  ssh -q $serverIP "ping $passedvar"
  #^ is done just to show the power of positional parameters.
done
}

#========[ SCRIPT ]==========

if [ $# -lt 2 ] 
  then
  printf "Usage: %s <file containing list of server hostnames> <passed variable> <functions> \n" "$(basename "$0")" >&2
  exit 64
  else 
  echo "Starting Script"
fi

FunctionC $2
$3
$4
exit

Auch OP:

Warum service = httpd setzen? Es kann besser sein, [testing und "service = $ 1" zu verwenden, wobei $ 1 httpd, splunkd oder ein anderer Dienst sein kann. Außerdem sollte die Variable http_status in "service_status" geändert werden, damit das Skript besser dokumentiert wird.

kilrainebc
quelle
1

Warum nicht verwenden pssh?

https://github.com/lilydjwg/pssh

Es ist ein paralleles SSH-Tool, das Unterstützung für das Abrufen einer Liste von Hosts aus einer Datei integriert hat:

pssh -h network_list.txt ps -ef | grep -v grep | grep $service | wc -l

Dann können Sie die Ausgabe nach Belieben analysieren

Daniel Scott
quelle