사용하지 않는 로컬 포트를 찾는 가장 쉬운 방법은 무엇입니까?

사용하지 않는 로컬 포트를 찾는 가장 쉬운 방법은 무엇입니까?

사용하지 않는 로컬 포트를 찾는 가장 쉬운 방법은 무엇입니까?

현재 나는 다음과 같은 것을 사용하고 있습니다 :

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

매우 우회적인 느낌이 들기 때문에 내가 놓친 내장 경로와 같은 더 쉬운 경로가 있는지 궁금합니다.

답변1

내 솔루션은 커널이 ip_local_port_range에서 포트를 할당해야 하는 포트 0에 바인딩하는 것이었습니다. 그런 다음 소켓을 닫고 구성에서 해당 포트 번호를 사용하십시오.

이는 꼭 필요한 경우가 아니면 커널이 포트 번호를 재사용하지 않는 것 같기 때문에 작동합니다. 포트 0에 대한 후속 바인딩에는 다른 포트 번호가 할당됩니다. 파이썬 코드:

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 0))
addr = s.getsockname()
print(addr[1])
s.close()

이것은 단지 포트 번호를 제공합니다. 60123.

이 프로그램을 10,000번 실행하면(이 프로그램을 동시에 실행해야 함) 10,000개의 다른 포트 번호를 얻게 됩니다. 그래서 저는 이 포트를 사용하는 것이 꽤 안전하다고 생각합니다.

답변2

애플리케이션이 이를 지원하는 경우 포트 0을 애플리케이션에 전달해 볼 수 있습니다. 애플리케이션이 이를 커널에 전달하면 요청 시 포트가 동적으로 할당되고 사용되지 않는 것이 보장됩니다(모든 포트가 이미 사용 중이면 할당이 실패합니다).

그렇지 않으면 이 작업을 수동으로 수행할 수 있습니다. 답변의 스크립트에는 경쟁 조건이 있으며 이를 피하는 유일한 방법은 열려고 시도하여 열려 있는지 자동으로 확인하는 것입니다. 포트가 사용 중인 경우 포트를 열지 못한 채 프로그램이 종료되어야 합니다.

예를 들어, GNU netcat을 사용하여 수신하려고 한다고 가정합니다.

#!/bin/bash
read lower_port upper_port < /proc/sys/net/ipv4/ip_local_port_range
while :; do
    for (( port = lower_port ; port <= upper_port ; port++ )); do
        nc -l -p "$port" 2>/dev/null && break 2
    done
done

답변3

하나의 선

나는 모든 범위에서 원하는 수의 포트를 스크랩할 수 있도록 신속하게 트릭을 수행하는 멋진 한 줄짜리 코드를 구성했습니다(가독성을 위해 여기서는 4줄로 분할).

comm -23 \
<(seq "$FROM" "$TO" | sort) \
<(ss -Htan | awk '{print $4}' | cut -d':' -f2 | sort -u) \
| shuf | head -n "$HOWMANY"

한 줄씩

comm알파벳 순서로 정렬되어야 하는 두 파일의 줄을 비교하는 유틸리티입니다. 세 개의 열(첫 번째 파일에만 나타나는 줄, 두 번째 파일에만 나타나는 줄, 공통 줄)을 출력합니다. 지정하면 -23다음 열을 억제하고 첫 번째 열만 유지합니다. 이를 사용하여 일련의 텍스트 줄로 표현된 두 세트의 차이를 얻을 수 있습니다. 나는 배웠다comm 여기.

첫 번째 파일은 선택할 수 있는 포트 범위입니다. 에서 까지 seq정렬된 숫자 시퀀스를 생성합니다. 결과는 숫자순이 아닌 알파벳순으로 정렬되고 첫 번째 파일로 파이프됩니다.$FROM$TOcommcomm프로세스 교체.

두 번째 파일은 명령을 호출하여 얻은 정렬된 포트 목록입니다 ss( -tTCP 포트를 의미하며 -a모든 포트는 설정되고 수신되며 -n숫자는 구문 분석을 시도하지 않음을 의미함 22) ssh. 그런 다음 awk로컬 주소와 포트가 포함된 네 번째 열만 선택합니다 . 구분 기호를 사용하여 cut주소와 포트를 구분하고 :후자( -f2)만 남깁니다. 그런 다음 요구 사항을 복제하지 않음으로써 요구 사항을 준수합니다 comm.sort-u

shuf이제 첫 번째 "$HOWMANY"포트를 얻는 데 사용할 수 있는 열려 있는 포트의 정렬된 목록이 있습니다 head -n.

개인 범위(49152-65535)에서 임의의 열린 포트 3개를 확보합니다.

comm -23 <(seq 49152 65535 | sort) <(ss -Htan | awk '{print $4}' | cut -d':' -f2 | sort -u) | shuf | head -n 3

예를 들어 다음과 같이 반환할 수 있습니다.

54930
57937
51399

노트

  • 무료 UDP 포트를 얻으려면 대신 in을 -t사용하세요 .-uss
  • 사용 가능한 포트를 무작위가 아닌 숫자로 정렬하려면 다음 shuf으로 바꾸십시오.sort -n

답변4

#!/bin/bash
read LOWERPORT UPPERPORT < /proc/sys/net/ipv4/ip_local_port_range
while :
do
        PORT="`shuf -i $LOWERPORT-$UPPERPORT -n 1`"
        ss -lpna | grep -q ":$PORT " || break
done
echo $PORT


"ss -lpn" - 연결이 설정된 포트만 표시합니다.
"ss -lpna"를 사용하여 수신 포트도 고려해야 합니다 .

Chris Dunn의 크레딧

관련 정보