함수의 모든 명령 캡처

함수의 모든 명령 캡처

저는 기능이 읽기 전용으로 간주되는 스크립트 세트로 작업하고 있습니다. 이러한 함수는 단순한 명령 목록이 아닙니다. 예를 들어 디렉터리를 반복하고 변경하거나 다른 함수를 호출할 수도 있습니다.

func() {
    cd folder/
    run command1
    mkdir folder2/ ; cd folder2/
    run command2
}

내가 원하는 것을 보여주기 위해 다음과 같이 스크립트를 변경할 수 있다고 잠시 가정해 보겠습니다.

func() {
    cd folder/
    string[0]="command1" ; run command1 |& tee out0.log ; result[0]="$?" ; finished_command_number 0
    mkdir folder2/ ; cd folder2/
    string[1]="command2" ; run command2 |& tee out1.log ; result[1]="$?" ; finished_command_number 1
}

따라서 파이프로 연결할 수는 있지만 사용하거나 반복할 수 없는 명령의 경우 cd문자열을 저장하고, 표준 출력(stderr)을 저장하고, 종료 코드를 저장한 다음 다른 명령을 실행하고 싶습니다. 그러나 이것을 추가할 수는 없습니다. func()를 사용하여 스크립트를 호출하는 스크립트에서 수행해야 합니다.

명령 후 호출 기능을 별도로 얻으려면 함수를 복사하고 를 사용하여 스크립트에서 실행해 보았지만 trap foo debug함수에 전파되지 않는 것 같습니다. 한 줄씩 복사하는 것은 작동하지 않을 것이라고 생각합니다. 왜냐하면 서브쉘 명령이 아닌 제어문이기 때문에 실제로 격리될 수 없기 때문입니다 cd.loops

문자열이 단지 명령 자체의 함수인 경우에는 여전히 유용합니다.

답변1

#!/bin/bash
# test.sh
post() {
        echo "post [$BASH_COMMAND] [$?]"
        echo "== $RANDOM =="
}
set -o functrace
trap post debug
func() {
        . check.sh
        tryme |& tee out.txt
}
func

출력은 무작위로 태그가 지정된 행을 기준으로 필터링될 수 있습니다. 여러 프로세스에서 얼마나 잘 작동하는지 확인하기 위해 이것을 더 테스트해야 하지만 짧은 명령에서는 잘 작동하는 것 같습니다. 디버그가 먼저 호출되었으므로 종료 코드는 하나의 명령보다 지연됩니다.

#!/bin/bash
# check.sh
tryme() {
        echo "one"
        echo "two"
        mkdir -p hello
        cd hello/
        echo "three"
        false
        echo "four"
}

===

$ bash test.sh 
post [func] [0]
== 22542 ==
post [func] [0]
== 10758 ==
post [. check.sh] [0]
== 9115 ==
post [tryme 2>&1] [0]
== 11979 ==
post [tee out.txt] [0]
== 17814 ==
post [tryme 2>&1] [0]
== 22838 ==
post [echo "one"] [0]
== 5251 ==
one
post [echo "two"] [0]
== 18036 ==
two
post [mkdir -p hello] [0]
== 4247 ==
post [cd hello/] [0]
== 21611 ==
post [echo "three"] [0]
== 24685 ==
three
post [false] [0]
== 8557 ==
post [echo "four"] [1]
== 7565 ==
four

답변2

귀하의 질문을 올바르게 읽으면 방법을 찾고 있습니다.

  • 함수 호출과 관계없이 stdout 및 stderr의 출력 캡처
  • 현재 작업 디렉토리를 보존하여 함수 실행 중 변경을 방지합니다.

이 작업은 매우 간단하게 수행할 수 있습니다.

#!/bin/bash
stdout=/path/to/output.std
stderr=/path/to/output.err

somefunc() {
    : Do things
}

( somefunc arg1 arg2 ) >> $stdout 2>> $stderr

서브셸에서 함수를 실행하면 작업 디렉터리 변경, 정상적으로 stdout 및 stderr로 출력하는 등 원하는 모든 작업을 수행할 수 있습니다. 서브셸이 종료되면 스크립트의 작업 디렉터리는 변경되지 않고 모든 stdout 및 stderr 출력이 캡처되어 로그 파일로 리디렉션됩니다.

명령의 종료 코드를 캡처하기 위해 배열(전역 또는 기타)을 추가하는 것은 간단합니다.

declare -a exitcodes
( exit 0 )
exitcodes+=( $? )
( exit 2 )
exitcodes+=( $? )
( exit 0 )
exitcodes+=( $? )

echo ${exitcodes[@]}

관련 정보