2010-02-18 11 views
6

पर लिखता है, मैं एक केपी स्क्रिप्ट (निष्पादन का उपयोग करके) में पाइप बनाना चाहता हूं जो पाइप को टी के लिए भेजता है, और आउटपुट को पाइप में भेजता है।एक पाइप बनाएं जो एकाधिक फ़ाइलों (टीई)

वर्तमान:

#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 

क्या मैं चाहें करने के लिए (लेकिन मैं वाक्य रचना सही नहीं है):

#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 

मैं कैसे कर सकता है इस पाइप को बनाओ?

+0

बैश कम से कम, अपने ब्लॉक में से प्रत्येक में अंतिम पंक्ति बेहतर रूप में वर्णित किया जाएगा में "देते STDERR को STDOUT" या "STDOUT करने के लिए STDERR अनुप्रेषित"। बाद में 2> डंप-स्टडआउट खाली हो जाएगा, लेकिन जो कुछ भी आप गूंजते हैं> और 2 उसी स्थान पर जाएंगे जैसे आप गूंजते हैं> & 1। – dubiousjim

उत्तर

5

यहां एक समाधान है जिसका मैं उपयोग करता हूं। यह मेरे मैक पर ksh के तहत काम करता है। यह जीवन को आसान बनाने के लिए start_logging() और stop_logging() फ़ंक्शंस में अच्छी तरह से encapsulated है।

कोड व्यवहार में इस तरह दिखता है:

# 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 

यहाँ पूरी फ़ाइल है। ऊपर दिए गए उदाहरण के साथ स्टार्ट और स्टॉप फ़ंक्शंस फ़ाइल के निचले हिस्से में हैं। इसे उपयोग करना आसान बनाने के लिए, बस अपनी फ़ाइल में स्टार्ट और स्टॉप फ़ंक्शंस डालें और उन्हें स्क्रिप्ट में स्रोत करें जहां आपको लॉगिंग की आवश्यकता है।

#!/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 
+0

कार्यान्वयन प्रदान करने के लिए धन्यवाद, मुझे वास्तव में उन कार्यों को पसंद है। –

0

मुझे पता है कि बाश नहीं है, लेकिन वहां बहुत अधिक ओवरलैप है, इसलिए शायद यह वहां भी काम करेगा।

process1 N> >(process2) 

एक subshell चल process2 बनाता है। यही कारण है कि subshell प्राप्त करता है अपने process1 की फाइल वर्णनकर्ता एन से डेटा stdin के रूप में तो विशेष रूप से, तुम कर सकते हो:

process1 1> >(tee -a mylog >&3) 

मैं कि क्या यह भी अगर process1exec साथ बदल दिया है काम करेंगे पता नहीं है, लेकिन आप दे सकते हैं यह एक कोशिश करो।

+0

अफसोस की बात है, कोई वाक्यविन्यास भी क्ष में काम नहीं करता है। –

0

ksh में |& और >&p हैं, लेकिन मैं उन्हें जो कुछ भी ढूंढ रहा हूं उसे करने के लिए नहीं मिल सका। शायद आप कर सकते हैं।

0

बजाय:

exec 1>tee -a ${Log} >&3

बस कार्य करें:

tee -a ${Log} >&3 &

tee यह के रूप में पृष्ठ भूमि में फॉर्क जाएगा, और फोन करने की प्रक्रिया की खपत होगी '(यानी अपनी स्क्रिप्ट का) STDIN उस समय tee फोर्क किया गया था।

+0

जैसे ही मुझे मौका मिलता है, मैं इसे आजमाउंगा, धन्यवाद। –

+0

यह मेरे परीक्षण में काम नहीं किया। टी ने शुरू करने के लिए शुरू किया और लिखा, लेकिन यह stdout का उपभोग नहीं किया। –

+0

आपके फ़ाइलहेडल सेटअप में कुछ और गलत हो सकता है; पूरी चीज शुरू करें और जहां कहीं भी जाता है उसे देखने/सत्यापित करने के लिए 'lsof' का उपयोग करें। – vladr

6

मैंने named pipes का उपयोग करके एक समाधान तैयार किया।

#!/bin/ksh 

LOG=~/testLog.log 
PIPE=~/logPipe 
mkfifo ${PIPE} 
exec 3>&1 #Save STDOUT as 3 
exec 4>&2 #Save STDERR as 4 
tee -a ${LOG} <${PIPE} >&3 & #Start tee off the logpipe in the background 
exec 1>${PIPE} #Redirect stdout to the pipe 
exec 2>&1 #Redirect STDERR to STDOUT 

echo "TEST" 
echo Test 2 

ls | grep -i "test" 

rm -f ${PIPE} #Remove the pipe 
+0

एक बहुत संक्षिप्त समाधान। धन्यवाद। –

संबंधित मुद्दे