আদেশযুক্ত STDOUT / STDERR কীভাবে ক্যাপচার করবেন এবং টাইমস্ট্যাম্প / উপসর্গ যুক্ত করবেন?


25

আমি প্রায় সমস্ত উপলভ্য অনুরূপ প্রশ্নগুলি অনুসন্ধান করেছি , কোনও ফলস্বরূপ।

সমস্যাটি বিস্তারিতভাবে বর্ণনা করি:

আমি কিছু অপ্রচলিত স্ক্রিপ্টগুলি চালিত করি এবং এটি স্ট্যান্ডার্ড আউটপুট এবং স্ট্যান্ডার্ড ত্রুটি লাইন তৈরি করতে পারে, আমি তাদের টার্মিনাল এমুলেটর দ্বারা প্রদর্শিত হিসাবে তাদের যথাযথ ক্রমে ক্যাপচার করতে চাই এবং তারপরে তাদের কাছে "STDERR:" এবং "STDOUT:" এর মতো একটি উপসর্গ যুক্ত করতে চাই।

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

আদর্শভাবে আমি এটি সম্পাদন করতে বাশের পরিবর্তে গো ব্যবহার করব , তবে আমি সক্ষম হইনি। বাফারিংয়ের কারণে পাইপগুলি স্বয়ংক্রিয়ভাবে সঠিক লাইনের ক্রম রাখতে নিষেধ করে।

কেউ কি এরকম কিছু করতে পেরেছেন? নাকি এটা কি অসম্ভব? আমি মনে করি যে যদি টার্মিনাল এমুলেটর এটি করতে পারে তবে তা নয় - সম্ভবত একটি ছোট সি প্রোগ্রাম তৈরি করে পিটিওয়াই (গুলি) আলাদাভাবে পরিচালনা করবে?

আদর্শভাবে আমি এই 2 টি স্ট্রিম (এসটিডিআউট এবং এসটিডিআরআর) পড়ার জন্য অ্যাসিঙ্ক্রোনাস ইনপুট ব্যবহার করব এবং তারপরে সেগুলি আমার প্রয়োজনীয়তার পরে পুনরায় মুদ্রণ করব, তবে ইনপুট ক্রমটি অত্যন্ত গুরুত্বপূর্ণ!

দ্রষ্টব্য: আমি স্টার্ডার্ড সম্পর্কে সচেতন তবে এটি আমার পক্ষে ব্যাশ স্ক্রিপ্টগুলির সাথে কাজ করে না এবং একটি উপসর্গ যুক্ত করার জন্য সহজেই সম্পাদনা করা যায় না (যেহেতু এটি মূলত প্রচুর পরিমাণে স্কাইস্কেলগুলি আবৃত করে)।

আপডেট: দুটি গিস্ট নীচে যোগ করা হয়েছে

(ধারাবাহিক ফলাফল প্রমাণ করতে আমি সরবরাহ করা নমুনা স্ক্রিপ্টে উপ-দ্বিতীয় এলোমেলো বিলম্বগুলি যুক্ত করা যেতে পারে)

আপডেট: @ গিলিস উল্লেখ করেছেন, এই প্রশ্নের সমাধানও এই অন্যান্য প্রশ্নের সমাধান করবে । তবে আমি এই সিদ্ধান্তে পৌঁছেছি যে এখানে এবং সেখানে যা চাওয়া হয়েছে তা করা সম্ভব নয়2>&1উভয় স্ট্রিম ব্যবহার করার সময় সঠিকভাবে পিটিআই / পাইপ স্তরে মার্জ করা হয় তবে স্ট্রিমগুলি পৃথকভাবে এবং সঠিক ক্রমে ব্যবহার করার জন্য সত্যই স্টেয়ার্ডের পদ্ধতির ব্যবহার করা উচিত যা সিস্টোল হুকিংকে আহ্বান করে এবং বিভিন্ন উপায়ে নোংরা হিসাবে দেখা যায়।

উপরের কেউ যদি আপত্তি জানাতে পারে তবে আমি এই প্রশ্নটি আপডেট করতে আগ্রহী।


1
এটি কি আপনি চান না? stackoverflow.com/questions/21564/…
slm

@ এসএমএল সম্ভবত না, যেহেতু ওপিকে বিভিন্ন স্ট্রিমে বিভিন্ন স্ট্রিং প্রিপেন্ড করা দরকার ।
পিটারফ

অর্ডারটি কেন এত গুরুত্বপূর্ণ তা আপনি ভাগ করে নিতে পারেন? আপনার সমস্যাটি ঘিরে অন্য কোনও উপায় থাকতে পারে ...
পেরিটার্ফ

@ পিটারফ এটি পূর্বশর্ত, যদি আমার ধারাবাহিক আউটপুট না পাওয়া যায় তবে আমি এটি পড়ার চেয়ে এটি / dev / নালকে প্রেরণ করব এবং এতে বিভ্রান্ত হব :) 2> & 1 উদাহরণস্বরূপ অর্ডার সংরক্ষণ করে, তবে এই ধরণের অনুমতি দেয় না কাস্টমাইজেশন যা আমি এই প্রশ্নে জিজ্ঞাসা করি
Deim0s

উত্তর:


12

আপনি কপ্রোসেস ব্যবহার করতে পারেন। সরল মোড়ক যা প্রদত্ত কমান্ডের উভয় আউটপুট দু'টি sedদৃষ্টান্তে সরবরাহ করে ( অন্যটির জন্য অন্যটির stderrজন্য stdout), যা ট্যাগিং করে।

#!/bin/bash
exec 3>&1
coproc SEDo ( sed "s/^/STDOUT: /" >&3 )
exec 4>&2-
coproc SEDe ( sed "s/^/STDERR: /" >&4 )
eval $@ 2>&${SEDe[1]} 1>&${SEDo[1]}
eval exec "${SEDo[1]}>&-"
eval exec "${SEDe[1]}>&-"

কয়েকটি জিনিস নোট করুন:

  1. এটি অনেক লোকের জন্য (আমাকে সহ) একটি যাদুর উদ্দীপনা - একটি কারণে (নীচে লিঙ্কিত উত্তরটি দেখুন)।

  2. কোনও গ্যারান্টি নেই যা এটি মাঝেমধ্যে দু'একটি লাইন অদলবদল করবে না - এটি সমস্ত নির্ভর করে ক্রেসোসেসগুলির সময় নির্ধারণের উপর। প্রকৃতপক্ষে, এটি প্রায় গ্যারান্টিযুক্ত যে এটি সময়ে যে কোনও সময় এটি করবে। তাই বলা হয় অর্ডার কঠোরভাবে একই পালন করলে আপনাকে হয়ত উভয় থেকে তথ্য প্রক্রিয়া করতে হবে, stderrএবং stdin, একই প্রক্রিয়ায় অন্যথায় কার্নেল নির্ধারণকারী করতে পারেন (এবং হবে) এটি একটি জগাখিচুড়ি ভুলবেন না।

    যদি আমি সমস্যাটি সঠিকভাবে বুঝতে পারি তবে এর অর্থ হ'ল উভয় প্রবাহকে একটি প্রক্রিয়াতে পুনঃনির্দেশ করার জন্য আপনাকে শেলটি নির্দেশ করতে হবে (যা এএফআইকে করা যেতে পারে)। সমস্যাটি তখন শুরু হয় যখন প্রথমে কোনটি প্রয়োগ করা উচিত তা সিদ্ধান্ত নেওয়া শুরু করে - এটি উভয় ডেটা উত্সকেই পোল করতে হবে এবং এক পর্যায়ে এমন অবস্থায় পৌঁছাতে হবে যেখানে এটি একটি প্রবাহকে প্রক্রিয়াজাত করবে এবং ডেটা শেষ হওয়ার আগে উভয় প্রবাহে পৌঁছে যাবে। এবং ঠিক সেখানেই এটি ভেঙে যায়। এর অর্থ এটিও হ'ল আউটপুট সিস্কলগুলির মতো মোড়ানো stderredসম্ভবত আপনার কাঙ্ক্ষিত ফলাফল অর্জনের একমাত্র উপায় (এবং তারপরেও কোনও কিছু মাল্টিপ্রেসেসর সিস্টেমে মাল্টিথ্রেড হয়ে যাওয়ার পরে আপনার সমস্যা হতে পারে)।

যতক্ষণ না কোপ্রোসেসেস স্ট্যাফেনের দুর্দান্ত উত্তরটি পড়তে ভুলবেন না আপনি কীভাবে বাশ-এ কপোক্রোক আদেশটি ব্যবহার করবেন? গভীরতা অন্তর্দৃষ্টি জন্য।


আপনার জবাবের জন্য @ পেটারফ ধন্যবাদ, তবে আমি অর্ডার সংরক্ষণের জন্য বিশেষভাবে খুঁজছি। দ্রষ্টব্য: আমি মনে করি আপনার ব্যবহারকারীর বিকল্প বিকল্পটি ব্যবহার করার কারণে আপনার দোভাষীকে বাশ করা উচিত (আমি ./test1.sh: 3: ./test1.sh: Syntax error: "(" unexpectedআপনার স্ক্রিপ্টটি অনুলিপি / আটকানোর মাধ্যমে
পেয়েছি

খুব সম্ভবত তাই, আমি এটি bashনিয়ে ছুটে এসেছি /bin/sh(আমি কেন এটি পেয়েছি তা নিশ্চিত নয়)।
পিটারফ

স্ট্রিমের মিশ্রণটি কোথায় ঘটতে পারে সে সম্পর্কে আমি প্রশ্নটি কিছুটা আপডেট করেছি।
পিটার্ফ

1
eval $@বেশ বগি। ব্যবহারের "$@"যদি আপনি একটি সঠিক কমান্ড লাইন হিসাবে আপনার আর্গুমেন্ট চালাতে চান - একটি স্তর যোগ evalব্যাখ্যা, হার্ড টু ভবিষ্যদ্বাণী করা (এবং সম্ভাব্য ক্ষতিকারক একটি গুচ্ছ মধ্যে ছোঁড়ার আপনি ফাইলের নামের বা অন্যান্য সামগ্রী হিসাবে আপনি নিয়ন্ত্রণ না পার করছি যুক্তি) আচরণ, এবং এমনকি আরও উদ্ধৃতি দিতে ব্যর্থ (একাধিক শব্দের মধ্যে স্পেস দিয়ে নামগুলি বিভক্ত করে, গ্লোবগুলি প্রসারিত করে এমনকি তাদের পূর্বে আক্ষরিক, ইত্যাদি হিসাবে উদ্ধৃত করা হয়েছিল)।
চার্লস ডাফি

1
এছাড়াও, আধুনিক-পর্যাপ্ত-টু-হ্যা-কোপ্রোসেসেস ব্যাশে, আপনার কোনও ভেরিয়েবলের নামক ফাইল বর্ণনাকারী বন্ধ করার দরকার নেই evalexec {SEDo[1]}>&-যেমনটি কাজ করবে (হ্যাঁ, ইচ্ছাকৃতভাবে এর $আগে {কোনওটির অভাব )।
চার্লস ডাফি

5

পদ্ধতি # 1। ফাইল বর্ণনাকারী এবং awk ব্যবহার করে

শিরোনামে এই এসও প্রশ্নোত্তর থেকে সমাধানগুলি ব্যবহার করে এরকম কিছু সম্পর্কে কী বলা যায়: পাঠ্যের লাইনে টাইমস্ট্যাম্পগুলি পুনরায় সরবরাহ করার জন্য কি কোনও ইউনিক্স ইউটিলিটি আছে? এবং এই SO প্রশ্নোত্তর শিরোনাম: পাইপ STDOUT এবং STDERR শেল স্ক্রিপ্টে দুটি পৃথক প্রক্রিয়া?

অভিগমন

পদক্ষেপ 1, আমরা ব্যাশে 2 টি ফাংশন তৈরি করি যা কল করার সময় টাইমস্ট্যাম্প বার্তাটি সম্পাদন করবে:

$ msgOut () {  awk '{ print strftime("STDOUT: %Y-%m-%d %H:%M:%S"), $0; fflush(); }'; }
$ msgErr () {  awk '{ print strftime("STDERR: %Y-%m-%d %H:%M:%S"), $0; fflush(); }'; }

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

$ { { { ...command/script... } 2>&3; } 2>&3 | msgErr; } 3>&1 1>&2 | msgOut

উদাহরণ

এখানে আমি একটি উদাহরণ aলিখেছি যা STDOUT এ লিখবে, 10 সেকেন্ডের জন্য ঘুমাবে, এবং তারপরে STDERR এ আউটপুট লিখবে। যখন আমরা এই কমান্ডের অনুক্রমটিকে উপরে আমাদের কনস্ট্রাক্টে রাখি আমরা আপনার নির্দিষ্ট হিসাবে ম্যাসেজিং পাই।

$ { { echo a; sleep 10; echo >&2 b; } 2>&3 | \
    msgErr; } 3>&1 1>&2 | msgOut
STDERR: 2014-09-26 09:22:12 a
STDOUT: 2014-09-26 09:22:22 b

পদ্ধতি # 2। টিকা-আউটপুট ব্যবহার করা হচ্ছে

প্যাকেজের annotate-outputঅংশ বলে একটি সরঞ্জাম রয়েছে devscriptsযা আপনি যা চান তা করবে। এটি কেবলমাত্র সীমাবদ্ধতা হ'ল এটি অবশ্যই আপনার জন্য স্ক্রিপ্টগুলি চালায়।

উদাহরণ

যদি আমরা আমাদের উপরের উদাহরণ কমান্ড সিকোয়েন্সটিকে এমন স্ক্রিপ্টে রাখি mycmds.bashযাতে:

$ cat mycmds.bash 
#!/bin/bash

echo a
sleep 10
echo >&2 b

এরপরে আমরা এটির মতো চালাতে পারি:

$ annotate-output ./mycmds.bash 
09:48:00 I: Started ./mycmds.bash
09:48:00 O: a
09:48:10 E: b
09:48:10 I: Finished with exitcode 0

আউটপুট ফর্ম্যাটটি টাইমস্ট্যাম্প অংশের জন্য নিয়ন্ত্রণ করা যেতে পারে তবে এর বাইরে নয়। তবে আপনি যা খুঁজছেন তা এটির মতোই আউটপুট, যাতে এটি বিলের সাথে খাপ খায়।


1
দুর্ভাগ্যক্রমে এটি সম্ভবত কিছু লাইন অদলবদলের সমস্যাও সমাধান করে না।
পিটার্ফ

ঠিক। আমার মনে হয় আমার এই প্রশ্নের উত্তর "সম্ভব নয়"। stderredআপনার সাথে ইভেন্টগুলি সহজেই লাইনের সীমানা নির্ধারণ করতে পারে না (তাই চেষ্টা করা হ্যাকিশ হবে)। আমি দেখতে চেয়েছিলাম যে কেউ এই সমস্যায় আমাকে সহায়তা করতে পারে তবে দৃশ্যত প্রত্যেকেই একক বাধা ( আদেশ ) ছেড়ে দিতে চায় যে প্রশ্নের মূল ভিত্তি
Deim0s

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