Estou procurando um método rápido e simples para testar adequadamente se uma determinada porta TCP está aberta em um servidor remoto, de dentro de um script do Shell.
Eu consegui fazer isso com o comando telnet, e funciona bem quando a porta é aberta, mas parece que o tempo limite não está disponível e fica travado ...
Aqui está uma amostra:
l_TELNET=`echo "quit" | telnet $SERVER $PORT | grep "Escape character is"`
if [ "$?" -ne 0 ]; then
echo "Connection to $SERVER on port $PORT failed"
exit 1
else
echo "Connection to $SERVER on port $PORT succeeded"
exit 0
fi
Eu preciso de uma maneira melhor ou de forçar o tempo limite do telnet se ele não se conectar em menos de 8 segundos, por exemplo, e retornar algo que eu possa pegar no Shell (código de retorno ou string no stdout).
Conheço o método Perl, que usa o módulo IO :: Socket :: INET e escreveu um script bem-sucedido que testa uma porta, mas prefere evitar o uso de Perl, se possível.
Nota: É disso que meu servidor está sendo executado (de onde eu preciso executar isso)
SunOS 5.10 Genérico_139556-08 i86pc i386 i86pc
Respostas:
Como apontado por B. Rhodes,
nc
fará o trabalho. Uma maneira mais compacta de usá-lo:Dessa forma
nc
, apenas será verificado se a porta está aberta, saindo com 0 em caso de sucesso, 1 em caso de falha.Para uma verificação interativa rápida (com um intervalo de 5 segundos):
fonte
-G#
para definir um tempo limite de conexão separado / além do-w#
tempo limite, que basicamente funciona como um tempo limite de leitura.-z
opção. Você pode considerar: unix.stackexchange.com/questions/393762/…É fácil o suficiente para fazer com os
-z
e-w TIMEOUT
opções paranc
, mas nem todos os sistemas tenhamnc
instalado. Se você possui uma versão recente o suficiente do bash, isso funcionará:O que está acontecendo aqui é que
timeout
executará o subcomando e o matará se ele não sair dentro do tempo limite especificado (1 segundo no exemplo acima). Nesse caso,bash
é o subcomando e usa seu tratamento especial / dev / tcp para tentar abrir uma conexão com o servidor e a porta especificados. Sebash
conseguir abrir a conexão dentro do tempo limite,cat
apenas a feche imediatamente (já que está lendo a partir de/dev/null
) e sairá com um código de status0
que será propagado atravésbash
e depoistimeout
. Se houverbash
uma falha na conexão antes do tempo limite especificado,bash
será encerrado com um código de saída 1, quetimeout
também retornará. E se o bash não conseguir estabelecer uma conexão e o tempo limite especificado expirar,timeout
matarábash
e sairá com um status de 124.fonte
/dev/tcp
disponível em sistemas diferentes do Linux? E os Macs em particular?timeout
também não existe no FreeBSD, e na minha antiga caixa do Ubuntu é um pacote instalável, mas não existe por padrão. Seria ótimo se houvesse uma maneira de fazer isso apenas no bash, sem ferramentas de terceiros, como timeout ou netcat.timeout
parece ser parte de coreutils GNU, e pode ser instalado em Macs com homebrew:brew install coreutils
. Ele estará disponível comogtimeout
.bash-2.04-devel
, embora o suporte a nomes de host possa ter sido adicionadobash-2.05-alpha1
.TOC:
timeout
nc
Usando bash e
timeout
:Observe que ele
timeout
deve estar presente no RHEL 6+ ou é encontrado alternativamente no GNU coreutils 8.22. No MacOS, instale-o usandobrew install coreutils
e use-o comogtimeout
.Comando:
Se você estiver parametrizando o host e a porta, especifique-os como
${HOST}
e${PORT}
acima. Não os especifique meramente como$HOST
e$PORT
, ou seja, sem os aparelhos; não vai funcionar neste caso.Exemplo:
Sucesso:
Falha:
Se você deve preservar o status de saída de
bash
,Usando
nc
:Observe que uma versão incompatível com versões anteriores
nc
é instalada no RHEL 7.Comando:
Observe que o comando abaixo é único, pois é idêntico para o RHEL 6 e 7. É apenas a instalação e a saída que são diferentes.
RHEL 6 (nc-1,84):
Instalação:
Exemplos:
Sucesso: Falha:Se o nome do host for mapeado para vários IPs, o comando com falha acima percorrerá muitos ou todos eles. Por exemplo:
RHEL 7 (nmap-ncat-6.40):
Instalação:
Exemplos:
Sucesso: Falha:Se o nome do host for mapeado para vários IPs, o comando com falha acima percorrerá muitos ou todos eles. Por exemplo:
Observações:
O argumento
-v
(--verbose
) e oecho $?
comando são obviamente apenas para ilustração.fonte
timeout 2 bash -c "</dev/tcp/canyouseeme.org/81"; echo $?
é um ótimo ponto!2>&1
a não echo estadoresult_test=$(nc -w 2 $ip_addreess 80 </dev/null 2>&1 ; echo $?)
Com
netcat
você pode verificar se uma porta está aberta assim:O valor de retorno
nc
será bem-sucedido se a porta TCP for aberta e falhará (normalmente o código de retorno 1) se não puder estabelecer a conexão TCP.Algumas versões
nc
serão interrompidas quando você tentar isso, porque elas não fecham a metade do soquete de envio mesmo depois de receber o final do arquivo/dev/null
. No meu próprio laptop Ubuntu (18.04), anetcat-openbsd
versão do netcat que eu instalei oferece uma solução alternativa: a-N
opção é necessária para obter um resultado imediato:fonte
nc
que não suportam a-w
bandeira.-z
suporte - funciona no RHEL / CentOS 7, por exemplo #-w
é necessária, caso contrário, o comando quando usado em um script pode travar por mais de dez segundos. Eu escrevi uma resposta que inclui-w
.nc host port -w 2 && echo it works
nc -vz localhost 3306
. Dá uma saída mais detalhada. Tentei apenas no mac.No Bash, usar arquivos de pseudo-dispositivo para conexões TCP / UDP é direto. Aqui está o script:
Teste:
Aqui está uma linha (sintaxe do Bash):
Observe que alguns servidores podem ser protegidos por firewall contra ataques de inundação SYN; portanto, você pode experimentar um tempo limite de conexão TCP (~ 75seg). Para solucionar o problema de tempo limite, tente:
Consulte: Como diminuir o tempo limite da chamada do sistema TCP connect ()?
fonte
telnet canyouseeme.org 81
também trava. Isso é controlado pelos seus limites de tempo limite, que provavelmente são codificados no bash. Consulte: diminuir o tempo limite da chamada do sistema TCP connect () .$SERVER
e$PORT
com chaves, pelo menos como${SERVER}
e${PORT}
.Eu precisava de uma solução mais flexível para trabalhar em vários repositórios git, então escrevi o seguinte código sh com base em 1 e 2 . Você pode usar o endereço do servidor em vez do gitlab.com e sua porta em substituição a 22.
fonte
Se você estiver usando o ksh ou o bash , ambos suportam o redirecionamento de E / S para / de um soquete usando a construção / dev / tcp / IP / PORT . Neste shell Korn exemplo, eu estou redirecionando não-op de ( : ) std-in de um soquete:
O shell imprime um erro se o soquete não estiver aberto:
Portanto, você pode usar isso como teste em uma condição if :
O no-op está em um subshell para que eu possa jogar fora o std-err se o redirecionamento do std-in falhar.
Costumo usar / dev / tcp para verificar a disponibilidade de um recurso por HTTP:
Essa linha única abre o descritor de arquivo 9 para leitura e gravação no soquete, imprime o HTTP GET no soquete e usa
cat
para ler a partir do soquete.fonte
</dev/tcp/canyouseeme.org/80
e depois</dev/tcp/canyouseeme.org/81
.Embora seja uma pergunta antiga, acabei de lidar com uma variante, mas nenhuma das soluções aqui era aplicável, então encontrei outra e a adicionei para a posteridade. Sim, eu sei que o OP disse que eles estavam cientes dessa opção e que não era adequada a eles, mas para qualquer um que a seguir poderá ser útil.
No meu caso, quero testar a disponibilidade de um
apt-cacher-ng
serviço local a partir de umadocker
compilação. Isso significa que absolutamente nada pode ser instalado antes do teste. Nãonc
,nmap
,expect
,telnet
oupython
.perl
no entanto, está presente, junto com as bibliotecas principais, então usei isso:fonte
Em alguns casos em que ferramentas como curl, telnet, nc ou nmap estão indisponíveis, você ainda tem uma chance com o wget
fonte
verifique as portas usando o bash
Exemplo
a porta 22 está aberta
Código
fonte
Se você deseja usar,
nc
mas não possui uma versão compatível-z
, tente usar--send-only
:e com tempo limite:
e sem pesquisa de DNS, se for um IP:
Ele retorna os códigos com
-z
base em se ele pode se conectar ou não.fonte
Suponho que seja tarde demais para uma resposta, e isso pode não ser bom, mas aqui está ...
Que tal colocá-lo dentro de um loop while com um cronômetro de algum tipo. Sou mais cara do Perl do que o Solaris, mas dependendo do shell que você estiver usando, você poderá fazer algo como:
Depois, basta adicionar um sinalizador no loop while, para que, se o tempo limite exceder o tempo limite, você pode citar o tempo limite como motivo da falha.
Suspeito que o telnet também tenha um interruptor de tempo limite, mas no topo da minha cabeça, acho que o exposto acima funcionará.
fonte
Eu precisava de um script curto, que foi executado no cron e não tem saída. Resolvo meu problema usando o nmap
Para executá-lo Você deve instalar o nmap porque não é o pacote instalado padrão.
fonte
nmap
A saída grepable de também pode ser útil-oG -
para enviá-la ao stdout. (o grep iria precisar de um bit de alteração)Isso usa o telnet nos bastidores e parece funcionar bem no mac / linux. Ele não usa o netcat devido às diferenças entre as versões no linux / mac, e isso funciona com uma instalação padrão do mac.
Exemplo:
is_port_open.sh
fonte
Com base na resposta mais votada, aqui está uma função para aguardar a abertura de duas portas, com um tempo limite também. Observe as duas portas que devem estar abertas, 8890 e 1111, bem como as max_attempts (1 por segundo).
fonte
nmap-ncat para testar a porta local que ainda não está em uso
fonte