#!/bin/bash #=============================================================================== # Linux 端口信息查看脚本 # 兼容: Ubuntu / Debian 及衍生版 # 功能: 显示 TCP、UDP、HTTP 端口服务信息 #=============================================================================== ## RED='\033[38;5;196m' GREEN='\033[38;5;46m' YELLOW='\033[38;5;226m' BLUE='\033[38;5;21m' MAGENTA='\033[38;5;201m' CYAN='\033[38;5;51m' WHITE='\033[38;5;255m' ORANGE='\033[38;5;208m' PINK='\033[38;5;219m' LIME='\033[38;5;154m' PURPLE='\033[38;5;141m' GOLD='\033[38;5;220m' GRAY='\033[38;5;244m' NC='\033[0m' SEPARATOR="━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" #=============================================================================== check_commands() { # echo -e "${CYAN}▸ 检测命令...${NC}" if command -v ss &> /dev/null; then PORT_CMD="ss" elif command -v netstat &> /dev/null; then PORT_CMD="netstat" else echo -e "${RED}✗ 错误: 未找到 ss 或 netstat 命令${NC}" echo -e "${YELLOW} 请安装: apt-get install net-tools${NC}" exit 1 fi # echo -e "${GREEN}✓ 使用命令: ${PORT_CMD}${NC}" } #=============================================================================== ## get_service_name() { local port=$1 case $port in 20) echo "FTP-DATA" ;; 21) echo "FTP" ;; 22) echo "SSH" ;; 23) echo "Telnet" ;; 25) echo "SMTP" ;; 53) echo "DNS" ;; 67|68) echo "DHCP" ;; 80) echo "HTTP" ;; 110) echo "POP3" ;; 123) echo "NTP" ;; 443) echo "HTTPS" ;; 3306) echo "MySQL" ;; 3389) echo "RDP" ;; 5432) echo "PostgreSQL" ;; 6379) echo "Redis" ;; 8080) echo "HTTP-Proxy" ;; 8443) echo "HTTPS-Alt" ;; 27017) echo "MongoDB" ;; *) echo "未知" ;; esac } #=============================================================================== show_tcp_ports() { echo -e "\n${SEPARATOR}" echo -e "${BLUE} 🔵 TCP 端口监听列表 ${NC}" echo -e "${SEPARATOR}" printf "${GREEN}%-6s %-10s %-14s %-10s %-20s${NC}\n" "协议" "端口" "服务(参考)" "PID" "进程名称" echo -e "${GRAY}──────────────────────────────────────────────────────────────────────────────${NC}" if [ "$PORT_CMD" = "ss" ]; then ss -tulnp 2>/dev/null | grep LISTEN | while IFS= read -r line; do addr=$(echo "$line" | awk '{print $5}') port="${addr##*:}" [[ "$port" =~ ^[0-9]+$ ]] || continue prog_field=$(echo "$line" | awk '{print $NF}') pid=$(echo "$prog_field" | grep -oP 'pid=\K[0-9]+' | head -1) name=$(echo "$prog_field" | sed -n 's/.*("\([^"]*\)".*/\1/p' | head -1) [ -z "$pid" ] && pid="-" [ -z "$name" ] && name="-" service=$(get_service_name "$port") printf "TCP|%-10s|%-14s|%-10s|%-20s\n" "$port" "$service" "$pid" "$name" done | sort -t'|' -k2 -n | uniq | while IFS='|' read -r p s rv pi n; do printf "${LIME}%-6s${NC} %-10s${NC} %-14s${NC} %-10s${NC} %-20s${NC}\n" "$p" "$s" "$rv" "$pi" "$n" done else netstat -tulnp 2>/dev/null | grep LISTEN | while read -r line; do port=$(echo "$line" | awk '{split($4,a,":"); print a[length(a)]}') [[ "$port" =~ ^[0-9]+$ ]] || continue prog=$(echo "$line" | awk '{print $NF}') pid=$(echo "$prog" | cut -d'/' -f1) name=$(echo "$prog" | cut -d'/' -f2 | cut -d' ' -f1) [ -z "$pid" ] && pid="-" [ -z "$name" ] && name="-" service=$(get_service_name "$port") printf "TCP|%-10s|%-14s|%-10s|%-20s\n" "$port" "$service" "$pid" "$name" done | sort -t'|' -k2 -n | uniq | while IFS='|' read -r p s rv pi n; do printf "${LIME}%-6s${NC} %-10s${NC} %-14s${NC} %-10s${NC} %-20s${NC}\n" "TCP" "$p" "$s" "$pi" "$n" done fi echo -e "${GRAY}──────────────────────────────────────────────────────────────────────────────${NC}" } #=============================================================================== show_udp_ports() { echo -e "\n${SEPARATOR}" echo -e "${MAGENTA} 🟣 UDP 端口监听列表 ${NC}" echo -e "${SEPARATOR}" printf "${PINK}%-6s %-10s %-14s %-10s %-20s${NC}\n" "协议" "端口" "服务(参考)" "PID" "进程名称" echo -e "${GRAY}──────────────────────────────────────────────────────────────────────────────${NC}" if [ "$PORT_CMD" = "ss" ]; then ss -ulnp 2>/dev/null | awk 'NR>1 && $1!="State"' | while IFS= read -r line; do addr=$(echo "$line" | awk '{print $4}') port="${addr##*:}" [[ "$port" =~ ^[0-9]+$ ]] || continue prog_field=$(echo "$line" | awk '{print $NF}') pid=$(echo "$prog_field" | grep -oP 'pid=\K[0-9]+' | head -1) name=$(echo "$prog_field" | sed -n 's/.*("\([^"]*\)".*/\1/p' | head -1) [ -z "$pid" ] && pid="-" [ -z "$name" ] && name="-" service=$(get_service_name "$port") printf "UDP|%-10s|%-14s|%-10s|%-20s\n" "$port" "$service" "$pid" "$name" done | sort -t'|' -k2 -n | uniq | while IFS='|' read -r p s rv pi n; do printf "${LIME}%-6s${NC} %-10s${NC} %-14s${NC} %-10s${NC} %-20s${NC}\n" "$p" "$s" "$rv" "$pi" "$n" done else netstat -ulnp 2>/dev/null | awk 'NR>1' | while read -r line; do port=$(echo "$line" | awk '{split($4,a,":"); print a[length(a)]}') [[ "$port" =~ ^[0-9]+$ ]] || continue prog=$(echo "$line" | awk '{print $NF}') pid=$(echo "$prog" | cut -d'/' -f1) name=$(echo "$prog" | cut -d'/' -f2 | cut -d' ' -f1) [ -z "$pid" ] && pid="-" [ -z "$name" ] && name="-" service=$(get_service_name "$port") printf "UDP|%-10s|%-14s|%-10s|%-20s\n" "$port" "$service" "$pid" "$name" done | sort -t'|' -k2 -n | uniq | while IFS='|' read -r p s rv pi n; do printf "${LIME}%-6s${NC} %-10s${NC} %-14s${NC} %-10s${NC} %-20s${NC}\n" "$p" "$s" "$rv" "$pi" "$n" done fi echo -e "${GRAY}──────────────────────────────────────────────────────────────────────────────${NC}" } #=============================================================================== show_http_ports() { echo -e "\n${SEPARATOR}" echo -e "${YELLOW} 🟡 HTTP/HTTPS 常用端口 ${NC}" echo -e "${SEPARATOR}" printf "${ORANGE}%-6s %-10s %-14s %-10s %-10s %-20s${NC}\n" "协议" "端口" "服务(参考)" "状态" "PID" "进程名称" echo -e "${GRAY}────────────────────────────────────────────────────────────────────────────────────────${NC}" http_ports="80 443 8080 8443 8000 8888 3000 5000" for port in $http_ports; do if [ "$PORT_CMD" = "ss" ]; then result=$(ss -tulnp 2>/dev/null | grep ":$port " | grep -v grep) if [ -n "$result" ]; then proto=$(echo "$result" | awk '{print $1}' | head -1 | tr '[:upper:]' '[:lower:]') prog_field=$(echo "$result" | awk '{print $NF}') pid=$(echo "$prog_field" | grep -oP 'pid=\K[0-9]+' | head -1) name=$(echo "$prog_field" | sed -n 's/.*("\([^"]*\)".*/\1/p' | head -1) [ -z "$pid" ] && pid="-" [ -z "$name" ] && name="-" service=$(get_service_name "$port") printf "${LIME}%-6s${NC} %-10s${NC} %-14s${NC} %-10s${NC} %-10s${NC} %-20s${NC}\n" "$proto" "$port" "$service" "监听中" "$pid" "$name" fi else result=$(netstat -tulnp 2>/dev/null | grep ":$port " | grep -v grep) if [ -n "$result" ]; then proto=$(echo "$result" | awk '{print $6}' | head -1 | tr '[:upper:]' '[:lower:]') prog=$(echo "$result" | awk '{print $7}') pid=$(echo "$prog" | cut -d'/' -f1) name=$(echo "$prog" | cut -d'/' -f2 | cut -d' ' -f1) [ -z "$pid" ] && pid="-" [ -z "$name" ] && name="-" service=$(get_service_name "$port") printf "${LIME}%-6s${NC} %-10s${NC} %-14s${NC} %-10s${NC} %-10s${NC} %-20s${NC}\n" "$proto" "$port" "$service" "监听中" "$pid" "$name" fi fi done echo -e "${GRAY}────────────────────────────────────────────────────────────────────────────────────────${NC}" echo -e "${GRAY}※ 服务(参考) 列为常用端口的默认服务名称,仅供参考,实际占用程序以进程名称列为准${NC}" } #=============================================================================== show_statistics() { echo -e "\n${SEPARATOR}" echo -e "${CYAN} 📊 端口统计信息 ${NC}" echo -e "${SEPARATOR}" if [ "$PORT_CMD" = "ss" ]; then tcp_count=$(ss -tuln 2>/dev/null | grep -c LISTEN) udp_count=$(ss -uln 2>/dev/null | awk 'NR>1 && $1 != "State" && /:[0-9]+/ {print}' | wc -l) else tcp_count=$(netstat -tuln 2>/dev/null | grep -c LISTEN) udp_count=$(netstat -uln 2>/dev/null | awk 'NR>1 && /:[0-9]+/ {print}' | wc -l) fi total=$((tcp_count + udp_count)) printf " ${BLUE}TCP 监听端口:${NC} ${GREEN}%d${NC}\n" "$tcp_count" printf " ${MAGENTA}UDP 监听端口:${NC} ${GREEN}%d${NC}\n" "$udp_count" printf " ${YELLOW}总 计:${NC} ${ORANGE}%d${NC}\n" "$total" } #=============================================================================== show_header() { clear echo -e "" echo -e "${SEPARATOR}" echo -e "${PURPLE} ║ Linux 系统端口信息查看工具${NC}" echo -e "${SEPARATOR}" echo -e " ${GOLD}▸ 兼容系统:${NC} ${WHITE}Ubuntu / Debian 及衍生版本${NC}" echo -e " ${GOLD}▸ 生成时间:${NC} ${WHITE}$(date '+%Y-%m-%d %H:%M:%S')${NC}" echo -e "${SEPARATOR}" } #=============================================================================== main() { show_header check_commands show_tcp_ports show_udp_ports show_http_ports show_statistics } main