如何将Bash脚本的stdout与stderr重定向到变量存储的文件路径?
问题根因
Bash执行任意命令(包括{}包裹的代码块)时,会先解析重定向部分的变量,再执行命令体。你将路径变量的定义放在了代码块内部,代码块尾部的重定向解析时变量尚未赋值,因此为空触发报错。同时原有代码存在两处语法错误:
source行的重定向符号被错误包进了双引号内- 代码块尾部重定向的stderr变量写法错误,应为
${stderr_file}而非{$stderr_file},且引号配对错误
解决方案
方案1:提前解析参数定义路径(推荐)
将参数解析、路径定义的逻辑移到代码块之前,重定向解析时变量已经完成赋值:
#!/bin/bash # 卫语句、参数解析提前到最前面 if [ $# -lt 2 ];then echo "参数不足" exit 1 fi # 提前定义日志路径 job_id="$1" log_dir="/some/path/${job_id}" mkdir -p "${log_dir}" # 必须提前创建目录避免报错 timestamp=$(date +%s) stdout_file="${log_dir}/${timestamp}.stdout" stderr_file="${log_dir}/${timestamp}.stderr" # 执行需要重定向的业务逻辑块 { # 引入并执行实际业务脚本,剩余参数直接透传 source "$2" "${@:3}" # 统计逻辑 # ... } > "${stdout_file}" 2> "${stderr_file}" echo "${stdout_file}"
方案2:内部用exec动态重定向
如果日志路径必须依赖代码块内部的计算逻辑,可以用exec动态修改当前shell的标准输出/错误指向,不需要额外包裹代码块:
#!/bin/bash # 卫语句 # ... # 解析入参计算路径 stdout_file="/some/path/$1/timestamp.stdout" stderr_file="/some/path/$1/timestamp.stderr" mkdir -p "$(dirname "${stdout_file}")" # 提前创建目录 # 动态重定向当前shell所有后续输出 exec 1>"${stdout_file}" 2>"${stderr_file}" # 引入并执行实际业务脚本 source "$2" "${@:3}" # 统计逻辑 # ... # 若需要后续输出恢复到终端,可执行 exec 1>/dev/stdout 2>/dev/stderr
注意事项
- 日志路径对应的目录必须提前用
mkdir -p创建,否则会触发目录不存在的报错 - 变量引用时统一加双引号,避免路径包含空格、特殊字符时解析错误
- 不需要给业务脚本单独加重复的重定向规则,避免日志内容重复或者覆盖
内容的提问来源于stack exchange,提问作者Lino
相关产品推荐
相关产品推荐

