Ansible:检查服务是否正在侦听特定端口
Ansible: Check if service is listening on a specific port
您将如何使用 Ansible 确认服务是否 运行 在特定端口上?
例如:
- Apache 运行 是否在端口 80 上?
- MySQL 是否正在侦听端口 3912?
- 是否Tomcat监听8080端口?
我知道有 service
和 wait_for
命令,它们分别检查服务是否 运行 以及端口是否正在使用 - 但我没有找到到目前为止检查特定服务是否正在侦听特定端口的任何内容。 service
和 wait_for
将指示有一个服务和一个端口,但不能保证该端口被该特定服务占用——它可能被任何东西占用。 wait_for
,据我了解,只是检查它是否被使用。
wait_for
上有一个 regex_search
参数,它提到在套接字连接中搜索特定字符串,但据我了解,这只是读取从该套接字下来的任何信息,而不是可以访问发送该信息的内容。
我们该怎么做?
ansible 中没有内置模块可以验证端口和服务的组合。您可能需要做的是找出对 netstat 等命令的适当调用,并通过 command or shell 模块调用它。例如,在 linux 框中,以下命令将向您显示正在侦听端口 80 的进程:
$ netstat -tunlp | grep ":80 " | sed -e 's/.*\///'
httpd
所以从 Ansible 你可能想做这样的事情:
- name: Get service on port 80
shell: netstat -tunlp | grep ":80 " | sed -e 's/.*\///'
register: results
- name: See what netstat returned
debug: var=results
如果您想更高级一些,您可以编写一个 shell 脚本来封装 netstat 调用并在将结果返回到 ansible 之前对输出做一些更详细的 parsing/validation。但是您需要在调用之前安装该脚本。
有几种方法可以解释您的问题,因此我将尝试同时回答这两种方法:
正在验证网络服务
如果您的目标是验证特定端口是否服务于特定应用程序协议,我会通过 运行 适当的客户端进行检查。
为了检查 Apache 和 Tomcat,我会 GET
一个特定的 url 并检查结果代码。例如:
- name: check if apache is running
command: curl -sf http://webserver/check_url
Tomcat.
也是如此
为了检查 MySQL,我会使用 MySQL 客户端:
- name: check if mysql is running
command: mysql -h dbhost -P dbport -e 'select 1'
验证哪个进程拥有套接字
如果您真的想查看 进程 是什么使特定端口处于打开状态,我想您可以结合使用 ss
和 grep
,但这似乎奇怪和不必要的。类似于:
- name: check if httpd has port 80 open
shell: ss -tp state listening sport = :80 | grep httpd
如果你想检查一个特定的进程 ID,你可以用 lsof
:
做类似的事情
- name: check that pid {{apache_pid}} is listening on port 80
shell: lsof -p 1036 -P | grep 'TCP \*:80'
但同样,我不一定觉得这些选项特别有用。前面部分的服务检查似乎更合适。
据我所知,没有内置模块可以执行此操作。使用 shell 模块或编写执行所有检查的小 shell 命令可能很简单。
您可以使用 fuser
命令来检查哪个进程正在侦听给定的 TCP 端口:
$ sudo fuser -n tcp 80
80/tcp: 20031 20080 20081
可以使用ps
查看进程名称:
$ ps hp 20031,20080,20081 -o comm
apache2
apache2
apache2
结合一切:
$ ps hp `fuser -n tcp 80 2> /dev/null | cut -d ' ' -f 2` -o comm
apache2
$ ps hp `fuser -n tcp 80 2> /dev/null | cut -d ' ' -f 2` -o comm | grep apache2 -q
$ echo $? # should be 0 if apache2 is listening on port 80
0
也许你看待这个问题的方式是错误的。
您将使用配置管理系统(如 Ansible)对您的系统进行更改,但您将使用 Serverspec
之类的东西来确保正确的进程正在侦听正确的端口。
此外,您的剧本应该以这样一种方式构建,即您永远不会处于不同服务可能在相同端口上侦听的模棱两可的情况。
您将如何使用 Ansible 确认服务是否 运行 在特定端口上?
例如:
- Apache 运行 是否在端口 80 上?
- MySQL 是否正在侦听端口 3912?
- 是否Tomcat监听8080端口?
我知道有 service
和 wait_for
命令,它们分别检查服务是否 运行 以及端口是否正在使用 - 但我没有找到到目前为止检查特定服务是否正在侦听特定端口的任何内容。 service
和 wait_for
将指示有一个服务和一个端口,但不能保证该端口被该特定服务占用——它可能被任何东西占用。 wait_for
,据我了解,只是检查它是否被使用。
wait_for
上有一个 regex_search
参数,它提到在套接字连接中搜索特定字符串,但据我了解,这只是读取从该套接字下来的任何信息,而不是可以访问发送该信息的内容。
我们该怎么做?
ansible 中没有内置模块可以验证端口和服务的组合。您可能需要做的是找出对 netstat 等命令的适当调用,并通过 command or shell 模块调用它。例如,在 linux 框中,以下命令将向您显示正在侦听端口 80 的进程:
$ netstat -tunlp | grep ":80 " | sed -e 's/.*\///'
httpd
所以从 Ansible 你可能想做这样的事情:
- name: Get service on port 80
shell: netstat -tunlp | grep ":80 " | sed -e 's/.*\///'
register: results
- name: See what netstat returned
debug: var=results
如果您想更高级一些,您可以编写一个 shell 脚本来封装 netstat 调用并在将结果返回到 ansible 之前对输出做一些更详细的 parsing/validation。但是您需要在调用之前安装该脚本。
有几种方法可以解释您的问题,因此我将尝试同时回答这两种方法:
正在验证网络服务
如果您的目标是验证特定端口是否服务于特定应用程序协议,我会通过 运行 适当的客户端进行检查。
为了检查 Apache 和 Tomcat,我会
GET
一个特定的 url 并检查结果代码。例如:- name: check if apache is running command: curl -sf http://webserver/check_url
Tomcat.
也是如此
为了检查 MySQL,我会使用 MySQL 客户端:
- name: check if mysql is running command: mysql -h dbhost -P dbport -e 'select 1'
验证哪个进程拥有套接字
如果您真的想查看 进程 是什么使特定端口处于打开状态,我想您可以结合使用 ss
和 grep
,但这似乎奇怪和不必要的。类似于:
- name: check if httpd has port 80 open
shell: ss -tp state listening sport = :80 | grep httpd
如果你想检查一个特定的进程 ID,你可以用 lsof
:
- name: check that pid {{apache_pid}} is listening on port 80
shell: lsof -p 1036 -P | grep 'TCP \*:80'
但同样,我不一定觉得这些选项特别有用。前面部分的服务检查似乎更合适。
据我所知,没有内置模块可以执行此操作。使用 shell 模块或编写执行所有检查的小 shell 命令可能很简单。
您可以使用 fuser
命令来检查哪个进程正在侦听给定的 TCP 端口:
$ sudo fuser -n tcp 80
80/tcp: 20031 20080 20081
可以使用ps
查看进程名称:
$ ps hp 20031,20080,20081 -o comm
apache2
apache2
apache2
结合一切:
$ ps hp `fuser -n tcp 80 2> /dev/null | cut -d ' ' -f 2` -o comm
apache2
$ ps hp `fuser -n tcp 80 2> /dev/null | cut -d ' ' -f 2` -o comm | grep apache2 -q
$ echo $? # should be 0 if apache2 is listening on port 80
0
也许你看待这个问题的方式是错误的。
您将使用配置管理系统(如 Ansible)对您的系统进行更改,但您将使用 Serverspec
之类的东西来确保正确的进程正在侦听正确的端口。
此外,您的剧本应该以这样一种方式构建,即您永远不会处于不同服务可能在相同端口上侦听的模棱两可的情况。