일부 명령이 실행되는 시간을 측정하는 스크립트가 있습니다.
“실제” time
명령 이 필요합니다. 예를 들어 /usr/bin/time
bash-built-in에는 -f
플래그 가 없기 때문에 바이너리입니다 .
아래는 디버깅 할 수있는 단순화 된 스크립트입니다.
#!/bin/bash
TIMESEC=$(echo blah | ( /usr/bin/time -f %e grep blah >/dev/null ) 2>&1 | awk -F. '{print $1}')
echo ABC--$TIMESEC--DEF
if [ "$TIMESEC" -eq 0 ] ; then
echo "we are here!"
fi
“test.sh”로 저장하고 다음을 실행하십시오.
$ bash test.sh
ABC--0--DEF
we are here!
그래서 효과가있었습니다.
이제 bash 명령 행에 “-x”를 추가하여 이것을 디버깅 해 보자 :
$ bash -x test.sh
++ echo blah
++ awk -F. '{print $1}'
+ TIMESEC='++ /usr/bin/time -f %e grep blah
0'
+ echo ABC--++ /usr/bin/time -f %e grep blah 0--DEF
ABC--++ /usr/bin/time -f %e grep blah 0--DEF
+ '[' '++ /usr/bin/time -f %e grep blah
0' -eq 0 ']'
test.sh: line 10: [: ++ /usr/bin/time -f %e grep blah
0: integer expression expected
“-x”를 사용할 때이 스크립트가 중단되는 이유는 무엇입니까?
답변
문제는이 줄입니다.
TIMESEC=$(echo blah | ( /usr/bin/time -f %e grep blah >/dev/null ) 2>&1 | awk -F. '{print $1}')
여기서 표준 출력과 일치하도록 표준 오류를 리디렉션합니다. bash는 추적 메시지를 표준 오류에 기록하고 있으며 (예를 들어) echo
bash 프로세스에서 다른 쉘 구성과 함께 내장 기능을 사용하고 있습니다.
당신이 같은 것으로 변경하면
TIMESEC=$(echo blah | sh -c "( /usr/bin/time -f %e grep blah >/dev/null )" 2>&1 | awk -F. '{print $1}')
이 문제를 해결하고 추적과 작업 사이에 적절한 타협이 될 수 있습니다.
++ awk -F. '{print $1}'
++ sh -c '( /usr/bin/time -f %e grep blah >/dev/null )'
++ echo blah
+ TIMESEC=0
+ echo ABC--0--DEF
ABC--0--DEF
+ '[' 0 -eq 0 ']'
+ echo 'we are here!'
we are here!
답변
서브 쉘을 떨어 뜨릴 수도 있습니다. 분명히 서로를 화나게하는 중첩 된 껍질입니다.
TIMESEC=$(
echo blah |
/usr/bin/time -f %e grep blah 2>&1 >/dev/null |
awk -F. '{print $1}'
)
당신이 할 경우 :
...| ( subshell ) 2>pipe | ...
… 서브 쉘을 호스팅 하는 파이프 라인의 해당 섹션을 처리하기 위해 시작된 서브 쉘을 시작합니다 . 셸이없는 셸 은 파이프 라인의 해당 섹션으로 ( 사용하도록 선택한 다른 종류의 {
복합 명령 에도; } >redirect
적용됨) 서브 쉘의 디버그 출력도 리디렉션하므로 믹싱 스트림을 종료합니다. 리디렉션 순서와 관련이 있습니다.
대신, 단순히 시도하려는 명령의 오류 출력 만 리디렉션 하고 호스트 셸의 출력을 stderr로 만들면 같은 문제가 발생하지 않습니다.
그래서 …
... | command 2>pipe 1>/dev/null | ...
… 호스트 쉘은 파이프로 호출하는 명령의 출력 만 리디렉션하는 동안 원하는 곳에 stderr를 계속 쓸 수 있습니다.
bash -x time.sh
+++ echo blah
+++ /usr/bin/time -f %e grep blah
+++ awk -F. '{print $1}'
++ TIMESEC=0
++ echo ABC--0--DEF
ABC--0--DEF
++ '[' 0 -eq 0 ']'
++ echo 'we are here!'
we are here!
그 문제에 대한…
TIMESEC=$(
echo blah |
/usr/bin/time -f %e grep blah 2>&1 >/dev/null
)
printf %s\\n "ABC--${TIMESEC%%.*}--DEF"
if [ "${TIMESEC%%.*}" -eq 0 ] ; then
echo "we are here!"
fi