You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux Shell中grapa程序stderr重定向至stdout失效问题求助

问题描述

我在Linux Shell中遇到了stderr重定向至stdout的异常问题:

  • 测试脚本some-binary内容如下:
    #!/bin/sh
    grapa -ccmd '$file().set("/dev/fd/2","Error\n")'
    
  • 执行./some-binary < ./my_input 2>test.txt时,test.txt能正常保存输出内容;
  • 但执行./some-binary < ./my_input 2>&1时,终端无任何输出,重定向未生效。

可通过以下Dockerfile复现问题:

FROM ubuntu:focal-20220801
RUN apt update
RUN apt install wget freeglut3 libxft2 libxext6 libxinerama1 libxcursor-dev -y
RUN wget https://github.com/grapa-dev/grapa/raw/master/bin/grapa-ubuntu64.tar.gz
RUN tar -xvf grapa-ubuntu64.tar.gz -C /usr/local/bin

执行测试命令:

docker run -it $(docker build -q .) /bin/bash
root@db9abeca8b5f:/# grapa -ccmd '$file().set("/dev/fd/2","Error\n")' >/dev/null 2>test.txt
root@db9abeca8b5f:/# cat test.txt 
Error
root@db9abeca8b5f:/# grapa -ccmd '$file().set("/dev/fd/2","Error\n")' >/dev/null 2>&1      
root@db9abeca8b5f:/# 
问题分析

核心原因是:你通过$file().set("/dev/fd/2", ...)直接打开并写入/dev/fd/2路径,而非复用grapa进程本身的stderr文件描述符(fd2)。

Shell的2>&1重定向逻辑是复制进程的fd2指向fd1的目标,但grapa并没有使用已有的fd2,而是重新打开/dev/fd/2。在grapa的实现中,这个操作可能绕过了Shell的重定向规则——比如它可能直接解析/dev/fd/2对应的原始设备(如终端),而非当前进程fd2实际指向的目标(重定向后的stdout),导致写入的内容无法被Shell的重定向捕获。

解决办法

方法1:使用grapa内置的stderr输出API(优先推荐)

查看grapa的官方文档,确认是否有直接输出到stderr的内置方法。比如类似$stderr().write("Error\n")的写法,这类方法会直接使用进程的stderr文件描述符,Shell的重定向规则就能正常生效。

方法2:通过Shell包装间接处理

如果grapa没有内置stderr输出API,可以用临时文件中转输出内容,再手动将内容输出到stderr:

#!/bin/sh
# 创建临时文件
temp_file=$(mktemp)
# 将grapa的stderr输出捕获到临时文件
grapa -ccmd '$file().set("/dev/fd/2","Error\n")' 2>"$temp_file"
# 将临时文件内容输出到当前进程的stderr(此时Shell的重定向会生效)
cat "$temp_file" >&2
# 清理临时文件
rm "$temp_file"

内容的提问来源于stack exchange,提问作者sazzy4o

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 06:36:26