추상적인

추상적인

set -x무작정 설정하는 것보다 스크립트 시작 부분에서 "실행 취소"(설정 전 상태로 돌아가기) 하고 싶습니다 +x. 이것이 가능합니까?

추신 : 확인했습니다여기;내가 아는 한 이것은 내 질문에 대한 대답이 아닌 것 같습니다.

답변1

추상적인

을 되돌리려 set -xset +x. 대부분의 경우 문자열의 반대는 : 과 동일한 문자열 set -str입니다 .+set +str

일반적으로 모든 errexit셸 옵션(bash에 대해 아래 참조)을 복원하려면(명령을 사용하여 변경됨 set) 다음을 수행할 수 있습니다(bash shopt옵션에 대해서도 아래 참조).

oldstate="$(set +o)"                # POSIXly store all set options.
.
.
set -vx; eval "$oldstate"         # restore all options stored.

충분해야 하지만 bash에는 set(or ) 및 일부를 통해 shopt -po액세스되는 두 가지 옵션 세트가 있습니다. 또한 bash는 shopt -p하위 쉘에 들어갈 때 지속 set -e(errexit) 되지 않습니다. 확장으로 생성된 옵션 목록은 $-셸에 다시 입력되지 않을 수 있습니다.

bash에서 전체 현재 상태를 캡처하려면 다음을 사용하십시오.

oldstate="$(shopt -po; shopt -p)"; [[ -o errexit ]] && oldstate="$oldstate; set -e"

inherit_errexit또는 플래그 설정이 마음에 들지 않는 경우 (그리고 bash는 ≥4.4입니다):

shopt -s inherit_errexit;    oldstate="$(shopt -po; shopt -p)"

더 긴 설명

세게 때리다

이 명령은 다음과 같습니다.

shopt -po xtrace

옵션 상태를 반영하는 실행 가능한 문자열을 생성하는 데 사용됩니다. 플래그는 p인쇄를 의미하고, 플래그는 명령에 의해 설정된 옵션(옵션 세트가 아님) o에 대해 묻는 것을 지정합니다.set오직명령을 통해 shopt). 이 문자열을 변수에 할당하고 스크립트 끝에서 실행하여 초기 상태를 복원할 수 있습니다.

# store state of xtrace option.
tracestate="$(shopt -po xtrace)"

# change xtrace as needed
echo "some commands with xtrace as externally selected"
set -x
echo "some commands with xtrace set"

# restore the value of xtrace to its original value.
eval "$tracestate"

이 솔루션은 여러 옵션과 동시에 작동합니다.

oldstate="$(shopt -po xtrace noglob errexit)"

# change options as needed
set -x
set +x
set -f
set -e
set -x

# restore to recorded state:
set +vx; eval "$oldstate"

set +vx긴 옵션 목록을 인쇄하지 않도록 추가되었습니다 .


옵션 이름을 나열하지 않으면

oldstate="$(shopt -po)"

모든 (설정) 옵션의 값을 제공합니다. 그리고 플래그를 생략하면 옵션을 사용하여 동일한 작업을 수행 o할 수 있습니다 .shopt

# store state of dotglob option.
dglobstate="$(shopt -p dotglob)"

# store state of all options.
oldstate="$(shopt -p)"

옵션이 설정되어 있는지 테스트해야 하는 경우 set가장 관용적인(Bash) 방법은 다음과 같습니다.

[[ -o xtrace ]]

이는 다른 두 가지 유사한 테스트보다 낫습니다.

  1. [[ $- =~ x ]]
  2. [[ $- == *x* ]]

모든 테스트에서 다음과 같이 작동합니다.

# record the state of the xtrace option in ts (tracestate):
[ -o xtrace ] && ts='set -x' || ts='set +x'

# change xtrace as needed
echo "some commands with xtrace as externally selected"
set -x
echo "some commands with xtrace set"

# set the xtrace option back to what it was.
eval "$ts"

옵션 상태를 테스트하는 방법은 다음과 같습니다 shopt.

if shopt -q dotglob
then
        # dotglob is set, so “echo .* *” would list the dot files twice.
        echo *
else
        # dotglob is not set.  Warning: the below will list “.” and “..”.
        echo .* *
fi

POSIX

모든 옵션을 저장하기 위한 간단한 POSIX 호환 솔루션은 set다음과 같습니다.

set +o

이것은POSIX 표준에 설명되어 있음처럼:

+o

    동일한 옵션 설정을 구현하는 명령으로 셸에 다시 입력하기에 적합한 형식으로 현재 옵션 설정을 표준 출력에 기록합니다.

간단히 말해서 다음과 같습니다.

oldstate=$(set +o)

set이 명령으로 설정된 모든 옵션의 값은 (일부 쉘에서는) 유지됩니다 .

마찬가지로 옵션을 원래 값으로 복원하는 것은 단순히 변수를 실행하는 문제입니다.

set +vx; eval "$oldstate"

이는 Bash를 사용하는 것과 동일합니다 shopt -po.아니요씌우다모두가능한불다옵션 중 일부만 제공되기 때문입니다 shopt.

배쉬 특별한 경우

shoptBash에는 다른 많은 쉘 옵션이 나열되어 있습니다.

$ shopt
autocd          off
cdable_vars     off
cdspell         off
checkhash       off
checkjobs       off
checkwinsize    on
cmdhist         on
compat31        off
compat32        off
compat40        off
compat41        off
compat42        off
compat43        off
complete_fullquote  on
direxpand       off
dirspell        off
dotglob         off
execfail        off
expand_aliases  on
extdebug        off
extglob         off
extquote        on
failglob        off
force_fignore   on
globasciiranges off
globstar        on
gnu_errfmt      off
histappend      on
histreedit      off
histverify      on
hostcomplete    on
huponexit       off
inherit_errexit off
interactive_comments    on
lastpipe        on
lithist         off
login_shell     off
mailwarn        off
no_empty_cmd_completion off
nocaseglob      off
nocasematch     off
nullglob        off
progcomp        on
promptvars      on
restricted_shell    off
shift_verbose   off
sourcepath      on
xpg_echo        off

이는 위에 설정된 변수에 추가되고 동일한 방식으로 복원될 수 있습니다.

$ oldstate="$oldstate;$(shopt -p)"
.
.                                   # change options as needed.
.
$ eval "$oldstate" 

배쉬의 set -e특별한 경우

set -eBash에서는 ( )의 값이 errexit서브셸 내에서 재설정되므로 set +o$(...) 서브셸 내에서 해당 값을 캡처하기가 어렵습니다.

해결 방법으로 다음을 사용하십시오.

oldstate="$(set +o)"; [[ -o errexit ]] && oldstate="$oldstate; set -e"

또는 (목표와 충돌하지 않고 bash가 이를 지원하는 경우) 이 inherit_errexit옵션을 사용할 수 있습니다.


노트: 각 셸은 설정 또는 설정 해제 옵션 목록을 약간 다르게 작성하므로(다른 옵션이 정의된 것은 말할 것도 없고) 문자열은 셸 간에 이식 가능하지 않지만 동일한 셸에서는 유효합니다.

zsh 특별한 경우

zsh또한 버전 5.3(POSIX 호환)부터 잘 작동합니다. 이전 버전에서는 set +o셸에 명령으로 다시 입력하는 데 적합한 형식으로 옵션을 인쇄한다는 점에서 POSIX를 부분적으로 따랐습니다.놓다옵션(인쇄되지 않습니다.설정되지 않음옵션).

mksh 특별한 경우

mksh(및 결과 lksh)는 아직 이 작업을 수행할 수 없습니다(MIRBSD KSH R54 2016/11/11). mksh 매뉴얼에는 다음 내용이 포함되어 있습니다.

향후 릴리스에서는 set +o가 POSIX 규격으로 작동하고 현재 옵션을 복원하는 명령을 인쇄합니다.

답변2

Almquist 셸 및 파생물(적어도 dashNetBSD/FreeBSD) 및 4.4 이상을 사용하면 다음을 사용하여 옵션을 함수에 대한 로컬(원하는 경우 로컬 변수에 대한 변수)로 설정할 수 있습니다.shbashlocal -$-

$ bash-4.4 -c 'f() { local -; set -x; echo test; }; f; echo no trace'
+ echo test
test
no trace

이는 다음에는 적용되지 않습니다.원천파일을 재정의하여 이 문제를 해결할 수 source있습니다 source() { . "$@"; }.

를 사용하면 ksh88옵션 변경은 기본적으로 기능별로 이루어집니다. 의 경우 ksh93이는 구문을 사용하여 정의된 함수에서만 발생합니다 function f { ...; }(범위 지정은 ksh88을 포함하여 다른 셸에서 사용되는 동적 범위 지정에 비해 정적입니다).

$ ksh93 -c 'function f { set -x; echo test; }; f; echo no trace'
+ echo test
test
no trace

에서는 다음 옵션을 사용하여 zsh이 작업을 수행합니다.localoptions

$ zsh -c 'f() { set -o localoptions; set -x; echo test; }; f; echo no trace'
+f:0> echo test
test
no trace

POSIXly에서는 다음과 같이 할 수 있습니다.

case $- in
  (*x*) restore=;;
  (*) restore='set +x'; set -x
esac
echo test
{ eval "$restore";} 2> /dev/null
echo no trace

그러나 일부 쉘은 + 2> /dev/null복원할 때 출력합니다(추적하다case물론, set -x구성이 이미 활성화된 경우입니다. 이 메서드는 또한 재진입이 불가능합니다(자신을 호출하는 함수나 동일한 트릭을 사용하는 다른 함수에서 수행하는 것과 같습니다).

바라보다https://github.com/stephane-chazelas/misc-scripts/blob/master/locvar.sh(POSIX 셸 변수 및 옵션의 로컬 범위) 이 문제를 해결하기 위해 스택을 구현하는 방법을 알아보세요.

모든 쉘에 대해 서브쉘을 사용하여 옵션 범위를 제한할 수 있습니다.

$ sh -c 'f() (set -x; echo test); f; echo no trace'
+ echo test
test
no trace

그러나 이는 옵션뿐만 아니라 모든 것(변수, 함수, 별칭, 리디렉션, 현재 작업 디렉터리...)의 범위를 제한합니다.

답변3

$-처음에 변수를 읽어 -x설정되어 있는지 확인한 다음 변수에 저장할 수 있습니다 .

if [[ $- == *x* ]]; then
  was_x_set=1
else
  was_x_set=0
fi

~에서배쉬 매뉴얼:

($-, 하이픈.) 호출 시 지정된 현재 옵션 플래그, 내장 설정에 의해 설정되거나 쉘 자체에 의해 설정(예: -i 옵션)으로 확장됩니다.

답변4

확실히 하기 위해, set -x이것이 스크립트 기간 동안 유효하고 임시 테스트 측정일 뿐이라면(출력의 영구적인 부분이 아님) 옵션을 사용하여 스크립트를 호출하십시오 -x.

$ bash -x path_to_script.sh

...또는 옵션을 추가하여 디버그 출력을 활성화하도록 스크립트(첫 번째 줄)를 일시적으로 변경합니다 -x.

#!/bin/bash -x
...rest of script...

나는 이것이 당신이 원하는 것에 비해 너무 광범위하다는 것을 알고 있지만 (내 경험에 따르면) 제거하고 싶은 임시 항목으로 스크립트를 지나치게 복잡하게 만들지 않고 활성화/비활성화하는 가장 쉽고 빠른 방법입니다.

관련 정보