【问题标题】:How to redirect stdout of zsh/bash and restore later如何重定向 zsh/bash 的标准输出并稍后恢复
【发布时间】:2019-11-25 15:37:46
【问题描述】:

在python中,你可以

sys.stdout = open('log', 'w') # begin redirect

然后输出将改为写入log

您可以使用

恢复正常行为
sys.stdout = sys.__stdout__   # end redirect, restore back

如何在zsh & bash中实现类似的效果?

附言,

  • 子shell中命令的stdout也应该被重定向。
  • ls > log 不是我想要的。

澄清一下,我想要的是

ls   # output to terminal
# begin redirect to `log`
ls   # output to `log`
find -type f   # output to `log`
...  # output to `log`
# end redirect, restore back
ls   # output to terminal

编辑 以下不是我想要的

  • 重定向一组命令。
  • tail -f 用于监控。

正如这个问题的前几行所说, 我想要的是

# ...
cmd1    # normal behavior
# begin redirection
cmd2   # redirect to file
# some times later
cmd2   # redirect to file
# ...
cmdN   # redirect to file
# end redirection
cmdN+1 # normal behavior
# ...

【问题讨论】:

    标签: bash zsh io-redirection


    【解决方案1】:

    通常,您会重定向命令组的输出,而不是重定向和恢复 shell 本身的输出。

    ls                    # to terminal
    {
      ls
      find -type f
    } > log               # to log
    ls                    # to terminal again
    

    { ... } 分隔的命令组的标准输出作为一个整体被重定向到一个文件。该组中的命令从该组继承其标准输出,而不是直接从 shell 继承。

    这类似于在 Python 中执行以下操作:

    from contextlib import redirect_stdout
    
    print("listing files to terminal")
    with open("log", "w") as f, redirect_stdout(f):
        print("listing files to log")
        print("finding files")
    print("listing files to terminal")
    

    在 shell 中,可以通过使用exec 来完成对标准输出的强制重定向,如demonstrated by oguz ismail,尽管命令组更清楚地说明了重定向的开始和结束位置。 (它还避免了需要找到一个未使用的文件描述符并记住更神秘的 shell 语法。)

    【讨论】:

    • 如何禁用缓冲?我听说在 glib 中 stderr 是无缓冲的,exec 3>&1 2>&3 1>&2 3>&1 >log 是否可以无缓冲工作?
    • 这是一个完全不同的问题。
    【解决方案2】:

    您可以使用tee 命令记录到文件以及打印到控制台:

    ls                         # output to terminal
    # begin redirect to `log`
    ls  | tee -a log           # output to `log`
    find -type f | tee -a log  # output to `log`
    ...  # output to `log`
    # end redirect, restore back
    ls   # output to terminal
    

    【讨论】:

    • 绝对值得一提。这也可以与@chepner 的答案中的分组一起使用
    【解决方案3】:

    使用exec 进行永久重定向。例如:

    ls              # to tty 
    exec 3>&1 >log  # redirect to log, save tty
    ls              # to log
    find -type f    # ditto
    exec >&3        # restore tty
    ls              # to tty
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-22
      • 2010-10-12
      • 1970-01-01
      • 2012-08-15
      相关资源
      最近更新 更多