创建一个写入多个文件的管道(tee) [英] Create a pipe that writes to multiple files (tee)
问题描述
我想在ksh脚本(使用exec)中创建一个管道,该管道将管道连接到tee,并将输出发送到管道.
I would like to create a pipe in a ksh script (using exec) that pipe's to a tee, and sends the output to a pipe.
当前
#Redirect EVERYTHING
exec 3>&1 #Save STDOUT as 3
exec 4>&2 #Save STDERR as 4
exec 1>${Log} #Redirect STDOUT to a log
exec 2>&1 #Redirect STDERR to STDOUT
我想 做什么(但我的语法不正确):
What'd I'd like to do (but I don't have the syntax correct):
#Redirect EVERYTHING
exec 3>&1 #Save STDOUT as 3
exec 4>&2 #Save STDERR as 4
exec 1>tee -a ${Log} >&3 #Redirect STDOUT to a log
exec 2>&1 #Redirect STDERR to STDOUT
如何创建此管道?
推荐答案
这是我使用的解决方案.它在我的Mac上在ksh下工作.它很好地封装在start_logging()和stop_logging()函数中,以简化生活.
Here's a solution I use. It works under ksh on my Mac. It's nicely encapsulated into start_logging() and stop_logging() functions to make life easy.
实践中的代码如下:
# Optional:
# Set the name and location of the log file.
# OUTPUT_LOG=output.log # default
# Set the name and location of the named pipe used.
# OUTPUT_PIPE=output.pipe # default
start_logging
# Default is to append to an existing log file.
# start_logging delete_existing_logfile
echo "This is on standard out"
echo "This is on standard err" >&2
stop_logging
这是整个文件.启动和停止功能以及上面的示例都在文件的底部.为了使它更易于使用,只需将start和stop函数放在它们自己的文件中,并在需要记录日志的脚本中提供它们.
Here is the whole file. The start and stop functions along with the example above are all at the bottom of the file. To make it easier to use, just put the start and stop functions in their own file and source them in the scripts where you need the logging.
#!/bin/sh
# Author: Harvey Chapman <hchapman _AT_ 3gfp.com>
# Description: POSIX shell functions that can be used with tee to simultaneously put
# stderr and stdout to both a file and stdout
#
# Based on:
# Re: How to redirect stderr and stdout to a file plus display at the same time
# http://www.travishartwell.net/blog/2006/08/19_2220
#
# Original example function from Travis Hartwell's blog.
# Note: I've made minor changes to it.
example()
{
OUTPUT_LOG=output.log
OUTPUT_PIPE=output.pipe
# This should really be -p to test that it's a pipe.
if [ ! -e $OUTPUT_PIPE ]; then
mkfifo $OUTPUT_PIPE
fi
# This should really be -f to test that it's a regular file.
if [ -e $OUTPUT_LOG ]; then
rm $OUTPUT_LOG
fi
exec 3>&1 4>&2
tee $OUTPUT_LOG < $OUTPUT_PIPE >&3 &
tpid=$!
exec > $OUTPUT_PIPE 2>&1
echo "This is on standard out"
echo "This is on standard err" >&2
exec 1>&3 3>&- 2>&4 4>&-
wait $tpid
rm $OUTPUT_PIPE
}
# A slightly reduced version of example()
example2()
{
OUTPUT_LOG=output.log
OUTPUT_PIPE=output.pipe
rm -f $OUTPUT_PIPE
mkfifo $OUTPUT_PIPE
rm -f $OUTPUT_LOG
tee $OUTPUT_LOG < $OUTPUT_PIPE &
tpid=$!
exec 3>&1 4>&2 >$OUTPUT_PIPE 2>&1
echo "This is on standard out"
echo "This is on standard err" >&2
exec 1>&3 3>&- 2>&4 4>&-
wait $tpid
rm -f $OUTPUT_PIPE
}
#
# Logging methods based on above. See the example below for how to use them.
#
# Usage: start_logging [delete_existing_logfile]
start_logging()
{
# Check to see if OUTPUT_LOG and OUTPUT_PIPE need to be defined.
if [ -z "$OUTPUT_LOG" ]; then
OUTPUT_LOG=output.log
fi
if [ -z "$OUTPUT_PIPE" ]; then
OUTPUT_PIPE=output.pipe
fi
# Make sure that we're not already logging.
if [ -n "$OUTPUT_PID" ]; then
echo "Logging already started!"
return 1
fi
# Always remove the log and pipe first.
rm -f $OUTPUT_PIPE
# Delete the logfile first if told to.
if [ "$1" = delete_existing_logfile ]; then
rm -f $OUTPUT_LOG
fi
mkfifo $OUTPUT_PIPE
tee -a $OUTPUT_LOG < $OUTPUT_PIPE &
OUTPUT_PID=$!
exec 3>&1 4>&2 >$OUTPUT_PIPE 2>&1
}
stop_logging()
{
# Make sure that we're currently logging.
if [ -z "$OUTPUT_PID" ]; then
echo "Logging not yet started!"
return 1
fi
exec 1>&3 3>&- 2>&4 4>&-
wait $OUTPUT_PID
rm -f $OUTPUT_PIPE
unset OUTPUT_PID
}
example3()
{
start_logging
#start_logging delete_existing_logfile
echo "This is on standard out"
echo "This is on standard err" >&2
stop_logging
}
#example
#example2
example3
这篇关于创建一个写入多个文件的管道(tee)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!