time コマンドと同様に、コマンドの終了コードを記録します。

time コマンドと同様に、コマンドの終了コードを記録します。

使用

time sleep 1

生産する:

$ time sleep 1

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

sleep終了コードや実行したいコマンドを印刷するために使用できるコマンドはありますか?

私が好きなもの:

$ log-exit-code sleep 1

たぶんそれで十分でしょうか?

sleep 1 && echo "$?"

答え1

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

関数内でリダイレクトして、printf標準出力やエラーストリームからゴミを得ることなくリダイレ​​クトを使用できます。/dev/ttytellexit

$ 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

答え2

牛に似た一種の栄養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に感謝します。

答え3

シェルラッパー機能などを使用してください。別の名前があるかもしれません。

$ 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それ以外の場合、エラーがないとトリガーされません(「ニュースがないのは良いニュース」の原則に従って)。

答え4

他のすべての答えについて気に入らない点(その創造性は本当に気に入っていますが):終了コードを表示しますが、変更することもあります。 (表示部分が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

関連情報