我想将流程的标准输出和标准错误重定向到单个文件。我在巴什怎么做?
当前回答
我想要一个解决方案,将stdout和stderr的输出写入日志文件,并且stderr仍在控制台上。所以我需要通过tee复制stderr输出。
这是我找到的解决方案:
command 3>&1 1>&2 2>&3 1>>logfile | tee -a logfile
第一次交换stderr和stdout然后将stdout附加到日志文件将stderr管道到tee,并将其附加到日志文件中
其他回答
# Close standard output file descriptor
exec 1<&-
# Close standard error file descriptor
exec 2<&-
# Open standard output as $LOG_FILE file for read and write.
exec 1<>$LOG_FILE
# Redirect standard error to standard output
exec 2>&1
echo "This line will appear in $LOG_FILE, not 'on screen'"
现在,一个简单的回显将写入$LOG_FILE,这对于守护进程非常有用。
对于原始帖子的作者,
这取决于你需要实现什么。如果您只需要重定向从脚本调用的命令,那么已经给出了答案。我的任务是在当前脚本中重定向,这会影响到前面提到的代码段之后的所有命令/内置程序(包括fork)。
另一个很酷的解决方案是重定向到标准错误和标准输出,并立即记录到日志文件,这涉及将“一个流”分成两个。此功能由“tee”命令提供,该命令可以一次写入/附加到多个文件描述符(文件、套接字、管道等):tee FILE1 FILE2…>(cmd1)>(cmd2)。。。
exec 3>&1 4>&2 1> >(tee >(logger -i -t 'my_script_tag') >&3) 2> >(tee >(logger -i -t 'my_script_tag') >&4)
trap 'cleanup' INT QUIT TERM EXIT
get_pids_of_ppid() {
local ppid="$1"
RETVAL=''
local pids=`ps x -o pid,ppid | awk "\\$2 == \\"$ppid\\" { print \\$1 }"`
RETVAL="$pids"
}
# Needed to kill processes running in background
cleanup() {
local current_pid element
local pids=( "$$" )
running_pids=("${pids[@]}")
while :; do
current_pid="${running_pids[0]}"
[ -z "$current_pid" ] && break
running_pids=("${running_pids[@]:1}")
get_pids_of_ppid $current_pid
local new_pids="$RETVAL"
[ -z "$new_pids" ] && continue
for element in $new_pids; do
running_pids+=("$element")
pids=("$element" "${pids[@]}")
done
done
kill ${pids[@]} 2>/dev/null
}
所以,从一开始。假设我们有一个终端连接到/dev/stdout(文件描述符#1)和/dev/stderr(文件描述符#2)。实际上,它可以是管道、插座或其他任何东西。
创建文件描述符(FD)#3和#4,并分别指向与#1和#2相同的“位置”。从现在起,更改文件描述符#1不会影响文件描述符#3。现在,文件描述符#3和#4分别指向标准输出和标准错误。这些将用作实际终端标准输出和标准误差。1> >(…)将标准输出重定向到括号中的命令括号(子shell)执行“tee”,读取exec的标准输出(管道),并通过另一个管道重定向到“logger”命令,到达括号中的子shell。同时,它将相同的输入复制到文件描述符#3(终端)第二部分非常类似,是关于对标准错误和文件描述符#2和#4执行相同的技巧。
运行具有上面一行和另外一行的脚本的结果:
echo "Will end up in standard output (terminal) and /var/log/messages"
…如下:
$ ./my_script
Will end up in standard output (terminal) and /var/log/messages
$ tail -n1 /var/log/messages
Sep 23 15:54:03 wks056 my_script_tag[11644]: Will end up in standard output (terminal) and /var/log/messages
如果您想看到更清晰的画面,请在脚本中添加以下两行:
ls -l /proc/self/fd/
ps xf
LOG_FACILITY="local7.notice"
LOG_TOPIC="my-prog-name"
LOG_TOPIC_OUT="$LOG_TOPIC-out[$$]"
LOG_TOPIC_ERR="$LOG_TOPIC-err[$$]"
exec 3>&1 > >(tee -a /dev/fd/3 | logger -p "$LOG_FACILITY" -t "$LOG_TOPIC_OUT" )
exec 2> >(logger -p "$LOG_FACILITY" -t "$LOG_TOPIC_ERR" )
它是相关的:将标准输出和标准错误写入syslog。
它几乎可以工作,但不能从xinetd;(
看看这里。应该是:
yourcommand &> filename
它将标准输出和标准错误重定向到文件名。
bash your_script.sh 1>file.log 2>&1
1> log指示shell将标准输出发送到file.log文件,2>&1告诉它将标准错误(文件描述符2)重定向到标准输出(文件描述符1)。
注意:正如liw.fi指出的那样,顺序很重要,2>&11>file.log不起作用。
对于tcsh,我必须使用以下命令:
command >& file
如果使用命令&>文件,它将给出“无效空命令”错误。
推荐文章
- 如何在shell管道中使用“jq”?
- 如何使用jq从JSON获得键名
- 图形化对?
- 我如何能匹配一个字符串与正则表达式在Bash?
- 为什么cURL返回错误“(23)Failed writing body”?
- 在Unix shell中计算一列数字
- 在bash脚本中否定if条件
- 如何撤消“set -e”使bash立即退出,如果任何命令失败?
- 如何在docker映像的新容器中运行bash ?
- 管道命令输出到tee,但也保存退出代码的命令
- 如何自动添加用户帐户和密码与Bash脚本?
- 是否有方法按列“uniq”?
- 如何在bash脚本中检查文件名的扩展名?
- 使用bash的变量中第一个大写字符
- 我如何才能快速和所有的数字在一个文件?