লগ ফাইল এবং কনসোল আউটপুট রচনা


101

ইউনিক্স শেল-এ, আমার একটি এনভিভি ফাইল রয়েছে ( এনভি ফাইলটি লগ ফাইলের নাম ও পথের মতো ব্যবহারকারী স্ক্রিপ্টটি চালানোর জন্য প্রয়োজনীয় প্যারামিটারগুলি সংজ্ঞায়িত করে, আউটপুটগুলিকে লগ করতে পুনরুদ্ধার করে, ডাটাবেস সংযোগের বিশদ ইত্যাদি ) যা সমস্ত আউটপুট পুনর্নির্দেশ করে ( প্রতিধ্বনি বার্তা) ) এবং নিম্নলিখিত কোড ব্যবহার করে সম্পাদিত স্ক্রিপ্ট থেকে লগ ফাইলটিতে ত্রুটি:

exec 1>>${LOG_FILE}
exec 2>>${LOG_FILE}

Env ফাইলটি প্রতিটি স্ক্রিপ্টের শুরুতে কার্যকর করা হয়। এনভিউ ফাইলের উপরের কোডের কারণে সমস্ত কনসোল আউটপুট যা ব্যবহারকারীর আউটপুট বা ত্রুটি হতে পারে তা লগ ফাইলে সরাসরি আউটপুট যা আমার আসলে প্রয়োজন।

তবে কিছু নির্বাচনী ব্যবহারকারীর আউটপুট রয়েছে যা আমি কনসোল এবং লগ ফাইল উভয়ই প্রদর্শিত করতে চাই। তবে উপরের কোডটির কারণে আমি এটি করতে পারছি না।

আমি জানি যে আমি যদি উপরের কোডটি সরিয়ে ফেলি তবে আমি এই মামলার জন্য পছন্দসই ফলাফল পেতে পারি, তবে আমাকে অন্য সমস্ত আউটপুট ম্যানুয়ালি লিখতে হবে যা কোনও সহজ কাজ নয়।

উপরের কোডগুলি না সরিয়ে কনসোল এবং লগ ফাইল উভয় ক্ষেত্রে আউটপুট পাওয়ার কোনও উপায় আছে কি?

উত্তর:


109
exec 3>&1 1>>${LOG_FILE} 2>&1

লগ ফাইলে stdout এবং stderr আউটপুট প্রেরণ করবে, কিন্তু কনসোলের সাথে সংযুক্ত fd 3 সহ আপনাকে ছেড়ে দেবে, তাই আপনি করতে পারেন

echo "Some console message" 1>&3

শুধু কনসোলে একটি বার্তা লিখতে, বা

echo "Some console and log file message" | tee /dev/fd/3

কনসোল এবং লগ ফাইল উভয়কেই একটি বার্তা লিখতে - এর আউটপুটটিকে তার নিজস্ব এফডি 1 (যা এখানে রয়েছে ) এবং যে ফাইলটিতে আপনি এটি লিখতে বলেছেন (যা এখানে এফডি 3, অর্থাৎ কনসোল) প্রেরণ করে তা উভয়কে প্রেরণ করে ।teeLOG_FILE

উদাহরণ:

exec 3>&1 1>>${LOG_FILE} 2>&1

echo "This is stdout"
echo "This is stderr" 1>&2
echo "This is the console (fd 3)" 1>&3
echo "This is both the log and the console" | tee /dev/fd/3

মুদ্রণ হবে

This is the console (fd 3)
This is both the log and the console

কনসোল এবং লাগাতে

This is stdout
This is stderr
This is both the log and the console

লগ ফাইল মধ্যে।


4
এটি আপনার পরামর্শ মতো কাজ করেছিল। তবে আমি টি / দেব / এফডি / 3 বুঝতে পারি নি । আমি জানি যে ফাইলটি লগ এবং কনসোলে বার্তা লিখেছিল, তবে আমি ঠিক বুঝতে পারি নি টি / র পরে ব্যবহৃত / দেব / এফডি / 3
অবিনাশ শ্রেষ্ট

@ শ্রেষ্ঠা এটি টি-এর অস্বাভাবিক ব্যবহার, আমি সম্মত। /dev/fd/3, একটি ফাইল নাম যে "বর্তমানে খোলা FD 3" বোঝায় তাই tee /dev/fd/3যাই হোক না কেন তার stdin আসে 1 FD লিখতে এবং 3 (FD হবে /dev/fd/3ফাইল)। এফডি 1 লগ ফাইলের সাথে সংযুক্ত থাকে, এফডি 3 কনসোলের সাথে সংযুক্ত থাকে।
আয়ান রবার্টস

এছাড়াও আপনি কেবল একটি ফাইল লিখতে চান এবং কনসোল চেষ্টা করে দেখতে চান না: echo "blah" | tee file1.txt | tee file2.txt >/dev/null 'ব্লাহ' ফাইল 1.txt এবং file2.txt এ রাখা হবে না, তবে কনসোলে লিখিত হবে না।
বিপদ 89

এটি আমার জন্য খুব সহায়ক ছিল। যদিও আমি এমন কিছু লক্ষ্য করেছি যা সম্ভবত বিষয়বস্তু হতে পারে তবে সম্ভবত আপনারা কেউ কেউ এর কারণগুলি জানেন। আমি বাশ স্ক্রিপ্ট থেকে আর স্ক্রিপ্টগুলি সম্পাদন করছি। বিভিন্ন আর ফাংশনের কনসোল আউটপুট রঙিন (যেমন আমি এটি সংজ্ঞায়িত করেছি)। কনসোল এবং লগফাইলে আউটপুট পুনর্নির্দেশের জন্য উপরের পদ্ধতির ব্যবহার করার সময়, কনসোল আউটপুট আর রঙিন হয় না। এর কারণ কী হতে পারে?
ডাইহেলস্টে

4
@ ডিহেলসটায় কিছু প্রোগ্রাম সনাক্ত করতে সক্ষম হয় যখন তাদের আউটপুটটি teeকোনও টার্মিনালে সরাসরি যাওয়ার পরিবর্তে (এই ক্ষেত্রে , যার ফলে টার্মিনালে লিখিত হয়) অন্য আউটপুটটি পাইপ করা হচ্ছে এবং তাদের আউটপুটটি ম্যাচের জন্য সামঞ্জস্য করে।
ইয়ান রবার্টস

43

হ্যাঁ, আপনি ব্যবহার করতে চান tee:

টি - স্ট্যান্ডার্ড ইনপুট থেকে পড়ুন এবং স্ট্যান্ডার্ড আউটপুট এবং ফাইলগুলিতে লিখুন

আর্গুমেন্ট হিসাবে ফাইলটি টি করতে এবং পাস করার জন্য কেবল আপনার আদেশটি পাইপ করুন:

exec 1 | tee ${LOG_FILE}
exec 2 | tee ${LOG_FILE}

এটি উভয়ই আউটপুটটি STDOUT এ মুদ্রণ করে এবং একই আউটপুট একটি লগ ফাইলে লেখায়। দেখুন man teeআরও তথ্যের জন্য।

নোট করুন যে এটি লগ ফাইলে stderr লিখবে না, সুতরাং আপনি যদি দুটি স্ট্রিম একত্রিত করতে চান তবে ব্যবহার করুন:

exec 1 2>&1 | tee ${LOG_FILE}

4
উপরের সমাধানটি কার্যকর হয়নি। আমার কাছে redirect.env ফাইলটি রয়েছে: ###### redirect.env ####### LOG_FILE = login.txt এক্সিকিউটিউট 1 2> & 1 | টি -a $ O LOG_FILE} নির্বাহী 1 | টি -a $ O LOG_FILE} exec 2 | টি-এ {O লগ_ফিল} ########## এবং কার্যকারী ফাইলটিতে নিম্নলিখিত কোড রয়েছে: ##### আউটপুট.শ ##### #! / বিন / শ redirect.env প্রতিধ্বনি "বৈধ আউটপুট" ech "অবৈধ আউটপুট" ################ তবে আমি ত্রুটি পেয়েছি: #### redirect.env: লাইন 3: এক্সিকিউ: 1: পাওয়া যায়নি redirect.env: লাইন 5: এক্সিকিউট: 1: পাওয়া যায় নি redirect.env: লাইন 6: এক্সিকিউ: 2: পাওয়া যায় নি #### এবং লগ ফাইলে আমি একই ত্রুটি পেয়েছি। আমি কি কিছু ভুল করছি?
অবিনাশ শ্রেষ্ঠ

এটি বলা খুব শক্ত কারণ আপনার মন্তব্যে নতুন লাইনগুলি ছড়িয়ে দেওয়া হয়েছে। আপনি সংক্ষেপের মতো কোথাও কোডের একটি পেস্ট যুক্ত করতে পারেন ?
জন কেয়ার্নস

4
আমি ফাইলগুলি ইউনিক্সরডাইরেক্ট লিঙ্কে যুক্ত করেছি । সম্পর্কিত ফাইল redirect.env এবং output.sh হয়
abinash শ্রেষ্ঠা

4
এই কোডটি কাজ করছে বলে মনে হচ্ছে না (কমপক্ষে আর কোনও নয়)। আপনি সাধারণত পাবেনscript.sh: line 5: exec: 1: not found
tftd

40

আমি জাঁটির উত্তরটি চেষ্টা করেছি, তবে আমি এটিও পেয়েছি

এক্সিকিউট: 1: পাওয়া যায় নি

ত্রুটি. এটিই আমার পক্ষে সবচেয়ে ভাল কাজ করে ( zsh এ কাজ করার বিষয়টি নিশ্চিত করেছেন):

#!/bin/bash
LOG_FILE=/tmp/both.log
exec > >(tee ${LOG_FILE}) 2>&1
echo "this is stdout"
chmmm 77 /makeError

ফাইলটি /tmp/both.log পরে থাকে

this is stdout
chmmm command not found 

আপনি টি থেকে -a সরিয়ে না নিলে /tmp/both.log সংযুক্ত থাকে।

ইঙ্গিত: >(...)একটি প্রক্রিয়া প্রতিস্থাপন। এটা তোলে দেয় execকরারtee যেমন যদি এটা একটি ফাইল ছিল কমান্ড।


4
এটি আমার জন্য আকর্ষণীয় কাজ করেছিল, অন্য উত্তরগুলি হিট বা মিস হয়েছে।
জে টেলর

এই স্নিপেট ভাগ করে নেওয়ার জন্য ধন্যবাদ। মনে হচ্ছে এটি ঠিক কাজ করছে (অন্যান্য উত্তরের তুলনায়)!
tftd

এটি কাজ করে, তবে এখন আমার শেল কার্যকর হওয়ার পরে আলাদা।
জোশ উসরে

@JoshUsre আপনি যদি কোনো সাহায্যের চান অথবা আপনি অন্য তাই ব্যবহারকারীদের সাহায্য করতে চাই, তাহলে দয়া করে ব্যাখ্যা কি ভিন্ন, এবং আপনার শেল, সংস্করণ, বর্ণনা ওএস ইত্যাদি ..
alfonx

4
আপনার যদি স্টডআউট এবং স্টডারর মধ্যে পার্থক্য করার প্রয়োজন না হয় তবে আপনি বিবৃতিগুলি একত্র করতে পারেন exec > >(tee ${LOG_FILE}) 2>&1
ডার্কড্রাগন

6

আমি টাইমস্ট্যাম্পের সাথে স্টডআউট এবং লগ ফাইলে লগগুলি প্রদর্শন করতে চেয়েছিলাম। উপরের উত্তরগুলির কোনওটিই আমার পক্ষে কার্যকর হয়নি। আমি প্রক্রিয়া প্রতিস্থাপন এবং এক্সিকিউট কমান্ড ব্যবহার করেছি এবং নিম্নলিখিত কোডটি নিয়ে এসেছি। নমুনা লগগুলি:

2017-06-21 11:16:41+05:30 Fetching information about files in the directory...

আপনার স্ক্রিপ্টের শীর্ষে নিম্নলিখিত লাইনগুলি যুক্ত করুন:

LOG_FILE=script.log
exec > >(while read -r line; do printf '%s %s\n' "$(date --rfc-3339=seconds)" "$line" | tee -a $LOG_FILE; done)
exec 2> >(while read -r line; do printf '%s %s\n' "$(date --rfc-3339=seconds)" "$line" | tee -a $LOG_FILE; done >&2)

আশা করি এটি কারও সাহায্য করবে!


হোস্ট ডিরেক্টরিতে লগইন করতে সমস্ত অ্যাপ্লিকেশন ত্রুটিগুলি লগ করা সম্ভব হয় যাতে এটি ডিভপসকে সহায়তা করে ....
প্রসাদ শিন্ডে

3

লগ ফাইলের জন্য আপনি পাঠ্য ডেটাতে প্রবেশের তারিখ করতে পারেন। নিম্নলিখিত কোড সাহায্য করতে পারে

# declaring variables

Logfile="logfile.txt"   
MAIL_LOG="Message to print in log file"  
Location="were is u want to store log file"

cd $Location   
if [ -f $Logfile ]  
then   
echo "$MAIL_LOG " >> $Logfile

else        

touch $Logfile   
echo "$MAIL_LOG" >> $Logfile    

fi  

আউটপুট: ২. লগ ফাইলটি প্রথম রানেই তৈরি হবে এবং পরবর্তী রানগুলি থেকে আপডেট করা থাকবে। ভবিষ্যতে রান লগ ফাইল নিখোঁজ ক্ষেত্রে, স্ক্রিপ্ট নতুন লগ ফাইল তৈরি করবে।


1

আমি পছন্দসই আউটপুট পাওয়ার একটি উপায় খুঁজে পেয়েছি। যদিও এটি কিছুটা অপ্রথাবিরোধী উপায় হতে পারে। যাইহোক এখানে এটি যায়। Redir.env ফাইলে আমার নিম্নলিখিত কোড রয়েছে:

#####redir.env#####    
export LOG_FILE=log.txt

      exec 2>>${LOG_FILE}

    function log {
     echo "$1">>${LOG_FILE}
    }

    function message {
     echo "$1"
     echo "$1">>${LOG_FILE}
    }

তারপরে আসল স্ক্রিপ্টে আমার কাছে নিম্নলিখিত কোডগুলি রয়েছে:

#!/bin/sh 
. redir.env
echo "Echoed to console only"
log "Written to log file only"
message "To console and log"
echo "This is stderr. Written to log file only" 1>&2

এখানে ইকো আউটপুটগুলি কেবল কনসোলের জন্য, লগ আউটপুটগুলিতে কেবল লগ ফাইল এবং বার্তা আউটপুটগুলি লগ ফাইল এবং কনসোল উভয়ই করে।

উপরের স্ক্রিপ্ট ফাইলটি কার্যকর করার পরে আমার নিম্নলিখিত ফলাফলগুলি রয়েছে:

কনসোলে

কনসোলে কনসোলে
প্রতিধ্বনিত হয়েছে কেবল
কনসোল এবং লগ করতে

লগ ফাইলের জন্য

লগ ফাইল ইন লগ ফাইল শুধুমাত্র লিখিত ফাইল এটি লিখিত
। শুধুমাত্র
কনসোল এবং লগ করার জন্যফাইল লগ করতে লিখিত

এই সাহায্য আশা করি।


1

এটি চেষ্টা করুন, এটি কাজ করবে:

log_file=$curr_dir/log_file.txt
exec > >(tee -a ${log_file} )
exec 2> >(tee -a ${log_file} >&2)

এটি exec > >(tee -a ${log_file} )আমার প্রয়োজনের জন্য নিখুঁত কাজ করে। উপরের পূর্ববর্তী সমাধানগুলি আমার স্ক্রিপ্টের অংশগুলিকে বাধা দেয় যা যদি ব্যর্থ হয় তবে প্রস্থান করার জন্য বাধ্য করবে force আপনাকে ধন্যবাদ
মিচেলকে

1
    #
    #------------------------------------------------------------------------------
    # echo pass params and print them to a log file and terminal
    # with timestamp and $host_name and $0 PID
    # usage:
    # doLog "INFO some info message"
    # doLog "DEBUG some debug message"
    # doLog "WARN some warning message"
    # doLog "ERROR some really ERROR message"
    # doLog "FATAL some really fatal message"
    #------------------------------------------------------------------------------
    doLog(){
        type_of_msg=$(echo $*|cut -d" " -f1)
        msg=$(echo "$*"|cut -d" " -f2-)
        [[ $type_of_msg == DEBUG ]] && [[ $do_print_debug_msgs -ne 1 ]] && return
        [[ $type_of_msg == INFO ]] && type_of_msg="INFO " # one space for aligning
        [[ $type_of_msg == WARN ]] && type_of_msg="WARN " # as well

        # print to the terminal if we have one
        test -t 1 && echo " [$type_of_msg] `date "+%Y.%m.%d-%H:%M:%S %Z"` [$run_unit][@$host_name] [$$] ""$msg"

        # define default log file none specified in cnf file
        test -z $log_file && \
            mkdir -p $product_instance_dir/dat/log/bash && \
                log_file="$product_instance_dir/dat/log/bash/$run_unit.`date "+%Y%m"`.log"
        echo " [$type_of_msg] `date "+%Y.%m.%d-%H:%M:%S %Z"` [$run_unit][@$host_name] [$$] ""$msg" >> $log_file
    }
    #eof func doLog

0

লগ ফাইলটিতে stdout এবং stderr উভয়ই যুক্ত করা আমি খুব দরকারী বলে মনে করি। আমি আলফোনাক্সের সাথে সমাধানটি দেখে খুশি হয়েছিলাম exec > >(tee -a), কারণ আমি কীভাবে এটি ব্যবহার করে সম্পন্ন করব তা ভাবছিলাম exec। আমি এখানে ডক সিনট্যাক্স ব্যবহার করে একটি সৃজনশীল সমাধান পেয়েছি এবং .: /unix/80707/how-to-output-text-to-both-screen-and-file-inside-a-hell -লিপি

আমি আবিষ্কার করেছি যে zsh এ, এখানে-ডক সমাধানটি stdout / stderr এবং লগ ফাইল উভয় আউটপুট অনুলিপি করতে "মাল্টো" কনস্ট্রাক্ট ব্যবহার করে পরিবর্তন করা যেতে পারে:

#!/bin/zsh
LOG=$0.log
# 8 is an arbitrary number;
# multiple redirects for the same file descriptor 
# triggers "multios"
. 8<<\EOF /dev/fd/8 2>&2 >&1 2>>$LOG >>$LOG
# some commands
date >&2
set -x
echo hi
echo bye
EOF
echo not logged

এটি execসমাধানের মতো পঠনযোগ্য নয় তবে এতে স্ক্রিপ্টের কেবলমাত্র অংশে লগ করার অনুমতি দেওয়ার সুবিধা রয়েছে। অবশ্যই, আপনি যদি ইওফ বাদ দেন তবে সম্পূর্ণ স্ক্রিপ্টটি লগিংয়ের সাথে কার্যকর করা হয়। আমি নিশ্চিত না কীভাবে zshমাল্টোগুলি প্রয়োগ করে তবে এর চেয়ে কম ওভারহেড থাকতে পারে tee। দুর্ভাগ্যক্রমে মনে হচ্ছে যে এর সাথে মাল্টো ব্যবহার করা যায় না exec

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.