bash获取su脚本执行的exitcode

时间:2016-12-07 16:50:06

标签: bash sh

当需要以特定用户身份运行时,我有一个shell脚本。所以我将该脚本称为如下,

su - testuser -c "/root/check_package.sh | tee -a /var/log/check_package.log" 

所以在此之后,当我检查最后一个执行exitcode时,它始终只返回0,即使该脚本失败也是如此。

我在下面尝试了一些没有用的东西,

su - testuser -c "/root/check_package.sh | tee -a /var/log/check_package.log && echo $? || echo $?"

是否可以通过su获得命令的exitcode。

2 个答案:

答案 0 :(得分:3)

此处的问题不是su,而是tee:默认情况下,shell退出时退出状态为最后一个管道组件;在您的代码中,该组件不是check_package.sh,而是tee

如果您的/bin/sh由bash提供(而不是ashdash或其他POSIX-baseline shell),请使用set -o pipefail导致完全管道如果它的任何组成部分失败,则失败:

su - testuser -c "set -o pipefail; /root/check_package.sh | tee -a /var/log/check_package.log"

或者,您可以通过重定向到进程替换来执行tee带外(尽管这需要您当前用户有权写入check_package.log):

su - testuser -c "/root/check_package.sh" > >(tee -a /var/log/check_package.log

答案 1 :(得分:2)

susudo都退出,并执行命令的退出状态(如果验证成功):

$ sudo false; echo $?
1
$ su -c false; echo $?
1

您的问题是su运行的命令管道是管道。管道的退出状态是tee命令(成功)的退出状态,但您真正想要的是管道中第一个命令的退出状态。

如果你的shell是bash,你有几个选择:

    在您的管道之前
  • set -o pipefail,如果其中任何一个命令失败,它将返回所有命令的最右侧失败值
  • 检查PIPESTATUS数组变量的特定成员 - 这可以为您提供第一个命令的退出状态,无论tee是否成功。

示例:

$ sudo bash -c "false | tee -a /dev/null"; echo $?
0
$ sudo bash -c "set -o pipefail; false | tee -a /dev/null"; echo $?
1
$ sudo bash -c 'false | tee -a /dev/null; exit ${PIPESTATUS[0]}'; echo $?
1

如果您的系统shell(在su -c中)是Bash,则使用/bin/sh将获得类似的结果。如果没有,那么你需要明确地调用bash,此时sudo显然更简单。