Как создать bash-скрипт для проверки SSH-соединения?

86

Я занимаюсь созданием сценария bash, который будет входить на удаленные машины и создавать закрытые и открытые ключи.

Моя проблема в том, что удаленные машины не очень надежны и не всегда работают. Мне нужен сценарий bash, который проверяет, установлено ли соединение SSH. Перед созданием ключей для будущего использования.

чутсу
источник
2
Как правило, один запускается ssh-keygenдля создания пары ключей на локальном компьютере, а затем ssh-copy-idдля копирования открытого ключа на удаленные машины. Кажется, ты делаешь иначе. Почему, какова твоя цель?
ephemient
1
Поскольку вы, очевидно, меняете способ установления соединений на удаленных машинах, рассмотрите возможность развертывания mosh . mosh.mit.edu Предназначен для дополнения SSH при нестабильных соединениях. У меня очень хороший опыт.
Aeyoun
@ephemient Я знаю, что это немного поздно, но кажется довольно очевидным, что их ключ был не для локальной машины или не для локального пользователя.
Брошенная тележка

Ответы:

170

Вы можете проверить это с помощью возвращаемого значения, которое дает вам ssh:

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

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

РЕДАКТИРОВАТЬ: Другой подход - использовать nmap (вам не нужны ключи или логин):

$ 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)

Но вам нужно будет ввести сообщение с помощью grep (Nmap не использует возвращаемое значение, чтобы показать, был ли порт отфильтрован, закрыт или открыт).

РЕДАКТИРОВАТЬ2:

Если вас интересует фактическое состояние ssh-порта, вы можете заменить его grep openна egrep 'open|closed|filtered':

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

Просто чтобы быть полным.

Тим Купер
источник
1
Для полноты, можете ли вы указать, какой код возврата означает успех, а какой - отказ от SSH?
Хенли Чиу,
Хотите знать, что, если попытка SSH просто зависнет?
Sibbs Gambling
2
Отличный ответ! Однако вы не упоминаете, что попытка подключиться к sshнеработающему хосту терпит неудачу только после тайм-аута, например, 60 секунд, что может быть недопустимым для некоторых случаев использования. Кроме того, если имя хоста определено в ~/.ssh/config, первый sshподход работает, а второй nmapне работает с Failed to resolve "<hostname>".
ssc
2
никаких объяснений по поводу команд ... или что вы на самом деле делаете .. что $?? etc
Toskan
Еще более краткая форма №1: ssh -q user@downhost exit | echo $?
передать
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
Однострочный вывод: (ssh -q -o "BatchMode = yes" -o "ConnectTimeout = 3" user@host.com "echo 2> & 1" && echo SSH_OK || echo SSH_NOK) | tail -n1
Xdg 01
21

Вы можете использовать что-то вроде этого

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

Будет выведено "ok", если ssh-соединение в порядке.

Адриа Сидре
источник
14

Дополняя ответ @Adrià Cidreвы можете:

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
источник
7

Пытаться:

echo quit | telnet IP 22 2>/dev/null | grep Connected
GUESSWHOz
источник
1
Проблема этого подхода в том, что он не распознает хосты, определенные в ssh_config (т.е. / etc / ssh / config или ~ / .ssh / config)
Ding-Yi Chen
1

sshКоманда ниже должна иметь код выхода при 0успешном соединении и ненулевое значение в противном случае.

ssh -q -o BatchMode=yes user@remote.com exit

if [ $? != "0" ]; then
    echo "Connection failed"
fi
матовый
источник
Большой! Я также рекомендую добавить -o ConnectTimeout = 5 для более быстрого выхода в случаях, когда порт назначения фильтруется.
Даниэль
0

На всякий случай, если кто-то только хочет проверить, открыт ли порт 22 на удаленном компьютере, полезна эта простая команда netcat. Я использовал его, потому что nmap и telnet были мне недоступны. Более того, моя конфигурация ssh использует пароль клавиатуры auth.

Это вариант решения, предложенного GUESSWHOz.

nc -q 0 -w 1 "${remote_ip}" 22 < /dev/null &> /dev/null && echo "Port is reachable" || echo "Port is unreachable"
Матьё К.
источник
0

Если вы хотите проверить, существует ли удаленная папка или какой-либо другой файл-тест:

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

Не забывайте кавычки в "$(ssh ...)".

Джонатан Х
источник
Это не отвечает на вопрос. OP хочет проверить, можно ли установить SSH-соединение, не проверяя файл в удаленном месте ssh.
Ракиб Фиха
0

Для подключения к серверу с несколькими интерфейсами

ssh -o ConnectTimeout=1 -q Necktwi@192.168.1.61;[ $? = 1 ] || ssh -o ConnectTimeout=1 -q Necktwi@192.168.1.51
Нектви
источник
0

Пример использования сценария 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

Ссылка выше предназначена для создания скрипта Python для проверки возможности подключения. Вы можете использовать аналогичный метод и использовать:

ping -w 1 -c 1 "IP Address" 

Команда для создания bash-скрипта.

Дирадж Кумар
источник
2
Это будет пинговать только удаленный IP. Не гарантирует, что соединение по ssh возможно.
RJ
Спасибо, что указали на это, вот код для ssh xlinu.blogspot.com/2019/09/… export user = "username" export pass = "password" export i = "hostname" export SSHPASS = $ pass sshpass -e ssh $ user @ $ i -q «echo $ i
Дирадж Кумар,
-7

Я чувствую, что вы пытаетесь решить не ту проблему. Разве вы не должны попытаться сделать демонов ssh более стабильными? Попробуйте запустить что-то вроде monit , которое проверит, запущен ли демон, и перезапустит его, если это не так (у вас будет время найти корень проблемы, стоящей за отключением sshd). Или сетевая услуга доставляет хлопоты? Попробуйте посмотреть man ifup. Неужели Whole Damn Thing просто хочет отключиться от вас? Что ж, это более серьезная проблема ... попробуйте просмотреть свои журналы (начните с системного журнала), чтобы найти сбои оборудования или службы, которые выключают ваш бокс (может быть, монитор температуры?).

Сделать ваши скрипты отказоустойчивыми - это здорово, но вы также можете сделать отказоустойчивым свой бокс.

Сэм Бисби
источник
4
Сэм: есть допустимые варианты использования, чтобы сценарий проверял это. Например (как и я): у меня на моей машине запущено задание cron для резервного копирования данных через rsync на мой домашний nas. Теперь я нахожусь на улице или даже довольно часто отключаюсь, и мне нужно перенести расписание, если соединение было недоступно. Мой боксен работает неплохо, но как говорится: всегда кабель (он же сеть)
stwissel