> 技术文档 > 防火墙跨平台管理shell脚本(麒麟V10/CentOS/Ubuntu/macOS)快速指南_跨平台 脚本

防火墙跨平台管理shell脚本(麒麟V10/CentOS/Ubuntu/macOS)快速指南_跨平台 脚本


一套脚本,一键执行常见防火墙操作:查询状态、开/关、防火墙自启动、开放/关闭端口。适用于麒麟V10、CentOS、Ubuntu 和 macOS

一、脚本核心功能

运维环境中往往混合使用多个发行版,防火墙命令( firewalld / ufw / pf )差异较大。

  • 核心功能
    1. 查询防火墙状态(已开启/已关闭/不支持/未知)
    2. 查询开机自启动状态(已开启/已关闭/不支持/未知)
    3. 开启/关闭 防火墙
    4. 设置/取消 开机自动启动
    5. 永久放行端口(TCP/UDP)
    6. 列出当前已放行端口(含协议/服务)
    7. 关闭指定端口(自动删除相关规则,无需再次选择协议)

二、环境准备

1. 脚本执行环境

  • 必须用 Bash 运行(脚本首行 #!/usr/bin/env bash),不能用 sh
  • 需要 sudo 或 root 权限。

2. 各系统依赖

  • 麒麟V10 / CentOSfirewalldfirewall-cmd
sudo yum install -y firewalldsudo systemctl start firewalldsudo systemctl enable firewalld
  • Ubuntuufw
sudo apt updatesudo apt install -y ufwsudo ufw enable
  • macOS:自带应用防火墙(socketfilterfw)和 Packet Filter(pf,配置文件 /etc/pf.conf

3. 工具支持

  • timeout(大多数 Linux 已预装;如无则安装 coreutils)。
  • 如脚本从 Windows 编辑后出现奇怪卡顿,执行:
dos2unix firewall_manager.sh

三、脚本核心思路

1. 跨平台检测

if [ \"$(uname)\" = \"Darwin\" ]; then OS_TYPE=\"macos\" elif [ -f /etc/os-release ]; then . /etc/os-release case \"$ID\" in kylin|kylin10|kylinv10) OS_TYPE=\"kylin\" ;; centos)  OS_TYPE=\"centos\" ;; ubuntu)  OS_TYPE=\"ubuntu\" ;; *)  OS_TYPE=\"unknown\" ;; esac else OS_TYPE=\"unknown\" fi

2. 状态获取统一用 timeout 防卡死

  • firewalld:
STATE=\"$(timeout 3s firewall-cmd --state 2>/dev/null || echo \"timeout\")\"
  • ufw:
STATUS_UFW=\"$(timeout 3s ufw status 2>/dev/null | head -n1 || echo \"timeout\")\"
  • systemctl is-enabled:
EN=\"$(timeout 2s systemctl is-enabled ufw 2>/dev/null || echo \"timeout\")\"
  • macOS 直接用 socketfilterfw --getglobalstate 查询 “State = 1/0”。

3. 端口关闭自动化(Ubuntu 下避免交互确认卡住):

 while true; do NUM=\"$(ufw status numbered | grep \"${PORT}/\" | head -n1 | sed -n \'s/^\\[ *\\([0-9]\\+\\)\\].*/\\1/p\')\" [ -z \"$NUM\" ] && break yes | ufw delete \"$NUM\" >/dev/null done

4. macOS pf 规则操作

  • 备份 /etc/pf.conf
cp /etc/pf.conf /etc/pf.conf.bak_$(date +%F_%T)
  • 新增:
echo \"pass in proto tcp from any to any port 8080\" >> /etc/pf.confpfctl -f /etc/pf.conf
  • 删除:
sed -i.bak \"/port[[:space:]]*8080/d\" /etc/pf.confpfctl -f /etc/pf.conf

四、使用步骤

1. 保存脚本并赋可执行权限

vim firewall_manager.sh# 粘贴下方“完整脚本”内容并保存chmod +x firewall_manager.sh

2. (如有 Windows 换行)转换格式

dos2unix firewall_manager.sh

3. 启动脚本(务必用 Bash)

sudo bash firewall_manager.sh

或者

./firewall_manager.sh

4. 交互示例

  • 运行后菜单显示:

防火墙跨平台管理shell脚本(麒麟V10/CentOS/Ubuntu/macOS)快速指南_跨平台 脚本


五、完整脚本(复制即用)

#!/usr/bin/env bash## 文件名:firewall_manager.sh# 说明:跨平台(麒麟V10、CentOS、Ubuntu、macOS)防火墙管理脚本## 功能:# 1. 显示防火墙状态(已开启/已关闭/不支持/未知)# 2. 显示开机自启动状态(已开启/已关闭/不支持/未知)# 3. 开启/关闭 防火墙# 4. 设置/取消 开机自启动# 5. 永久放行端口(TCP/UDP)# 6. 查看已开放端口(数字+协议/服务)# 7. 关闭指定端口(自动删除,非交互式)## 注意:# - 必须用 Bash 运行,不要用 sh:# chmod +x firewall_manager.sh# sudo bash firewall_manager.sh# - 需 root 或 sudo 权限# - 使用 timeout 防止命令卡住# - Ubuntu 下 ufw delete 由 yes 自动确认# --------------------- 判断操作系统 ---------------------OS_TYPE=\"\"if [ \"$(uname)\" = \"Darwin\" ]; then OS_TYPE=\"macos\"elif [ -f /etc/os-release ]; then . /etc/os-release case \"$ID\" in kylin|kylin10|kylinv10) OS_TYPE=\"kylin\" ;; centos)  OS_TYPE=\"centos\" ;; ubuntu)  OS_TYPE=\"ubuntu\" ;; *)  OS_TYPE=\"unknown\" ;; esacelse OS_TYPE=\"unknown\"fi# --------------------- 辅助函数 ---------------------print_line() { echo \"---------------------------------------------\"}command_exists() { command -v \"$1\" >/dev/null 2>&1}die() { echo \"Error: $1\" 1>&2 exit 1}# --------------------- 获取防火墙状态 ---------------------get_firewall_status() { case \"$OS_TYPE\" in centos|kylin) if command_exists firewall-cmd; then STATE=\"$(timeout 3s firewall-cmd --state 2>/dev/null || echo \"timeout\")\" if [ \"$STATE\" = \"running\" ]; then echo \"enabled\" elif [ \"$STATE\" = \"timeout\" ]; then echo \"unknown\" else echo \"disabled\" fi else echo \"unsupported\" fi ;; ubuntu) if command_exists ufw; then STATUS_UFW=\"$(timeout 3s ufw status 2>/dev/null | head -n1 || echo \"timeout\")\" case \"$STATUS_UFW\" in *\"Status: active\"*) echo \"enabled\" ;; *\"timeout\"*) echo \"unknown\" ;; *)  echo \"disabled\" ;; esac else echo \"unsupported\" fi ;; macos) if command_exists /usr/libexec/ApplicationFirewall/socketfilterfw; then GSTATE=\"$(/usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate 2>&1)\" case \"$GSTATE\" in *\"State = 1\"*) echo \"enabled\" ;; *) echo \"disabled\" ;; esac else echo \"unsupported\" fi ;; *) echo \"unknown\" ;; esac}# --------------------- 获取开机自启动状态 ---------------------get_autostart_status() { case \"$OS_TYPE\" in centos|kylin) if command_exists systemctl; then EN=\"$(timeout 2s systemctl is-enabled firewalld 2>/dev/null || echo \"timeout\")\" if [ \"$EN\" = \"enabled\" ]; then echo \"enabled\" elif [ \"$EN\" = \"timeout\" ]; then echo \"unknown\" else echo \"disabled\" fi else echo \"unsupported\" fi ;; ubuntu) if command_exists systemctl; then EN=\"$(timeout 2s systemctl is-enabled ufw 2>/dev/null || echo \"timeout\")\" if [ \"$EN\" = \"enabled\" ]; then echo \"enabled\" elif [ \"$EN\" = \"timeout\" ]; then echo \"unknown\" else echo \"disabled\" fi else echo \"unsupported\" fi ;; macos) ST=\"$(get_firewall_status)\" if [ \"$ST\" = \"enabled\" ]; then echo \"enabled\" else echo \"disabled\" fi ;; *) echo \"unknown\" ;; esac}# --------------------- 各操作实现 ---------------------# 1. 开启防火墙enable_firewall() { case \"$OS_TYPE\" in centos|kylin) systemctl start firewalld && systemctl enable firewalld ;; ubuntu) ufw --force enable ;; macos) /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate on ;; *) die \"无法在此系统上开启防火墙\" ;; esac}# 2. 关闭防火墙disable_firewall() { case \"$OS_TYPE\" in centos|kylin) systemctl stop firewalld && systemctl disable firewalld ;; ubuntu) ufw disable ;; macos) /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate off ;; *) die \"无法在此系统上关闭防火墙\" ;; esac}# 3. 设置开机自启动enable_autostart() { case \"$OS_TYPE\" in centos|kylin) systemctl enable firewalld ;; ubuntu) systemctl enable ufw ;; macos) echo \"macOS 上只要防火墙被启用,就会开机自启动。\" ;; *) die \"无法在此系统上设置开机自启动\" ;; esac}# 4. 取消开机自启动disable_autostart() { case \"$OS_TYPE\" in centos|kylin) systemctl disable firewalld ;; ubuntu) systemctl disable ufw ;; macos) echo \"macOS 上关闭防火墙即可取消开机自启动。\" ;; *) die \"无法在此系统上取消开机自启动\" ;; esac}# 5. 永久开放端口open_port() { read -p \"请输入要开放的协议 (tcp/udp): \" PROTO PROTO=\"$(echo \"$PROTO\" | tr \'[:upper:]\' \'[:lower:]\')\" if [ \"$PROTO\" != \"tcp\" ] && [ \"$PROTO\" != \"udp\" ]; then echo \"协议只能是 tcp 或 udp\" return fi read -p \"请输入要开放的端口号 (1-65535): \" PORT echo \"$PORT\" | grep -E \'^[0-9]+$\' >/dev/null 2>&1 || { echo \"端口号不合法。\"; return; } if [ \"$PORT\" -lt 1 ] || [ \"$PORT\" -gt 65535 ]; then echo \"端口号不合法。\" return fi case \"$OS_TYPE\" in centos|kylin) firewall-cmd --permanent --add-port=${PORT}/${PROTO} && firewall-cmd --reload ;; ubuntu) ufw allow ${PORT}/${PROTO} ;; macos) PF_CONF=\"/etc/pf.conf\" BACKUP_PATH=\"/etc/pf.conf.bak_$(date +%F_%T)\" echo \"正在备份 /etc/pf.conf 到 $BACKUP_PATH\" cp \"$PF_CONF\" \"$BACKUP_PATH\" || { echo \"备份失败,请检查权限。\"; return; } RULE=\"pass in proto $PROTO from any to any port $PORT\" grep -Fxq \"$RULE\" \"$PF_CONF\" && { echo \"规则已存在: $RULE\"; return; } echo \"\" >> \"$PF_CONF\" echo \"# 由 firewall_manager.sh 添加 $(date \'+%F %T\')\" >> \"$PF_CONF\" echo \"$RULE\" >> \"$PF_CONF\" pfctl -f \"$PF_CONF\" && pfctl -e 2>/dev/null && echo \"端口 $PORT/$PROTO 已添加并生效。\" \\ || echo \"pf 规则加载失败,请手动检查 /etc/pf.conf。\" ;; *) echo \"该系统不支持自动开放端口。\" ;; esac}# 6. 查看已开启的端口list_ports() { echo \"当前已开放的端口:\" case \"$OS_TYPE\" in centos|kylin) if command_exists firewall-cmd; then echo \"-- 通过 firewall-cmd 列出端口 --\" firewall-cmd --list-ports echo echo \"-- 通过 firewall-cmd 列出服务 --\" firewall-cmd --list-services else echo \"firewall-cmd 未安装,无法列出端口。\" fi ;; ubuntu) if command_exists ufw; then echo \"-- ufw 状态信息 --\" ufw status verbose else echo \"ufw 未安装,无法列出端口。\" fi ;; macos) echo \"-- pf 规则列表 (包含端口规则) --\" pfctl -sr | grep \'port\' ;; *) echo \"该系统不支持查看已开放端口。\" ;; esac}# 7. 关闭指定端口(无需选择协议,也不会卡在确认提示)close_port() { read -p \"请输入要关闭的端口号 (1-65535): \" PORT echo \"$PORT\" | grep -E \'^[0-9]+$\' >/dev/null 2>&1 || { echo \"端口号不合法。\"; return; } if [ \"$PORT\" -lt 1 ] || [ \"$PORT\" -gt 65535 ]; then echo \"端口号不合法。\" return fi case \"$OS_TYPE\" in centos|kylin) firewall-cmd --permanent --remove-port=${PORT}/tcp firewall-cmd --permanent --remove-port=${PORT}/udp firewall-cmd --reload && echo \"端口 $PORT 已关闭(TCP/UDP)。\" || echo \"关闭端口失败,请检查。\" ;; ubuntu) if command_exists ufw; then while true; do NUM=\"$(ufw status numbered | grep \"${PORT}/\" | head -n1 | sed -n \'s/^\\[ *\\([0-9]\\+\\)\\].*/\\1/p\')\" [ -z \"$NUM\" ] && break yes | ufw delete \"$NUM\" >/dev/null done echo \"端口 $PORT 已关闭(UDP/TCP)。\" else echo \"ufw 未安装,无法关闭端口。\" fi ;; macos) PF_CONF=\"/etc/pf.conf\" BACKUP_PATH=\"/etc/pf.conf.bak_$(date +%F_%T)\" echo \"正在备份 /etc/pf.conf 到 $BACKUP_PATH\" cp \"$PF_CONF\" \"$BACKUP_PATH\" || { echo \"备份失败,请检查权限。\"; return; } echo \"从 /etc/pf.conf 删除与端口 $PORT 相关的行...\" sed -i.bak \"/port[[:space:]]*$PORT/d\" \"$PF_CONF\" && pfctl -f \"$PF_CONF\" && echo \"端口 $PORT 相关规则已删除并生效。\" || echo \"删除规则失败,请手动检查 /etc/pf.conf。\" ;; *) echo \"该系统不支持关闭端口。\" ;; esac}# --------------------- 主菜单 ---------------------while true; do clear echo \"======== 防火墙管理脚本 ========\" print_line FW_STATUS=\"$(get_firewall_status)\" AUTO_STATUS=\"$(get_autostart_status)\" echo \"当前操作系统: $OS_TYPE\" echo -n \"防火墙状态 : \" if [ \"$FW_STATUS\" = \"enabled\" ]; then echo \"已开启\" elif [ \"$FW_STATUS\" = \"disabled\" ]; then echo \"已关闭\" else echo \"未知/不支持\" fi echo -n \"开机自启状态 : \" if [ \"$AUTO_STATUS\" = \"enabled\" ]; then echo \"已开启\" elif [ \"$AUTO_STATUS\" = \"disabled\" ]; then echo \"已关闭\" else echo \"未知/不支持\" fi print_line echo \"请选择操作:\" echo \" 1) 开启防火墙\" echo \" 2) 关闭防火墙\" echo \" 3) 设置开机自启动\" echo \" 4) 取消开机自启动\" echo \" 5) 永久开放指定端口\" echo \" 6) 查看已开启的端口\" echo \" 7) 关闭指定端口\" echo \" 0) 退出脚本\" print_line read -p \"输入选项 [0-7]: \" CHOICE case \"$CHOICE\" in 1) enable_firewall && echo \"操作完成:防火墙已开启。\" read -p \"按回车继续...\" ;; 2) disable_firewall && echo \"操作完成:防火墙已关闭。\" read -p \"按回车继续...\" ;; 3) enable_autostart && echo \"操作完成:已设置开机自启动。\" read -p \"按回车继续...\" ;; 4) disable_autostart && echo \"操作完成:已取消开机自启动。\" read -p \"按回车继续...\" ;; 5) open_port read -p \"按回车继续...\" ;; 6) list_ports read -p \"按回车继续...\" ;; 7) close_port read -p \"按回车继续...\" ;; 0) echo \"退出脚本。\" exit 0 ;; *) echo \"无效选项,请重新输入。\" sleep 1 ;; esacdone

千万要听话哦~

  • 必须用 Bash 运行(./firewall_manager.shbash firewall_manager.sh),不能用 sh
  • 对可能挂起的命令统一用 timeout 限时,避免卡死。
  • Ubuntu 下关闭端口用 yes | ufw delete … 自动确认。
  • macOS 下编辑 /etc/pf.conf 追加/删除规则后调用 pfctl -f 重载。

按此脚本即可跨麒麟 V10 / CentOS / Ubuntu / macOS 一键管理防火墙,极大简化运维复杂度。祝使用顺利!

四川饮食文化