টার্মিনালে প্রদর্শন করার সময় কীভাবে tee
আউটপুট ( STDOUT
) লিখতে হয় তা আমি জানি :aaa.sh
bbb.out
./aaa.sh | tee bbb.out
আমি এখন STDERR
নামক কোনও ফাইলটিতে কীভাবে লিখব ccc.out
, যখন এটি প্রদর্শিত হচ্ছে?
টার্মিনালে প্রদর্শন করার সময় কীভাবে tee
আউটপুট ( STDOUT
) লিখতে হয় তা আমি জানি :aaa.sh
bbb.out
./aaa.sh | tee bbb.out
আমি এখন STDERR
নামক কোনও ফাইলটিতে কীভাবে লিখব ccc.out
, যখন এটি প্রদর্শিত হচ্ছে?
উত্তর:
আমি ধরে নিচ্ছি আপনি এখনও টার্মিনালে STDERR এবং STDOUT দেখতে চান। আপনি জোশ কেলির উত্তরের জন্য যেতে পারেন, তবে আমি tail
পটভূমিতে প্রায় রাখছি যা আপনার লগ ফাইলটিকে খুব হ্যাকিশ এবং ক্লডজিকে আউটপুট করে। আপনি কীভাবে এক্সট্রা এফডি রাখতে এবং পরে এটি মেরে ক্লিনআপ করা প্রয়োজন তা প্রযুক্তিগতভাবে এটি একটিতে করা উচিত তা লক্ষ্য করুন trap '...' EXIT
।
এই কাজ করতে একটি ভাল উপায় আছে, এবং আপনি ইতিমধ্যে এটি আবিষ্কার করেছি: tee
।
কেবলমাত্র এটি আপনার স্টাডাউটের জন্য ব্যবহারের পরিবর্তে স্টাডাউটের জন্য একটি টি এবং স্টাডারের জন্য একটি রাখুন। আপনি কিভাবে এটি সম্পাদন করবেন? প্রক্রিয়া প্রতিস্থাপন এবং ফাইল পুনঃনির্দেশ:
command > >(tee -a stdout.log) 2> >(tee -a stderr.log >&2)
আসুন এটি বিভক্ত করুন এবং ব্যাখ্যা করুন:
> >(..)
>(...)
(প্রক্রিয়া বিকল্প) একটি ফিফো তৈরি করে এবং tee
এটি শুনতে দেয় । তারপরে, এটি আপনার প্রথমে শুনছে এমন ফিফোর >
STDOUT পুনর্নির্দেশের জন্য (ফাইল পুনর্নির্দেশ) ব্যবহার করে।command
tee
দ্বিতীয়টির জন্য একই জিনিস:
2> >(tee -a stderr.log >&2)
আমরা আবার প্রক্রিয়া প্রতিস্থাপন ব্যবহার করে এমন একটি tee
প্রক্রিয়া তৈরি করি যা এসটিডিআইএন থেকে পড়ে এবং এতে ফেলা হয় stderr.log
। tee
এর ইনপুটটি STDOUT এ ফিরে আসে, তবে যেহেতু এর ইনপুটটি আমাদের STDERR, তাই আমরা tee
এর STDOUT পুনরায় আমাদের STDERR এ পুনঃনির্দেশ করতে চাই । তারপরে আমরা ফাইলের পুনর্নির্দেশকে command
ফিফোর ইনপুট ( tee
এর এসটিডিএন) এ পুনঃনির্দেশ করতে ব্যবহার করি ।
Http://mywiki.wooledge.org/BashGuide/InputAndOutput দেখুন
প্রক্রিয়া প্রতিস্থাপন হ'ল সেই সত্যই সুন্দর জিনিসগুলির মধ্যে একটি যা আপনি bash
আপনার শেল হিসাবে বেছে নেওয়ার বোনাস হিসাবে পেয়েছেন sh
(পসিক্স বা বোর্ন)।
ইন sh
, আপনাকে ম্যানুয়ালি জিনিসগুলি করতে হবে:
out="${TMPDIR:-/tmp}/out.$$" err="${TMPDIR:-/tmp}/err.$$"
mkfifo "$out" "$err"
trap 'rm "$out" "$err"' EXIT
tee -a stdout.log < "$out" &
tee -a stderr.log < "$err" >&2 &
command >"$out" 2>"$err"
$ echo "HANG" > >(tee stdout.log) 2> >(tee stderr.log >&2)
যা কাজ করে তবে ইনপুটটির জন্য অপেক্ষা করে। এমনটা হওয়ার কোনও সাধারণ কারণ আছে কি?
/bin/bash 2> err
এবং/bin/bash -i 2> err
(echo "Test Out";>&2 echo "Test Err") > >(tee stdout.log) 2> >(tee stderr.log >&2)
কেন সহজভাবে না:
./aaa.sh 2>&1 | tee -a log
এটি কেবল পুনঃনির্দেশ stderr
করে stdout
, তাই টি লগ এবং স্ক্রিনে প্রতিধ্বনিত করে। হতে পারে আমি কিছু মিস করছি, কারণ অন্যান্য সমাধানগুলির মধ্যে কিছু সত্যিই জটিল বলে মনে হচ্ছে।
দ্রষ্টব্য: বাশ সংস্করণ 4 যেহেতু আপনি এর |&
জন্য সংক্ষেপণ হিসাবে ব্যবহার করতে পারেন 2>&1 |
:
./aaa.sh |& tee -a log
./aaa.sh |& tee aaa.log
কাজ করে (ব্যাশে)।
set -o pipefail
অনুসরণ করেন ;
বা &&
আমি ভুল না হয়ে থাকেন তবে আপনি প্রস্থান স্থিতি ধরে রাখতে পারবেন ।
এটি গুগলের মাধ্যমে এটির সন্ধানকারীদের জন্য দরকারী হতে পারে। আপনি যে উদাহরণটি ব্যবহার করতে চান তা কেবল অস্বীকার করুন। অবশ্যই আউটপুট ফাইলগুলির নাম পরিবর্তন করতে দ্বিধা বোধ করবেন।
#!/bin/bash
STATUSFILE=x.out
LOGFILE=x.log
### All output to screen
### Do nothing, this is the default
### All Output to one file, nothing to the screen
#exec > ${LOGFILE} 2>&1
### All output to one file and all output to the screen
#exec > >(tee ${LOGFILE}) 2>&1
### All output to one file, STDOUT to the screen
#exec > >(tee -a ${LOGFILE}) 2> >(tee -a ${LOGFILE} >/dev/null)
### All output to one file, STDERR to the screen
### Note you need both of these lines for this to work
#exec 3>&1
#exec > >(tee -a ${LOGFILE} >/dev/null) 2> >(tee -a ${LOGFILE} >&3)
### STDOUT to STATUSFILE, stderr to LOGFILE, nothing to the screen
#exec > ${STATUSFILE} 2>${LOGFILE}
### STDOUT to STATUSFILE, stderr to LOGFILE and all output to the screen
#exec > >(tee ${STATUSFILE}) 2> >(tee ${LOGFILE} >&2)
### STDOUT to STATUSFILE and screen, STDERR to LOGFILE
#exec > >(tee ${STATUSFILE}) 2>${LOGFILE}
### STDOUT to STATUSFILE, STDERR to LOGFILE and screen
#exec > ${STATUSFILE} 2> >(tee ${LOGFILE} >&2)
echo "This is a test"
ls -l sdgshgswogswghthb_this_file_will_not_exist_so_we_get_output_to_stderr_aronkjegralhfaff
ls -l ${0}
exec >
এর অর্থ, কোনও ফাইলের বর্ণনাকারীর লক্ষ্য নির্দিষ্ট গন্তব্যে নিয়ে যাওয়া। ডিফল্টটি 1, সুতরাং, exec > /dev/null
এই অধিবেশন থেকে এখন থেকে stdout এর আউটপুটটিকে / dev / null এ সরান। এই অধিবেশনটির জন্য বর্তমান ফাইল বর্ণনাকারী করে দেখা যায় ls -l /dev/fd/
। চেষ্টা করে দেখুন! তারপরে দেখুন যখন আপনি exec 2>/tmp/stderr.log.
অতিরিক্ত হিসাবে ইস্যু করবেন তখন কী হয় , এর exec 3>&1
অর্থ, 3 নম্বর সহ একটি নতুন ফাইল বর্ণনাকারী তৈরি করুন এবং এটি ফাইল বর্ণনাকারীর টার্গেটে পুনর্নির্দেশ করুন 1 উদাহরণস্বরূপ, কমান্ড জারি হওয়ার পরে লক্ষ্যটি পর্দা ছিল।
স্ট্যাডারকে কোনও ফাইলে পুনর্নির্দেশের জন্য, স্ক্রিনে স্টডআউট প্রদর্শন করুন এবং স্টডআউটকে একটি ফাইলে সংরক্ষণ করুন:
./aaa.sh 2> ccc.out | tee ./bbb.out
সম্পাদনা : স্ট্যাডার এবং স্টডআউট উভয়ই স্ক্রিনে প্রদর্শন করতে এবং উভয় কোনও ফাইলে সংরক্ষণ করতে, আপনি ব্যাশের আই / ও পুনঃনির্দেশ ব্যবহার করতে পারেন :
#!/bin/bash
# Create a new file descriptor 4, pointed at the file
# which will receive stderr.
exec 4<>ccc.out
# Also print the contents of this file to screen.
tail -f ccc.out &
# Run the command; tee stdout as normal, and send stderr
# to our file descriptor 4.
./aaa.sh 2>&4 | tee bbb.out
# Clean up: Close file descriptor 4 and kill tail -f.
exec 4>&-
kill %1
অন্য কথায়, আপনি স্টাডাউটকে একটি ফিল্টার ( tee bbb.out
) এবং স্টার্ডারকে অন্য ফিল্টারে ( tee ccc.out
) এ পাইপ করতে চান । অন্য কমান্ডে স্টডআউট ব্যতীত অন্য কোনও কিছুর পাইপ দেওয়ার কোনও স্ট্যান্ডার্ড উপায় নেই তবে ফাইল বিবরণকারীদের জাগল করে আপনি এটিকে ঘিরে কাজ করতে পারেন।
{ { ./aaa.sh | tee bbb.out; } 2>&1 1>&3 | tee ccc.out; } 3>&1 1>&2
এছাড়াও দেখুন কীভাবে গ্রেড স্ট্যান্ডার্ড ত্রুটি স্ট্রিম (স্টডার)? এবং কখন আপনি কোনও অতিরিক্ত ফাইল বর্ণনাকারী ব্যবহার করবেন?
ব্যাশে (এবং ksh এবং zsh), তবে ড্যাশের মতো অন্য পসিক্স শেলগুলিতে নয়, আপনি প্রক্রিয়া বিকল্প ব্যবহার করতে পারেন :
./aaa.sh > >(tee bbb.out) 2> >(tee ccc.out)
সাবধান! বাশ-এ, এই কমান্ডটি ./aaa.sh
শেষ হওয়ার সাথে সাথেই ফিরে আসবে , এমনকি যদি tee
কমান্ডগুলি এখনও কার্যকর করা হয় (ksh এবং zsh উপ-প্রক্রিয়াগুলির জন্য অপেক্ষা করে না)। আপনি যদি এমন কিছু করেন তবে সমস্যা হতে পারে ./aaa.sh > >(tee bbb.out) 2> >(tee ccc.out); process_logs bbb.out ccc.out
। সেক্ষেত্রে ফাইল বর্ণনাকারী জাগলিং বা এর পরিবর্তে ksh / zsh ব্যবহার করুন।
sh
, ক্রোন কাজের জন্য দরকারী, যেখানে প্রক্রিয়া প্রতিস্থাপন উপলব্ধ নয়।
যদি ব্যাশ ব্যবহার করা হয়:
# Redirect standard out and standard error separately
% cmd >stdout-redirect 2>stderr-redirect
# Redirect standard error and out together
% cmd >stdout-redirect 2>&1
# Merge standard error with standard out and pipe
% cmd 2>&1 |cmd2
ক্রেডিট (আমার মাথার উপরে থেকে উত্তর না) এখানে যায়: http://www.cygwin.com/ml/cygwin/2003-06/msg00772.html
আমার ক্ষেত্রে, একটি স্ক্রিপ্ট কমান্ড চালাচ্ছিল যখন স্টডআউট এবং স্ট্ডার উভয়ই একটি ফাইলে পুনর্নির্দেশ করছিল, এরকম কিছু:
cmd > log 2>&1
আমার এটি আপডেট করার দরকার ছিল যে যখন কোনও ব্যর্থতা হয় তখন ত্রুটি বার্তাগুলির উপর ভিত্তি করে কিছু পদক্ষেপ নেওয়া উচিত। আমি অবশ্যই ডুপটি সরিয়ে 2>&1
স্ক্রিপ্ট থেকে স্টডারকে ক্যাপচার করতে পারি তবে ত্রুটি বার্তাগুলি রেফারেন্সের জন্য লগ ফাইলে যাবে না। @ লুনাথের গৃহীত উত্তর একই কাজ করার কথা থাকলেও এটি পুনর্নির্দেশ করে stdout
এবং stderr
বিভিন্ন ফাইলগুলিতে, যা আমি চাই তা নয়, তবে এটি আমার সঠিক সমাধানটি সামনে আসতে আমাকে সহায়তা করেছিল:
(cmd 2> >(tee /dev/stderr)) > log
উপরোক্ত সঙ্গে, লগ উভয় একটি কপি থাকবে stdout
এবং stderr
আমি ক্যাপচার করতে পারেন stderr
সম্পর্কে চিন্তা না করেও আমার স্ক্রিপ্ট থেকে stdout
।
নিম্নলিখিতটি কর্নশেল (ksh) এর জন্য কাজ করবে যেখানে প্রক্রিয়া প্রতিস্থাপন উপলব্ধ নেই,
# create a combined(stdin and stdout) collector
exec 3 <> combined.log
# stream stderr instead of stdout to tee, while draining all stdout to the collector
./aaa.sh 2>&1 1>&3 | tee -a stderr.log 1>&3
# cleanup collector
exec 3>&-
এখানে বাস্তব কৌতুক, এর ক্রম 2>&1 1>&3
যা আমাদের ক্ষেত্রে পুননির্দেশনা stderr
করতে stdout
এবং পুননির্দেশনা stdout
বর্ণনাকারী থেকে 3
। এই মুহুর্তে stderr
এবং stdout
এখনও একত্রিত হয় না।
কার্যত, stderr
(যেমন stdin
) tee
এটি লগইন করা হয় stderr.log
এবং বর্ণনাকারী 3 এ পুনর্নির্দেশও করা হয়।
এবং 3
বিবরণকারী এটি সর্বদা লগ ইন করে combined.log
। সুতরাং combined.log
উভয় stdout
এবং থাকে stderr
।
আপনি যদি zsh ব্যবহার করছেন তবে আপনি একাধিক পুনঃনির্দেশগুলি ব্যবহার করতে পারেন, সুতরাং আপনার এমনকি প্রয়োজনও নেই tee
:
./cmd 1>&1 2>&2 1>out_file 2>err_file
এখানে আপনি কেবল প্রতিটি স্ট্রিমকে নিজের এবং লক্ষ্য ফাইলে পুনর্নির্দেশ করছেন ।
পুরো উদাহরণ
% (echo "out"; echo "err">/dev/stderr) 1>&1 2>&2 1>/tmp/out_file 2>/tmp/err_file
out
err
% cat /tmp/out_file
out
% cat /tmp/err_file
err
নোট করুন যে এটির জন্য MULTIOS
বিকল্পটি সেট করার প্রয়োজন (যা পূর্বনির্ধারিত)।
MULTIOS
একাধিক পুনঃনির্দেশ চেষ্টা করার সময় অন্তর্নিহিত
tee
গুলি বা সম্পাদন করুনcat
( পুনঃনির্দেশ দেখুন )।