BashスクリプトはFirewalldからサービスリストを削除できません。

BashスクリプトはFirewalldからサービスリストを削除できません。

firewalldBashスクリプトを介して設定されたすべての既存のサービスを消去しようとしています。

# 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以下を返します。

Warning: NOT_ENABLED: {cockpit,dhcpv6-client,ssh}
success

firewall-cmd問題は、無効にするサービスのリストがリストではなく単一のサービス名として解釈されることです。シェルで手動で実行すると、まったく同じ(コピー/貼り付け)コマンドが期待どおりに機能します。

コピーするスクリプトの例:

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}"

結果:

シェル結果

スクリプトで実行することと、直接シェルコマンドで実行することの違いは何ですか?


更新:@fra-sanが提案したようにスクリプトを実行しようとしましたが、set -xスクリプトで実行すると次の結果が表示されます。

結果

シェルで実行したときの結果は次のとおりです。

ここに画像の説明を入力してください。

インタラクティブに実行すると、シェル(および/またはファイアウォール)が異なる動作をするように見え、サービスリストを3つの別々のフラグ--remove-service=に展開します。これは非常に予期しない動作です。

ベストアンサー1

firewall-cmdこの点に関して、スクリプトでコマンドを実行することと対話的に実行することには違いはありません。代わりに、基本的に他の2つのコマンドを実行しています。

行動で見るものは支柱の拡張:注文する

firewall-cmd --permanent --remove-service={cockpit,dhcpv6-client,ssh}

Bashによって拡張

firewall-cmd --permanent --remove-service=cockpit --remove-service=dhcpv6-client --remove-service=ssh

これはスクリプトとコマンドラインの両方で発生します。ただし、シェルは追加の拡張トリガー文字を検索するために拡張結果を解析しません。したがって、コマンドは

firewall-cmd --permanent --remove-service="${EXISTING_SERVICES}"

スクリプトから次に展開します。

firewall-cmd --permanent --remove-service={cockpit,dhcpv6-client,ssh}

そしてその形式で動作します(中括弧内の式はこの時点で文字通り受け入れられます)。

これは有効なコマンドではないようですfirewall-cmd。引用するman firewall-cmd、構文は次--remove-serviceのとおりです。

... --remove-service=service

サービスを削除します。このオプションは複数回指定できます。

一度に複数のサービスを削除するための推奨される方法は次のとおりです。

firewall-cmd ... --remove-service=foo --remove-service=bar ...

Bashを使用すると、配列を使用してアクティブなサービスを保存し、それらを削除するための適切なオプションのリストを作成できます。

services=( $(firewall-cmd --permanent --list-services) )
firewall-cmd --permanent "${services[@]/#/--remove-service=}"

${services[@]/#/--remove-service=}Bashパラメータ拡張のパターン置換形式はどこにありますか?#各配列要素の先頭にある空の文字列を一致させ、に置き換えます--remove-service=

あまり効率的ではありませんが、場合によってはiffirewall-cmdのシャットダウン状態が変わるため、一度に1つのサービスを追加/削除する方が実用的かもしれません。0少なくともどんなに多くのタスクが失敗しても、1つのタスクは成功します。その場合は、次のことを好むことができます。

services=( $(firewall-cmd --permanent --list-services) )
for serv in "${services[@]}"
do
  firewall-cmd --permanent --remove-service="$serv" || echo "failed: $serv" >&2
done

おすすめ記事