firewalld
Bash 스크립트를 통해 구성된 모든 기존 서비스를 지우려고 합니다 .
# 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
이와 관련하여 스크립트에서 명령을 실행하는 것과 대화식으로 실행하는 것 사이에는 차이가 없습니다. 대신 근본적으로 다른 두 가지 명령을 실행하고 있습니다.
당신이 행동에서 보는 것은버팀대 확장: 주문하다
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=
.
비록 덜 효율적이지만 어떤 경우에는 if firewall-cmd
의 종료 상태가 변경되므로 한 번에 하나의 서비스를 추가/제거하는 것이 더 실용적일 수 있습니다.0
적어도아무리 많은 작업이 실패하더라도 하나의 작업은 성공합니다. 그렇다면 다음을 선호할 수 있습니다.
services=( $(firewall-cmd --permanent --list-services) )
for serv in "${services[@]}"
do
firewall-cmd --permanent --remove-service="$serv" || echo "failed: $serv" >&2
done