仅当命令成功时,如何才能抑制输出?

Mat*_*oli 26 scripting error-handling

我想通过抑制通常成功的辅助命令的输出来简化脚本的输出。

但是,-q当它们偶尔失败时,在它们上使用会隐藏输出,所以我无法理解错误。此外,这些命令将其输出记录在stderr.

有没有办法在命令成功时才抑制的输出?

例如(但不限于)这样的事情:

mycommand | fingerscrossed
Run Code Online (Sandbox Code Playgroud)

如果一切顺利,fingerscrossed捕获输出并丢弃它。否则它会将其回显到标准或错误输出(无论如何)。

Ste*_*itt 41

moreutils'chronic命令就是这样做的:

chronic mycommand
Run Code Online (Sandbox Code Playgroud)

将吞下mycommand的输出,除非它失败,在这种情况下会显示输出。

  • 请注意,它将整个输出存储在内存中。 (7认同)
  • 谢谢。我认为大多数 Unix 操作系统上都没有默认安装它? (2认同)

mik*_*erv 12

### do this bit once at the top of your script
divert=
exec 3<>"${divert:=$(mktmp)}" 4<>/dev/null
rm -- "$divert"; unset divert
### then do this bit as often as needed
command >&3 2>&3
cat <&3 >&"$(((RTN=$?)?2:4))"
Run Code Online (Sandbox Code Playgroud)

那应该可以解决问题。它将每个的输出缓冲command到一个已删除的临时文件中,然后/dev/null根据其返回状态是否不为零将其输出虹吸到或 stderr 中。因为临时文件被提前删除,除了当前 shell 及其文件描述符上的子进程(禁止/proc/$pid/fd具有适当权限的偷偷摸摸的窥探)之外,任何进程都无法读取它,并且在您完成后不需要清理。

也许在 linux 系统上更方便的解决方案:

divert(){
    "$@" >&3 2>&3 ||
    eval "cat <&3
          return $?"
}   3<<"" 3<>/dev/fd/3
Run Code Online (Sandbox Code Playgroud)

......,在大多数炮弹,很像其他的,不同之处在于,你可以这样调用它:divert some simple-command with args。小心 中的高输出命令"$@",尽管 for dashyash,或其他一些用管道做 here-documents 的 shell - 我认为在这些 shell 中可能会填充管道缓冲区(在 linuxes 上的默认值约为 128kb),因此死锁. 不过,对于kshmkshbashzsh或 Bourne shell 来说,这不应该是一个问题——所有这些基本上与我在上面对exec.


Cos*_*tas 9

通常在出现错误的情况下,命令会向stderr您输出消息,因此对于您的任务,您只需抑制stdout

mycommand > /dev/null
Run Code Online (Sandbox Code Playgroud)

  • [小心](https://lh3.googleusercontent.com/-VHkETr8YmO0/Uy01sQV6smI/AAAAAAAAAYL8/jQauPTn5luQ/w506-h504/dev.png) (9认同)

Mat*_*oli 9

我刚刚在另一个问题上找到了这个简单得多的答案:

output=`mycommand 2>&1` || echo $output
Run Code Online (Sandbox Code Playgroud)

奇迹般有效!


Jac*_*all 5

打造属于自己的慢性病

my_chronic() {
  tmp=$(mktemp) || return # this will be the temp file w/ the output
  "$@"  > "$tmp" 2>&1 # this should run the command, respecting all arguments
  ret=$?
  [ "$ret" -eq 0 ] || cat "$tmp"  # if $? (the return of the last run command) is not zero, cat the temp file
  rm -f "$tmp"
  return "$ret" # return the exit status of the command
}
Run Code Online (Sandbox Code Playgroud)