시간 명령과 유사한 명령의 로그 종료 코드


10

사용

time sleep 1

수율 :

$ time sleep 1

real    0m1.005s
user    0m0.001s
sys     0m0.001s

종료 코드 sleep또는 인쇄 하려는 명령 을 인쇄하는 데 사용할 수있는 명령이 있습니까?

좋아하는 것 :

$ log-exit-code sleep 1

아마도 이것으로 충분합니까?

sleep 1 && echo "$?"

3
아니, sleep 1 && echo $?그것은 ... 제로 때만자는 세포의 코드를 인쇄 할 것이다
사토 가쓰라

오, 당신이 맞아요
Alexander Mills

1
sleep 1 && echo "$?" || echo "$?"
jesse_b

2
나는 지금까지 다른 모든 것들이 원래의 반환 값을 버릴 때 답을 추가했습니다. 이것은 imo가 나쁜 것입니다 (해답 후 $?는 항상 0이므로 disply이므로 항상 작동합니다. 원래 반환 값을 표시 한 후 반환합니다. 따라서 관찰자에게 표시하지만 스크립트의 나머지 부분에 대해서는 '숨기기'하여 현재 "$?"를 사용하여 중요한 명령이 반환되는지 확인할 수 없습니다. 0 또는 다른 것 ...)
Olivier Dulac

1
또한 아래의 모든 솔루션은이 기능을 쉽게 구현할 수 있습니다. 예를 들어 Kusalananda는 다음과 같습니다.EXIT_CODE=$(tellexit command)
jesse_b

답변:


4

지금까지 내 테스트에서 다음과 같이 작동했습니다.

command && echo "$?" || echo "$?"

종료 코드가 성공하거나 실패한 경우 종료 코드를 에코하도록 지시합니다.

Sato가 아래에서 지적했듯이 이것은 본질적으로 다음과 같습니다.

command; echo "$?"

및 / 또는 명령을 가치있게 만들 수있는 한 가지는 다음과 같습니다.

command && echo "Success! Exit Code: $?" || echo "Failure! Exit Code: $?"

Olivier의 관심사와 같이 스크립트가 종료 코드에서 작동하도록하려면 문제가되지 않습니다. 스크립트는 다음과 같습니다.

command
case "$?" in; 
    0) echo "Command exited with: 0"
       <command if good>
       ;;
    1) echo "Command exited with: 1"
        <command if bad>
        ;;
    255) echo "Command exited with: 255"  # for ssh maybe?
         <command if 255>
         ;;
    *) echo "Command exited with: >2"
        <command for other exit code>
        ;;
esac

13
어, 그게 command; echo $?어때요?
Satō Katsura

4
나는 그렇지 않다고 생각합니다. command; echo $?훨씬 더 나은 대답입니다.
jesse_b

이게 최선의 선택 인 것 같아서 누군가 동의하지 않으면 대답으로 선택했습니다. lmk
Alexander Mills

@AlexanderMills 당신 만이 당신의 질문에 가장 적합한 답을 알고 있습니다 :-)
Kusalananda

1
나는 이것을 싫어한다 : 이것은 항상 성공 command ; echo $?하기 때문에 종료 코드를 변경 echo $?하므로 그 뒤에 새로운 값 $? 이 원래 리턴 코드가 나중에 유용 할 경우를 대비하여 원래 리턴 코드를 표시 한 후에도 유지할 수있는 방법이 있습니다 (예 : 스크립트에서 리턴 코드를 확인하는 것이 계속되는 방법을 결정하기 전에 중요 함). 여러 솔루션 중 하나에 대한 내 대답을 참조하십시오 (대부분의 답변은 같은 방식으로 변경 될 수 있습니다)
Olivier Dulac

11

cmd && echo "$?"필연적으로 0을 인쇄하기 때문에 작동하지 않습니다 ( echo이전 명령을 성공적으로 완료하면 실행됩니다).

짧은 쉘 기능은 다음과 같습니다.

tellexit () {
    "$@"

    local err="$?"
    printf 'exit code\t%d\n' "$err" >/dev/tty
    return "$err"
}

이것은 명령과 유사한 방식으로 주어진 명령의 종료 코드를 인쇄합니다 time.

$ tellexit echo "hello world"
hello world
exit code       0

$ tellexit false
exit code       1

함수 에서 printfto 를 리디렉션하면 표준 출력 또는 오류 스트림에 정크가 없어도 리디렉션과 함께 /dev/tty계속 사용할 수 있습니다 tellexit.

$ tellexit bash -c 'echo hello; echo world >&2' >out 2>err
exit code       0
$ cat out
hello
$ cat err
world

종료 코드를 변수에 저장하여 호출자에게 반환 할 수 있습니다.

$ tellexit false || echo 'failed'
exit code       1
failed

동일한 기능의 더 멋진 버전은 종료 코드가 128보다 큰 경우 명령을 종료 한 신호를 출력합니다 (신호로 인해 종료됨을 의미 함).

tellexit () {
    "$@"

    local err="$?"

    if [ "$err" -gt 128 ]; then
        printf 'exit code\t%d (%s)\n' "$err" "$(kill -l "$err")" >/dev/tty
    else
        printf 'exit code\t%d\n' "$err" >/dev/tty
    fi

    return "$err"
}

테스트 :

$ tellexit sh -c 'kill $$'
exit code       143 (TERM)

$ tellexit sh -c 'kill -9 $$'
Killed
exit code       137 (KILL)

( / / / /이 local필요 하거나 다른 쉘도 이해할 수 있도록 변경할 수 있습니다 .)ashpdkshbashzshtypeset


멋지다, tellexit을 어떻게 사용하겠습니까? 액션 pls에서 보여주십시오
Alexander Mills

1
@AlexanderMills 업데이트를 참조하십시오.
Kusalananda

2
원래 반환 값을 유지하고 결국 반환해야합니다.
Olivier Dulac

@OlivierDulac 정말 좋은 관찰! 수정하겠습니다.
Kusalananda

7

쉘 랩퍼 기능을 사용하십시오. 아마 다른 이름으로.

$ exito() { "$@"; echo $?; }
$ exito true
0
$ exito false
1
$ exito echo "test test"      
test test
0
$ 

(물론 이것은 표준 출력을 손상시킬 수 있으므로 tty@Kusalananda에 표시된 것과 같이 사용하거나 대화 형 컨텍스트 외부에서는 사용하지 마십시오.)

이식 할 수없는 영역으로 이동하여 일부 셸은 마지막 파이프 라인이 아닌 파이프 라인의 모든 명령 상태 (예 : 전체 파이프 라인에서 오류를보고하려는 경우 ZSH)를보고 할 수 있습니다.

% TRAPZERR() { print >/dev/tty $pipestatus }
% perl -e 'exit 42' | perl -e 'exit 99'
42 99
% false | perl -e 'exit 42' | perl -e 'exit 99'
1 42 99
% perl -e 'exit 42' | perl -e 'exit 99' | true
% 

TRAPZERR 그렇지 않으면 오류가 없을 때 ( "뉴스가 희소식이 아닙니다"교장) 실행되지 않습니다.


1
원래 반환 값을 유지하고 결국 반환해야합니다. (-, 등으로 시작하지 않는) 간단한 일을 표시 (printf, echo)하면 항상 작동하며 그 후에는 "$?" 디스플레이로 값이 "0"일을 지금하고있다
올리비에 Dulac에게

7

GNU time는 이것을위한 옵션을 가지고 있습니다 :

time -f %x sleep 1
0

신호 2에 의해 종료 되지 않으면 종료 코드 1을 통과합니다 .

$ /usr/bin/time -f %x sleep 1; echo $?
0
0

$ /usr/bin/time -f %x sleep 2x; echo $?
sleep: invalid time interval ‘2x’
Try 'sleep --help' for more information.
1
1

$ /usr/bin/time -f %x sleep 60s; echo $? # Press ^C before a minute elapses
0
2

신호 강제 종료 상황을 알고 / 처리 -v하려면 문자열에 대한 stderr을 전달 하고 grep하십시오 Command terminated by signal.


1 종료 코드가 통과되었음을 알리는 Olivier Dulac에게 감사합니다.
2 또한 킬 신호 종료 코드가 통과하지 않음을 지적한 Stéphane Chazelas에게 감사합니다.


1
interresting. GNU 만 해당하지만 나머지 코드는 다음 코드의 나머지 부분에 대해 원래 리턴 코드를 유지합니다 (즉, 다른 답변과 달리 "0"으로 대체하지 않음)
Olivier Dulac

2
0명령이 종료되면 반환합니다 .
Stéphane Chazelas

2
@ bishop, 나는 0이 이상적이지 않다는 것에 동의합니다. 그러나 신호에 의해 명령이 종료 될 때보고 할 내용에 대한 일반적인 합의는 없습니다. 128+ 신호 번호를 반환하는 것은 몇몇 쉘에서 사용됩니다. 또한 같은 것들을 참조 256+signum하거나 384+signum또는 signum/256또는 signum/256+0.5코어가 생성 된 경우 (실제로 의해 반환 된 상태를 waitpid()256으로 나눈 값). 어떤 사람들은 ( sigint또는 같은 sigquit+core) 텍스트 표현을 줄 것 입니다. 그래도 gnu.coreutils.bugs 뉴스 그룹에 대해 논의 할 가치가 있습니다.
Stéphane Chazelas

3
(실제로 time의 일부가 아닌 coreutils그것의, 그 자체 패키지 자체의 버그 메일 링리스트 (bug-time@gnu.org가) 포함)
스테판 Chazelas가

1
@bishop system()은 Brian Kernighan ( kin awk) 또는 nawkSolaris ( awkFreeBSD)에서 파생 된 FreeBSD 의 전통적인 awk와 같은 전통적인 awk 입니다. 코어 덤프 크기가 ​​제한되지 않은 경우 awk 'BEGIN{print system("kill -s ABRT $$")}'출력 0.523438합니다. 의 동작 gawk과 행동을 변화와 함께 최근 변경 --traditional또는 --posix(또한의 반환 가치를 close(cmd)더 변화를)
스테판 Chazelas가를

2

나는 다른 모든 답변을 싫어합니다 (영리함을 좋아하지만) 종료 코드를 표시하지만 IT를 변경합니다. (표시 부분은 true이므로 리턴 코드는 0입니다)

다음은 수정 된 버전입니다.

do_and_tell () {
   "$@"
   returncode="$?"
   printf "Execution of : \n%s\n yelded a return code of: \n%s\n" "$*" "$returncode"
   return $returncode  # the interresting addition... keeps the commands return value.
}

## usage:

prompt$ do_and_tell true
Execution of : 
true
 yelded a return code of: 
0

prompt$ echo $?
0

prompt$ do_and_tell false
Execution of : 
false
 yelded a return code of: 
1

prompt$ echo $?
1

실제로 @bishop answer는이 값을 유지하는 유일한 방법이지만 GNU 버전을 time항상 사용할 수있는 것은 아닙니다.
Olivier Dulac

2

좀 더 견고하게하려면 종료 상태를 별도의 FD로 보내 stdout / stderr와 독립적으로 처리 할 수 ​​있습니다.

exit_status() {
    "$@"
    rv=$?
    echo >&3 "$rv"
    return "$rv"
}

# exit status and stdout to stdout:
> exit_status echo "hello" 3>&1
hello
0

# exit_status to stdout, stdout to /dev/null
> exit_status echo "hello" 3>&1 1>/dev/null
0
> exit_status ehco "hello" 3>&1 1>/dev/null
ehco: command not found
127

# exit_status to stdout, stdout and stderr to /dev/null
> exit_status ehco "hello" 3>&1 &>/dev/null
127

FD3로 무언가를해야하거나 그렇지 않을 것 Bad file descriptor입니다.

이것은 다른 프로그램이 하나 이상의 FD를 수신하게함으로써 이들 출력을 다른 프로그램의 입력에 제공하도록 추가로 구성 될 수 있습니다. 이것을 90 년대 초반 Kibana의 일종으로 사용할 수 있습니다 :)


원래 반환 값을 유지하고 결국 반환해야합니다. (-, 등으로 시작하지 않는) 간단한 일을 표시 (printf, echo)하면 항상 작동하며 그 후에는 "$?" 디스플레이로 값이 "0"일을 지금하고있다
올리비에 Dulac에게

1

다른 모든 (매우 흥미로운) 답변 은 OP가 요청한 정확한 질문을 다루지 만 실제로는 상황이 더 간단합니다. 종료 상태를 변수 (명령 바로 다음에)에 저장하고 원하는 방식으로보고하거나 기록하면됩니다. 예를 들어 / dev / stderr로 인쇄하거나 로그 파일에 문자 메시지로 쓰거나 추가하십시오. 또한 후속 코드에서 의사 결정 / 흐름 제어에 사용하기 위해 보존됩니다.

그것이 기능에 있다면 :

function some-function () {
    local rc ## to avoid side effects
    ...
    some-command ## run any command
    rc=$?  ## save the return status in a variable
    echo "some-command returned $rc" ## optionally tell the user about it
    ...
    return $rc  ## at the end, if appropriate
}

스크립트에 직접있는 경우 :

some-command ## run any command
rc=$?  ## save the return status in a variable
echo "some-command returned $rc" ## optionally tell the user about it
...
exit $rc    ## at the end to tell any calling script about it, if appropriate

( 정확한 질문에 대한 답변이 아니기 때문에 성행위와 취재 )

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