"watch" 명령을 사용하여 따옴표(")가 있는 여러 명령을 묶는 방법은 무엇입니까?

"watch" 명령을 사용하여 따옴표(")가 있는 여러 명령을 묶는 방법은 무엇입니까?

watch다음 명령 체인을 사용하고 싶습니다 .

journalctl | grep 'UFW BLOCK' | grep 'DST=192.168.0.2' | awk '{printf "%-4s%-3s%-10s%-1s%+16s\n", $1, $2, $3, $7, $11, $18, $19}'

watch일반적으로 명령 계통 에 적용하고 싶을 때 명령 계통을 따옴표로 묶습니다.

watch "COMMAND_1 | COMMAND_2 | ... | COMMAND_n"

그러나 위와 같은 명령 중 하나에 또 다른 인용문이 있으면 문제가 발생합니다. 이 문제에 대한 해결책은 무엇입니까?

답변1

인용문에 대한 걱정을 피하려면 다음 문서를 사용하세요.

shell_code=$(cat << 'EOF'
  journalctl |
    awk '
      /UFW BLOCK/ && index($0, "DST=192.168.0.2 ") {
         printf "%-4s%-3s%-10s%-1s%+16s\n", $1, $2, $3, $7, $11, $18, $19
      }'
EOF
)

watch "$shell_code"

(또는 구현에서 아직 명령줄을 해석하기 위해 셸을 시작하지 않고 대신 명령 자체를 실행하는 watch sh -c "$shell_code"경우 , 요즘에는 이러한 구현이 점점 더 드물어지고 있습니다.)watchwatch

기타 참고사항:

  • awk할 수 있는 대부분의 작업을 수행할 수 grep있으므로 서로 연결할 필요가 거의 없습니다.

  • .단일 문자와 일치하는 정규식 연산자입니다. 정규식 일치를 사용하는 대신 or 를 사용하여 이스케이프 하거나 in 또는 in 을 사용하여 하위 문자열 검색을 grep 192.168.0.2수행 192.168.012할 수 있습니다 .[.]\.-Fgrepindex()awk

  • 검색 문자열에 추가 공백을 추가하지 않으면 DST=192.168.0.2다음과 같은 항목 도 DST=192.168.0.234찾을 수 있습니다. 사용하면 grep -Fw DST=192.168.0.2두 가지 문제가 모두 해결됩니다.

  • $s 또는 s를 이스케이프하는 것을 잊어버리고 명령 주입 취약점이 발생하기 쉽기 때문에 쉘 코드를 묶는 데 큰따옴표를 사용하지 않을 것입니다 `(변수의 내용이 쉘 코드로 해석될 수 있음). 작은따옴표에는 특수 문자가 포함되지 않으므로 더 안전합니다. 여기에는 s 자체가 포함되므로 '(적어도 Bourne과 같은 쉘에서는) 's를 에 포함 할 수는 없지만 항상 로 연결 되어 ( 백슬래시로 인용) '...'로 입력할 수 있습니다 . 그래서 여기 있습니다:'foo'\''bar''foo'\'''bar'

    watch 'journalctl |
       awk '\''
         /UFW BLOCK/ && index($0, "DST=192.168.0.2 ") {
            printf "%-4s%-3s%-10s%-1s%+16s\n", $1, $2, $3, $7, $11, $18, $19
         }'\'
    
  • journalctl새로운 로그 항목이 도착하면 이를 표시하는 -f/ 모드 가 있습니다 . --follow전체 로그를 반복해서 검색하는 대신 이 방법을 사용할 수 있습니다.


1Run 의 구현은 watch인수가 공백으로 연결된 코드를 해석하지만 / 옵션을 사용하여 명령을 직접 실행할 수 있으므로 다른 언어 해석기(예: 또는 )에서 코드를 더 쉽게 해석할 수 있습니다.procps-ngsh-x--execwatch -x zsh -c 'zsh code'watch -x perl -e 'perl code'

² 그러나 완전성을 위해 이 옵션이 활성화되면 zsh(Bourne과 유사하지만 rc 및 csh 기능도 있음)는 'foo''bar'작은따옴표로 묶인 문자열 내에 작은따옴표를 포함할 수 있습니다.rcrcquotes

관련 정보