我希望找到进程(例如apache2)正在侦听的端口,并且只将这个(tcp)端口号打印到一个文件file1.txt。
如何确保只有端口号(80),而不是'*',才是输出?
由Edit编辑以添加OP在评论中提供的重要信息:
请注意,此序列来自我的系统:
$ ss -atpln | grep apache2产出如下:
LISTEN 0 511 *:80 *:* users:(("apache2",pid=55338,fd=4),("apache2",pid=55337,fd=4),("apache2",pid=856,fd=4))发布于 2021-08-02 01:20:08
# ss -atpln | awk -F ':|[[:blank:]]+' '/apache2/ {print $5}'
443
443
443
80
80
80这使用冒号或一个或多个“空白”字符(即空格或制表符)作为字段分隔符,这意味着我们要打印的字段(端口号)现在是字段5。
没有必要使用grep,如果您已经在使用awk - awk很有能力在没有grep的帮助下完成模式匹配。
输出可能应该通过管道传输到sort -u,以便只打印唯一的端口号。
顺便说一句,如果您想知道为什么示例输出在443和80中各有三行,那么在我的系统中,apache2被配置为在端口80和443上侦听三个不同的IP地址(三个不同的vhost),而不仅仅是在*:80和*:443上。
发布于 2021-08-02 19:54:35
我将使用perl并对输入进行更显式的匹配,以提取信息:
ss -Otpln |
perl -slne '
print $1 if m{
^ LISTEN \s+ # State
\d+ \s+ # Recv-Q
\d+ \s+ # Send-Q
(?: 0\.0\.0\.0 | \[::\] | \*) : (\d+) \s+ # source address on INADDR_ANY
# or INADDR6_ANY only
\S+ \s+ # dest address
users: .* \(" \Q$name\E ",pid # match on process name
}x && ! $already_seen{$1}++' -- -name=apache2您的输出格式与我的不同(通配符0.0.0.0用于通配符IPv4地址,[::]用于IPv6 one,而D3用于获取*),这表明ss输出格式可能不太稳定。您可以使用ss代替lsof,它具有一种用于批处理的模式,并且可以通过进程名进行匹配:
lsof -Fn -wnMPa -c apache2 -i tcp -s tcp:listen |
sed -n 's/^n\*://p' |
sort -nu它还将使其可移植到非Linux系统。
https://unix.stackexchange.com/questions/662922
复制相似问题