所以我有类似的想法:
set -eo pipefail
ssh localhost "ls; exit 1" | cat > output
我以为 pipefail 会阻止 cat 写入输出(因为 ssh 会话的退出代码),但似乎不会。然后我尝试创建一个 fifo,但我不确定如何在不消耗 fifo 中的内容的情况下读取 ssh 的退出状态,因为它似乎会等到某些东西“消耗”它。
set -eo pipefail
[[ -e /tmp/sshdump ]] && rm /tmp/sshdump; mkfifo /tmp/sshdump;
ssh localhost "ls; exit 1" > /tmp/sshdump &
wait $! && cat > output
那么,我该如何:
- 避免在第一个例子中过早地使管道退出(并且不到达 cat)?
- 在不消耗 fifo 内容的情况下检查 ssh 的退出代码?
如果重要的话,POSIX 兼容的解决方案总是受欢迎的,但 bash 也很好。在我的特定情况下,我使用的是 windows 和 git-bash,所以可能有一些我不知道的怪癖。
编辑:全面披露,我可能应该从一开始就解释我想要实现的目标,而不是将其简化到问题不能正确反映意图的程度。我试图将远程 ssh shell 上的“mysqldump”输出直接通过管道传输到我机器上的“wp db import”,而无需创建中间文件。我最初认为 pipefail 会停止管道,从而在发生故障时阻止我端的导入。我之所以希望这样做,是因为无需创建临时文件,而且代码更少。
当 shell 处理
它在实际运行任何命令之前设置重定向和管道。因此在运行
output
之前被创建或截断cat
。这里还有另一个问题:
pipefail
它只会改变确定管道退出状态的方式,它不会控制管道内的执行,即使有set -e
。管道中的所有命令都是同时设置的(或足够接近),它们不是按顺序运行的。这意味着cat
与一起运行,并且在大多数情况下会在会话以代码 1 退出之前ssh
处理输出。ls
执行所需操作的一种方法是将输出存储在某处,并且仅在命令
ssh
成功时才处理它:请注意,
mktemp
创建的文件仅可由所有者读取和写入,因此您可能需要随后调整权限。shell
ksh93
有一个内置的方法来做到这一点:执行与上述相同的操作,同时还负责恢复文件的原始权限(如果在开始时已经存在)或尊重 umask(如果之前不存在)。
写入单独的文件(最终重命名为目标)的另一个好处是文件
output
是自动创建或替换的。尝试打开的另一个进程绝不output
会发现它未完成。