পাঠকের সুবিধার জন্য, এই রেসিপিটি এখানে here
- ভেরিয়েবলের স্ট্যাডার ধরতে অনেলাইনার হিসাবে পুনরায় ব্যবহার করা যেতে পারে
- এখনও কমান্ডের রিটার্ন কোড অ্যাক্সেস দেয়
- একটি অস্থায়ী ফাইল বর্ণনাকারী 3 ত্যাগ করে (যা অবশ্যই আপনার দ্বারা পরিবর্তন করা যেতে পারে)
- এবং এই অস্থায়ী ফাইল বর্ণনাকারীদের অভ্যন্তরীণ কমান্ডের কাছে প্রকাশ করে না
আপনি ধরতে চান stderr
কিছু command
মধ্যে var
আপনি কি করতে পারেন
{ var="$( { command; } 2>&1 1>&3 3>&- )"; } 3>&1;
এরপরে আপনার সমস্ত কিছু রয়েছে:
echo "command gives $? and stderr '$var'";
যদি command
সহজ হয় (এর মতো কিছু নয় a | b
) তবে আপনি ভিতরের দিকটি ছেড়ে দিতে পারেন {}
:
{ var="$(command 2>&1 1>&3 3>&-)"; } 3>&1;
একটি সহজ পুনরায় ব্যবহারযোগ্য- bash
ফাংশনে আবৃত (সম্ভবত সংস্করণ 3 এবং এর জন্য উপরের প্রয়োজন local -n
):
: catch-stderr var cmd [args..]
catch-stderr() { local -n v="$1"; shift && { v="$("$@" 2>&1 1>&3 3>&-)"; } 3>&1; }
ব্যাখ্যা:
local -n
উপকরণ "$ 1" (যা এর জন্য পরিবর্তনশীল catch-stderr
)
3>&1
stdout পয়েন্টগুলি সংরক্ষণ করতে ফাইল বর্ণনাকারী 3 ব্যবহার করে
{ command; }
(বা "$ @") তারপরে আউটপুট ক্যাপচারের মধ্যে কমান্ডটি কার্যকর করে $(..)
- দয়া করে মনে রাখবেন যে সঠিক ক্রমটি এখানে গুরুত্বপূর্ণ (এটি ভুল উপায়ে ফাইল বর্ণনাকারীদের ভুলভাবে বদল করে):
2>&1
stderr
আউটপুট ক্যাপচারে পুনঃনির্দেশ করে$(..)
1>&3
stdout
আউটপুট থেকে $(..)
"বাইরের" stdout
যা ফাইল বিবরণীতে সংরক্ষণ করা হয়েছিল পুনরায় পুনর্নির্দেশ করে 3 নোট করুন যে stderr
এখনও উল্লেখ করে যেখানে এফডি 1 আগে চিহ্নিত হয়েছিল: আউটপুট ক্যাপচারিংয়ের দিকে$(..)
3>&-
তারপরে ফাইলের বিবরণী 3 বন্ধ করে দেয় কারণ এটির আর প্রয়োজন command
হয় না , যেমন হঠাৎ করে কোনও অজানা ফাইল ফাইল বিবরণী প্রদর্শিত না হয়। দ্রষ্টব্য যে বাইরের শেলটিতে এখনও এফডি 3 খোলা আছে, তবে command
তা দেখতে পাবে না।
- দ্বিতীয়টি গুরুত্বপূর্ণ, কারণ কিছু প্রোগ্রাম যেমন
lvm
অপ্রত্যাশিত ফাইল বর্ণনাকারীদের সম্পর্কে অভিযোগ করে। এবং lvm
অভিযোগ stderr
- আমরা কি ধরতে যাচ্ছি!
আপনি যদি সেই অনুসারে অভিযোজিত হন তবে আপনি এই রেসিপিটির সাথে অন্য কোনও ফাইল বর্ণনাকারী ধরতে পারেন। অবশ্যই ফাইল বর্ণনাকারী 1 ব্যতীত (এখানে পুনর্নির্দেশের যুক্তিটি ভুল হবে তবে ফাইল বর্ণনাকারী 1 এর জন্য আপনি কেবল var=$(command)
যথারীতি ব্যবহার করতে পারেন )।
নোট করুন যে এই কোরবানির ফাইল ফাইল বর্ণনাকারী ৩. যদি আপনার যদি সেই ফাইল বর্ণনাকারীর প্রয়োজন হয় তবে নির্দ্বিধায় এই সংখ্যাটি পরিবর্তন করুন। তবে সচেতন থাকুন যে কয়েকটি শেল (1980 এর দশক থেকে) অনুসরণ 99>&1
করা যুক্তি হিসাবে বুঝতে পারে (এটি কোনও সমস্যা নয় )।9
9>&1
bash
এছাড়াও নোট করুন যে কোনও ভেরিয়েবলের মাধ্যমে এই FD 3 কে কনফিগারযোগ্য করে তোলা সহজ নয়। এটি জিনিসগুলি খুব অপঠনযোগ্য করে তোলে:
: catch-var-from-fd-by-fd variable fd-to-catch fd-to-sacrifice command [args..]
catch-var-from-fd-by-fd()
{
local -n v="$1";
local fd1="$2" fd2="$3";
shift 3 || return;
eval exec "$fd2>&1";
v="$(eval '"$@"' "$fd1>&1" "1>&$fd2" "$fd2>&-")";
eval exec "$fd2>&-";
}
সুরক্ষা দ্রষ্টব্য: প্রথম 3 টি যুক্তি catch-var-from-fd-by-fd
অবশ্যই তৃতীয় পক্ষ থেকে নেওয়া উচিত নয়। সর্বদা তাদের "স্থিতিশীল" ফ্যাশনে স্পষ্টভাবে দিন give
না-না-না catch-var-from-fd-by-fd $var $fda $fdb $command
, কখনই না!
যদি আপনি কোনও ভেরিয়েবল ভেরিয়েবলের সাথে পাস করতে চান তবে কমপক্ষে এটি নিম্নরূপ করুন:
local -n var="$var"; catch-var-from-fd-by-fd var 3 5 $command
এটি আপনাকে প্রতিটি শোষণের বিরুদ্ধে রক্ষা করবে না, তবে কমপক্ষে কমপক্ষে সাধারণ স্ক্রিপ্টিং ত্রুটিগুলি সনাক্ত এবং এড়াতে সহায়তা করে।
মন্তব্য:
catch-var-from-fd-by-fd var 2 3 cmd..
হিসাবে একই catch-stderr var cmd..
shift || return
আপনি যদি যুক্তিগুলির সঠিক সংখ্যাটি দিতে ভুলে যান তবে কুরুচিপূর্ণ ত্রুটিগুলি রোধ করার কিছু উপায়। শেলটি বন্ধ করা অন্য উপায় হতে পারে (তবে এটি কমান্ডলাইন থেকে পরীক্ষা করা কঠিন করে তোলে)।
- রুটিনটি এমন লেখা হয়েছিল যে এটি বোঝা আরও সহজ। কেউ ফাংশনটি এমনভাবে পুনরায় লিখতে পারেন যাতে এটির প্রয়োজন হয় না
exec
তবে এটি সত্যই কদর্য হয়।
- এই রুটিনটি অ-
bash
পাশাপাশি যেমন প্রয়োজন নেই তখন আবার লিখতে পারে local -n
। তবে আপনি স্থানীয় ভেরিয়েবল ব্যবহার করতে পারবেন না এবং এটি অত্যন্ত কুৎসিত হয়!
- এছাড়াও লক্ষ করুন যে
eval
গুলি নিরাপদ ফ্যাশনে ব্যবহৃত হয়। সাধারণত eval
বিপজ্জনক হিসাবে বিবেচিত হয়। তবে এক্ষেত্রে এটি "$@"
(সালিশী আদেশগুলি কার্যকর করার জন্য) ব্যবহার করা ছাড়া আর মন্দ নয় । তবে দয়া করে এখানে প্রদর্শিত হিসাবে সঠিক এবং সঠিক উদ্ধৃতিটি ব্যবহার করার বিষয়ে নিশ্চিত হন (অন্যথায় এটি খুব বিপজ্জনক হয়ে ওঠে )।
ERROR=$(./useless.sh | sed 's/Output/Useless/' 2>&1 1>/dev/ttyX)