如何将STDERR重定向至select选中的STDOUT对应进程句柄?
解决Perl中STDERR和STDOUT同时输出到分页器(如less)的问题
正确实现方案
直接将STDOUT和STDERR都重定向到分页器的管道句柄,无需依赖select()(若需要用select()也可兼容):
#!/usr/bin/perl # 启动分页器并创建管道 open(my $pager, '|-', 'less') or die "无法启动less: $!"; # 将STDOUT复制到分页器管道 open(STDOUT, '>&', $pager) or die "重定向STDOUT失败: $!"; # 将STDERR复制到当前的STDOUT(即分页器) open(STDERR, '>&', STDOUT) or die "重定向STDERR失败: $!"; # 关闭原分页器句柄(避免文件描述符泄漏,不影响输出) close($pager); print "STDOUT内容 - 将显示在less中\n"; print STDERR "STDERR内容 - 同样会显示在less中\n";
你之前尝试失败的原因
方法3的问题:
select($pager)仅改变了Perl的默认输出句柄,但全局的STDOUT句柄仍然指向原终端。此时执行open(STDERR, '>&', STDOUT),是把STDERR重定向到终端而非分页器。方法4的问题:
open(STDERR, '>', $pager)是错误用法——Perl会把文件句柄$pager当成字符串文件名,输出到一个类似GLOB(0x123456)的临时文件中,自然看不到内容。正确的句柄复制必须用>&语法。
兼容select()的写法
如果一定要用select()设置默认输出,只需确保先完成STDOUT的重定向:
#!/usr/bin/perl open(my $pager, '|-', 'less') or die "无法启动less: $!"; # 先将STDOUT重定向到分页器 open(STDOUT, '>&', $pager) or die "重定向STDOUT失败: $!"; open(STDERR, '>&', STDOUT) or die "重定向STDERR失败: $!"; # 此时select(STDOUT)或select($pager)效果一致 select(STDOUT); print "默认输出(STDOUT)\n"; print STDERR "错误输出(STDERR)\n"; close($pager);
额外提示
- 若需判断是否需要启动分页器(比如仅当STDOUT是终端时),可以用
-t STDOUT检查:if (-t STDOUT) { # 启动分页器并重定向输出 } else { # 直接输出到原STDOUT/STDERR } - 该方案无需额外Perl模块,兼容Git Bash for Windows环境。
内容的提问来源于stack exchange,提问作者DevSolar
相关产品推荐
相关产品推荐

