首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Bash脚本无法从Firewalld中删除服务列表

Bash脚本无法从Firewalld中删除服务列表
EN

Unix & Linux用户
提问于 2021-05-12 18:49:39
回答 1查看 477关注 0票数 0

我试图通过bash脚本清除在firewalld中配置的所有现有服务。

代码语言:javascript
复制
# produces {cockpit,dhcpv6-client,ssh} as an example
local EXISTING_SERVICES="{$(firewall-cmd --permanent --list-service | sed -e 's/ /,/g')}"
# firewall-cmd --permanent --remove-service={cockpit,dhcpv6-client,ssh}
firewall-cmd --permanent --remove-service="${EXISTING_SERVICES}"

当运行此操作时,firewall-cmd返回:

代码语言:javascript
复制
Warning: NOT_ENABLED: {cockpit,dhcpv6-client,ssh}
success

问题似乎是firewall-cmd将服务列表解释为禁用为单个服务名称,而不是一个列表。当我从shell手动运行该命令时,相同的(复制/粘贴)命令的工作方式与预期相同。

要复制的示例脚本:

代码语言:javascript
复制
EXISTING_SERVICES="{$(firewall-cmd --permanent --list-service | sed -e 's/ /,/g')}"
echo "firewall-cmd --permanent --remove-service=${EXISTING_SERVICES}"
firewall-cmd --permanent --remove-service="${EXISTING_SERVICES}"

结果:

通过脚本和直接shell命令运行这个程序有什么区别?

Update:按照@fra的建议,尝试使用set -x运行脚本,在从脚本运行时产生以下结果:

从shell运行以下结果:

在交互运行时,外壳(和/或firewalld)的行为似乎有所不同,并将服务列表扩展为3个单独的--remove-service=标志。这是非常出乎意料的行为。

EN

回答 1

Unix & Linux用户

回答已采纳

发布于 2021-05-12 21:08:12

firewall-cmd与此无关,在脚本中运行命令与以交互方式运行命令之间没有区别。相反,您正在执行两个根本不同的命令。

您在实际操作中看到的是支撑展开:命令

代码语言:javascript
复制
firewall-cmd --permanent --remove-service={cockpit,dhcpv6-client,ssh}

被Bash扩展为

代码语言:javascript
复制
firewall-cmd --permanent --remove-service=cockpit --remove-service=dhcpv6-client --remove-service=ssh

这在脚本和命令行中都会发生。但是,请注意,shell从未解析展开的结果,以寻找进一步的扩展触发字符。因此,命令

代码语言:javascript
复制
firewall-cmd --permanent --remove-service="${EXISTING_SERVICES}"

在您的脚本中展开为

代码语言:javascript
复制
firewall-cmd --permanent --remove-service={cockpit,dhcpv6-client,ssh}

并以这种形式运行(大括号中的表达式在这一点上是字面意思)。

这似乎不是一个有效的firewall-cmd命令。引用man firewall-cmd的话,--remove-service的语法是

.-删除服务=服务删除服务可以多次指定此选项。

建议在一次运行中删除多个服务的预期方法是

代码语言:javascript
复制
firewall-cmd ... --remove-service=foo --remove-service=bar ...

使用Bash,您可以使用数组存储已启用的服务,并生成相应的选项列表以删除它们:

代码语言:javascript
复制
services=( $(firewall-cmd --permanent --list-services) )
firewall-cmd --permanent "${services[@]/#/--remove-service=}"

其中,${services[@]/#/--remove-service=}是Bash的参数扩展模式替换形式-- #匹配每个数组元素开头的空字符串,并将其替换为--remove-service=

虽然效率较低,但在某些情况下,一次添加/删除一个服务可能更实用,因为无论有多少操作失败,如果至少一个操作成功,则firewall-cmd的退出状态设置为0。然后,您可能会更喜欢这样的东西:

代码语言:javascript
复制
services=( $(firewall-cmd --permanent --list-services) )
for serv in "${services[@]}"
do
  firewall-cmd --permanent --remove-service="$serv" || echo "failed: $serv" >&2
done
票数 3
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/649428

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档