CentOS7下GNU time输出重定向至文件丢失问题问询
问题原因
/dev/stdout并非实时流,它是指向当前进程stdout对应文件实体的符号链接。当脚本输出重定向到文件时,/dev/stdout会直接指向该文件。- GNU
time使用--output=/dev/stdout时,会独立打开目标文件进行写入;而脚本的EXIT陷阱是通过bash已打开的stdout文件描述符写入内容。两者的文件指针操作不同步,陷阱的写入会直接覆盖或截断time的输出内容。 - 本质冲突:直接操作
/dev/stdout文件实体,与通过bash的stdout流写入是两个独立的文件操作,指针位置不共享,导致time的输出被冲掉。
解决办法
方法1:文件描述符重定向(推荐)
放弃--output参数,利用GNU time默认输出到stderr的特性,通过文件描述符重定向将time的输出合并到程序的stdout,同时保留程序的stderr:
# 先设置环境变量 export YOUR_ENV_VAR=target_value # 核心执行命令 { /usr/bin/time -p program.exe 2>&1 1>&3; } 3>&1 2>&4
原理:
- 用文件描述符
3保存原stdout,4保存原stderr 2>&1将time的输出(原本在stderr)重定向到原stdout1>&3将程序的stdout重定向到原stdout,确保程序输出与time记录流向同一目标- 程序的stderr仍保留原路径,仅输出关键警告/错误
方法2:临时文件中转输出
将time的输出先写入临时文件,脚本退出前再将临时文件内容追加到stdout,避开直接操作/dev/stdout的冲突:
# 设置环境变量 export YOUR_ENV_VAR=target_value # 创建临时文件 time_log=$(mktemp) # 退出陷阱:输出time记录并清理临时文件 trap 'cat "$time_log" >> /dev/stdout; rm -f "$time_log"' EXIT # 执行程序,time输出写入临时文件 /usr/bin/time -p --output="$time_log" --append program.exe
原理:
- 临时文件独立存储
time的输出,不受陷阱函数对stdout的写入操作影响 - EXIT陷阱在脚本退出前统一将临时文件内容追加到stdout,保证内容不丢失
方法3:调整陷阱写入行为(仅限简单场景)
如果必须保留--output=/dev/stdout,确保陷阱函数对stdout的写入为追加模式,且等待time执行完成后再触发:
# 设置环境变量 export YOUR_ENV_VAR=target_value # 先执行time,等待子进程完成写入 /usr/bin/time -p --output="/dev/stdout" --append program.exe # 陷阱用追加模式写入,避免覆盖 trap 'echo "脚本退出提示" >> /dev/stdout' EXIT
注意:
- 此方法仅适用于脚本无后台进程的场景,否则陷阱可能在
time写入完成前触发 - 若陷阱输出内容较多,仍存在覆盖
time输出的风险,可靠性不如前两种方法
内容的提问来源于stack exchange,提问作者DrewAtWork
相关产品推荐
相关产品推荐

