如何在Linux系统中创建stdout/stderr之外的自定义文件描述符
自定义文件描述符实现方案
需求说明
需要创建一个可与/dev/stdin、/dev/stdout、/dev/stderr共存的特殊文件描述符(可映射为/dev/fd/3和/dev/customout,也可命名为customerr),让所有程序与脚本能像使用stderr一样调用它,具体执行要求如下:
示例脚本(demo.sh)
#!/usr/bin/env bash echo hello from fd 3 aka customout >& /dev/customout echo hello from stdout
预期执行效果
屏蔽customout时:
./demo.sh 3>/dev/null仅输出stdout(含stderr)内容:
hello from stdout屏蔽stdout时:
./demo.sh 1>/dev/null仅输出customout(含stderr)内容:
hello from fd 3 aka customout无重定向执行时:
./demo.sh输出stdout、stderr与customout所有内容:
hello from fd 3 aka customout hello from stdout
解决方案
方法1:实现全局可用的/dev/customout
Linux中/dev/fd/3是进程级临时描述符,要让/dev/customout全局映射到fd3,需完成两步配置:
创建udev规则绑定设备文件
创建udev规则文件/etc/udev/rules.d/99-custom-fd.rules:SUBSYSTEM=="misc", KERNEL=="fd", ACTION=="add", RUN+="/bin/ln -sf /proc/self/fd/3 /dev/customout"重新加载udev规则生效:
udevadm control --reload-rules && udevadm trigger此配置会让每个进程的
/dev/customout指向自身的fd3。全局初始化fd3
要让所有新进程默认将fd3指向终端(和stdout/stderr一致),可修改shell全局启动脚本:
在/etc/bash.bashrc中添加:# 初始化fd3指向当前终端 exec 3>&1若希望它更贴近stderr的定位,可改为
exec 3>&2,并将设备名改为/dev/customerr。
方法2:脚本内独立初始化
如果不需要全局可用,仅在特定脚本或进程中使用,可直接在脚本开头初始化fd3:
#!/usr/bin/env bash # 初始化fd3指向stdout(默认终端),支持外部重定向修改 exec 3>&1 echo hello from fd 3 aka customout >&3 echo hello from stdout
这种方式完全符合预期执行效果:
- 执行
./demo.sh 3>/dev/null时,fd3被重定向到null,仅输出stdout内容 - 执行
./demo.sh 1>/dev/null时,stdout被屏蔽,fd3仍指向终端,输出customout内容
关键说明
/dev/fd/3是进程独立的文件描述符,全局/dev/customout本质是映射当前进程的fd3- 要让所有程序直接使用
/dev/customout,必须确保进程启动时fd3已被正确打开(默认指向终端或其他目标)
内容的提问来源于stack exchange,提问作者Elfen Dew
相关产品推荐
相关产品推荐

