bash 通过管道从子shell获取退出代码

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9277827/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 01:33:57  来源:igfitidea点击:

Get exit code from subshell through the pipes

bashpipeexit-codeteesubshell

提问by ДМИТРИЙ МАЛИКОВ

How can I get exit code of wgetfrom the subshell process?

如何wget从子shell进程中获取退出代码?

So, main problem is that $?is equal 0. Where can $?=8be founded?

所以,主要问题是$?等于0。在哪里可以$?=8成立?

$> OUT=$( wget -q "http://budueba.com/net" | tee -a "file.txt" ); echo "$?"
0

It works without tee, actually.

tee实际上,它没有.

$> OUT=$( wget -q "http://budueba.com/net" ); echo "$?"
8

But ${PIPESTATUS}array (I'm not sure it's related to that case) also does not contain that value.

但是${PIPESTATUS}数组(我不确定它与那种情况有关)也不包含该值。

$> OUT=$( wget -q "http://budueba.com/net" | tee -a "file.txt" ); echo "${PIPESTATUS[1]}"    

$> OUT=$( wget -q "http://budueba.com/net" | tee -a "file.txt" ); echo "${PIPESTATUS[0]}"
0

$> OUT=$( wget -q "http://budueba.com/net" | tee -a "file.txt" ); echo "${PIPESTATUS[-1]}"
0

So, my question is - how can I get wget's exit code through teeand subshell?

所以,我的问题是 - 我怎样才能wget通过teesubshel​​l获取退出代码?

If it could be helpful, my bash version is 4.2.20.

如果有帮助,我的 bash 版本是4.2.20.

回答by Christian.K

By using $()you are (effectively) creating a subshell. Thus the PIPESTATUSinstance you need to look at is only available inside your subshell (i.e. inside the $()), since environment variables do not propagate from child to parent processes.

通过使用$()您(有效地)创建了一个子shell。因此,PIPESTATUS您需要查看的实例仅在您的子外壳内(即在 内$())可用,因为环境变量不会从子进程传播到父进程。

You could do something like this:

你可以这样做:

  OUT=$( wget -q "http://budueba.com/net" | tee -a "file.txt"; exit ${PIPESTATUS[0]} );
  echo $? # prints exit code of wget.

You can achieve a similar behavior by using the following:

您可以使用以下方法实现类似的行为:

  OUT=$(wget -q "http://budueba.com/net")
  rc=$? # safe exit code for later
  echo "$OUT" | tee -a "file.txt"

回答by Mrskman

Beware of this when using localvariables:

使用local变量时要注意这一点:

local OUT=$(command; exit 1)
echo $? # 0

OUT=$(command; exit 1)
echo $? # 1

回答by maxdev137

Copy the PIPESTATUS array first. Any reads destroy the current state.

首先复制 PIPESTATUS 数组。任何读取都会破坏当前状态。

declare -a PSA  
cmd1 | cmd2 | cmd3  
PSA=( "${PIPESTATUS[@]}" )

I used fifos to solve the sub-shell/PIPESTATUS problem. See bash pipestatus in backticked command?
I also found these useful: bash script: how to save return value of first command in a pipeline?
and https://unix.stackexchange.com/questions/14270/get-exit-status-of-process-thats-piped-to-another/70675#70675

我使用fifos来解决子shell/PIPESTATUS问题。在反引号命令中看到 bash pipestatus 吗?
我还发现这些很有用: bash 脚本:如何在管道中保存第一个命令的返回值?
https://unix.stackexchange.com/questions/14270/get-exit-status-of-process-thats-piped-to-another/70675#70675