first commit
This commit is contained in:
201
port-info/AGENTS.md
Normal file
201
port-info/AGENTS.md
Normal file
@@ -0,0 +1,201 @@
|
||||
# AGENTS.md - Agent Coding Guidelines
|
||||
|
||||
This document provides guidelines for agents working in this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
This is a **Bash shell script** project for displaying Linux port information (TCP, UDP, HTTP services). The main file is `port_info.sh`.
|
||||
|
||||
## Build / Lint / Test Commands
|
||||
|
||||
### Running the Script
|
||||
```bash
|
||||
# Make executable and run
|
||||
chmod +x port_info.sh
|
||||
./port_info.sh
|
||||
|
||||
# Or run directly with bash
|
||||
bash port_info.sh
|
||||
```
|
||||
|
||||
### Linting
|
||||
Use **shellcheck** for static analysis:
|
||||
```bash
|
||||
# Install shellcheck (if not present)
|
||||
apt-get install shellcheck # Debian/Ubuntu
|
||||
yum install epel-release && yum install ShellCheck # RHEL/CentOS
|
||||
|
||||
# Run shellcheck on the script
|
||||
shellcheck port_info.sh
|
||||
|
||||
# Run with specific severity levels
|
||||
shellcheck -S error port_info.sh # Errors only
|
||||
shellcheck -S warning port_info.sh # Warnings and errors
|
||||
```
|
||||
|
||||
### Testing a Single Function
|
||||
Bash doesn't have traditional unit tests, but you can test functions interactively:
|
||||
```bash
|
||||
# Source the script and test specific functions
|
||||
source port_info.sh
|
||||
get_service_name 80 # Test port-to-service lookup
|
||||
check_commands # Test command detection
|
||||
```
|
||||
|
||||
### Syntax Validation
|
||||
```bash
|
||||
# Check bash syntax without executing
|
||||
bash -n port_info.sh
|
||||
```
|
||||
|
||||
## Code Style Guidelines
|
||||
|
||||
### File Organization
|
||||
- Single script files for small utilities
|
||||
- Use clear section separators: `#===============================================================================`
|
||||
- Group related functions together
|
||||
- Main execution at the bottom of the file
|
||||
|
||||
### Formatting
|
||||
- Indentation: 4 spaces
|
||||
- Use `#!/bin/bash` shebang (not `#!/bin/sh` for bash-specific features)
|
||||
- Maximum line length: ~100 characters (flexible for output formatting)
|
||||
- Use uppercase for constants/variables, lowercase for function names
|
||||
|
||||
### Variable Naming
|
||||
- Constants (colors, separators): UPPERCASE with underscores, e.g., `RED`, `SEPARATOR`
|
||||
- Global variables: UPPERCASE, e.g., `PORT_CMD`
|
||||
- Local variables in functions: lowercase with underscores, e.g., `local port=$1`
|
||||
- Function names: lowercase with underscores, e.g., `check_commands()`
|
||||
|
||||
### Functions
|
||||
```bash
|
||||
# Good function definition
|
||||
function_name() {
|
||||
local arg1=$1
|
||||
local arg2=$2
|
||||
|
||||
# function body
|
||||
|
||||
return 0 # Always return explicit status
|
||||
}
|
||||
|
||||
# Or with function keyword
|
||||
check_commands() {
|
||||
# ...
|
||||
}
|
||||
```
|
||||
|
||||
### Color Variables
|
||||
Define colors at the top of the script using ANSI escape codes:
|
||||
```bash
|
||||
RED='\033[38;5;196m'
|
||||
GREEN='\033[38;5;46m'
|
||||
NC='\033[0m' # No Color - always reset at end
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
- Use `command -v` to check command availability
|
||||
- Redirect stderr with `2>/dev/null` for expected errors
|
||||
- Exit with status 1 on fatal errors: `exit 1`
|
||||
- Use descriptive error messages with colors
|
||||
|
||||
### Input Handling
|
||||
- Prefer arguments over interactive input
|
||||
- Validate inputs before processing
|
||||
- Use `local` for all function parameters
|
||||
- Check for required arguments
|
||||
|
||||
### String Comparisons
|
||||
```bash
|
||||
# String equality
|
||||
if [ "$var" = "value" ]; then
|
||||
# ...
|
||||
fi
|
||||
|
||||
# Numeric comparison
|
||||
if [ "$num" -eq 0 ]; then
|
||||
# ...
|
||||
fi
|
||||
|
||||
# Regex matching
|
||||
if [[ "$port" =~ ^[0-9]+$ ]]; then
|
||||
# ...
|
||||
fi
|
||||
```
|
||||
|
||||
### Output Formatting
|
||||
- Use `printf` for formatted output (not `echo` for complex output)
|
||||
- Use color codes with `${COLOR}...${NC}` pattern
|
||||
- Consistent column widths in tables
|
||||
|
||||
### Common Patterns
|
||||
|
||||
#### Command Availability Check
|
||||
```bash
|
||||
if command -v ss &> /dev/null; then
|
||||
PORT_CMD="ss"
|
||||
elif command -v netstat &> /dev/null; then
|
||||
PORT_CMD="netstat"
|
||||
else
|
||||
echo -e "${RED}Error: command not found${NC}"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
#### Reading Lines
|
||||
```bash
|
||||
while IFS= read -r line; do
|
||||
# process line
|
||||
done < <(command)
|
||||
```
|
||||
|
||||
#### Safe Variable Usage
|
||||
- Always quote variables: `"$var"` not `$var`
|
||||
- Use `${var}` for clarity in complex expressions
|
||||
- Initialize variables before use
|
||||
|
||||
### Shellcheck Compliance
|
||||
Run `shellcheck` and fix all warnings:
|
||||
- SC2086: Quote variables to prevent word splitting
|
||||
- SC2166: Use `&&` instead of `-a` in test expressions
|
||||
- SC2027: Quote strings containing newlines
|
||||
- SC2248: Prefer printf over echo
|
||||
|
||||
## File Extensions
|
||||
- Bash scripts: `.sh`
|
||||
- No extension for executable scripts (optional)
|
||||
|
||||
## Documentation
|
||||
- Add Chinese comments for Chinese-language projects
|
||||
- Use section headers: `#===============================================================================`
|
||||
- Document function purpose before definition
|
||||
- Include usage information in comments
|
||||
|
||||
## Dependencies
|
||||
This script requires:
|
||||
- `ss` or `netstat net` (from-tools package)
|
||||
- Standard Linux utilities: `awk`, `grep`, `sed`, `sort`, `uniq`
|
||||
|
||||
## Common Tasks
|
||||
|
||||
### Adding a New Port Service
|
||||
Edit `get_service_name()` function in `port_info.sh`:
|
||||
```bash
|
||||
get_service_name() {
|
||||
local port=$1
|
||||
case $port in
|
||||
80) echo "HTTP" ;;
|
||||
443) echo "HTTPS" ;;
|
||||
3306) echo "MySQL" ;;
|
||||
# Add new port here
|
||||
9000) echo "PHP-FPM" ;;
|
||||
*) echo "未知" ;;
|
||||
esac
|
||||
}
|
||||
```
|
||||
|
||||
### Adding a New Display Section
|
||||
1. Create a new function following existing patterns
|
||||
2. Add function call in `main()`
|
||||
3. Use consistent color scheme and formatting
|
||||
260
port-info/port_info.sh
Executable file
260
port-info/port_info.sh
Executable file
@@ -0,0 +1,260 @@
|
||||
#!/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
|
||||
Reference in New Issue
Block a user