【问题标题】:How to pipe output to stdout and variable? [duplicate]如何将输出通过管道传输到标准输出和变量? [复制]
【发布时间】:2021-05-18 10:01:28
【问题描述】:

当我运行以下脚本时,ls -la 的输出存储到变量 $output

#! /bin/sh

output=$(ls -la)

如何将ls -la 的输出通过管道传输到stdout$output

我在运行borgbackup 的上下文中询问,它可以在备份期间输出很长时间。

我希望能够在手动运行脚本时跟踪进度,同时将输出存储在 $output 中以通过电子邮件将其发送给系统管理员。

【问题讨论】:

  • 探索tee(1)
  • 您可能已经知道解析ls 的输出的陷阱。但由于这个问题的未来读者可能不会,我仍然觉得有必要发布这个阅读材料:mywiki.wooledge.org/ParsingLs
  • 你看这两个答案给你一个答案。我想教你一些东西。
  • 不要将标准输出与 tty 混为一谈。使用 tee 写信给/dev/stdout,而不是/dev/tty
  • 但请注意,您需要写入主外壳的/dev/stdout,而不是子外壳的标准输出。例如exec 3> /dev/stdout; output=$(ls -la | tee /dev/fd/3)

标签: bash sh


【解决方案1】:

使用tee

output=$(ls -lta | tee /dev/tty)

另一种方法是创建STDOUT 的副本,然后再次使用tee 将输出发送到那里;

# Create copy of stdout
exec 3>&1

# Run command
output=$(ls -lta | tee /dev/fd/3)

# Close copy
exec 3>&-

【讨论】:

  • 有趣,谢谢!与tee 相比,使用/dev/fd 方法是否有优势?
  • 不太确定,也许这在调用多个命令时很有用。我想这取决于你的实际情况!
  • 如果您只需要打印到标准输出,则使用/dev/tty/dev/stdout 更具可读性。
  • OP 要求输出到stdout,而不是/dev/tty,这不一样,甚至可能不存在。 exec 部分是正确的。
  • @0stone0 我正在尝试了解更多关于exec 3>&1 的信息,但找不到可理解的文档(我可能缺少一些基础知识)。写入exec 3>&1 是否以任何方式写入磁盘还是仅用于内存?
【解决方案2】:

使用tee util 并将其传递给/dev/tty 以打印标准输出。

box: ~/demo
➜ out=$(ls -la | tee /dev/tty)
total 16
drwxr-xr-x    4 chen  staff   128 Feb 15 15:59 .
drwxr-xr-x+ 103 chen  staff  3296 Feb 15 15:59 ..
-rw-r--r--    1 chen  staff   141 Sep  1 12:38 docker-compose.yml
-rw-r--r--    1 chen  staff    84 Sep  1 12:31 ubuntu.Dockerfile
box: ~/demo
➜ echo $out
total 16
drwxr-xr-x    4 chen  staff   128 Feb 15 15:59 .
drwxr-xr-x+ 103 chen  staff  3296 Feb 15 15:59 ..
-rw-r--r--    1 chen  staff   141 Sep  1 12:38 docker-compose.yml
-rw-r--r--    1 chen  staff    84 Sep  1 12:31 ubuntu.Dockerfile

【讨论】:

  • OP 要求输出到stdout,而不是/dev/tty,这不一样,可能事件不存在。
  • @xhienne /dev/tty 适用于 Linux 和 Mac。
  • “作品”是什么意思?首先,我是说这不一样(你必须知道/dev/stdout != /dev/stderr != /dev/tty)。其次,这个问题没有标记 Linux 或 Mac。第三,我应该说程序并不总是连接到终端,即使在 Linux 或 Mac 中也是如此。
  • 嗯.. 你是对的,除了默认情况下,每个sh 进程都连接到这些流。因此,使用上面的 OP 脚本,在 Mac 和 Linux 上都可以正常工作,无需任何额外的特别注意。所以它回答了 OP 问题。
  • 默认情况下,每个sh 进程都连接到stdout 和stderr,对,但绝对不能保证/dev/tty(例如,Cron 作业未连接到终端)。但你误会了:我是说你不应该假设 stdout = tty (即使存在 tty,stdout 也可以重定向到其他东西)。标准输出就是标准输出,仅此而已。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-05
  • 2017-05-11
  • 1970-01-01
相关资源
最近更新 更多