일시적으로 bash 옵션 설정 해제 -x

일시적으로 bash 옵션 설정 해제 -x

set -x나는 무슨 일이 일어나고 있는지 보여주기 위해 스크립트에서 이것을 사용하는 것을 좋아합니다 . 특히 스크립트가 CI/CD 파이프라인에서 실행되고 사실 이후에 일부 오류를 디버그해야 할 수도 있는 경우에는 더욱 그렇습니다.

이것에 대한 한 가지 성가신 점은 일부 텍스트(예: 상태 메시지 등)를 사용자에게 다시 에코하려는 경우 "I'm starting to do $X"해당 메시지가 두 번 출력된다는 것입니다. 한 번은 echo명령 자체를 에코하고 한 번은 echo해당 명령의 출력으로 출력됩니다.

이것을 더 좋게 만들 수 있는 좋은 방법이 있나요? 한 가지 해결책은 다음과 같습니다.

set -x

... bunch of normal commands that get echoed

(
  # Temporarily don't echo, so we don't double-echo
  set +x
  echo "Here is my status message"
)

... rest of commands get echoed again

하지만 이렇게 하면 두 가지 문제가 발생합니다.

  1. 사용자에게 무언가를 말하고 싶을 때마다 작성해야 할 양이 많고, 매번 설명이 필요할 정도로 "명백하지" 않습니다.
  2. set +x또한 이는 바람직하지 않다는 점을 반영합니다 .

잘 작동하는 다른 옵션이 있습니까?

그것은 마치@Make의 기능은 에코를 억제하기 위해 앞에 를 추가하는 것입니다.그러면 좋겠지만 Bash에서는 그런 기능을 찾을 수 없었습니다.

답변1

Bash에서 다음과 같이 이를 달성할 수 있습니다.아니요set -x캡처 대신 사용 DEBUG하고 자체 추적을 수행하십시오.

#!/bin/bash

set -T

trap '! [[ "$BASH_COMMAND" =~ ^(echo|printf) ]] &&
      printf "+ %s\n" "$BASH_COMMAND"' DEBUG

foo=bar
echo This is a test
echo $foo
[[ $foo = bar ]] && /usr/bin/printf 'Matched\n'

아이디어는 해당 줄의 정규식에 무시하려는 명령을 추가하는 것입니다 trap. 위의 명령을 실행하면 다음이 생성됩니다.

+ foo=bar
This is a test
bar
+ [[ $foo = bar ]]
+ /usr/bin/printf 'Matched\n'
Matched

set -T트랩이 쉘 함수에 의해 상속되는지 확인하십시오.

트랩을 활성화 및 비활성화하는 별도의 메커니즘을 추가할 수 있습니다.예를 들어쉘 변수를 사용하십시오:

#!/bin/bash

set -T

status() {
        NOTRACE=1 echo "$@"
}

trap '! [[ "$BASH_COMMAND" =~ ^(status|NOTRACE=) ]] &&
      printf "+ %s\n" "$BASH_COMMAND"' DEBUG

foo=bar
test=$(echo baz)
echo This is a test
status This is a status report
echo $foo
[[ $foo = bar ]] && /usr/bin/printf 'Matched\n'

이것은 생산할 것입니다

+ foo=bar
+ test=$(echo baz)
+ echo This is a test
This is a test
This is a status report
+ echo $foo
bar
+ [[ $foo = bar ]]
+ /usr/bin/printf 'Matched\n'
Matched

답변2

그것은 끔찍한 크루거이고 그것을 제안하는 것이 더럽다고 느껴지지만... 당신은 사용할 수 있습니다마법의 별칭. 이 트릭의 핵심은 별칭이 명령 실행의 구문 분석 단계의 일부로 확장되므로 set -x함수와 달리 확장 시 아무것도 인쇄되지 않는다는 것입니다. 따라서 별칭을 만들고 명령 앞에 "close -x" 상용구를 추가한 다음 마지막에 "reopen" 상용구를 실행하는 echo함수도 필요하다는 것을 발견할 수 있습니다 .-x

또한 스크립트에서 별칭 확장을 활성화해야 합니다. 일반적으로 비활성화되어 있으므로 예를 들어 grep별칭과 같은 것이 있으면 grep --color스크립트에서 사용할 때마다 색상 코드가 무작위로 삽입되지 않습니다 grep. 따라서 가장 안전한 방법은 unalias -a먼저 실행하여 문제를 일으킬 수 있는 별칭을 제거하는 것입니다.

어쨌든 코드는 다음과 같습니다.

unalias -a
shopt -s expand_aliases
alias cleanecho='{ set +x; } 2>/dev/null; resetx_after echo'
resetx_after() { "$@"; set -x; }

set -x
cleanecho "Ha, ha, you can't see the command that printed this!"

작동 방식: 유사한 명령이 다음 cleanecho "something"으로 확장됩니다.

{ set +x; } 2>/dev/null; resetx_after echo "something"

{ set +x; } 2>/dev/null꺼짐 -x모드(자체 추적을 /dev/null로 리디렉션) 그런 다음 resetx_after echo "something"다음을 실행하고 실행합니다.

{ echo "something"; set -x; }

...문자열을 인쇄한 다음 -x추적을 다시 켜세요.

그런데 다른 명령도 비슷하게 사용하려면 printf비슷한 별칭을 추가하면 됩니다.

alias cleanprintf='{ set +x; } 2>/dev/null; resetx_after printf'

...또는 접두사로 사용할 일반적인 don-trace-this 별칭을 만듭니다.

alias notrace='{ set +x; } 2>/dev/null; resetx_after'
notrace printf 'set -x disabled for this command\n'

답변3

단순한. 이미 절반쯤 왔으니 그냥 set -x동네 로 이사가세요

#!/bin/sh
echo a
(
    set -x
    echo b
)
echo c
$ a.sh
a
+ echo b
b
c

스크립트의 일부를 추적하고 싶지 않다면 두 부분으로 나누어 추적하세요.

#!/bin/sh
echo a
(
    set -x
    echo b
)
echo c
(
    set -x
    echo d
)
echo e

전체 스크립트보다는 의심되는 부분만 추적하세요.

관련 정보