惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
F
Fortinet All Blogs
量子位
G
Google Developers Blog
J
Java Code Geeks
N
Netflix TechBlog - Medium
博客园 - 聂微东
宝玉的分享
宝玉的分享
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
月光博客
月光博客
The Cloudflare Blog
Apple Machine Learning Research
Apple Machine Learning Research
爱范儿
爱范儿
雷峰网
雷峰网
M
MIT News - Artificial intelligence
T
Tailwind CSS Blog
V
Visual Studio Blog
阮一峰的网络日志
阮一峰的网络日志
博客园 - 三生石上(FineUI控件)
Microsoft Azure Blog
Microsoft Azure Blog
aimingoo的专栏
aimingoo的专栏
Martin Fowler
Martin Fowler
有赞技术团队
有赞技术团队
T
The Blog of Author Tim Ferriss

hsfzxjy 的博客

解决 VSCode + CMake + MSVC 编译器信息乱码的问题 使用 3090 部署 1.58bit 动态量化版 DeepSeek R1 671b 如何在 VS Code DevContainer 中配置 HTTP 代理 如何在跳板机背后的服务器上使用 VS Code Remote - Containers Cohesive Digests for Ints and Floats Rust 中的隐匿概念 —— Place(位置) 美术馆 一尺之槌,日取其半,1075日而竭 老生常谈:使用 Cloudflare 自选 IP 加速站点访问 辩义 State、Nation 与 Country 将 Base64 编码的数据快速转换为 Uint8Array 折腾 NPU·第1章 —— 搭建 Level Zero 开发环境 折腾 NPU·第0章 —— Intel NPU 概述与 Level-Zero 新增域名 monad.run CSS 中为特定字符设置不同字体 Arbitary Lifetime Transmutation via Rust Unsoundness Dijkstra 算法的延伸 Manacher 回文计数算法 硬卧 Go Fact: Zero-sized Field at the Rear of a Struct Has Non-zero Size Display *big.Rat Losslessly and Smartly in Golang 代码的仪式 Building Electron From Scratch 中式亲属称谓研究之一:构建半群 Some Notes on Kotlin Coroutines Git sparse-checkout and partial clones for Mega-Repos 辩义“封建” Diving from the CUDA Error 804 into a bug of libnvidia-container Modern Cryptography, GPG and Integration with Git(hub) Move the Root Partition of Ubuntu
Obtain a Random Available TCP Port with Bash
2021-03-10 · via hsfzxjy 的博客

On Linux, we might sometimes want to choose an unused TCP port randomly. This occurs from time to time on a server, when the administrator wants to expose an HTTP port for a user. Or, you just need an available port for IPC. Let’s make it happen with pure bash scripting.

function unused_port() {
N=${1:-1}
comm -23 \
<(seq "1025" "65535" | sort) \
<(ss -Htan |
awk '{print $4}' |
cut -d':' -f2 |
sort -u) |
shuf |
head -n "$N"
}

We would take apart the function step by step in the following paragraphs.

Tirst step is to obtain a list of occupied ports, which can be accomplished by command

ss is a tool for investigating sockets, which prints out ports currently used in the form of a table:

State        Recv-Q   Send-Q                               Local Address:Port                              Peer Address:Port               Process
ESTAB 0 0 127.0.0.1:45342 127.0.0.1:1081
...

Argument -Htan controls the printing style of ss. -H removes table header; -t lists only TCP ports; -a lists all ports, including listening and unlistening ones; -n enforces ports to be printed numerically 1. The command produces an output like:

LISTEN       0        128                                        0.0.0.0:17500                                            0.0.0.0:*
LISTEN 0 128 127.0.0.1:17600 0.0.0.0:*

We then use some string manipulation tools to extract the port numbers:

ss -Htan |

awk '{print $4}' |
cut -d':' -f2 |
sort -u

Here, awk '{print $4}' selects the 4th item (e.g., 0.0.0.0:17500) from each line. cut -d':' -f2 splits each item with : and prints out the second part (e.g., 17500). sort -u sorts the items and removes duplicated ones.

Now we’ve got the list of unavailable ports. We might name it as LIST2 for simplicity. The next step is to create another list LIST1 by “inversing” LIST2. By “inversing” we mean LIST1 (disjointly) unioning LIST2 would be equal to FULLLIST (all legal ports).

FULLLIST can be obtained easily with seq "1025" "65535" | sort. The “inverse” operation, meanwhile, can be achieved using comm.

Simply, comm takes two files FILE1 and FILE2 as input, and produces output with three columns:

  • Column 1 contains lines unique to FILE1;
  • Column 2 contains lines unique to FILE2;
  • Column 3 contains lines common to both files.

Apparently we only needs the first column, so use -23 to suppress the other two ones. Put them together as:

comm -23 \
<(seq "1025" "65535" | sort) \
<(ss -Htan |
awk '{print $4}' |
cut -d':' -f2 |
sort -u)

The syntax <(command) is known as process substitution. It is equivalent to:

  • Spawn command in current shell and pipe its stdout to /dev/fd/<some number>;
  • Substitute <(...) with /dev/fd/<some number>.

The last step, we further incorporate the command into a convenient function.


function unused_port() {
N=${1:-1}

comm -23 \
<(seq "1025" "65535" | sort) \
<(ss -Htan |
awk '{print $4}' |
cut -d':' -f2 |
sort -u) |

shuf |
head -n "$N"

}

The function receives an argument N, shuffles the available port numbers, and choose N ports from the list.

Code is available at hsfzxjy/bashi on Github.

References


Author: hsfzxjy.
Link: .
License: CC BY-NC-ND 4.0.
All rights reserved by the author.
Commercial use of this post in any form is NOT permitted.
Non-commercial use of this post should be attributed with this block of text.