programing

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

powerit 2023. 4. 28. 21:46
반응형

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

셸 스크립트에서 호출된 모든 셸 명령을 반향하고 변수 이름을 확장하려면 어떻게 해야 합니까?

예를 들어, 다음 행이 주어집니다.

ls $DIRNAME

스크립트에서 명령을 실행하고 다음을 표시합니다.

ls /full/path/to/some/dir

이 목적은 호출된 모든 셸 명령과 해당 인수의 로그를 저장하는 것입니다.이러한 로그를 생성하는 더 좋은 방법이 있을까요?

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

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

사용하다set +x그리고.set +v위의 설정을 해제합니다.

스크립트의 첫 줄에 다음과 같이 입력할 수 있습니다.#!/bin/sh -x(또는)-v)와한 효과를 set -x(또는)-v 에 설명합니다.는 대본의 후반부에 있습니다.

위의 내용은 다음과 함께 작동합니다./bin/sh.

속성 및 디버깅에 대한 자세한 내용은 bash-hackers의 Wiki를 참조하십시오.

$ cat shl
#!/bin/bash                                                                     

DIR=/tmp/so
ls $DIR

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

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

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

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

ls $PWD

이렇게 하면 모든 변수가 확장되고 명령 출력 전에 전체 명령이 인쇄됩니다.

출력:

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

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

#!/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

스크립트에서 선택한 줄을 줄로 감싸서 이 항목을 전환할 수도 있습니다.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

선택한 라인을 반향하는 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

그러나 이 경우 명령에 대한 새 하위 셸을 생성해야 하는 오버헤드가 발생합니다.

TLDPBash Guide for Bascher에 따르면: 2장. 스크립트 작성디버깅:

2.3.1.

$ bash -x script1.sh

...

이제 소스포지에서 사용할 수 있는 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

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

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

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

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

그러면 모든 명령이 반향됩니다.

bash -x example_script.sh

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

스크립트에 -x 옵션을 저장할 수도 있습니다.지정하기만 하면 됩니다.-x셰방에 있는 옵션.

######## 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

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

bash -x foo.sh

모든 대답을 종합해보니 이것이 가장 좋고 단순한 것으로 나타났습니다.

#!/bin/bash
# https://stackoverflow.com/a/64644990/8608146
exe(){
    set -x
    "$@"
    { set +x; } 2>/dev/null
}
# example
exe go generate ./...

{ set +x; } 2>/dev/nullhttps://stackoverflow.com/a/19226038/8608146 에서

여기에 언급된 대로 명령의 종료 상태가 필요한 경우

사용하다

{ STATUS=$?; set +x; } 2>/dev/null

그리고 다음을 사용합니다.$STATUS나중에 처럼exit $STATUS마지막에

조금 더 유용한 것.

#!/bin/bash
# https://stackoverflow.com/a/64644990/8608146
_exe(){
    [ $1 == on  ] && { set -x; return; } 2>/dev/null
    [ $1 == off ] && { set +x; return; } 2>/dev/null
    echo + "$@"
    "$@"
}
exe(){
    { _exe "$@"; } 2>/dev/null
}

# examples
exe on # turn on same as set -x
echo This command prints with +
echo This too prints with +
exe off # same as set +x
echo This does not

# can also be used for individual commands
exe echo what up!

zsh의 경우, 에코

setopt VERBOSE

디버깅을 위해서는

setopt XTRACE

복합 명령이 반향될 수 있도록 하기 위해 사용합니다.eval플러스 소츠exe명령을 에코하고 실행하는 기능.이 기능은 piped 명령을 실행하지 않으면 none 또는 piped 명령의 초기 부분만 표시되는 piped 명령에 유용합니다.

평가 없음:

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

위해서csh그리고.tcsh,넌 할 수 있다.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.

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

bash -x exampleScript.sh

출력은 다음과 같습니다.

여기에 이미지 설명 입력

소트의 대답에 따라.

강조 표시 없이 마크다운 출력을 생성할 수 있습니다(언어가 지정되지 않음).

set -x
exe() { echo "\`\$\$  ${@/eval/} \`" ; "$@" ; }

대본

set -x
exe() { echo "\`\$\$  ${@/eval/} \`" ; "$@" ; }
echo
echo -----------------------------------------------------------
echo # Setup
echo Lets take a random keyframe from in.mp4:
echo
exe eval "kfn=20"
echo
echo "kf=\$(ffprobe -v error -select_streams v -show_frames -print_format csv in.mp4 | grep 'frame,video,0,1' | head -$kfn | tail -1 | perl -pe 's|frame,video,0,1,.*?,(.*?),.*|\1|') "
exe eval "kf=$(ffprobe -v error -select_streams v -show_frames -print_format csv in.mp4 | grep 'frame,video,0,1' | head -$kfn | tail -1 | perl -pe 's|frame,video,0,1,.*?,(.*?),.*|\1|') "
echo
echo Lets select keyframe at $kf. Here are the timestamps of the all the frames from in.mp4 around this keyframe.
echo
exe eval "ffprobe -v error -select_streams v -show_frames -print_format csv in.mp4  | perl -pe 's|frame,video,0,(.*?),.*?,(.*?),.*|\2  \1|' | perl -pe 's|(.*?)  1|\1\tKF|' |  perl -pe 's|(.*?)  0|\1|' |grep -A 5 -B 5 --color $kf"
echo
echo Lets compare 2 methods of split: actual losslesscut 3.53.0 and another one
echo

산출량


in.mp4에서 임의의 키 프레임을 사용합니다.

$$ kfn=20

kf=$(ffprobe -v error -select_probe v -show_frames -print_format csv in.mp4 | grep 'frame, video, 0, video, 0, 1' | head -20 | tail -1 | perl -pe's | frame, video, 0, 1, ?(.*|\1|)

$$ kf=3.803792

3.803792에서 키 프레임을 선택합니다.여기 이 키 프레임 주위의 in.mp4의 모든 프레임의 타임스탬프가 있습니다.

$$ ffprobe -v error -select_streams v -show_frames -print_format csv in.mp4 | perl -pe 's|frame,video,0,(.*?),.*?,(.*?),.*|\2 \1|' | perl -pe 's|(.*?) 1|\1\tKF|' | perl -pe 's|(.*?) 0|\1|' |grep -A 5 -B 5 --color 3.803792

3.720375
3.737083
3.753750
3.770417
3.787125
**3.803792**   KF
3.820500
3.837167
3.853833
3.870542
3.887208

언급URL : https://stackoverflow.com/questions/2853803/how-to-echo-shell-commands-as-they-are-executed

반응형