쉘 명령이 실행될 때 에코하는 방법


911

쉘 스크립트에서 모든 쉘 명령을 에코하고 변수 이름을 어떻게 확장합니까?

예를 들어 다음과 같은 줄이 있습니다.

ls $DIRNAME

스크립트가 명령을 실행하고 다음을 표시하고 싶습니다.

ls /full/path/to/some/dir

목적은 호출 된 모든 쉘 명령 및 해당 인수의 로그를 저장하는 것입니다. 그런 로그를 생성하는 더 좋은 방법이 있습니까?

답변:


1042

set -x또는 set -o xtrace변수를 확장하고 줄 앞에 작은 + 부호를 인쇄합니다.

set -v또는 set -o verbose인쇄하기 전에 변수를 확장하지 않습니다.

set +xset +v을 사용 하여 위 설정을 끄십시오.

스크립트의 첫 번째 줄에서 나중에 스크립트에서 (또는 ) 와 동일한 효과를 갖도록 #!/bin/sh -x(또는 -v) 넣을 수 있습니다 .set -x-v

위의에서도 작동합니다 /bin/sh.

set속성디버깅 에 대한 bash-hackers 위키를 참조하십시오 .

$ cat shl
#!/bin/bash                                                                     

DIR=/tmp/so
ls $DIR

$ bash -x shl 
+ DIR=/tmp/so
+ ls /tmp/so
$

7
실행중인 번호가 매겨진 줄을 확인하려면 stackoverflow.com/a/17805088/1729501
user13107

3
반향 할 때 명령과 결과 출력을 구별하기 위해 명령을 색칠하려면 어떻게해야합니까?
Lewis Chan

10
반향 음이 들릴 때 보컬 로이드 같은 음성 합성기를 통해 각 명령을 노래하고 싶을 때 멀리서하는 일을 듣고 음악을 즐길 수 있다면 어떨까요? 아마도 입력과 출력에 대해 다른 목소리로 들릴 것입니다.
ADJenks

(ABS는 오랜 실무 사례를 수정하라는 요청, 오랜 커뮤니티 구성원이 경쟁 리소스를 만들도록 유도하는 시점에 이르기까지 오랜 시간 동안 반응이 없었습니다. 공식 bash 매뉴얼 은 더 나은 리소스가 될 것입니다).
Charles Duffy

316

set -x 당신이 원하는 것을 줄 것입니다.

다음은 셸 스크립트의 예입니다.

#!/bin/bash
set -x #echo on

ls $PWD

명령을 출력하기 전에 모든 변수를 확장하고 전체 명령을 인쇄합니다.

산출:

+ ls /home/user/
file1.txt file2.txt

21
그런 식으로 "verbose"라는 단어를 사용해도 아무런 효과가 없습니다. 당신은 할 수 set -o verbose또는 set -v(전용 "자세한 정보") 또는 set -o xtrace또는 set -x(전용 "xtrace") 또는 set -xv(모두) 또는 set -o xtrace -o verbose(모두).
추후 공지가있을 때까지 일시 중지되었습니다.

이것은 잘 작동하지만 "verbose"가 $ 1을 덮어 씁니다.
JasonS

90

함수를 사용하여 명령을 에코하고 실행합니다.

#!/bin/bash
# Function to display commands
exe() { echo "\$ $@" ; "$@" ; }

exe echo hello world

어떤 출력

$ echo hello world
hello world

보다 복잡한 명령 파이프 등의 경우 eval을 사용할 수 있습니다.

#!/bin/bash
# Function to display commands
exe() { echo "\$ ${@/eval/}" ; "$@" ; }

exe eval "echo 'Hello, World!' | cut -d ' ' -f1"

어떤 출력

$  echo 'Hello, World!' | cut -d ' ' -f1
Hello

이 답변에 대한 투표가 많지 않습니다. 그것이 나쁜 생각 인 이유가 있습니까? 나를 위해 일하고 내가 찾고있는 것 같습니다 ...
fru1tbat

1
모든 명령을 인쇄하지 않으려는 경우이 방법이 가장 적합합니다. ++ set +x깨끗해 보이는 것뿐만 아니라 전원을 끌 때 출력을 피합니다 . 단 하나 또는 두 개의 문장에 대해서는 서브 쉘을 사용한 bhassel의 대답이 가장 편리합니다.
브렌트 파우스트

이것이 내가 찾고있는 것입니다! 아니 set +x, 그것은 모든 명령에 영향을 미칩니다.
Hlung

11
이것의 주요 단점은 출력이 인용 정보를 잃어 버린다는 것입니다. 당신은 구별 할 수 cp "foo bar" bazcp foo "bar baz"예를 들어,. 따라서 사용자에게 진행 정보를 표시하는 데 좋습니다. 출력 디버깅 또는 재현 가능한 명령 기록에는 적합하지 않습니다. 다른 사용 사례. 에서가 zsh, 당신은으로 인용 보존 할 수 있습니다 :q수정 :exe() { echo '$' "${@:q}" ; "$@" ; }
앤드류 Janke

2
이 답변이 마음에 들지 않습니다. 당신이 보는 것이 당신이 얻는 것이 아닌 많은 경우가 있습니다 (특히 공백, 따옴표, 이스케이프 된 문자, 변수 / 표현 대체 등). echoed 명령을 터미널에 맹목적으로 붙여 넣지 말고 실행한다고 가정하십시오. 같은 방식으로. 또한 두 번째 기술은 해킹 일 뿐이며 eval명령에서 다른 단어 인스턴스를 제거합니다. 따라서 제대로 작동 할 것으로 기대하지 마십시오 exe eval "echo 'eval world'"!
mwfearnley

88

예를 들어, set -x및 에 줄 바꿈을 사용하여 스크립트에서 선택 라인에 대해 이것을 전환 할 수도 있습니다 set +x.

#!/bin/bash
...
if [[ ! -e $OUT_FILE ]];
then
   echo "grabbing $URL"
   set -x
   curl --fail --noproxy $SERV -s -S $URL -o $OUT_FILE
   set +x
fi

54

shuckc의 대답 선택 라인을 반향에 대한 몇 가지 단점을 가지고 : 다음으로 끝날 set +x명령뿐만 아니라 에코되고, 당신은 함께 종료 코드를 테스트 할 수있는 기능 잃게 $?가 덮어 도착 이후를 set +x.

또 다른 옵션은 서브 쉘에서 명령을 실행하는 것입니다.

echo "getting URL..."
( set -x ; curl -s --fail $URL -o $OUTFILE )

if [ $? -eq 0 ] ; then
    echo "curl failed"
    exit 1
fi

다음과 같은 출력을 제공합니다.

getting URL...
+ curl -s --fail http://example.com/missing -o /tmp/example
curl failed

그러나 명령에 대한 새 서브 쉘을 작성하는 오버 헤드가 발생합니다.


7
++ set +x출력 을 피하는 좋은 방법 .
브렌트 파우스트

3
더 나은 : 교체 if [ $? -eq 0 ]와 함께 if (set -x; COMMAND).
Amedee Van Gasse

35

또 다른 옵션은 "-x"를 명령 줄 대신 스크립트 맨 위에 두는 것입니다.

$ cat ./server
#!/bin/bash -x
ssh user@server

$ ./server
+ ssh user@server
user@server's password: ^C
$

이 사이에 정확히 동일하게 작동하지 않습니다 ./myScriptbash myScript. 그래도 좋은 지적입니다, 감사합니다.
altendky

27

초보자를위한 TLDPBash Guide에 따르면 : 2 장. 스크립트 작성 및 디버깅 :

2.3.1. 전체 스크립트에서 디버깅

$ bash -x script1.sh

...

SourceForge 에서 사용할 수있는 Bash 용 본격적인 디버거가 있습니다 . 이러한 디버깅 기능은 3.x부터 최신 Bash 버전에서 사용할 수 있습니다.

2.3.2. 스크립트의 일부에 대한 디버깅

set -x            # Activate debugging from here
w
set +x            # Stop debugging from here

...

표 2-1. 세트 디버깅 옵션 개요

    Short  | Long notation | Result
    -------+---------------+--------------------------------------------------------------
    set -f | set -o noglob | Disable file name generation using metacharacters (globbing).
    set -v | set -o verbose| Prints shell input lines as they are read.
    set -x | set -o xtrace | Print command traces before executing command.

...

또는 원하는 옵션을 첫 번째 행 쉘 선언에 추가하여 스크립트 자체에서 이러한 모드를 지정할 수 있습니다. 일반적으로 UNIX 명령의 경우와 같이 옵션을 결합 할 수 있습니다.

#!/bin/bash -xv

18

Bash 스크립트 이름 앞에 명령 행에서 "bash -x"를 입력하십시오. 예를 들어, foo.sh를 실행하려면 다음을 입력하십시오.

bash -x foo.sh

11

옵션을 사용하여 디버그 모드에서 Bash 스크립트를 실행할 수 있습니다 .-x

모든 명령이 반영됩니다.

bash -x example_script.sh

# Console output
+ cd /home/user
+ mv text.txt mytext.txt

스크립트에 -x 옵션을 저장할 수도 있습니다 . -xshebang 에서 옵션을 지정하십시오 .

######## example_script.sh ###################
#!/bin/bash -x

cd /home/user
mv text.txt mytext.txt

##############################################

./example_script.sh

# Console output
+ cd /home/user
+ mv text.txt mytext.txt

2
또한 bash -vx동일하지만 변수 보간없이 할 것
loa_in_을

4

zsh의 경우 echo

 setopt VERBOSE

디버깅을 위해

 setopt XTRACE

2

를 들어 cshtcsh, 당신이 할 수있는 set verbose또는set echo (또는 당신도 모두 설정할 수 있지만 일부 중복 대부분의 시간을 될 수 있습니다).

그만큼 verbose 옵션은 입력 한 것과 정확히 동일한 쉘 표현식을 인쇄합니다.

echo옵션은 스폰을 통해 실행될 내용을 더 많이 나타냅니다.


http://www.tcsh.org/tcsh.html/Special_shell_variables.html#verbose

http://www.tcsh.org/tcsh.html/Special_shell_variables.html#echo


Special shell variables

verbose If set, causes the words of each command to be printed, after history substitution (if any). Set by the -v command line option.

echo If set, each command with its arguments is echoed just before it is executed. For non-builtin commands all expansions occur before echoing. Builtin commands are echoed before command and filename substitution, because these substitutions are then done selectively. Set by the -x command line option.


1
$ cat exampleScript.sh
#!/bin/bash
name="karthik";
echo $name;

bash -x exampleScript.sh

출력은 다음과 같습니다.

여기에 이미지 설명을 입력하십시오


터미널의 색상 정의 (RGB, 숫자)는 무엇입니까?
Peter Mortensen

1

복합 명령을 반향 할 수 있도록 eval플러스 Soth의 exe기능을 사용 하여 명령을 반향하고 실행합니다. 이것은 그렇지 않으면 파이프 명령의 초기 부분 만 표시하거나 표시하지 않는 파이프 명령에 유용합니다.

평가없이 :

exe() { echo "\$ $@" ; "$@" ; }
exe ls -F | grep *.txt

출력 :

$
file.txt

평가와 함께 :

exe() { echo "\$ $@" ; "$@" ; }
exe eval 'ls -F | grep *.txt'

어떤 출력

$ exe eval 'ls -F | grep *.txt'
file.txt
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.