当需要以特定用户身份运行时,我有一个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。
答案 0 :(得分:3)
此处的问题不是su
,而是tee
:默认情况下,shell退出时退出状态为最后一个管道组件;在您的代码中,该组件不是check_package.sh
,而是tee
。
如果您的/bin/sh
由bash提供(而不是ash
,dash
或其他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)
su
和sudo
都退出,并执行命令的退出状态(如果验证成功):
$ 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
显然更简单。