暂时将 STDOUT 重定向到另一个文件描述符,但仍重定向到屏幕

暂时将 STDOUT 重定向到另一个文件描述符,但仍重定向到屏幕

我正在编写一个脚本,在其中执行一些命令,这些命令在 上显示一些输出STDOUTSTDERR以及,但这没问题)。我需要我的脚本生成一个 .tar.gz 文件到STDOUT,因此脚本中执行的一些命令的输出也会转到STDOUT,这以输出中无效的 .tar.gz 文件结束。

因此,简而言之,可以将第一个命令输出到屏幕(因为我仍然想看到输出),但不是通过STDOUT?另外,我想保持STDERR不变,以便只有错误消息出现在那里。

举一个简单的例子来说明我的意思。这是我的脚本:

#!/bin/bash

# the output of these commands shouldn't go to STDOUT, but still appear on screen
some_cmd foo bar
other_cmd baz

#the following command creates a tar.gz of the "whatever" folder,
#and outputs the result to STDOUT
tar zc whatever/

我试过弄乱exec文件描述符,但仍然无法让它工作:

#!/bin/bash

# save STDOUT to #3
exec 3>&1

# the output of these commands should go to #3 and screen, but not STDOUT
some_cmd foo bar
other_cmd baz

# restore STDOUT
exec 1>&3

# the output of this command should be the only one that goes to STDOUT
tar zc whatever/

我想我缺少STDOUT在第一次执行后关闭并再次重新打开它之类的东西,但我找不到正确的方法来做到这一点(现在的结果与我没有添加execs

答案1

stdout 是屏幕。stdout 和“屏幕”之间没有区别。

在这种情况下,我只需在1>&2子 shell 中将 stdout 临时重定向到 stderr。这将导致命令的输出显示在屏幕上,但不会在程序的 stdout 流中。

#!/bin/bash

# the output of these commands shouldn't go to STDOUT, but still appear on screen

# Start a subshell
(
    1>&2                # Redirect stdout to stderr
    some_cmd foo bar
    other_cmd baz
)
# At the end of the subshell, the file descriptors are 
# as they usually are (no redirection) as the subshell has exited.

#the following command creates a tar.gz of the "whatever" folder,
#and outputs the result to STDOUT
tar zc whatever/

您是否需要将此脚本的输出通过管道传输到其他内容?通常,您只需使用标志将 tar 写入文件-f或仅在 tar 命令上执行重定向:(tar zc whatever > filename.tar.gz除非您将其放在磁带等设备上或将其用作副本形式)。

答案2

-f如果您使用开关到 tar 命令来告诉 tar 写入文件,是不是更容易呢?

tar zcf whatever.tar.gz whatever/

如果这不能满足您的要求,那么您将必须单独重定向每个可能写入 STDOUT 的命令

some_cmd foo bar 1>&2

答案3

我认为您正在寻找某种多路复用。

这是一个如何将时间戳附加到每个标准输出行的简单示例:http://www.podciborski.co.uk/programming/perl/add-a-timestamp-to-every-stdout-line/

您可以使用一些特殊标签代替时间戳来标记日志行。然后您必须在另一端删除这些行。因此用法如下:

ssh user@remoteserver the_script.sh | create_tar.sh filename

create_tar.sh 应该是打印带有日志标签的行并将其他行重定向到文件的脚本。

相关内容