Qual é a maneira mais fácil de encontrar uma porta local não utilizada?
Atualmente estou usando algo semelhante a este:
port=$RANDOM
quit=0
while [ "$quit" -ne 1 ]; do
netstat -a | grep $port >> /dev/null
if [ $? -gt 0 ]; then
quit=1
else
port=`expr $port + 1`
fi
done
Parece terrivelmente rotativo, então estou me perguntando se há um caminho mais simples, como um embutido, que eu perdi.
shell
networking
shell-script
netstat
mybuddymichael
fonte
fonte
-n
ao netstat e a um grep mais seletivo). A maneira de fazer isso é tentar abrir uma porta no modo que você precisar e tentar outra se ela não estiver disponível.ssh -D
como um servidor SOCKS.Respostas:
Se o seu aplicativo suportar, você pode tentar passar a porta 0 para o aplicativo. Se seu aplicativo passar isso para o kernel, a porta será alocada dinamicamente no momento da solicitação e é garantida que não esteja em uso (a alocação falhará se todas as portas já estiverem em uso).
Caso contrário, você pode fazer isso manualmente. O script na sua resposta tem uma condição de corrida, a única maneira de evitá-lo é verificar atomicamente se está aberto, tentando abri-lo. Se a porta estiver em uso, o programa deve sair com uma falha ao abrir a porta.
Por exemplo, diga que você está tentando ouvir com o GNU netcat.
fonte
$port
no programa real como emwhile ...; done; program --port $port
.Minha solução é ligar a porta 0, que solicita ao kernel que aloque uma porta a partir do ip_local_port_range. Em seguida, feche o soquete e use esse número de porta na sua configuração.
Isso funciona porque o kernel não parece reutilizar números de porta até que seja absolutamente necessário. As ligações subsequentes à porta 0 alocam um número de porta diferente. Código Python:
Isso fornece apenas um número de porta, por exemplo.
60123
.Execute este programa 10.000 vezes (você deve executá-los simultaneamente) e obterá 10.000 números de porta diferentes. Portanto, acho que é bastante seguro usar as portas.
fonte
python -c 'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()'
{ 1: 7006, 2: 1249, 3: 151, 4: 8, 5: 1, 6: 1}
ruby -e 'puts Addrinfo.tcp("", 0).bind { |s| s.local_address.ip_port }'
One-liner
Eu montei um belo one-liner que serve rapidamente a esse objetivo, permitindo pegar um número arbitrário de portas em um intervalo arbitrário (aqui está dividido em 4 linhas para facilitar a leitura):
Linha por linha
comm
é um utilitário que compara linhas em dois arquivos que devem aparecer classificados em ordem alfabética. Ele produz três colunas: linhas que aparecem apenas no primeiro arquivo, linhas que aparecem apenas no segundo arquivo e linhas comuns. Ao especificar-23
, suprimimos as últimas colunas e mantemos apenas a primeira. Podemos usar isso para obter a diferença de dois conjuntos, expressos como uma sequência de linhas de texto. Eu aprendi sobrecomm
aqui .O primeiro arquivo é o intervalo de portas que podemos selecionar.
seq
produz uma sequência classificada de números de$FROM
a$TO
. O resultado é classificado em ordem alfabética (em vez de numericamente) e canalizado paracomm
o primeiro arquivo usando a substituição do processo .O segundo arquivo é a lista ordenada de portas, que obtemos chamando o
ss
comando (com-t
as portas TCP intencionados,-a
que significa que todos - estabelecida e ouvir - e-n
numérico - não tentar resolver, por exemplo,22
assh
). Em seguida, escolhemos apenas a quarta coluna comawk
, que contém o endereço local e a porta. Usamoscut
para dividir endereço e porta com o:
delimitador e manter apenas o último (-f2
).ss
Também produzimos um cabeçalho, do qual nos livramos dogrep
ping para seqüências não vazias de números que não são maiores que 5. Em seguida, cumprimoscomm
o requisito desort
ing sem duplicatas-u
.Agora temos uma lista ordenada de portas abertas, que podemos
shuf
fle para, em seguida, pegar o primeiro"$HOWMANY"
aqueles comhead -n
.Exemplo
Pegue as três portas abertas aleatórias no intervalo privado (49152-65535)
poderia retornar por exemplo
Notas
-t
com-u
noss
para obter as portas UDP gratuitos vez.shuf
porsort -n
se você preferir obter as portas disponíveis ordenadas numericamente em vez de aleatoriamentefonte
Créditos a Chris Down
fonte
Aparentemente, as conexões TCP podem ser usadas como descritores de arquivo no linux a partir do bash / zsh. A função a seguir usa essa técnica e deve ser mais rápida do que chamar netcat / telnet.
Instruções de uso: Ligue a saída a uma variável e use em scripts. Testado no Ubuntu 16.04
fonte
ksh93
também.$[$LPORT + ($RANDOM % ($UPORT-$LPORT))]
.\n
para qualquer porta de escuta embora :) eu sugiro adicionar-n
. Isso ainda tentará abrir uma conexão, mas não enviará nada, mas será desconectado imediatamente.Aqui está um "oneliner" eficiente, multiplataforma, que consome todas as portas em uso e oferece o primeiro disponível a partir de 3000:
Você pode simplesmente juntar todas as linhas para tê-lo em uma linha. Se você deseja obter o primeiro disponível a partir de um número de porta diferente, altere a atribuição para
i
nofor
loop.Funciona em Mac e Linux, e é por isso que o
[:.]
regex é necessário.fonte
-a
e não-t
apenas olhar para os soquetes TCP (6)?ss -Htnl
pode ser melhor (e mais rápido! - não que eu me importe com isso: P).-t
, pelo menos aquele fornecido pela Apple ess
também não está presente no macOS.netstat -aln
até funciona no Solaris.No Linux, você pode fazer algo como:
Para encontrar a primeira porta livre acima de 1080. Observe que isso
ssh -D
seria vinculado à interface de loopback; portanto, em teoria, você poderia reutilizar a porta 1080 se um soquete a vincular a outro endereço. Outra maneira seria realmente tentar vinculá-lo:fonte
ssh -D
, não vejo melhor opção. A-O forward
opção dessh
não retorna um erro quando o encaminhamento falha.Esta é a versão que eu uso:
O comando
shuf -n 1 -i 49152-65535
fornece uma porta "aleatória" no intervalo dinâmico. Se já estiver sendo usado, outra porta nesse intervalo será tentada.O comando
netstat -atun
lista todas as portas (-a) TCP (-t) e UDP (-u) sem perder tempo para determinar os nomes de host (-n).fonte
Isso faz parte de uma função que tenho no meu .bashrc, que cria dinamicamente túneis SSH e tenta usar qualquer porta em um intervalo:
YMMV
fonte
Ainda outra corrida neste velho cavalo de hobby:
Este código faz uso puramente portátil de
netstat
,egrep
,awk
, e al. Observe que apenas a chamada é emitida para comandos externos, para obter uma lista das portas tomadas no início. Pode-se solicitar uma ou mais portas gratuitas:e comece em uma porta arbitrária:
fonte
Minha combinação de outras respostas acima. Pegue:
Com shuf -n1, pegamos um número aleatório do intervalo (-i) em / proc / sys / net / ipv4 / ip_local_port_range. Como o shuf precisa da sintaxe com traço, usamos tr para alterar a guia em um traço.
Em seguida, use o netstat para nos mostrar todas as conexões (-a) tcp e udp (-u -t) em números (-n), se encontrarmos nossa porta aleatória $ port nessa (inicie com a: e termine com w whitespace ( \ s) então precisamos de uma outra porta e então continue.Else (grep -q tem um código de retorno> 0, deixamos o loop while e $ port estão definidas.
fonte
Se você tem python por aí, eu faria o seguinte:
fonte
Escrevi este pequeno script Python2 / 3 que pode ajudá-lo na próxima vez:
https://github.com/sdenel/find-unused-local-port
fonte
Minha opinião ... a função tenta encontrar
n
portas livres consecutivas:fonte