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