linux - 内部变量 PIPESTATUS

标签 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

最佳答案

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

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

这里有两个选择:

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

关于linux - 内部变量 PIPESTATUS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30075050/

相关文章:

linux - 使用 printf 以特殊格式打印值

c++ - 如何在 C++ 中使用 Mosquitto 发布文件?

json - Bash 脚本/JSON - 从 {"Key":"Duration","Value":"N"中提取数值}

c - 保留寄存器?

ruby-on-rails - 使用通配符时,只有一个文件在 rails runner 中运行

bash - 如何获取内置命令的内置?

linux - 使用现有的 docker 镜像创建新的 Docker 镜像

bash - mongodb 导出和删除文档

java - Hbase 使用 importTsv 导入 ^A (CTRL A) 分隔文件

linux - Bash 在传递给另一个 bash shell 时丢弃命令行参数