Как сделать SSH с таймаутом в скрипте?

173

Я выполняю сценарий подключения через SSH без пароля на удаленном хосте. Я хочу установить тайм-аут, чтобы, если удаленный хост работал бесконечно долго, я хотел выйти из этого сеанса ssh и продолжить другие строки в моем скрипте sh.

Есть идеи, как это сделать?

user57421
источник
Это, вероятно, должно быть закрыто, чтобы соответствовать закрытию полного дубликата о том, как уменьшить значение тайм-аута соединения ssh [закрыто]
Murmel
Если вы перенаправили сюда только «остаться в sshсеансе больше времени » (вопрос «Как увеличить время ожидания соединения SSH?»), Это неправильное место . Ответ по этой ссылке о ssh-timeout .
Питер Краусс

Ответы:

288
ssh -o ConnectTimeout=10  <hostName>

Где 10 - время в секундах. Этот тайм-аут относится только к созданию соединения.

user57421
источник
4
ConnectTimeout только устанавливает тайм-аут на настройку соединения, верно?
Орельен Уомс,
10
Это на самом деле не работает, поскольку «удаленному хосту требуется бесконечное время для запуска»: «ssh -o ConnectTimeout = 5 хост« sleep 10 »» ждет 10 секунд, а не 5.
Ferry Boender
109

Используйте -o ConnectTimeoutи -o BatchMode=yes -o StrictHostKeyChecking=no.

ConnectTimeout предотвращает зависание скрипта, BatchMode предотвращает его зависание при неизвестном хосте, YES для добавления в known_hosts, а StrictHostKeyChecking автоматически добавляет отпечаток пальца.

**** ПРИМЕЧАНИЕ **** «StrictHostKeyChecking» предназначался только для внутренних сетей, где вы доверяете своим хостам. В зависимости от версии клиента SSH сообщение «Вы уверены, что хотите добавить свой отпечаток» может привести к зависанию клиента на неопределенное время (в основном это старые версии, работающие в AIX). Большинство современных версий не страдают от этой проблемы. Если вам приходится иметь дело с отпечатками пальцев на нескольких хостах, я рекомендую поддерживать файл known_hosts с помощью какого-либо инструмента управления конфигурацией, такого как puppet / ansible / chef / salt / etc.

Doug
источник
11
Это не только -o StrictHostKeyChecking=noне решает вопрос, но это ужасная идея, если вы заботитесь о безопасности, что может быть причиной того, что вы используете SSH в первую очередь.
Дольф
9
Полезно указать возможные последствия для безопасности -o StrictHostKeyChecking = no. Однако это предотвратит зависание скрипта во время выполнения.
Даг
2
ПРЕДУПРЕЖДЕНИЕ!!!! Как писал @Dolph, НЕ используйте, StrictHostKeyChecking=noесли вы вообще заботитесь о безопасности. @Doug: скрипт не будет зависать - он просто будет настаивать на том, чтобы вы сначала подключились к удаленному хосту вручную, чтобы он узнал хост. Но это защитит вас от атак MITM. Пожалуйста, отредактируйте этот ответ, чтобы отразить это, так как это очень опасный совет. И это даже не просили.
Johndodo
2
Обновил мой ответ. По моему опыту, это может привести к зависанию некоторых клиентов.
Дуг
50

попробуй это:

timeout 5 ssh user@ip

timeout выполняет команду ssh (с аргументами) и отправляет SIGTERM, если ssh не возвращается через 5 секунд. для получения более подробной информации о тайм-ауте, прочитайте этот документ: http://man7.org/linux/man-pages/man1/timeout.1.html

или вы можете использовать параметр ssh:

ssh -o ConnectTimeout=3 user@ip
Ли Хо
источник
4
Если вы ищете эту команду на Mac, попробуйте brew install coreutilsи затем используйте gtimeout (источник: stackoverflow.com/questions/3504945/timeout-command-on-mac-os-x ).
Larcher
3
Это может не делать то, что вы хотите. Рассмотрим команду. timeout 3s ssh user@server 'sleep 5; echo blarg >> /tmp/blarg' Это убивает процесс на стороне клиента SSH, но / tmp / blarg по-прежнему изменяется на удаленном сервере. Это означает, что, если вы выполняете на удаленном сервере невыполненную работу с интенсивным использованием ЦП, вы будете пропускать процессы.
Джейми Дэвис
1
@JamieDavis как насчет ssh user @ server 'timeout 5s sleep 10'?
FilipR
18

Вы также можете связаться с флагом

-o ServerAliveInterval = <сек>
поэтому SSH-клиент будет отправлять нулевой пакет на сервер каждую <secs>секунду, чтобы поддерживать соединение. В Linux это также может быть установлено глобально /etc/ssh/ssh_configили для каждого пользователя ~/.ssh/config.

Патрицио Бертони
источник
4
Это звучит как противоположность того, что просит вопрос.
Davor Cubranic
1

Если все остальное терпит неудачу (включая отсутствие timeoutкоманды), концепция в этом сценарии оболочки будет работать:

 #!/bin/bash
 set -u
 ssh $1 "sleep 10 ; uptime" > /tmp/outputfile 2>&1 & PIDssh=$!
 Count=0
 while test $Count -lt 5 && ps -p $PIDssh > /dev/null
 do
    echo -n .
    sleep 1
    Count=$((Count+1))
 done
 echo ""

 if ps -p $PIDssh > /dev/null
 then
    echo "ssh still running, killing it"
    kill -HUP $PIDssh
 else
    echo "Exited"
 fi
Филип Кернс
источник
0

Ну, вы могли бы использовать nohup для запуска того, что вы используете в «неблокирующем режиме». Таким образом, вы можете просто продолжать проверять, запускается ли то, что должно было выполняться, иначе выходите.

nohup ./my-script-that-may-take-long-to-finish.sh &
./check-if-previous-script-ran-or-exit.sh
echo "Сценарий закончился 15 февраля 2011 г., 9:20"> /tmp/done.txt

Итак, во втором вы просто проверьте, существует ли файл.

Эдуардо
источник
Имеет смысл. но, скрипт, который работает, дает мне некоторый вывод, который отображается на консоли .. как проверить, выполнялся ли мой предыдущий скрипт или завершился? $? или что-нибудь еще?
user57421
Ну, вы можете заставить этот скрипт создать файл, когда закончите. Я добавил комментарий к ответу .... grrr
Eduardo