前言:脚本编写不是一蹴而就,需要根据当前场景和实际需求不断测试和调整,最重要的是勇于踏出敢于尝试的这一步。
任务需求:在ansible-vault加密环境下,使用root权限批量将项目上所有服务器的tcp端口过滤掉22, 25, 53, 443,631,9100,10050端口 后显示出来;判断服务器上如果有jps命令的就执行,输出的所有的程序的PID,并显示PID对应的进程,查出各PID对应的端口;如果没有jps命令的服务器就只显示过滤后的端口信息。
1.0版本:
第一步:写一个在ansible上执行的脚本yaml文件
---
- name: 项目名
hosts: 项目hosts名
user: 普通用户
vars_files:
- "secrets.yml"
vars:
ansible_ssh_pass: "{{ lookup('vars', 'dms_password') }}"
ansible_become_pass: "{{ lookup('vars', 'dms_password') }}"
tasks:
- name: just test
become: yes
become_user: root
become_method: sudo
shell: netstat -tlnp
第二步执行命令:ansible-playbook -i /etc/ansible/hosts ***.yaml --ask-vault-pass -v
这个是输出项目上所有服务器的tcp端口,然后手动排查系统默认端口,各web服务,中间件和数据库等自己判断,jar应用又下一步来完成统计。
第三步 写个jps-pid-端口的脚本
这里我将错误的脚本和达不到的效果的脚本都列举出来
脚本1:
#!/bin/bash
# 获取 root 用户下的所有 Java 进程的 PID 和名称
PIDS_NAMES=$(sudo jps | awk '{print $1","$2}')
# 遍历每个 PID 和名称,查找对应的端口
for PID_NAME in $PIDS_NAMES; do
PID=$(echo $PID_NAME | cut -d, -f1)
NAME=$(echo $PID_NAME | cut -d, -f2)
echo "PID: $PID, Name: $NAME"
# 使用 lsof 查找端口
PORTS=$(sudo lsof -a -p $PID -i -n | grep LISTEN | awk '{print $9}' | cut -d: -f2)
# 或者使用 netstat 查找端口
# PORTS=$(sudo netstat -anp | grep $PID | grep LISTEN | awk '{print $4}' | cut -d: -f2)
echo "Ports: $PORTS"
echo "----------------------------------------"
done
执行结果:
结论:有的jar程序无法显示出对应的端口
脚本2:
#!/bin/bash
# 执行 jps 命令获取进程信息
jps_output=$(jps -l)
# 提取 PID 和进程名
IFS=$'\n'
for line in $jps_output; do
pid=$(echo $line | awk '{print $1}')
process_name=$(echo $line | awk '{print $2}')
# 使用 netstat 查找 PID 对应的端口
ports=$(sudo netstat -nlp | awk '$7 ~ /'$pid'/{print $4}' | awk -F ':' '{print $NF}')
echo "PID: $pid, Process: $process_name, Ports: $ports"
done
执行结果:
结论:无法显示对应端口
脚本3:
#!/bin/bash
# 检查jps和netstat命令是否存在
if ! command -v jps &> /dev/null; then
echo "jps 命令未找到,请确保Java已安装。"
exit 1
fi
if ! command -v netstat &> /dev/null; then
echo "netstat 命令未找到,请确保net-tools已安装。"
exit 1
fi
# 获取所有Java进程的PID和命令行参数
java_processes=$(jps -l)
# 检查jps命令是否成功执行
if [ $? -ne 0 ]; then
echo "jps 命令执行失败。"
exit 1
fi
echo "Java进程的PID和命令行参数:"
echo "$java_processes"
# 定义一个函数来查找进程的端口
find_ports_for_pid() {
local pid=$1
# 使用netstat和grep查找PID对应的端口
netstat -tulnp | grep "$pid" | awk '{print $4}'
}
# 遍历所有Java进程
for process in $java_processes; do
# 提取PID
pid=$(echo $process | cut -d ' ' -f 1)
# 打印PID
echo "查找 PID: $pid 对应的端口..."
# 查找端口
find_ports_for_pid "$pid"
# 打印分隔线
echo "----------"
done
执行结果:
结论:端口没有并排显示,不方便统计
脚本F:
#!/bin/bash
# 执行 jps 命令获取进程信息
jps_output=$(jps -l)
# 提取 PID 和进程名
IFS=$'\n'
for line in $jps_output; do
pid=$(echo $line | awk '{print $1}')
process_name=$(echo $line | awk '{print $2}')
# 使用 netstat 查找 PID 对应的端口
ports=$(sudo netstat -nlp | awk '$7 ~ /'$pid'/{print $4}' | awk -F ':' '{print $NF}')
ports_array=($ports)
ports_str=""
for port in "${ports_array[@]}"; do
if [ -n "$ports_str" ]; then
ports_str="$ports_str,"
fi
ports_str="$ports_str$port"
done
echo "PID: $pid, Process: $process_name, Ports: $ports_str"
done
执行结果:
结论:完美!
2.0版本:
1.0版本所有步骤,也就是整个需求又自动化工具ansible一键完成。
写一个在ansible上执行的脚本yaml文件
- name: 项目名
hosts: 项目hosts
user: 普通用户
vars_files:
- "secrets.yml"
vars:
ansible_ssh_pass: "{{ lookup('vars', 'dms_password') }}"
ansible_become_pass: "{{ lookup('vars', 'dms_password') }}"
tasks:
- name: Gather filtered TCP ports
become: yes
become_user: root
become_method: sudo
shell: "netstat -tlnp | grep LISTEN | awk '{print $4}' | cut -d: -f2 | grep -Ev '22|25|53|443|631|9100|10050'"
register: filtered_ports
- name: Display filtered TCP ports
become: yes
become_user: root
become_method: sudo
debug:
var: filtered_ports.stdout_lines
- name: Check if jps shell is available
become: yes
become_user: root
become_method: sudo
shell: "which jps"
register: jps_check
failed_when: false
- name: Gather Java process information
become: yes
become_user: root
become_method: sudo
shell: "jps -l"
register: jps_output
when: jps_check.stdout | length > 0
- name: Display Java process information
become: yes
become_user: root
become_method: sudo
debug:
var: jps_output.stdout_lines
when: jps_check.stdout | length > 0
- name: Gather ports for Java processes
become: yes
become_user: root
become_method: sudo
shell: "lsof -a -p {{ item }} -i -n | grep LISTEN | awk '{print $9}' | cut -d: -f2"
loop: "{{ jps_output.stdout_lines | map('regex_replace', '^(.*) (.*)$', '\\1') | list }}"
register: java_process_ports
when: jps_check.stdout | length > 0
- name: Display ports for Java processes
become: yes
become_user: root
become_method: sudo
debug:
var: java_process_ports.results | map(attribute='stdout_lines') | list
when: jps_check.stdout | length > 0
执行结果:
这里只能展示最后的结果,没有报错和失败的,上面的输出信息涉及公司隐私