未使用のローカルポートを見つける最も簡単な方法は何ですか?
現在私は次のようなものを使用しています:
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 の後続バインディングには別のポート番号が割り当てられます。 Pythonコード:
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
一つの線
私はすべての範囲で必要な数のポートをスクラップするためにトリックをすばやく実行する素晴らしい1行コードを設定しました(読みやすくするためにここでは4行に分割)。
comm -23 \
<(seq "$FROM" "$TO" | sort) \
<(ss -Htan | awk '{print $4}' | cut -d':' -f2 | sort -u) \
| shuf | head -n "$HOWMANY"
一行ずつ
comm
アルファベット順にソートする必要がある2つのファイルの行を比較するユーティリティ。 3つの列(最初のファイルにのみ表示される行、2番目のファイルにのみ表示される行、共通行)を出力します。指定すると、-23
次の列を抑制し、最初の列のみを保持します。これを使用して、一連のテキスト行で表される2つのセットの違いを得ることができます。私は学んだcomm
ここ。
最初のファイルは選択できるポート範囲です。から順にseq
並べられた数値シーケンスを生成します。結果は、数値順ではなくアルファベット順にソートされ、最初のファイルにパイプされます。$FROM
$TO
comm
comm
プロセスの交換。
2番目のファイルは、コマンドを呼び出すことによって得られたソートされたポートのリストですss
(-t
TCPポートを意味し、-a
すべてのポートが設定および受信され、-n
数字は解析を試みないことを意味します22
)ssh
。次に、awk
ローカルアドレスとポートを含む4番目の列のみを選択します。区切り文字を使用して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
使用してください。-u
ss
- 使用可能なポートをランダムではない数字で並べ替えるには、次のよう
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のクレジット