Упрощенная версия некоторых функций из моих ~/.bashrc и ~/.zshrc (полностью POSIX-совместимая, готовая для ваших сценариев оболочки):
# true if we have the given command(s)
we_have() { type "$@" >/dev/null 2>&1; }
# Usage: probe SERVER PORT|SERVICE
# returns true when SERVER has PORT opened (and responds within one second)
if we_have nc
then probe() { nc -zw1 "$@" >/dev/null 2>&1; }
else probe() { echo X |telnet -e X "$@" >/dev/null 2>&1; }
fi
# Usage: poke SERVER [PORT|SERVICE]
# As probe. Also: PORT defaults to 80 (http) and reports the result
poke() {
local RETVAL STATUS
probe "$1" "${2:-80}"
RETVAL=$?
if [ $RETVAL != 0 ]; then
STATUS=" not"
fi
echo "could$STATUS connect to port ${2:-80} on host '$1'"
return $RETVAL
}
Это поддерживает номера портов и любые имена сервисов, проиндексированные в /etc/services
. (Будьте внимательны, чтобы проверить это; если ваш тест не пройден из-за неверного имени службы, вы не узнаете.)
Некоторые примеры тестов:
$ poke localhost ssh
could connect to port ssh on host 'localhost'
$ poke localhost 12345
could not connect to port 12345 on host 'localhost'
Используйте probe
если вы хотите написать что-то только с возвращаемым значением, например
if probe localhost ssh; then
echo something contingent on hosting ssh goes here
fi
Если у вас установлена nmap
версии 5+, вы можете использовать вместо команды ncat --send-only --recv-only -w 334ms $1 $2
команду nc
. Это терпит неудачу быстрее (я остановился на 334 мс. Nc разрешает только с точностью до секунды, так что вы застряли в ожидании целую секунду).
Обратите внимание, что это не проверяет, что размещается, только то, что порт открыт. 99% времени это достаточно хорошо Если вам нужно больше, попробуйте что-то вроде этого:
nmap -sV -p ssh localhost |grep -qi 'open.*ssh.*ssh[^?]'
Это скажет nmap сканировать порт ssh (22) на сервере localhost и определить информацию о сервисе / версии. В моей системе без grep он сообщает:
Starting Nmap 6.40 ( http://nmap.org ) at 2014-02-14 17:01 PST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000048s latency).
Other addresses for localhost (not scanned): 127.0.0.1
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 6.4p1 Debian 2 (protocol 2.0)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 0.24 seconds
Таким образом, команда grep просматривает первый экземпляр SSH (который просто указывает на соответствие в /etc /services) на хост-сервер и информацию о версии, которая должна соответствовать "ssh" (без учета регистра). Флаг -q
просто подавляет вывод (так что это может заменить probe
). Если nmap не может понять, что это за сервис, он скажет ssh?
, поэтому регулярное выражение grep избегает совпадения с этим.
Давайте объединим их, чтобы сделать это быстро, но все же проверять, действительно ли SSH обслуживается:
# Usage: vet_ssh SERVER [PORT|SERVICE]
# True when SERVER has PORT (default=22) both opened and serving SSH
vet_ssh() {
probe $1 ${2:-22} && nmap -sV -p ${2:-22} $1 |grep -qiE 'open.....*ssh[^?]'
}
Теперь вы можете использовать vet_ssh
вместо probe
в функции poke
Это будет почти так же быстро, как моя оригинальная функция poke
: это та же скорость, когда порт не открыт, немного медленнее, когда порт открыт и обслуживает SSH, и прилично медленнее, когда открыт и обслуживает что-то, что nmap не может быстро распознать (или вообще). Регулярное выражение grep здесь немного отличается для размещения альтернативных портов.
В случае, если я полностью неверно истолковал ваш вопрос ... если вы хотите узнать, подключены ли вы к этому серверу (а не могли ли вы это сделать), используйте netstat
следующим образом:
# Usage: am_i_sshed_to SERVER [PORT|SERVICE]
# True when you have an established connection to SERVER on PORT (default=22)
am_i_sshed_to() {
local IP_QUERY=`host "$1" |awk -v port="${2:-22}" '
$2 != "mail" { printf "-e %s:%s ", $NF, port }
'`
netstat -tn |grep -w $IP_QUERY |grep -wq ESTABLISHED
}
Затем вы можете использовать am_i_sshed_to
таким же образом, как probe
или vet_ssh
.
(Пояснение: netstat
очень долго ищет каждый адрес. Нам нужен только один поиск для одного сервера, который мы хотим проверить, поэтому мы кешируем его в первой строке. Команда awk
говорит, что любая строка, не обсуждающая доставку почты, должна заканчиваться ($NF
) в IP. Сделайте это запросом grep для нашего предстоящего вызова netstat, поэтому 1.2.3.4
становится, например, -e 1.2.3.4:22
и мы можем иметь несколько IP-адресов (до нескольких сотен, прежде чем мы достигнем ограничений размера командной строки). Затем мы запускаем netstat, смотря только на TCP-соединения и ничего не сопоставляя с именем. Мы подбираем слова (не совпадающие с «11.2.3.4:22» или «1.2.3.4:2234») для нашего кэшированного запроса (обратите внимание на преднамеренное отсутствие кавычек, они нам не нужны, и они изменят структуру аргумента !) и затем убедитесь, что соединение все еще установлено. Опять же, у grep -q
нет вывода, так что это замена для probe
но не для poke
)