- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在 Perl 中(使用版本 5.30.0),是否可以通过编程方式(即在我的 Perl 代码中)更改一些设置,这会导致 STDOUT 和 STDERR 被重定向到我的 Perl 进程将要处理的任何子进程的文本文件从那一点开始?这里的困难是我不控制实际启动那些子进程的代码(如果我控制了,这将是非常微不足道的)。我希望我可以在我的 Perl 进程中设置某种 IO 标志,这将导致所有新启动的子进程将它们的 STDOUT/STDERR channel 重定向到我选择的目的地(除非 system()/exec()/用于启动它们的任何调用显式提供另一个 STDOUT/STDERR 目标)。
我需要它的(高度简化的)用例如下。我编写了一个通用库函数,它执行调用者指定的任务,除其他外,将用户提供的任务生成的所有 STDOUT/STDERR 输出存储在文本文件中。该任务以 Perl 函数引用的形式提供。到目前为止,我只是设法重定向了我的 Perl 进程生成的 STDOUT/STDERR 输出:
local *STDOUT;
local *STDERR;
open( STDOUT, '>', $buildLogFilePath ) or die sprintf(
"ERROR: [%s] Failed to redirect STDOUT to \"%s\"!\n",
$messageSubject,
$buildLogFilePath
);
open ( STDERR, '>&', STDOUT ) or die sprintf(
"ERROR: [%s] Failed to redirect STDERR to \"%s\"!\n",
$messageSubject,
$buildLogFilePath
);
因此,只要用户提供的函数不启动任何子进程,我的功能就可以按预期工作,但是当它启动子进程时,该进程的输出将转到默认的 STDOUT/STDERR channel ,有效地破坏了我的功能。
编辑:我最终使用了下面 ikegami 描述的 STDOUT/STDERR 重新指向技巧。为了更容易地重用这个技巧,我将代码包装在一个小实用程序类中,该实用程序类在构造函数中重定向 STDOUT/STDERR,然后在析构函数中将它们恢复为原始值:
package TemporaryOutputRedirector;
use strict;
use warnings FATAL => 'all';
use Carp::Assert;
sub new
{
my ( $class, $newDest ) = @_;
open( my $savedStdout, '>&', STDOUT ) or die sprintf(
"ERROR: Failed to save original STDOUT in process %i!\n",
$$
);
open( STDOUT, '>', $newDest ) or die sprintf(
"ERROR: Failed to redirect STDOUT to \"%s\" in process %i!\n",
$newDest,
$$
);
open( my $savedStderr, '>&', STDERR ) or die sprintf(
"ERROR: Failed to save original STDERR in process %i!\n",
$$
);
open ( STDERR, '>&', STDOUT ) or die sprintf(
"ERROR: Failed to redirect STDERR in process %i!\n",
$$
);
my %memberData = (
'newDest' => $newDest,
'savedStdout' => $savedStdout,
'savedStderr' => $savedStderr
);
return bless \%memberData, ref $class || $class;
}
sub DESTROY
{
my ( $self ) = @_;
my $savedStdout = $$self{ 'savedStdout' };
assert( defined( $savedStdout ) );
open( STDOUT, '>&', $savedStdout ) or warn sprintf(
"ERROR: Failed to restore original STDOUT in process %i!\n",
$$
);
my $savedStderr = $$self{ 'savedStderr' };
assert( defined( $savedStderr ) );
open( STDERR, '>&', $savedStderr ) or warn sprintf(
"ERROR: Failed to restore original STDERR in process %i!\n",
$$
);
}
1;
这样,只需要创建一个 TemporaryOutputRedirector
的实例,执行应该重定向其输出的代码,然后让 TemporaryOutputRedirector
超出范围并让它的析构函数恢复原来的 STDOUT/STDERR channel 。
最佳答案
当您打开文件句柄时,它会使用下一个可用的文件描述符。 STDIN、STDOUT 和 STDERR 通常分别与 fd 0、1 和 2 相关联。如果进程中没有其他打开的句柄,则 open
创建的下一个句柄将使用文件描述符 3。
如果将 fd 3 与 STDOUT 相关联,许多事情将继续有效。那是因为 Perl 代码通常处理 Perl 文件句柄而不是文件描述符。例如,print LIST
实际上是 print { select() } LIST
,默认情况下与 print STDOUT LIST
相同。因此,您的更改主要在 Perl 中起作用。
然而,当你执行一个程序时,它得到的只是文件描述符。它得到 fd 0、1 和 2。它甚至可能得到 fd 3,但它并不关心这个。它会输出到 fd 1。
一个简单的解决方案是删除 local *STDOUT;本地 *STDERR;
.
*STDOUT
是一个 glob,一个包含 *STDOUT{IO}
的结构,即有问题的句柄。
通过使用 local *STDOUT
,您可以将 glob 替换为空的。原始的不会被破坏——当 local
超出范围时它会被恢复——所以与现在匿名的 glob 关联的 Perl 文件句柄不会被关闭,所以与该句柄不会关闭,因此后续的 open
无法重用该 fd。
如果您避免执行 local *STDOUT
,这意味着您将一个打开的句柄传递给 open
。 open
在这种情况下表现特殊:它将“重新打开”已经与 Perl 句柄相关联的 fd,而不是创建一个新的 fd。
$ perl -e'
open( local *STDOUT, ">", "a" ) or die;
open( local *STDERR, ">&", STDOUT ) or die;
print(fileno(STDOUT), "\n");
system("echo foo");
'
foo
$ cat a
3
$ perl -e'
open( STDOUT, ">", "a" ) or die;
open( STDERR, ">&", STDOUT ) or die;
print(fileno(STDOUT), "\n");
system("echo foo");
'
$ cat a
1
foo
如果您希望重定向是临时的。您必须使用文件描述符。
$ perl -e'
open( local *SAVED_STDOUT, ">&", STDOUT) or die;
open( STDOUT, ">", "a" ) or die;
print(fileno(STDOUT), "\n");
system("echo foo");
open( STDOUT, ">&", SAVED_STDOUT) or die;
print(fileno(STDOUT), "\n");
system("echo bar");
'
1
bar
$ cat a
1
foo
关于windows - 为将由父进程启动的所有子进程重定向 STDOUT 和 STDERR,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58877124/
我想阅读 php://stderr。怎么做到的? php://stderr 和 STDERR 是否写入同一个文件?因为在写入 php://stderr 后,我尝试使用 stream_get_conte
我不确定这个问题是 Python 还是 shell 问题。 我有一个 Python 程序,它在命令上使用子进程调用,该命令可以在 stderr 上发出错误消息。我自己的程序也使用 sys.stderr
如何重定向命令的输出,以便 stdout 和 stderr 都记录在文件中,并且我仍然希望 stderr 显示为输出。 我也不想使用 bash 来执行此操作。有这样的办法吗? 最佳答案 这很简单: $
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 7 年前。 Improve this qu
我得到了以下批处理命令 echo 1 & echo 2 1>&2 & echo 3 有时这会打印 1 2 3有时 132 我怎样才能控制顺序?我必须得到订单。 是否有启用以下功能的命令? echo 1
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: Ruby $stdout vs. STDOUT STDERR 通常比使用 $stderr 更受青睐,还是相反
这是我经常尝试完成的任务。我想将 stderr 和 stdout 都记录到日志文件中。但我只想打印到控制台 stderr。 我尝试过使用 tee,但是一旦我使用“2>&1”合并了 stderr 和 s
我想要做的是将 stderr 重定向到 stdout,而不更改 stderr 的输出。 比如说,命令在stderr中有输出,我想将stderr中的所有内容输出到屏幕,同时还通过grep处理信息并将其保
我正在尝试重定向一些 bash 脚本输出。我想做的是: ./some_script.sh 2> error.log >> all_output.log 2>&1 我想将 stderr 放在一个文件中,
我想将 stdout 和 stderr 的输出重定向到一个公共(public)文件: ./foo.sh >stdout_and_stderr.txt 2>&1 但也只是将 stderr 重定向到一个单
我想运行几个命令,并将所有输出捕获到日志文件中。我还想将任何错误打印到屏幕上(或者可以选择将输出邮寄给某人)。 这是一个例子。以下命令将运行三个命令,并将所有输出(STDOUT 和 STDERR)写入
在其他语言中(如 bash 和 Python),当我们生成一个子进程时,这个新进程将从父进程继承 stdout 和 stderr。这意味着子进程的任何输出都将打印到终端以及父进程的输出。 我们如何在
这个问题在这里已经有了答案: IO Redirection - Swapping stdout and stderr (4 个答案) 关闭 7 年前。 我想将应该转到 stdout 的所有内容重定向
我有一个 shell 脚本,我想将其 stdout 和 stderr 写入日志文件。我知道这可以通过 sh script.sh >> both.log 2>&1 但是,我还想同时将 stderr 写入
git clone 将其输出写入 stderr,如记录 here .我可以使用以下命令重定向它: git clone https://myrepo c:\repo 2>&1 但这会将所有输出(包括错误
以下将 stdout 写入日志文件并打印 stderr: bash script.sh >> out.log 这再次将 stdout 和 stderr 写入日志文件: bash script.sh >
我正在调试一个在 PHP 5.4 上使用 Slim 和 NotORM 的项目。将 NotORM 设置为 Debug模式时,NotORM 跟踪语句: fwrite(STDERR, "$backtrace
到目前为止我所做的是: #!/bin/bash exec 2> >(sed 's/^/ERROR= /') var=$( sleep 1 ; hostname ;
我在远程机器上通过 SSH 执行一系列操作,我正在传输它的标准输出和标准错误,然后由写入器使用它,写入本地标准输出和标准错误,以及字节缓冲区。 就在编写器使用它之前,我想对其执行一系列字符串操作,然后
现在我有一些使用 Popen.communicate() 的代码从子进程(设置 stdin=PIPE 和 stderr=PIPE)运行命令并捕获 stderr 和 stdout。 问题在于 commu
我是一名优秀的程序员,十分优秀!