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.


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.


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

2
Wyjście w jednym wierszu: (ssh -q -o "BatchMode = yes" -o "ConnectTimeout = 3" user@host.com "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


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

7

Próbować:

echo quit | telnet IP 22 2>/dev/null | grep Connected

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 user@remote.com exit

if [ $? != "0" ]; then
    echo "Connection failed"
fi

Ś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"

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 ...)".


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

Aby połączyć się z serwerem z wieloma interfejsami

ssh -o ConnectTimeout=1 -q Necktwi@192.168.1.61;[ $? = 1 ] || ssh -o ConnectTimeout=1 -q Necktwi@192.168.1.51

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

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.


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.


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.