여러 파일에서 특정 문자열을 확인한 다음 발견되면 제거하는 bash 스크립트를 작성하려고 합니다. 여기에 내가 가지고 있는 것이 있고 그것이 효과가 있을 것이라고 생각하지만 부분적으로만 가능합니다. 파일의 항목은 삭제되지만 두 번째로 실행하면 "Nothing to do..." 메시지가 표시되지 않습니다.
#!/bin/bash
files=(
'/etc/rsyslog.conf'
'/etc/rsyslog.d/remote.conf'
'/etc/rsyslog.d/01-remote.conf'
)
tmpcheck="for f in ${files[*]}; do cat $f | grep blah | wc -l; done"
#for f in ${files[*]}; do cat $f | grep collector.acuity.com | wc -l; done
if [[ "$tmpcheck" != 1 ]];then
for f in "${files[@]}";do
echo -e "Removing blah from $f"
sed -i "/blah/d" "$f"
done
echo -e "Restarting rsyslog service"
systemctl restart rsyslog.service
else
echo -e "Nothing to do, blah has been removed from $f"
fi
어떤 도움이라도 큰 도움이 될 것입니다.
답변1
tmpcheck
코드의 주요 문제(쌍 할당)는 다른 답변에서 지적되었습니다. 수정된/수정되지 않은 파일의 이름을 인쇄하는 것이 필수가 아니라고 가정하는 약간 다른 접근 방식은 다음과 같습니다.
if grep -q -- blah "${files[@]}"
then
sed -i -e '/blah/d' -- "${files[@]}"
systemctl restart rsyslog.service
else
printf '%s\n' 'Nothing to do'
fi
여기서 주요 아이디어는 다음과 같습니다.
- 필요한 경우가 아니면 출력을 저장하고 나중에 테스트하는 대신 복합 명령 내에서 직접 명령의 (
grep
) 종료 상태를 사용하십시오.if
- 루프에서 유틸리티를 호출하는 것은 덜 효율적입니다. 가능할 때마다 여러 파일을 인수로 사용하여 호출하는 것이 가장 좋습니다.
또한 표시되는 코드에서는 이러한 문제가 발생하지 않지만 다음을 수행합니다.
- 옵션 닫기 태그(
--
)를 추가하면 비정상적인 파일 이름을 방지할 수 있습니다. printf
더 안전한특히 확장된 결과를 인쇄할 때 더욱 그렇습니다echo
.
답변2
for 루프 내부의 말도 안되는 내용을 확인하고 싶다고 생각합니다. tmpcheck 변수는 필요하지 않습니다. 대신 $restartrsyslog
rsyslog를 한 번만 다시 시작할 수 있습니다.
files=(
'/etc/rsyslog.conf'
'/etc/rsyslog.d/remote.conf'
'/etc/rsyslog.d/01-remote.conf'
)
restartrsyslog=
for f in "${files[@]}";do
if grep -q blah "$f"; then
echo -e "Removing blah from $f"
sed -i "/blah/d" "$f"
restartrsyslog=yes
else
echo -e "Nothing to do, blah has been removed from $f"
fi
done
if [[ -n $restartrsyslog ]] ; then
echo -e "Restarting rsyslog service"
systemctl restart rsyslog.service
fi
답변3
변수 는 tmpcheck
해당 명령의 출력이 아닌 명령으로 설정되며 1과 같지 않으므로 표현식은 항상 true로 평가됩니다. $( ... )
명령의 출력을 바꾸려면 이 구성을 사용해야 합니다 . 또한 파일을 반복할 필요는 없지만, 그렇게 하는 경우 ${files[*]}
해당 파일을 대신 사용해서는 안 됩니다 ${files[@]}
. 또한 파일을 읽을 수 있으므로 cat
단일 파일로 파이프 할 필요가 없고 결과를 선택적으로 계산할 수 있으므로 파이프 로 연결할 필요도 없습니다 . 마지막으로 왜 1이 아닌지 확인하고 싶습니까 ? 2 이상이면 어떻게 되나요?grep
grep
grep
wc -l
grep
-c
tmpcheck
이것이 당신에게 효과가 있습니까?
#!/bin/bash
files=(
'/etc/rsyslog.conf'
'/etc/rsyslog.d/remote.conf'
'/etc/rsyslog.d/01-remote.conf'
)
tmpcheck=$(cat "${files[@]}" | grep -c blah)
if (($tmpcheck>=1)); then
for f in "${files[@]}";do
echo -e "Removing blah from $f"
sed -i "/blah/d" "$f"
done
echo -e "Restarting rsyslog service"
systemctl restart rsyslog.service
else
echo -e "Nothing to do, blah has been removed from $f"
fi