Jak utworzyć skrypt bash, aby sprawdzić połączenie SSH?

86

Jestem w trakcie tworzenia skryptu bash, który logowałby się do zdalnych maszyn i tworzył klucze prywatne i publiczne.

Mój problem polega na tym, że zdalne maszyny nie są zbyt niezawodne i nie zawsze działają. Potrzebuję skryptu bash, który sprawdziłby, czy połączenie SSH jest aktywne. Przed faktycznym utworzeniem kluczy do wykorzystania w przyszłości.

chutsu
źródło
2
Zazwyczaj uruchamia się, ssh-keygenaby wygenerować parę kluczy na komputerze lokalnym, a następnie ssh-copy-idskopiować klucz publiczny na komputery zdalne. Wygląda na to, że robisz coś inaczej. Dlaczego, jaki jest twój cel?
ephemient
1
Ponieważ oczywiście zmieniasz sposób nawiązywania połączeń przez maszyny zdalne, rozważ wdrożenie mosh . mosh.mit.edu Ma na celu uzupełnienie SSH na niestabilnych połączeniach. Mam z tym bardzo dobre doświadczenia.
Aeyoun
@ephemient Wiem, że jest trochę późno, ale wydaje się całkiem proste, że klucz nie był przeznaczony dla maszyny lokalnej lub nie dla użytkownika lokalnego.
Opuszczony

Odpowiedzi:

170

Możesz to sprawdzić za pomocą wartości zwracanej przez ssh:

$ ssh -q user@downhost exit
$ echo $?
255

$ ssh -q user@uphost exit
$ echo $?
0

EDYCJA: Innym podejściem byłoby użycie nmap (nie musisz mieć kluczy ani rzeczy do logowania):

$ a=`nmap uphost -PN -p ssh | grep open`
$ b=`nmap downhost -PN -p ssh | grep open`

$ echo $a
22/tcp open ssh
$ echo $b
(empty string)

Ale będziesz musiał grepować wiadomość (nmap nie używa wartości zwracanej do pokazania, czy port był filtrowany, zamknięty czy otwarty).

EDYCJA2:

Jeśli jesteś zainteresowany w rzeczywistym stanem ssh-portu, można zastąpić grep openz egrep 'open|closed|filtered':

$ nmap host -PN -p ssh | egrep 'open|closed|filtered'

Żeby być kompletnym.

Tim Cooper
źródło
1
Aby być kompletnym, czy u możesz wskazać, który kod powrotu oznacza sukces, a który oznacza niepowodzenie SSH?
Henley Chiu
Zastanawiasz się, co się stanie, jeśli próba SSH po prostu się zawiesi?
Sibbs Gambling
2
Świetna odpowiedź! Nie wspominasz jednak, że próba sshprzejścia do wyłączonego hosta kończy się niepowodzeniem dopiero po przekroczeniu limitu czasu wynoszącego np. 60 sekund - co może być przeszkodą w niektórych zastosowaniach. Ponadto, jeśli nazwa hosta jest zdefiniowana w ~/.ssh/config, pierwsze sshpodejście działa, podczas gdy drugie nmapzawodzi Failed to resolve "<hostname>".
ssc
2
nie ma żadnego wyjaśnienia na temat poleceń… lub tego, co faktycznie robisz… co to jest $?? itd.
Toskan
Jeszcze bardziej zwięzła forma nr 1: ssh -q user@downhost exit | echo $? przeprowadź połączenie w echo
philn5d
22
ssh -q -o "BatchMode=yes" -i /home/sicmapp/.ssh/id_rsa <ID>@<Servername>.<domain> "echo 2>&1" && echo $host SSH_OK || echo $host SSH_NOK
Brian Ott
źródło
2
Wyjście w jednym wierszu: (ssh -q -o "BatchMode = yes" -o "ConnectTimeout = 3" [email protected] "echo 2> & 1" && echo SSH_OK || echo SSH_NOK) | ogon -n1
Xdg
21

Możesz użyć czegoś takiego

$(ssh -o BatchMode=yes -o ConnectTimeout=5 user@host echo ok 2>&1)

Spowoduje to wyświetlenie komunikatu „ok”, jeśli połączenie ssh jest prawidłowe

Adrià Cidre
źródło
14

Uzupełnienie odpowiedzi @Adrià Cidremożesz zrobić:

status=$(ssh -o BatchMode=yes -o ConnectTimeout=5 user@host echo ok 2>&1)

if [[ $status == ok ]] ; then
  echo auth ok, do something
elif [[ $status == "Permission denied"* ]] ; then
  echo no_auth
else
  echo other_error
fi
iarroyo
źródło
7

Próbować:

echo quit | telnet IP 22 2>/dev/null | grep Connected
GUESSWHOz
źródło
1
Problem z tym podejściem polega na tym, że nie rozpoznaje hostów zdefiniowanych w ssh_config (tj. / Etc / ssh / config lub ~ / .ssh / config)
Ding-Yi Chen
1

Poniższe sshpolecenie powinno mieć kod zakończenia 0po pomyślnym połączeniu i wartość niezerową w przeciwnym razie.

ssh -q -o BatchMode=yes [email protected] exit

if [ $? != "0" ]; then
    echo "Connection failed"
fi
matowe
źródło
Świetny! Polecam również dodanie -o ConnectTimeout = 5, dla szybszego wyjścia w przypadkach, gdy port docelowy jest filtrowany.
Daniel
0

Na wypadek, gdyby ktoś chciał tylko sprawdzić, czy port 22 jest otwarty na zdalnej maszynie, to proste polecenie netcat jest przydatne. Użyłem go, ponieważ nmap i telnet nie były dla mnie dostępne. Co więcej, moja konfiguracja ssh używa uwierzytelniania hasłem klawiatury.

Jest to wariant rozwiązania zaproponowanego przez GUESSWHOz.

nc -q 0 -w 1 "${remote_ip}" 22 < /dev/null &> /dev/null && echo "Port is reachable" || echo "Port is unreachable"
Mathieu C.
źródło
0

Jeśli chcesz sprawdzić, czy folder zdalny istnieje, lub naprawdę przetestować inny plik:

if [ -n "$(ssh "${user}@${server}" [ -d "$folder" ] && echo 1; exit)" ]; then
    # exists
else
    # doesn't exist
fi

Nie zapomnij o cudzysłowach w "$(ssh ...)".

Jonathan H.
źródło
To nie odpowiada na pytanie. OP chce sprawdzić, czy można nawiązać połączenie SSH, nie sprawdzając pliku w zdalnej lokalizacji ssh.
Rakib Fiha
0

Przykład użycia skryptu BASH 4+:

# -- ip/host and res which is result of nmap (note must have nmap installed)
ip="192.168.0.1"
res=$(nmap ${ip} -PN -p ssh | grep open)

# -- if result contains open, we can reach ssh else assume failure) --
if [[ "${res}" =~ "open" ]] ;then
    echo "It's Open! Let's SSH to it.."
else
    echo "The host ${ip} is not accessible!"
fi
Mike Q
źródło
0

https://onpyth.blogspot.com/2019/08/check-ping-connectivity-to-multiple-host.html

Powyższy link służy do stworzenia skryptu Python do sprawdzania łączności. Możesz użyć podobnej metody i użyć:

ping -w 1 -c 1 "IP Address" 

Polecenie do utworzenia skryptu bash.

Dheeraj Kumar
źródło
2
Spowoduje to wysłanie pinga tylko do zdalnego adresu IP. Nie gwarantuje, że połączenie ssh jest możliwe.
RJ
Dzięki za zwrócenie uwagi, oto kod dla ssh xlinu.blogspot.com/2019/09/… export user = "nazwa użytkownika" export pass = "password" export i = "hostname" export SSHPASS = $ pass sshpass -e ssh $ user @ $ i -q "echo $ i is Accessible"
Dheeraj Kumar
-7

Wydaje mi się, że próbujesz tutaj rozwiązać niewłaściwy problem. Nie powinieneś próbować uczynić demonów ssh bardziej stabilnymi? Spróbuj uruchomić coś takiego jak monit , który sprawdzi, czy demon działa i zrestartuje go, jeśli tak nie jest (dając ci czas na znalezienie głównego problemu związanego z zamykaniem się sshd). A może usługa sieciowa jest kłopotliwa? Spróbuj spojrzeć man ifup. Czy Całe Cholerne Po prostu lubi się na tobie zamknąć? Cóż, to większy problem ... spróbuj przejrzeć swoje logi (zacznij od syslog), aby znaleźć awarie sprzętu lub usługi, które wyłączają twój boxen (może monitor temperatury?).

Sprawienie, by twoje skrypty były odporne na błędy, jest świetne, ale możesz też chcieć, aby twój boxen był odporny na błędy.

Sam Bisbee
źródło
4
Sam: istnieją ważne przypadki użycia, w których skrypt sprawdza to. Np. (Jak ja): Mam zadanie cron uruchomione na moim komputerze, aby wykonać kopię zapasową moich danych przez rsync do mojego domowego nas. Teraz jestem na zewnątrz lub nawet często się rozłączam i muszę zmienić harmonogram, jeśli połączenie nie było dostępne. Mój boxen działa całkiem nieźle, ale jak to się mówi: to zawsze kabel (aka sieciowy)
stwissel