前言:脚本编写不是一蹴而就,需要根据当前场景和实际需求不断测试和调整,最重要的是勇于踏出敢于尝试的这一步。
任务需求:在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 testbecome: yesbecome_user: rootbecome_method: sudoshell: 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; doPID=$(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; dopid=$(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; thenecho "jps 命令未找到,请确保Java已安装。"exit 1
fiif ! command -v netstat &> /dev/null; thenecho "netstat 命令未找到,请确保net-tools已安装。"exit 1
fi# 获取所有Java进程的PID和命令行参数
java_processes=$(jps -l)# 检查jps命令是否成功执行
if [ $? -ne 0 ]; thenecho "jps 命令执行失败。"exit 1
fiecho "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# 提取PIDpid=$(echo $process | cut -d ' ' -f 1)# 打印PIDecho "查找 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; dopid=$(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[@]}"; doif [ -n "$ports_str" ]; thenports_str="$ports_str,"fiports_str="$ports_str$port"doneecho "PID: $pid, Process: $process_name, Ports: $ports_str"
done
执行结果:
结论:完美!
2.0版本:
1.0版本所有步骤,也就是整个需求又自动化工具ansible一键完成。
写一个在ansible上执行的脚本yaml文件
- name: 项目名hosts: 项目hostsuser: 普通用户vars_files:- "secrets.yml"vars:ansible_ssh_pass: "{{ lookup('vars', 'dms_password') }}"ansible_become_pass: "{{ lookup('vars', 'dms_password') }}"tasks:- name: Gather filtered TCP portsbecome: yesbecome_user: rootbecome_method: sudoshell: "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 portsbecome: yesbecome_user: rootbecome_method: sudodebug:var: filtered_ports.stdout_lines- name: Check if jps shell is availablebecome: yesbecome_user: rootbecome_method: sudoshell: "which jps"register: jps_checkfailed_when: false- name: Gather Java process informationbecome: yesbecome_user: rootbecome_method: sudoshell: "jps -l"register: jps_outputwhen: jps_check.stdout | length > 0- name: Display Java process informationbecome: yesbecome_user: rootbecome_method: sudodebug:var: jps_output.stdout_lineswhen: jps_check.stdout | length > 0- name: Gather ports for Java processesbecome: yesbecome_user: rootbecome_method: sudoshell: "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_portswhen: jps_check.stdout | length > 0- name: Display ports for Java processesbecome: yesbecome_user: rootbecome_method: sudodebug:var: java_process_ports.results | map(attribute='stdout_lines') | listwhen: jps_check.stdout | length > 0
执行结果:
这里只能展示最后的结果,没有报错和失败的,上面的输出信息涉及公司隐私