কোনও চলকটিতে স্ট্যান্ডার্ড ত্রুটি কীভাবে সংরক্ষণ করা যায়


181

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

useless.sh

echo "This Is Error" 1>&2
echo "This Is Output" 

এবং আমার কাছে আরও একটি শেল স্ক্রিপ্ট রয়েছে:

alsoUseless.sh

./useless.sh | sed 's/Output/Useless/'

আমি "ইজ ইজ ইজ ত্রুটি", বা বেকর্ড.শ থেকে অন্য কোনও স্টাডারকে একটি চলকতে ক্যাপচার করতে চাই। আসুন একে ERROR বলি।

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

সুতরাং, মূলত, আমি করতে চাই

./useless.sh 2> $ERROR | ...

কিন্তু এটি স্পষ্টতই কাজ করে না।

আমি এটাও করতে পারি যে আমি করতে পারি

./useless.sh 2> /tmp/Error
ERROR=`cat /tmp/Error`

তবে এটি কুৎসিত এবং অপ্রয়োজনীয়।

দুর্ভাগ্যক্রমে, যদি এখানে কোনও উত্তর না আসে তবে আমি এটি করতে যাচ্ছি।

আমি আশা করছি অন্য উপায় আছে।

কারও কি আরও ভাল ধারণা আছে?


4
স্টাডাউট ঠিক কি জন্য ব্যবহার করতে চান? আপনি কি এটি কনসোলে সহজেই দেখতে চান? অথবা আপনি এর আউটপুট ক্যাপচার / পুনঃনির্দেশ করছেন? যদি এটি কেবল কনসোলের দিকে থাকে তবে আপনি স্ট্যান্ডআউটকে কনসোল এবং রিডারকে স্টেডআর এটিকে ক্যাপচার করতে পুনঃনির্দেশ করুন:ERROR=$(./useless.sh | sed 's/Output/Useless/' 2>&1 1>/dev/ttyX)
টিম কার্স্টেন

উত্তর:


91

ত্রুটি ফাইলটি এভাবে ক্যাপচার করা আরও পরিষ্কার হবে:

ERROR=$(</tmp/Error)

শেলটি এটি সনাক্ত করে catএবং ডেটা পেতে ' ' চালাতে হবে না।

বড় প্রশ্নটি শক্ত। এটি করার সহজ উপায় আছে বলে আমি মনে করি না। আপনাকে পুরো পাইপলাইনটি সাব-শেলের মধ্যে তৈরি করতে হবে, শেষ পর্যন্ত একটি চূড়ান্ত স্ট্যান্ডার্ড আউটপুট একটি ফাইলে প্রেরণ করা হবে, যাতে আপনি ত্রুটিগুলি স্ট্যান্ডার্ড আউটপুটে পুনর্নির্দেশ করতে পারেন।

ERROR=$( { ./useless.sh | sed s/Output/Useless/ > outfile; } 2>&1 )

নোট করুন যে আধা-কোলন প্রয়োজন (ক্লাসিক শাঁসগুলিতে - বোর্ন, কর্ন - নিশ্চিতভাবে; সম্ভবত বাশেও)। '' {}'সংযুক্ত কমান্ডগুলির উপরে I / O পুনঃনির্দেশ করে। লিখিত হিসাবে, এটি sedখুব ত্রুটি ক্যাপচার করবে ।

সতর্কতা: সাধারণভাবে অনির্যুক্ত কোড - নিজের ঝুঁকিতে ব্যবহার করুন।


1
আমি আশা করেছিলাম এমন কিছু সত্যই ক্রেজিট ট্রিক হবে যা আমি জানতাম না, তবে মনে হচ্ছে এটি এটি is ধন্যবাদ।
সাইকোটিকা 0

9
যদি আপনার স্ট্যান্ডার্ড আউটপুটটির প্রয়োজন না হয় তবে আপনি এটির /dev/nullপরিবর্তে এটিকে পুনর্নির্দেশ করতে পারেন outfile(আপনি যদি আমার মতো হন তবে আপনি গুগলের মাধ্যমে এই প্রশ্নটি পেয়েছেন, এবং ওপি-র মতো প্রয়োজনীয়তা নেই)
মার্ক এরিচ

2
অস্থায়ী ফাইল ছাড়াই একটি উত্তরের জন্য, এখানে দেখুন
টম হেল

1
এখানে ফাইলগুলিতে এটা পুনঃনির্দেশিত ছাড়া এটা করতে একটি উপায়; এটা সোয়াপিং খেলেন stdoutএবং stderrবের এবং ফিরে। তবে সাবধান , যেমন এখানে বলা হয়েছে:
ব্যাশে

69

alsoUseless.sh

এটি আপনাকে আপনার useless.shস্ক্রিপ্টের আউটপুট পাইপ করতে দেয় যেমন কমান্ডের মাধ্যমে sedএবং stderrনামের সাথে একটি ভেরিয়েবল সংরক্ষণ করে error। পাইপের ফলাফল stdoutপ্রদর্শনের জন্য পাঠানো হয় বা অন্য কমান্ডে পাইপ করা হয়।

এটি করার জন্য প্রয়োজনীয় পুনর্নির্দেশগুলি পরিচালনা করতে এটি বেশ কয়েকটি অতিরিক্ত ফাইল বর্ণনাকারী সেট আপ করে।

#!/bin/bash

exec 3>&1 4>&2 #set up extra file descriptors

error=$( { ./useless.sh | sed 's/Output/Useless/' 2>&4 1>&3; } 2>&1 )

echo "The message is \"${error}.\""

exec 3>&- 4>&- # release the extra file descriptors

4
ফাইল বর্ণনাকারী সেট এবং বন্ধ করতে 'এক্সিকিউট' ব্যবহার করা ভাল কৌশল। স্ক্রিপ্টটি তত্ক্ষণাত বন্ধ হয়ে গেলে সত্যিই ঘনিষ্ঠতার দরকার নেই।
জোনাথন লেফলার

3
আমি উভয় stderrএবং stdoutভেরিয়েবল ক্যাপচার করব ?
জিঙ্গি

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

1
@ t00bs: readপাইপ থেকে ইনপুট গ্রহণ করে না। আপনি যা প্রদর্শনের চেষ্টা করছেন তা অর্জন করতে আপনি অন্যান্য কৌশল ব্যবহার করতে পারেন।
পরবর্তী বিজ্ঞপ্তি না দেওয়া পর্যন্ত বিরতি দেওয়া হয়েছে।

2
সহজ হতে পারে, এর সাথে: ত্রুটি = $ (./useless.sh | সেডস / আউটপুট / অপব্যবহার / '2> & 1 1> এবং 3)
জোসলিন

63

স্টার্ডারকে স্টাডাউটে পুনর্নির্দেশ, স্ট্যান্ডআউটে টু / ডিভ / নাল, এবং তারপরে ব্যাকটিক্স ব্যবহার করতে বা $()পুনঃনির্দেশিত স্টডারকে ক্যাপচার করতে:

ERROR=$(./useless.sh 2>&1 >/dev/null)

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

যে কমান্ডগুলি কেবল স্ট্ডারকে আউটপুট প্রেরণ করে, তাদের ক্যাপচার করার সহজ উপায়টি উদাহরণস্বরূপPY_VERSION="$(python --version 2>&1)"
জন মার্ক

9

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

if result=$(useless.sh 2>&1); then
    stdout=$result
else
    rc=$?
    stderr=$result
fi

সাধারণ দৃশ্যের জন্য কাজ করে যেখানে আপনি সাফল্যের ক্ষেত্রে যথাযথ আউটপুট আশা করতে পারেন, বা ব্যর্থতার ক্ষেত্রে স্ট্যাডারের উপর একটি ডায়াগনস্টিক বার্তা।

মনে রাখবেন যে শেলের নিয়ন্ত্রণ বিবৃতি ইতিমধ্যে $?হুডের নীচে পরীক্ষা করে; তাই দেখতে যা কিছু

cmd
if [ $? -eq 0 ], then ...

এটি কেবল একটি আনাড়ি, একঘেয়েমি বলার উপায়

if cmd; then ...

এটি আমার জন্য কাজ করেছে: my_service_status = $ (পরিষেবা_আর_তুল্য অবস্থা 2> এবং 1) ধন্যবাদ !!
জে রিচার্ডস্জ

6
# command receives its input from stdin.
# command sends its output to stdout.
exec 3>&1
stderr="$(command </dev/stdin 2>&1 1>&3)"
exitcode="${?}"
echo "STDERR: $stderr"
exit ${exitcode}

1
commandএখানে একটি খারাপ পছন্দ, কারণ আসলে এই নামে একটি বিল্টিন রয়েছে। yourCommandআরও স্পষ্ট করার জন্য এটি বা এ জাতীয় তৈরি করতে পারে।
চার্লস ডাফি

4

পাঠকের সুবিধার জন্য, এই রেসিপিটি এখানে 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>&1stderrআউটপুট ক্যাপচারে পুনঃনির্দেশ করে$(..)
    • 1>&3stdoutআউটপুট থেকে $(..)"বাইরের" stdoutযা ফাইল বিবরণীতে সংরক্ষণ করা হয়েছিল পুনরায় পুনর্নির্দেশ করে 3 নোট করুন যে stderrএখনও উল্লেখ করে যেখানে এফডি 1 আগে চিহ্নিত হয়েছিল: আউটপুট ক্যাপচারিংয়ের দিকে$(..)
    • 3>&-তারপরে ফাইলের বিবরণী 3 বন্ধ করে দেয় কারণ এটির আর প্রয়োজন commandহয় না , যেমন হঠাৎ করে কোনও অজানা ফাইল ফাইল বিবরণী প্রদর্শিত না হয়। দ্রষ্টব্য যে বাইরের শেলটিতে এখনও এফডি 3 খোলা আছে, তবে commandতা দেখতে পাবে না।
    • দ্বিতীয়টি গুরুত্বপূর্ণ, কারণ কিছু প্রোগ্রাম যেমন lvmঅপ্রত্যাশিত ফাইল বর্ণনাকারীদের সম্পর্কে অভিযোগ করে। এবং lvmঅভিযোগ stderr- আমরা কি ধরতে যাচ্ছি!

আপনি যদি সেই অনুসারে অভিযোজিত হন তবে আপনি এই রেসিপিটির সাথে অন্য কোনও ফাইল বর্ণনাকারী ধরতে পারেন। অবশ্যই ফাইল বর্ণনাকারী 1 ব্যতীত (এখানে পুনর্নির্দেশের যুক্তিটি ভুল হবে তবে ফাইল বর্ণনাকারী 1 এর জন্য আপনি কেবল var=$(command)যথারীতি ব্যবহার করতে পারেন )।

নোট করুন যে এই কোরবানির ফাইল ফাইল বর্ণনাকারী ৩. যদি আপনার যদি সেই ফাইল বর্ণনাকারীর প্রয়োজন হয় তবে নির্দ্বিধায় এই সংখ্যাটি পরিবর্তন করুন। তবে সচেতন থাকুন যে কয়েকটি শেল (1980 এর দশক থেকে) অনুসরণ 99>&1করা যুক্তি হিসাবে বুঝতে পারে (এটি কোনও সমস্যা নয় )।99>&1bash

এছাড়াও নোট করুন যে কোনও ভেরিয়েবলের মাধ্যমে এই 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বিপজ্জনক হিসাবে বিবেচিত হয়। তবে এক্ষেত্রে এটি "$@"(সালিশী আদেশগুলি কার্যকর করার জন্য) ব্যবহার করা ছাড়া আর মন্দ নয় । তবে দয়া করে এখানে প্রদর্শিত হিসাবে সঠিক এবং সঠিক উদ্ধৃতিটি ব্যবহার করার বিষয়ে নিশ্চিত হন (অন্যথায় এটি খুব বিপজ্জনক হয়ে ওঠে )।

3

আমি এটি কীভাবে করেছি তা এখানে:

#
# $1 - name of the (global) variable where the contents of stderr will be stored
# $2 - command to be executed
#
captureStderr()
{
    local tmpFile=$(mktemp)

    $2 2> $tmpFile

    eval "$1=$(< $tmpFile)"

    rm $tmpFile
}

ব্যবহারের উদাহরণ:

captureStderr err "./useless.sh"

echo -$err-

এটি একটি অস্থায়ী ফাইল ব্যবহার করে । তবে কমপক্ষে কুরুচিপূর্ণ জিনিসগুলি কোনও ফাংশনে আবৃত থাকে।


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

@ স্টেফান চিয়ারস, এটি এখানেও আলোচনা করা হয়েছে । :)
শ্যাডো উইজার্ড আপনার পক্ষে

1
এটি করার চেয়ে নিরাপদ উপায় আছে eval। উদাহরণস্বরূপ, printf -v "$1" '%s' "$(<tmpFile)"যদি আপনার TMPDIRভেরিয়েবলটি দূষিত মানের (অথবা আপনার গন্তব্য ভেরিয়েবলের নামের মধ্যে একটি মান থাকে) সেট করা থাকে তবে নির্বিচারে কোড চালনার ঝুঁকি নেবে না ।
চার্লস ডাফি

1
তেমনি, rm -- "$tmpFile"আরও শক্তিশালী rm $tmpFile
চার্লস ডাফি

2

এটি একটি আকর্ষণীয় সমস্যা যার প্রতি আমি আশা করি এখানে একটি মার্জিত সমাধান রয়েছে। দুঃখের বিষয়, আমি মিঃ লেফ্লারের মতো একই সমাধানটি শেষ করেছি, তবে আমি যুক্ত করব যে আপনি উন্নত পাঠযোগ্যতার জন্য বাশ ফাংশনটির ভিতরে থেকে অকেজো কল করতে পারেন:

#! / বিন / ব্যাশ

অকেজো ফাংশন
    /tmp/useless.sh | সেড / আউটপুট / অকেজো /
}

ত্রুটি = $ (বেহুদা)
প্রতিধ্বনি $ ত্রুটি

অন্য সমস্ত ধরণের আউটপুট পুনঃনির্দেশকে অবশ্যই একটি অস্থায়ী ফাইল দ্বারা ব্যাক করা উচিত।


2

POSIX

STDERR কিছু পুনর্নির্দেশ যাদু দ্বারা ক্যাপচার করা যেতে পারে:

$ { error=$( { { ls -ld /XXXX /bin | tr o Z ; } 1>&3 ; } 2>&1); } 3>&1
lrwxrwxrwx 1 rZZt rZZt 7 Aug 22 15:44 /bin -> usr/bin/

$ echo $error
ls: cannot access '/XXXX': No such file or directory

নোট করুন যে কমান্ডের STDOUT এর পাইপিং (এখানে ls) অন্তঃস্থরের ভিতরে করা হয় { }। যদি আপনি একটি সাধারণ কমান্ড কার্যকর করেন (যেমন, পাইপ নয়) তবে আপনি এই অভ্যন্তরীণ ধনুর্বন্ধনীগুলি সরিয়ে ফেলতে পারেন।

আপনি কমান্ডের বাইরে পাইপ করতে পারবেন না যেহেতু পাইপিং একটি সাবশেল ইন করে bashএবং সাবসেলের zshভেরিয়েবলের অ্যাসাইনমেন্টটি বর্তমান শেলের জন্য উপলব্ধ হবে না।

সজোরে আঘাত

ইন bash, ফাইল বিবরণকারী 3 টি অব্যবহৃত বলে ধরে নেওয়া ভাল না:

{ error=$( { { ls -ld /XXXX /bin | tr o Z ; } 1>&$tmp ; } 2>&1); } {tmp}>&1; 
exec {tmp}>&-  # With this syntax the FD stays open

মনে রাখবেন এটি এতে কাজ করে না zsh


সাধারণ ধারণার জন্য এই উত্তর ধন্যবাদ ।


1

এই পোস্টটি আমার নিজের উদ্দেশ্যে একই ধরণের সমাধান নিয়ে আসতে সহায়তা করেছে:

MESSAGE=`{ echo $ERROR_MESSAGE | format_logs.py --level=ERROR; } 2>&1`

তারপরে যতক্ষণ না আমাদের বার্তাটি খালি স্ট্রিং নয়, আমরা এটিকে অন্য স্টাফগুলিতে প্রেরণ করি। এটি আমাদের ফর্ম্যাট_লগস.পি কোনও ধরণের পাইথন ব্যতিক্রম ব্যর্থ হলে তা আমাদের জানতে দেবে।


1

স্ট্যান্ডার ক্যাপচার করুন এবং মুদ্রণ করুন

ERROR=$( ./useless.sh 3>&1 1>&2 2>&3 | tee /dev/fd/2 )

ভাঙ্গন

আপনি $()স্টডআউট ক্যাপচার করতে ব্যবহার করতে পারেন, তবে আপনি পরিবর্তে স্ট্যাডারকে ক্যাপচার করতে চান। সুতরাং আপনি stdout এবং stderr অদলবদল। স্ট্যান্ডার্ড অদলবদল অ্যালগরিদমে অস্থায়ী স্টোরেজ হিসাবে fd 3 ব্যবহার করা।

আপনি কপি করতে চান এবং teeঅনুলিপি তৈরি করতে মুদ্রণ করুন । এই ক্ষেত্রে আউটপুট কনসোলে না গিয়ে teeক্যাপচার করা হবে $(), তবে স্টার্ডার (অফ tee) এখনও কনসোলে যাবে তাই আমরা teeবিশেষ ফাইলের মধ্য দিয়ে দ্বিতীয় আউটপুট হিসাবে ব্যবহার করব /dev/fd/2যেহেতু teeকোনও এফডি পরিবর্তে ফাইল পাথ প্রত্যাশা করে সংখ্যা।

দ্রষ্টব্য: এটি একটি একক লাইনে ক্রম পুনঃনির্দেশ এবং আদেশের বিষয়। পাইপলাইনটির শেষে $()স্টাডআউটটি ধরছে teeএবং পাইপলাইন নিজেই স্ট্যান্ডটিকে স্টেডাউটের দিকে যাত্রা ./useless.shকরবে আফটারের teeপরে আমরা স্টিডিনকে অদলবদল করেছিলাম এবং স্ট্যান্ডআউটের জন্য ./useless.sh

./Useless.sh এর stdout ব্যবহার করা

ওপি জানিয়েছে যে তিনি এখনও (কেবল প্রিন্ট নয়) স্ট্যান্ডআউট ব্যবহার করতে চান, যেমন ./useless.sh | sed 's/Output/Useless/'

কোনও সমস্যা নেই কেবল স্টাডাউট এবং স্টাডার অদলবদল করার আগেই। আমি এটিকে কোনও ফাংশন বা ফাইলে (এছাড়াও- ব্যবহারহীন.শ) স্থানান্তরিত করার এবং উপরের লাইনে ./useless.sh এর জায়গায় কল করার পরামর্শ দিচ্ছি।

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


1

টম হালের উত্তরে কিছুটা বিশ্লেষণ করে, আমি পুনরায় ব্যবহারের পুনরায় ব্যবহারের জন্য কোনও ফাংশনে পুনর্নির্দেশ যোগটি গুটিয়ে ফেলা সম্ভব পেয়েছি। উদাহরণ স্বরূপ:

#!/bin/sh

capture () {
    { captured=$( { { "$@" ; } 1>&3 ; } 2>&1); } 3>&1
}

# Example usage; capturing dialog's output without resorting to temp files
# was what motivated me to search for this particular SO question
capture dialog --menu "Pick one!" 0 0 0 \
        "FOO" "Foo" \
        "BAR" "Bar" \
        "BAZ" "Baz"
choice=$captured

clear; echo $choice

এটি আরও সহজতর করা প্রায় অবশ্যই সম্ভব। বিশেষত-পুঙ্খানুপুঙ্খভাবে পরীক্ষা করা হয়নি, তবে এটি ব্যাশ এবং কেএসএস উভয়ের সাথেই কাজ করে বলে মনে হচ্ছে।


0

আপনি যদি কোনও অস্থায়ী ফাইলের ব্যবহারকে বাইপাস করতে চান তবে আপনি প্রক্রিয়া বিকল্পটি ব্যবহার করতে সক্ষম হতে পারেন। আমি এখনও এটি কাজ করতে পারেনি। এটা আমার প্রথম প্রচেষ্টা ছিল:

$ .useless.sh 2> >( ERROR=$(<) )
-bash: command substitution: line 42: syntax error near unexpected token `)'
-bash: command substitution: line 42: `<)'

তারপরে চেষ্টা করেছি

$ ./useless.sh 2> >( ERROR=$( cat <() )  )
This Is Output
$ echo $ERROR   # $ERROR is empty

যাহোক

$ ./useless.sh 2> >( cat <() > asdf.txt )
This Is Output
$ cat asdf.txt
This Is Error

প্রক্রিয়া প্রতিস্থাপনটি সাধারণত সঠিক জিনিসটি করে চলেছে ... দুর্ভাগ্যক্রমে, যখনই আমি কোনও পরিবর্তনশীলকে ক্যাপচার করার চেষ্টা করে কোনও >( )কিছু দিয়ে এসটিডিনকে গুটিয়ে রাখি $(), আমি এর বিষয়বস্তুগুলি হারিয়ে ফেলছি $()। আমি মনে করি এটি এর কারণ $()একটি উপ-প্রক্রিয়া চালু করে যা পিতামাতার প্রক্রিয়ার মালিকানাধীন / dev / fd তে ফাইল বর্ণনাকারীর অ্যাক্সেস নেই।

প্রক্রিয়া প্রতিস্থাপনটি আমাকে ডেটা স্ট্রিমের সাথে কাজ করার সক্ষমতা কিনে দিয়েছে যা এসটিডিআরআর আর নেই, দুর্ভাগ্যক্রমে আমি যেভাবে চাই সেগুলি এটির ব্যবহার করতে সক্ষম হবে বলে মনে হয় না।


1
আপনি যদি না করেন ./useless.sh 2> >( ERROR=$( cat <() ); echo "$ERROR" )তবে এর আউটপুট দেখতে পাবেন ERROR। সমস্যাটি হ'ল প্রক্রিয়া প্রতিস্থাপনটি একটি সাব-শেলটিতে চালিত হয়, সুতরাং সাব-শেলের মধ্যে সেট মানটি প্যারেন্ট শেলকে প্রভাবিত করে না।
জোনাথন লেফলার

0
$ b=$( ( a=$( (echo stdout;echo stderr >&2) ) ) 2>&1 )
$ echo "a=>$a b=>$b"
a=>stdout b=>stderr

3
এটি দেখতে একটি ভাল ধারণা বলে মনে হচ্ছে, তবে ম্যাক ওএসএক্স ১০.৮.৫ এ এটি মুদ্রণ করেa=> b=>stderr
সীমানা

3
আমি @ হিথবর্ডার্সের সাথে একমত; এটি প্রদর্শিত আউটপুট উত্পাদন করে না। এখানে সমস্যাটি হ'ল aএকটি সাব-শেলটিতে মূল্যায়ন ও নির্ধারিত হয় এবং সাব-শেলটিতে অ্যাসাইনমেন্ট প্যারেন্ট শেলকে প্রভাবিত করে না। (উবুন্টু 14.04 এলটিএসের পাশাপাশি ম্যাক ওএস এক্স 10.10.1 তে পরীক্ষা করা হয়েছে))
জোনাথন লেফলার

উইন্ডোজ গিটব্যাশ একই। সুতরাং, এটি কাজ করে না। ( GNU bash, version 4.4.12(1)-release (x86_64-pc-msys))
কারবি


এই কোডটি প্রশ্নের উত্তর দিতে পারে, কেন এবং / অথবা এই কোডটির প্রশ্নের উত্তর কীভাবে তার দীর্ঘমেয়াদী মানকে উন্নত করে সে সম্পর্কে অতিরিক্ত প্রসঙ্গ সরবরাহ করে।
εηοιτ.εηοιτ.βε


0

আপনার আদেশগুলি প্রমাণ করার সময় ত্রুটির জন্য :

execute [INVOKING-FUNCTION] [COMMAND]

execute () {
    function="${1}"
    command="${2}"
    error=$(eval "${command}" 2>&1 >"/dev/null")

    if [ ${?} -ne 0 ]; then
        echo "${function}: ${error}"
        exit 1
    fi
}

চর্বি উত্পাদনতে অনুপ্রাণিত :


আইডিয়োম্যাটিক সলিউশনটি হ'ল কার্যের ভিতরে নির্ধারিত কাজটি টপপুট if। আমাকে একটি পৃথক সমাধান পোস্ট করুন।
ট্রিপলি


0

ইয়েলো অ্যাপলের উত্তরের উন্নতি :

স্ট্যাডারকে কোনও ভেরিয়েবলের ক্যাপচার করার জন্য এটি একটি বাশ ফাংশন

stderr_capture_example.sh:

#!/usr/bin/env bash

# Capture stderr from a command to a variable while maintaining stdout
# @Args:
# $1: The variable name to store the stderr output
# $2: Vararg command and arguments
# @Return:
# The Command's Returnn-Code or 2 if missing arguments
function capture_stderr {
  [ $# -lt 2 ] && return 2
  local stderr="$1"
  shift
  {
    printf -v "$stderr" '%s' "$({ "$@" 1>&3; } 2>&1)"
  } 3>&1
}

# Testing with a call to erroring ls
LANG=C capture_stderr my_stderr ls "$0" ''

printf '\nmy_stderr contains:\n%s' "$my_stderr"

পরীক্ষামূলক:

bash stderr_capture_example.sh

আউটপুট:

 stderr_capture_example.sh

my_stderr contains:
ls: cannot access '': No such file or directory

এই ফাংশনটি কোনও dialogকমান্ডের প্রত্যাবর্তিত পছন্দ ক্যাপচার করতে ব্যবহার করা যেতে পারে ।

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