记录命令的退出代码,类似于 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 "$?"不起作用,因为它必然只打印零(echo只有在成功完成前面的命令时才会执行)。

这是一个简短的 shell 函数:

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这需要ash// pdksh/ bashzsh或者您可以将其更改为typeset其他一些 shell 也可以理解的形式。)

答案2

GNUtime有一个选项:

time -f %x sleep 1
0

通过退出代码1,除非被信号2杀死:

$ /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并 grep 字符串的 stderr Command terminated by signal


1感谢 Olivier Dulac 指出退出代码已通过。
2另外,感谢 Stéphane Chazelas 指出终止信号退出代码无法通过。

答案3

使用 shell 包装函数之类的东西。可能有不同的名字。

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

(这当然会破坏标准输出,因此要么使用tty@Kusalananda 所示的内容,要么不要在交互式上下文之外使用它。)

转向不可移植的领域,一些 shell 可以报告管道中所有命令的状态,而不仅仅是最后一个命令的状态,例如在 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

相关内容