内部变量PIPESTATUS

时间:2015-05-06 11:11:23

标签: linux bash shell

我是linux和bash脚本的新手,我查询了这个内部变量PIPESTATUS,它是一个数组,并将各个命令的退出状态存储在管道中。

在命令行上:

 $  find /home | /bin/pax -dwx ustar | /bin/gzip -c > myfile.tar.gz
 $ echo ${PIPESTATUS[*]}
 $ 0 0 0

在命令行上工作正常但是当我将此代码放入bash脚本时,它只显示一个退出状态。我在命令行上的默认SHELL只是bash。

有人请帮助我理解为什么这种行为正在发生变化?我应该怎么做才能在脚本中完成这项工作?

#!/bin/bash

cmdfile=/var/tmp/cmd$$
backfile=/var/tmp/backup$$

find_fun() {
    find /home
}

cmd1="find_fun | /bin/pax -dwx ustar"
cmd2="/bin/gzip -c"

eval "$cmd1 | $cmd2 > $backfile.tar.gz " 2>/dev/null

echo -e " find ${PIPESTATUS[0]} \npax ${PIPESTATUS[1]} \ncompress ${PIPESTATUS[2]} > $cmdfile

2 个答案:

答案 0 :(得分:0)

您使用脚本遇到的问题是运行与在命令行上运行的代码相同的代码。您正在运行不同的代码。即脚本添加了eval。如果你要在eval中包装命令行测试,你会发现它以类似的方式失败。

eval版本失败的原因(仅在PIPESTATUS中为您提供一个值)是因为您不再执行管道。您正在对包含管道的字符串执行eval。这类似于执行/bin/bash -c 'some | pipe | line'。实际由当前shell运行的东西是单个命令,因此它只有一个退出代码。

你有两个选择:

  1. 摆脱eval(你应该这样做,因为eval通常是要避免的)并停止使用字符串作为命令(有关为什么这样做的更多信息,请参阅Bash FAQ 050是一个坏主意。
  2. echo "${PIPESTATUS[@]}"移至eval,然后捕获(并拆分/解析)结果输出。 (这在几乎所有方面都显然是一个更糟糕的解决方案。)

答案 1 :(得分:-1)

而不是$ {PIPESTATUS [0]}使用$ {PIPESTATUS [@]}

与bash中的任何数组一样,PIPESTATUS [0]包含第一个命令退出状态。如果你想获得所有这些,你必须使用PIPESTATUS [@],它返回数组的所有内容。

我不确定当你在命令行中尝试它时它为什么会起作用。我测试了它,但我没有得到与你相同的结果。