Эффективно проверить, открыт ли порт в Linux?


197

Из скрипта bash как быстро узнать, есть ли порт 445 / прослушивается на сервере.

Я попробовал несколько вариантов, но я хочу что-то быстрое:
1. lsof -i :445 (занимает секунды)
2. netstat -an |grep 445 |grep LISTEN(занимает секунды)
3. telnet(не возвращается)
4. nmap, netcatнедоступны на сервере

Было бы хорошо узнать способ, который не перечисляет сначала и greps после этого.


1
Доступен ли netcat? У него есть быстрый путь отказа IIRC. netcat.sourceforge.net
JimR

5
netstat -lnt-tи без -a) ограничит вывод только прослушиванием TCP-соединений. Это может немного ускорить. Вы можете добавить -4IPv4, только если вам не нужен IPv6.
Бартош Мочульски

lsof -i - личный фаворит.
Мэтт Джойс

14
netstat -an | grep PORTNUMBER | grep -i listenЕсли вывод пуст, порт не используется.
automatix

Я не знаю, почему lsofэто медленно для вас, но обычно это лучшее из перечисленных вами решений. Ваше netstatрешение не очень надежно (вы можете угадать его всякий раз, когда используете grep; в любом случае оно возвращает true, если кто-то слушает, например, 4450). telnetи на netcatсамом деле попытаться создать соединение, которое не всегда может быть тем, что вы хотите.
Петерсон

Ответы:


155

Удивление, которое я недавно узнал, заключается в том, что Bash изначально поддерживает tcp-соединения в качестве дескрипторов файлов . Использовать:

exec 6<>/dev/tcp/ip.addr.of.server/445
echo -e "GET / HTTP/1.0\n" >&6
cat <&6

Я использую 6 в качестве дескриптора файла, потому что 0,1,2 - это stdin, stdout и stderr. 5 иногда используется Bash для дочерних процессов , поэтому 3,4,6,7,8 и 9 должны быть безопасными.

В соответствии с комментарием ниже, чтобы проверить прослушивание на локальном сервере в сценарии:

exec 6<>/dev/tcp/127.0.0.1/445 || echo "No one is listening!"
exec 6>&- # close output connection
exec 6<&- # close input connection

Чтобы определить, слушает ли кто-то, попытайтесь подключиться с помощью обратной связи. Если это не удается, то порт закрыт или нам не разрешен доступ. После этого закройте соединение.

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


2
Это просто повешено для меня.
Аман Джайн

@AmanJain cat ждет выхода EOF или Ctrl-C. Вам нужно будет настроить это для вашего протокола. Кстати вы запускаете это на удаленный сервер?
Спенсер Ратбун,

Я хочу встроить код проверки порта в скрипт на сервере, в /etc/init.d/
Aman Jain

@ AmanJain Я обновил его для локальной системы. Вы просто хотите проверить правильность прослушивания? Нет проверки протокола, например, запросить страницу через http?
Спенсер Рэтбун,

1
Это не надежный метод, так как не все ОС (например, Ubuntu 16, как я обнаружил сегодня) поставляются с bash, скомпилированным для построения /dev/tcp/IP/PORTдерева
dyasny

107

Здесь есть очень короткий термин «быстрый ответ»: как проверить, открыт ли удаленный порт TCP из сценария Shell?

nc -z <host> <port>; echo $?

Я использую его с 127.0.0.1 в качестве «удаленного» адреса.

возвращает «0», если порт открыт, и «1», если порт закрыт.

например

nc -z 127.0.0.1 80; echo $?

-z Указывает, что nc должен просто сканировать прослушивающие демоны, не отправляя им никаких данных. Ошибочно использовать эту опцию в сочетании с опцией -l.


2
Кажется, это самый простой способ, спасибо. Ссылка на образец скрипта больше не работает, но все же довольно самоочевидна.
derFunk

Ницца! Это намного быстрее, чем другие ответы на сервере с множеством открытых портов. Возврат за <0,01 секунды для меня, в то время как netstat / lsof займет 1 с +
Тим

2
Флаг -z недоступен в ncat на основе nmap, с которым поставляются самые последние дистрибутивы: Fedora, Centos и т. Д. (Nmap-ncat-6.01-9.fc18.x86_64)
Зак

9
Необычно, это возвращает «0», если порт открыт, и «1», если порт закрыт.
Шон

3
Команды @Sean unix обычно возвращают «0» для обозначения успеха и ненулевое значение для сбоя. Таким образом, «0» указывает, что он успешно подключен и ненулевой, что он не подключился по какой-то причине. Обратите внимание, однако, что некоторые версии 'nc' не поддерживают аргумент '-z', поэтому stackoverflow.com/a/25793128/6773916 , возможно, является лучшим решением.
Рич Седман,

89

Вы можете использовать netstat таким образом для более быстрых результатов:

В Linux:

netstat -lnt | awk '$6 == "LISTEN" && $4 ~ /\.445$/'

На Mac:

netstat -anp tcp | awk '$6 == "LISTEN" && $4 ~ /\.445$/'

Это выведет список процессов, прослушивающих порт (445 в этом примере), или ничего не выведет, если порт свободен.


1
Ваш синтаксис netstat неверен. netstat -ln --tcp работает, но все еще медленно
Аман Джайн

6
На самом деле это правильный синтаксис, но, вероятно, вы используете Linux, а я на Mac. Для Linux используйте это:netstat -lnt | awk '$6 == "LISTEN" && $4 ~ ".445"'
anubhava

21
это ничего не выводило.
Юрген Павел

1
Вопрос был о Linux, хотя, возможно, комментарий должен быть в ответе.
UpTheCreek,

1
Для проверки на порт 80 мне нужно было использовать awk '$6 == "LISTEN" && $4 ~ "80$"'. Вместо проверки точки перед номером порта с помощью \.80я использовал 80$. В противном случае это также соответствует IP-адресам, содержащим .80и порты, начинающиеся с 80таких как 8000.
Патрик Осци

37

Вы можете использовать Netcat для этого.

nc ip port < /dev/null

подключается к серверу и снова напрямую закрывает соединение. Если netcat не может подключиться, он возвращает ненулевой код завершения. Код выхода хранится в переменной $ ?. Например,

nc ip port < /dev/null; echo $?

вернет 0, если и только если netcat может успешно подключиться к порту.


1
Этот ответ нуждается в большем количестве голосов. nc отлично работает в этом случае. трюк / dev / tcp умный, но кажется сложным реализовать скрипт с прерываниями сигнала.
Авиндра Гулчаран

5
ncимеет -zфлаг для этой цели, который не требует ввода от /dev/null. Там уже ответ, используя -zфлаг выше.
Абе Воелкер,

2
@AbeVoelker Не все версии nc поддерживают флаг -z. Я нахожусь на CentOS 7 и нашел решение Тони, что мне нужно.
Шадониня,

@Shadoninja Хорошо знать! Если бы я мог изменить легкомысленность из моего комментария от 2014 года, я бы сделал.
Абе Воелкер,

«nc» больше не поддерживает «-z», поэтому этот ответ кажется лучшим решением.
Рич Седман,

18

Основываясь на ответе Спенсера Рэтбуна, используя bash:

true &>/dev/null </dev/tcp/127.0.0.1/$PORT && echo open || echo closed

Хорошо, это подавит сообщение «Соединение отказано». Автоматический выход, если служба принимает соединение без ожидания навсегда.
Seff

Лучшее решение для служб, которые не отправляют данные после нового подключения. Примерно в 20 раз быстрее, чем вызов netcat. Может быть сокращен до: &>/dev/null </dev/tcp/127.0.0.1/$PORT
Энс

16

они перечислены в / proc / net / tcp.

это второй столбец после ":" в шестнадцатеричном виде:

> cat /proc/net/tcp
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode                                                     
   0: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 10863 1 ffff88020c785400 99 0 0 10 -1                     
   1: 0100007F:0277 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 7983 1 ffff88020eb7b3c0 99 0 0 10 -1                      
   2: 0500010A:948F 0900010A:2328 01 00000000:00000000 02:00000576 00000000  1000        0 10562454 2 ffff88010040f7c0 22 3 30 5 3                   
   3: 0500010A:E077 5F2F7D4A:0050 01 00000000:00000000 02:00000176 00000000  1000        0 10701021 2 ffff880100474080 41 3 22 10 -1                 
   4: 0500010A:8773 16EC97D1:0050 01 00000000:00000000 02:00000BDC 00000000  1000        0 10700849 2 ffff880104335440 57 3 18 10 -1                 
   5: 0500010A:8772 16EC97D1:0050 01 00000000:00000000 02:00000BF5 00000000  1000        0 10698952 2 ffff88010040e440 46 3 0 10 -1                  
   6: 0500010A:DD2C 0900010A:0016 01 00000000:00000000 02:0006E764 00000000  1000        0 9562907 2 ffff880104334740 22 3 30 5 4                    
   7: 0500010A:AAA4 6A717D4A:0050 08 00000000:00000001 02:00000929 00000000  1000        0 10696677 2 ffff880106cc77c0 45 3 0 10 -1  

так что я предполагаю, что один из них :50в третьем столбце должен быть stackoverflow: o)

искать man 5 procболее подробную информацию. и выбор этого вместе с sed и т. д. оставлен как упражнение для нежного читателя ...


10
ss -tl4 '( sport = :22 )'

2 мс достаточно быстро?

Добавьте двоеточие, и это работает на Linux


2
Великий, ssдаже немного быстрее, чем nc. lдля прослушивания , 4для IPv4; sportобозначает (конечно) исходный порт . Приведенная выше команда предполагает наличие прослушиваемого TCP-порта ( tопция): использовать uопцию для UDP или ни один из них для обоих протоколов. Больше информации ssкак всегда на Nixcraft . ПРИМЕЧАНИЕ: ssфильтры здесь не работают, не знаю почему (bash 4.3.11, утилита ss, iproute2-ss131122), должны идти с grep .
Кампа

Жаль, что ssкоманда не возвращает код завершения, отражающий ее нахождение; он всегда возвращает 0 код выхода.
Джон Грин

| grep LISTEN?
leucos

Я получаю State Recv-Q Send-Q Local Address:Port Peer Address:Portи сейчас? Что это значит?
Черный


6
nc -l 8000

Где 8000 - номер порта. Если порт свободен, он запустит сервер, который вы можете легко закрыть. Если это не так, он выдаст ошибку:

nc: Address already in use

5

Я хотел проверить, открыт ли порт на одном из наших тестовых серверов Linux. Я смог сделать это, пытаясь соединиться с telnet с моей машины разработчика на тестовый сервер. На твоей девайс машине попробуй запустить:

$ telnet test2.host.com 8080
Trying 05.066.137.184...
Connected to test2.host.com

В этом примере я хочу проверить, открыт ли порт 8080 на хосте test2.host.com


1

tcping - отличный инструмент с очень низкими издержками. У него также есть аргумент тайм-аута, чтобы ускорить его:

[root@centos_f831dfb3 ~]# tcping 10.86.151.175 22 -t 1
10.86.151.175 port 22 open.
[root@centos_f831dfb3 ~]# tcping 10.86.150.194 22 -t 1
10.86.150.194 port 22 user timeout.
[root@centos_f831dfb3 ~]# tcping 1.1.1.1 22 -t 1
1.1.1.1 port 22 closed.

1
Не уверен, что tcping стоит устанавливать, когда решение Spencer не требует дополнительных установок, но это определенно самое чистое и удобочитаемое решение.
bdombro

1

Вы также можете использовать команду netcat

[location of netcat]/netcat -zv [ip] [port]

или

nc -zv [ip] [port]

-z - устанавливает nc для простого сканирования на предмет прослушивания демонов, без фактической отправки им данных.
-v - включает подробный режим.


-2

nmapэто правильный инструмент. Просто используйтеnmap example.com -p 80

Вы можете использовать его с локального или удаленного сервера. Это также поможет вам определить, блокирует ли доступ брандмауэр.


-4

Если вы используете iptables, попробуйте:

iptables -nL

или

iptables -nL | grep 445

это просто перечисляет правила iptables ... которые могут не иметь отношения к открытым портам.
Дэвид Гудвин
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.