如果第一个命令失败,则阻止第二个命令在 bash 管道中启动

sto*_*qlt 11 bash zsh pipe

在学习(或多或少)一些关于管道的有用讨论后,例如 获取通过管道传输到另一个进程的进程的退出状态和当管道中的一个进程失败时退出,我仍然无法避免在第一个命令失败时启动第二个命令。我是否缺少有关管道的基本细节?

所以例如

$ somecommand | tar -T - -czf /tmp/someProject.tar.gz
Run Code Online (Sandbox Code Playgroud)

tar.gz如果somecommand不能正常工作并且只产生一些错误消息而不是预期的文件列表,则不应创建几乎为空的文件。

ilk*_*chu 23

是的,那里有一些关于管道的基本细节。

管道的要点是并行运行两个或多个命令,这样可以避免必须完整存储所有数据,并且可以节省时间,因为所有进程都可以同时工作。这根据定义意味着第二个命令在第一个退出之前启动,因此第一个的退出状态尚不可用。

简单的解决方法是改用临时文件。这里的存储应该不是什么大问题,因为我们只传递文件名列表,而不是数据本身。例如:

tmp=$(mktemp)
if somecommand > "$tmp"; then
    tar -T - -czf /tmp/someProject.tar.gz < "$tmp"
fi
rm -f "$tmp"
Run Code Online (Sandbox Code Playgroud)

或者确实像 terdon 评论一样,只要tar运行,然后在somecommand失败后删除 tar 文件。但是,如果somecommand在失败之前生成了部分但重要的文件列表,那么在创建要删除的存档时仍然会导致一些不必要的 I/O。

此外,至少在 GNU tar 中,默认情况下-T会处理一些看起来像命令行选项的引号和行,所以如果你有讨厌的文件名,你可能需要考虑到这一点,或者查看--verbatim-files-from, 或--null. 其他 tar 实现可能存在类似的问题。


Adm*_*Bee 10

似乎您误解了管道命令的性质。

在命令管道中,所有命令都是并行启动的(参见此处示例)。这就是为什么在您的构造中无法tar“等待”成功完成somecommand,因为它会tar读取somecommand创建的输出。

您可以应用一些解决方法来缓解这种情况:

  • 将 的输出缓冲somecommand在临时文件中,只有tar在somecommand信号的退出状态“成功”时才运行,然后将其删除(仅当您有足够的存储空间时才可行)
  • 正如@terdon 所提到的,如果失败,请使用该pipefail选项删除不可用的tar.gz文件somecommand。


归档时间:

查看次数:

1034 次

最近记录:

5 年,2 月 前