স্ক্রিনে কেবল স্ট্যাডার দেখান তবে স্টডআউট এবং স্টার্ডার উভয়ই ফাইলটিতে লিখুন


24

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

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


উত্তর:


14

এমনকি কোনও পুনঃনির্দেশ ছাড়াই, বা কিছুই ছাড়া >logfile 2>&1, আপনাকে প্রজন্মের ক্রম অনুযায়ী আউটপুট দেখার গ্যারান্টি দেওয়া হয় না।

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

"[টি] তিনি আদেশ দেন যে তারা ঘটবে" কেবলমাত্র অ্যাপ্লিকেশনটির জন্যই এটি পরিচিত। স্টাডাউট / স্ট্ডার জুড়ে আউটপুট অর্ডার করা একটি সুপরিচিত - ক্লাসিক, সম্ভবত - সমস্যা।


7

আপনি যখন নির্মাণটি ব্যবহার করবেন: stderr এবং stdout1>stdout.log 2>&1 উভয়ই ফাইলে পুনঃনির্দেশিত হয়ে যায় কারণ স্ট্যাডার পুনঃনির্দেশের আগে স্টাডআউট পুনঃনির্দেশ সেট আপ করা হয় ।

আপনি বিপরীতমুখী আপনি পেতে পারেন, তাহলে stdout- এ একটি ফাইল থেকে আপনাকে পুনঃনির্দেশিত এবং তারপর কপি দ্বারা stderr করার stdout- এ যাতে আপনি নল এটি করতে পারেন tee

$ cat test
#!/bin/sh
echo OUT! >&1
echo ERR! >&2

$ ./test 2>&1 1>stdout.log | tee stderr.log
ERR!

$ cat stdout.log
OUT!

$ cat stderr.log
ERR!

এটি আপনাকে একই ফাইলটিতে দুটি স্ট্রিম লগ করতে দেয় না।
শিল্পীেক্স

1
@artistoex: আপনি কেবল tee -aএকই ফাইলের সাথে একই ফাইলের 1>উভয় আউটপুট যোগ করতে ব্যবহার করতে পারেন । এর মতো কিছু:./test 2>&1 1>out+err.log | tee -a out+err.log
মোমোয়া

কেন জানি না, তবে এটি wget -O - www.google.deআমার পক্ষে কার্যকর হয় না। (নীচের সমাধানের সাথে তুলনা করুন)
শিল্পীপেক্স

4
tee -aকোনও কিছুই যদি পুনঃনির্দেশিত না হয় তবে একই আউটপুট যা কনসোলে থাকবে তা নির্ভরযোগ্যভাবে ব্যবহার করে না। আউটপুটটি যা যায় teeতা কমান্ড থেকে সরাসরি আসা আউটপুটটির সাথে তুলনা করে কিছুটা বিলম্বিত হতে পারে এবং লগে পরে প্রদর্শিত হতে পারে।
গিলস 20'৩ এ '

এটি আমার পক্ষে কাজ করে না, আউট + এরআরলগ খালি। এবং হ্যাঁ, আমি একই ফাইলটিতে স্টেডারর এবং স্ট্যান্ডার্ড চাই
আন্দ্রেয়াস

7

আমি নীচের লাইনটি ব্যাশ স্ক্রিপ্টের শীর্ষে রেখে এটি সম্পাদন করতে সক্ষম হয়েছি:

exec 1>>log 2> >(tee -a log >&2)

এটি স্টাডআউটটিকে ফাইলে log( 1>>log) ফাইলে ডাইরেক্ট করবে , তারপরে স্ট্যাডারকে ফাইলের log( 2> >(tee -a log) এ পুনরায় ডাইরেক্ট করবে এবং স্ট্যাডারকে ফিরিয়ে আনবে ( >&2)এই ভাবে, আমি একটি ফাইল পাই log, যা স্টাডআউট এবং স্ট্যাডার উভয়কে ক্রমানুসারে দেখায়, এবং স্টার্ডারও হয়) যথারীতি পর্দায় প্রদর্শিত

ক্যাচটি হ'ল এটি কেবলমাত্র যখন আমি ফাইলটিতে যুক্ত করি তখনই এটি কাজ করে work যদি আমি সংযোজন না করি তবে দেখা যাচ্ছে যে দুটি পুনর্নির্দেশগুলি একে অপরকে ক্লোবার করে এবং আমি কেবল যে কোনও ফলাফল শেষ করি last


একটি কাস্টম স্ট্রিং অন্তর্ভুক্ত করার জন্য এটি STDERR লাইনগুলিকে "সংশোধন" করার কোনও উপায় যাতে আপনি এটিতে সহজেই গ্রেপ করতে পারেন?
IMTheNachoMan

1

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

{ { echo out; echo err 1>&2; } 2>&1 >&3 | tee /dev/tty; } >log 3>&1
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^   ^^^^^^^^^^^^    ^^^^^^^^^
  command produces output      stdout3                    log
  command produces error       stderr1   dup to terminal  log

এটিও আমার পক্ষে বেশিরভাগ কাজ করে না, আমি প্রথমে স্টডআউট লাইনগুলি পাই এবং তারপরে 'লগ' ফাইলে সমস্ত স্টার্ডার লাইন পাই। উদাহরণ: cho {প্রতিধ্বনি; প্রতিধ্বনির ত্রুটি 1> & 2; প্রতিধ্বনি 2; ইকো এরর 2 1> & 2; } 2> & 1> & 3 | টি / দেব / টিটিআই; log> লগ 3> & 1
আন্দ্রেয়াস

1
@ আন্দ্রেস: ওহ, দুহ, teeএখানেও একটি বিলম্বের পরিচয় দেয়। আমি মনে করি না খাঁটি শেল সমাধান আছে। আসলে আমি আশ্চর্য হয়েছি যে কোনও উপায়ে অ্যাপ্লিকেশনটি সংশোধন না করেই কোনও সমাধান রয়েছে কিনা।
গিলস 21:38 এ '

1

স্ট্যান্ডার স্ক্রিনে লিখতে এবং উভয় স্ট্যাডার লিখতে এবং একটি ফাইলে স্টাডআউট লিখতে - এবং স্টার্ডার এবং স্টাডআউটের জন্য লাইনগুলি একই ক্রমে বেরিয়ে আসতে হবে যদি তারা উভয়ই পর্দায় লিখিত হয়:

একটি কঠিন সমস্যা হিসাবে পরিণত হয়েছে, বিশেষত "একই ক্রম" থাকা সম্পর্কে আপনি যে অংশটি আশা করবেন তা যদি আপনি কেবল স্ক্রিনে লিখে থাকেন। সহজ শর্তে: প্রত্যেককে তার নিজের ফাইলে লিখুন, লাইনটি তৈরি হওয়ার সঠিক সময়টি সহ প্রতিটি লাইন চিহ্নিত করতে কিছু পটভূমি-প্রক্রিয়া যাদু করুন (এবং প্রতিটি ফাইলের মধ্যে) এবং তারপরে: "লেজ - ফলো" স্ট্যাডার ফাইলটি স্ক্রিনে রেখে দিন , তবে উভয় "stderr" এবং "stdout" একসাথে দেখতে - ধারাবাহিকভাবে - দুটি ফাইল (প্রতিটি লাইনে সঠিক সময় চিহ্ন সহ) একসাথে বাছাই করুন।

কোড:

# Set the location of output and the "first name" of the log file(s)
pth=$HOME
ffn=my_log_filename_with_no_extension
date >>$pth/$ffn.out
date >>$pth/$ffn.err
# Start background processes to handle 2 files, by rewriting each one line-by-line as each line is added, putting a label at front of line
tail -f $pth/$ffn.out | perl -nle 'use Time::HiRes qw(time);print substr(time."0000",0,16)."|1|".$_' >>$pth/$ffn.out.txt &
tail -f $pth/$ffn.err | perl -nle 'use Time::HiRes qw(time);print substr(time."0000",0,16)."|2|".$_' >>$pth/$ffn.err.txt &
sleep 1
# Remember the process id of each of 2 background processes
export idout=`ps -ef | grep "tail -f $pth/$ffn.out" | grep -v 'grep' | perl -pe 's/\s+/\t/g' | cut -f2`
export iderr=`ps -ef | grep "tail -f $pth/$ffn.err" | grep -v 'grep' | perl -pe 's/\s+/\t/g' | cut -f2`
# Run the command, sending stdout to one file, and stderr to a 2nd file
bash mycommand.sh 1>>$pth/$ffn.out 2>>$pth/$ffn.err
# Remember the exit code of the command
myexit=$?
# Kill the two background processes
ps -ef | perl -lne 'print if m/^\S+\s+$ENV{"idout"}/'
echo kill $idout
kill $idout
ps -ef | perl -lne 'print if m/^\S+\s+$ENV{"iderr"}/'
echo kill $iderr
kill $iderr
date
echo "Exit code: $myexit for '$listname', list item# '$ix', bookcode '$bookcode'"

হ্যাঁ, এটি বিশদ বলে মনে হচ্ছে এবং এর ফলাফল 4 টি আউটপুট ফাইল (যার মধ্যে 2 টি আপনি মুছতে পারেন)। এটি প্রদর্শিত হচ্ছে এটি সমাধান করা একটি কঠিন সমস্যা, তাই এটি বেশ কয়েকটি প্রক্রিয়া গ্রহণ করেছে।

শেষ পর্যন্ত, আপনি যে অনুক্রমের প্রত্যাশা করবেন তার দুটি স্টাডাউট এবং স্টাডারের ফলাফলগুলি দেখতে এটি চালান:

cat $pth/$ffn.out.txt $pth/$ffn.err.txt | sort

ক্রমটি স্ট্যান্ডআউট এবং স্টেডার উভয়ই পর্দায় চলে যাওয়ায় এটি অন্তত খুব কাছাকাছি হওয়ার একমাত্র কারণ: প্রতিটি একক লাইনটি মিলিসেকেন্ডে টাইমস্ট্যাম্প সহ চিহ্নিত করা হয় with

প্রক্রিয়াটি চলার সাথে সাথে স্ক্রিনারে স্টার্ডার দেখতে এটি ব্যবহার করুন:

tail -f $pth/$ffn.out

আশা করি এটি কাউকে সাহায্য করবে, যিনি আসল প্রশ্ন জিজ্ঞাসা করার অনেক পরে এখানে এসেছিলেন।


নিখুঁত প্রচেষ্টার জন্য +1, আমার একটি অনুরূপ ধারণা ছিল (পার্লের মাধ্যমে উভয় স্ট্রিমের টাইমস্ট্যাম্পগুলি) তবে এটি বাস্তবায়নের জন্য সংগ্রাম করে যাচ্ছিলাম। এটি আমার পক্ষে কাজ করে কিনা তা তদন্ত করব (অর্থাত্ যদি এটি আউটপুটগুলির ক্রমটি ঠিক রাখে, অন্যরা সমাধান হিসাবে স্ট্যাডার এবং স্টাডাউটের ট্যাগিংয়ের মধ্যে অ্যাসিঙ্ক্রোনিকটির কারণে জিনিসগুলি কিছুটা স্থানান্তরিত করে)
অলিভিয়ার ডুলাক

0

দিন fকমান্ড তোমার মত কার্যকর করা চাই, তাহলে এই হতে

( exec 3>/tmp/log; f 2>&1 1>&3 |tee >(cat)>&3 )

আপনি যা চান তা আপনাকে দেওয়া উচিত উদাহরণস্বরূপ wget -O - www.google.deএটি দেখতে হবে:

( exec 3>/tmp/googlelog; wget -O - www.google.de 2>&1 1>&3 |tee >(cat)>&3 )

1
এটি প্রায় আমার জন্য কাজ করে তবে লগ ফাইলে আমি প্রথমে সমস্ত স্টাডআউট লাইন পাই এবং তারপরে সমস্ত স্টেডারর লাইন পাই। আমি চাই তারা এগুলি যেমন ঘটে থাকে প্রাকৃতিক ক্রমে অন্তর্বর্তী হয়।
আন্দ্রেয়াস

0

আমি এখানে যা পড়েছি তা প্রদত্ত, কেবলমাত্র সমাধানটি হ'ল টাইমলাইস / টাইমস্ট্যাম্পের সাথে স্টোউট বা স্টারআর প্রতিটি লাইনটি আগে থেকেই চালিত করা। তারিখ +% s সেকেন্ডে পেতে পারে তবে শৃঙ্খলা বজায় রাখতে ধীর হতে পারে। এছাড়াও লগ একরকম বাছাই করতে হবে। আমি সক্ষম চেয়ে বেশি কাজ।


0

আমি এই সঠিক প্রয়োজনের সাথে লড়াই করেছি এবং শেষ পর্যন্ত কোনও সহজ সমাধান খুঁজে পেল না। পরিবর্তে আমি যা করে শেষ করেছি তা হ'ল:

TMPFILE=/tmp/$$.log
myCommand > $TMPFILE 2>&1
[ $? != 0 ] && cat $TMPFILE
date >> myCommand.log
cat $TMPFILE >> myCommand.log
rm -f $TMPFILE

এটি স্টাডাউট এবং স্ট্ডার যুক্ত করে সঠিক আন্তঃবাহিত ক্রমে, লগ ফাইলে। এবং যদি কোনও ত্রুটি ঘটে (কমান্ডের প্রস্থান স্থিতি দ্বারা নির্ধারিত হিসাবে), এটি সম্পূর্ণ আউটপুট (স্টাডআউট এবং স্ট্ডার) স্ট্যাডআউটে পুনরায় প্রেরণ করে যথাযথ আন্তঃবাহিত ক্রমে। আমি এটি আমার প্রয়োজনের জন্য যুক্তিসঙ্গত আপস বলে মনে করেছি। আপনি যদি ক্রমবর্ধমান একাধিক রানের চেয়ে একক রান চালানোর লগ ফাইল চান তবে এটি আরও সহজ:

myCommand > myCommand.log 2>&1
[ $? != 0 ] && cat myCommand.log

0

স্ট্যান্ডার থেকে কমান্ড-প্রতিস্থাপিত tee -a, এবং stdout একই ফাইলে সংযুক্ত:

./script.sh 2> >(tee -a outputfile) >>outputfile

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

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