পুনর্নির্দেশ স্ট্যাডার এবং বাশে স্টাডআউট


678

আমি প্রক্রিয়াটির stdout এবং stderr উভয়ই একটি ফাইলে পুনর্নির্দেশ করতে চাই। বাশে আমি কীভাবে এটি করব?


2
আমি বলতে চাই এটি একটি আশ্চর্যজনকভাবে কার্যকর প্রশ্ন। অনেকে এটি কীভাবে করবেন তা জানেন না, কারণ তাদের প্রায়শই এটি করতে হয় না এবং এটি বাশের সেরা নথিভুক্ত আচরণ নয়।
রবার্ট ডাব্লুএম রুইদিসুয়েলি

2
কখনও কখনও এটি আউটপুট দেখতে (যথারীতি) এবং এটি কোনও ফাইলে পুনর্নির্দেশ করা দরকারী। নীচে মার্কো দ্বারা উত্তর দেখুন। (আমি এটি এখানে বলছি কারণ কোনও সমস্যা সমাধানের পক্ষে যথেষ্ট হলে কেবল প্রথম গৃহীত উত্তরের দিকে নজর রাখা সহজ, তবে অন্যান্য উত্তরগুলি প্রায়শই দরকারী তথ্য সরবরাহ করে))
jvriesem

উত্তর:


761

এখানে একবার দেখুন । হতে হবে:

yourcommand &>filename

(উভয় stdoutএবং stderrফাইল নাম পুনর্নির্দেশ )।


29
এই বাক্য গঠনটি বাশ হ্যাকার্স উইকির অনুসারে অবচিত করা হয়েছে । তাই কি?
সালমান ভন আব্বাস

20
Wiki.bash-hackers.org/scriptting/obsolete এর মতে , এটি পসিক্সের অংশ নয় এমন অর্থে এটি অপ্রচলিত বলে মনে হচ্ছে, তবে বাশ ম্যান পৃষ্ঠাটি নিকট ভবিষ্যতে বাশ থেকে এটি সরানোর কোনও উল্লেখ করেনি। ম্যান পৃষ্ঠাটি '&>' ওভার '> &' এর জন্য একটি অগ্রাধিকার নির্দিষ্ট করে, যা অন্যথায় সমতুল্য।
চিপনার

13
আমি অনুমান করি যে আমাদের &> ব্যবহার করা উচিত নয় কারণ এটি পসিক্সে নেই এবং সাধারণ শেল যেমন "ড্যাশ" এটি সমর্থন করে না।
স্যাম ওয়াটকিন্স

27
একটি অতিরিক্ত ইঙ্গিত: আপনি যদি এটি কোনও স্ক্রিপ্টে ব্যবহার করেন তবে নিশ্চিত হয়ে নিন যে এটির #!/bin/bashপরিবর্তে এটি শুরু হয় #!/bin/sh, কারণ এতে বাশ প্রয়োজন।
টোর ক্লিংবার্গ

8
এবং >> >> ওভাররাইটের পরিবর্তে সংযোজন করতে।
আলেকজান্ডার গনচি

448
do_something 2>&1 | tee -a some_file

এই stdout- এ এবং stdout- এ দ্বারা stderr পুনর্নির্দেশ করতে যাচ্ছে some_file এবং stdout- এ এটা মুদ্রণ।


16
এআইএক্স (কেএসএল) এ আপনার সমাধান কাজ করে। গৃহীত উত্তর do_something &>filenameদেয় না। +1 টি।
4'13 প্রতিরোধ

11
@ ড্যানিয়েল, তবে এই প্রশ্নটি বিশেষত বাশ সম্পর্কে
জন লা রুই

3
আমি Ambiguous output redirect.কোন ধারণা পাই কেন?
আলেকজান্দ্রে হোল্ডেন ডেলি

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

8
দ্রষ্টব্য যে (ডিফল্টরূপে) এর পার্শ্ব-প্রতিক্রিয়া রয়েছে যা $?এর প্রস্থান স্থিতিটিকে আর উল্লেখ করে না do_something, তবে প্রস্থান করার স্থিতি tee
ফ্লিম

255

আপনি পুনর্নির্দেশ করতে পারেন দ্বারা stderr করার stdout- এ এবং stdout- এ একটি ফাইলে:

some_command >file.log 2>&1 

Http://tldp.org/LDP/abs/html/io-redirection.html দেখুন

এই ফর্ম্যাটটি সর্বাধিক জনপ্রিয় &> বিন্যাসের চেয়ে বেশি পছন্দ করা হয় যা কেবল বাশে কাজ করে। বোর্ন শেল এটি ব্যাকগ্রাউন্ডে কমান্ড চালানো হিসাবে ব্যাখ্যা করা যেতে পারে। এছাড়াও ফর্ম্যাটটি আরও পঠনযোগ্য 2 (এটি এসটিডিআরআর) 1 (এসটিডিআউট) এ পুনঃনির্দেশিত।

সম্পাদনা: মন্তব্যে নির্দেশিত অনুসারে অর্ডার পরিবর্তন করা হয়েছে


47
এই স্ট্যাডারকে মূল স্টডআউটে পুনর্নির্দেশ করে, যেখানে স্টডআউট যাচ্ছে সেই ফাইলের দিকে নয়। '> File.log' পরে '2> & 1' রাখুন এবং এটি কার্যকর হয়।

1
কিছু_কম্যান্ড &> ফাইল.লগের মাধ্যমে এই পদ্ধতির সুবিধা কী?
ubermonkey

6
আপনি যদি কোনও ফাইলে সংযোজন করতে চান তবে আপনার অবশ্যই এটি করতে হবে: প্রতিধ্বনি "foo" 2> & 1 1 >> বার.টেক্সট এএএফএইকি &>
স্লেপি দ্য ফিশ

9
আরগ, দুঃখিত, প্রতিধ্বনি "ফু" 1 >> বার.টিএসটি 2> & 1
স্লিপিএফিশ

11
আমি মনে করি যে 2> & 1 স্ট্যাডারকে স্টাডাউটে পুনঃনির্দেশ করে যা ভুল; আমি বিশ্বাস করি এটি স্টাডারকে একই জায়গায় পাঠায় যে স্টাডাউট এই মুহুর্তে সময়ের সাথে চলেছে তা বলা আরও সঠিক। সুতরাং প্রথম পুনর্নির্দেশের পরে 2> & 1 এ রাখুন প্রয়োজনীয়।
জেডজি

201
# Close STDOUT file descriptor
exec 1<&-
# Close STDERR FD
exec 2<&-

# Open STDOUT as $LOG_FILE file for read and write.
exec 1<>$LOG_FILE

# Redirect STDERR to STDOUT
exec 2>&1

echo "This line will appear in $LOG_FILE, not 'on screen'"

এখন, সহজ প্রতিধ্বনি $ LOG_FILE এ লিখবে। ডিমনাইজিংয়ের জন্য দরকারী।

মূল পোস্টটির লেখকের কাছে,

এটি আপনার কী অর্জন করতে হবে তা নির্ভর করে। আপনার স্ক্রিপ্ট থেকে আপনি যে আদেশটি কল করেছেন তার মধ্যে যদি আপনাকে কেবল পুনর্নির্দেশের প্রয়োজন হয় তবে উত্তরগুলি ইতিমধ্যে দেওয়া আছে। আমার বর্তমান স্ক্রিপ্টের মধ্যে পুনর্নির্দেশ সম্পর্কে যা উল্লিখিত কোড স্নিপেটের পরে সমস্ত কমান্ড / বিল্ট-ইনগুলিতে (কাঁটাচামচ সহ) প্রভাবিত করে।


আরেকটি দুর্দান্ত সমাধান হ'ল স্টডি-এরর / আউট এবং লগার বা লগ ফাইল একবারে পুনর্নির্দেশ সম্পর্কে যা "একটি স্ট্রিম" কে দুটি ভাগে যুক্ত করে। এই কার্যকারিতাটি 'টি' কমান্ড দ্বারা সরবরাহ করা হয়েছে যা একাধিক ফাইল বর্ণনাকারী (ফাইল, সকেট, পাইপ, ইত্যাদিতে) একবারে লিখতে / সংযোজন করতে পারে: টি FILE1 ফাইল 2 ...> (সেমিডি 1)> (সেমিডি 2) ...

exec 3>&1 4>&2 1> >(tee >(logger -i -t 'my_script_tag') >&3) 2> >(tee >(logger -i -t 'my_script_tag') >&4)
trap 'cleanup' INT QUIT TERM EXIT


get_pids_of_ppid() {
    local ppid="$1"

    RETVAL=''
    local pids=`ps x -o pid,ppid | awk "\\$2 == \\"$ppid\\" { print \\$1 }"`
    RETVAL="$pids"
}


# Needed to kill processes running in background
cleanup() {
    local current_pid element
    local pids=( "$$" )

    running_pids=("${pids[@]}")

    while :; do
        current_pid="${running_pids[0]}"
        [ -z "$current_pid" ] && break

        running_pids=("${running_pids[@]:1}")
        get_pids_of_ppid $current_pid
        local new_pids="$RETVAL"
        [ -z "$new_pids" ] && continue

        for element in $new_pids; do
            running_pids+=("$element")
            pids=("$element" "${pids[@]}")
        done
    done

    kill ${pids[@]} 2>/dev/null
}

তো, শুরু থেকেই। ধরে নেওয়া যাক আমাদের / dev / stdout (FD # 1) এবং / dev / stderr (FD # 2) এর সাথে টার্মিনাল সংযুক্ত আছে। অনুশীলনে, এটি একটি পাইপ, সকেট বা যা কিছু হতে পারে।

  • # 3 এবং # 4 এফডি তৈরি করুন এবং যথাক্রমে # 1 এবং # 2 হিসাবে একই "অবস্থান" এ নির্দেশ করুন। এফডি # 1 পরিবর্তন করা এখন থেকে এফডি # 3 কে প্রভাবিত করে না। এখন, FDs # 3 এবং # 4 যথাক্রমে STDOUT এবং STDERR এ নির্দেশ করে। এগুলি বাস্তব টার্মিনাল STDOUT এবং STDERR হিসাবে ব্যবহৃত হবে ।
  • 1>> (...) পেরেন্সে আদেশ দেওয়ার জন্য STDOUT পুনর্নির্দেশ করে
  • পেরেনস (সাব-শেল) এক্সিকিউটির এসটিডুউট (পাইপ) থেকে 'টি' রিডিং কার্যকর করে এবং পেরেনের সাব-শেলের জন্য অন্য পাইপের মাধ্যমে 'লগার' কমান্ডে পুনর্নির্দেশ করে। একই সময়ে এটি একই ইনপুটটি এফডি # 3 (টার্মিনাল) এ অনুলিপি করে
  • দ্বিতীয় অংশটি, খুব অনুরূপ, STDERR এবং FDs # 2 এবং # 4 এর জন্য একই কৌশল করে।

উপরোক্ত লাইনটি যুক্ত করে একটি স্ক্রিপ্ট চালানোর ফলাফল এবং অতিরিক্ত এটি:

echo "Will end up in STDOUT(terminal) and /var/log/messages"

...নিম্নরূপ:

$ ./my_script
Will end up in STDOUT(terminal) and /var/log/messages

$ tail -n1 /var/log/messages
Sep 23 15:54:03 wks056 my_script_tag[11644]: Will end up in STDOUT(terminal) and /var/log/messages

আপনি যদি আরও পরিষ্কার ছবি দেখতে চান তবে স্ক্রিপ্টে এই 2 টি লাইন যুক্ত করুন:

ls -l /proc/self/fd/
ps xf

1
শুধুমাত্র একটি ব্যতিক্রম প্রথম উদাহরণে আপনি লিখেছেন: এক্সিকিউট 1 <> O LOG_FILE ILE এটি আসল লগফাইলে সর্বদা owwritten হয়। আসল লগিনের জন্য আরও ভাল উপায় হ'ল: এক্সিকিউটিভ 1 >> O LOG_FILE এর ফলে লগটি সবসময় সংযুক্ত থাকে।
Znik

4
যদিও এটি উদ্দেশ্যগুলির উপর নির্ভর করে এটি সত্য। আমার পদ্ধতিটি সর্বদা একটি অনন্য এবং টাইমস্ট্যাম্পড লগ ফাইল তৈরি করা। অন্যটি সংযোজন করা হয়। দুটি উপায়ই 'লোগ্রোটেটেবল'। আমি পৃথক ফাইল পছন্দ করি যার জন্য কম
পার্সিংয়ের

1
আপনার দ্বিতীয় সমাধানটি তথ্যবহুল, তবে সমস্ত ক্লিনআপ কোডের সাথে কী আছে? এটি প্রাসঙ্গিক বলে মনে হচ্ছে না এবং যদি তা হয় তবে কেবল একটি অন্যথায় ভাল উদাহরণকেই গণ্ডগোল করে। আমি এটিকে সামান্য পুনরায় কাজ করতে দেখতে চাই যাতে এফডি 1 এবং 2 লগারে পুনর্নির্দেশ না করা হয় বরং 3 এবং 4 এর ফলে যাতে এই স্ক্রিপ্টটি কল করে যে কোনও কিছু স্ট্যান্ডআউট == 1 সাধারণ অনুমানের অধীনে আরও 1 এবং 2 কে ম্যানিপুলেট করতে পারে এবং স্টেডার == 2, তবে আমার সংক্ষিপ্ত পরীক্ষাটি আরও জটিল বিষয়টিকে বোঝায়।
JFlo

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

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

41
bash your_script.sh 1>file.log 2>&1

1>file.logশেলটি ফাইলটিতে STDOUT প্রেরণের নির্দেশ দেয় file.logএবং 2>&1STDERR (ফাইল বর্ণনাকারী 2) কে STDOUT (ফাইল বর্ণনাকারী 1) এ পুনঃনির্দেশ করতে বলে।

দ্রষ্টব্য: অর্ডারটি liw.fi হিসাবে উল্লেখ করেছে, 2>&1 1>file.logকাজ করে না।


21

কৌতূহলীভাবে, এটি কাজ করে:

yourcommand &> filename

তবে এটি একটি সিনট্যাক্স ত্রুটি দেয়:

yourcommand &>> filename
syntax error near unexpected token `>'

আপনাকে ব্যবহার করতে হবে:

yourcommand 1>> filename 2>&1

10
&>>BASH 4 এ কাজ করছে বলে মনে হচ্ছে:$ echo $BASH_VERSION 4.1.5(1)-release $ (echo to stdout; echo to stderr > /dev/stderr) &>> /dev/null
user272735

15

সংক্ষিপ্ত উত্তর: Command >filename 2>&1বাCommand &>filename


ব্যাখ্যা:

নিম্নলিখিত কোডটি বিবেচনা করুন যা স্টডআউট শব্দটি "স্টডআউট" এবং স্টার্ডর শব্দ "স্টেডারআর" মুদ্রণ করে।

$ (echo "stdout"; echo "stderror" >&2)
stdout
stderror

নোট করুন যে 'এবং' অপারেটর বাশকে বলে যে 2 একটি ফাইল বর্ণনাকারী (যা স্ট্যাডারকে নির্দেশ করে) এবং কোনও ফাইলের নাম নয়। যদি আমরা '&' বাদ দিয়ে থাকি তবে এই কমান্ডটি stdoutstdout এ মুদ্রণ করবে এবং "2" নামে একটি ফাইল তৈরি করে লিখবেstderror সেখানে ।

উপরের কোডটি পরীক্ষা করে আপনি নিজেরাই দেখতে পারবেন ঠিক কীভাবে পুনর্নির্দেশ অপারেটররা কাজ করে। উদাহরণস্বরূপ, দুটি বর্ণনাকারীর মধ্যে কোন ফাইলটি পরিবর্তন করে নীচের দুটি লাইনের কোডে 1,2পুনঃনির্দেশিত করা /dev/nullহয়েছে স্টাডআউট থেকে সমস্ত কিছু এবং যথাক্রমে স্ট্যাডার থেকে সমস্ত কিছু মুছে ফেলা হবে (যা মুদ্রিত রয়েছে)।

$ (echo "stdout"; echo "stderror" >&2) 1>/dev/null
stderror
$ (echo "stdout"; echo "stderror" >&2) 2>/dev/null
stdout

এখন, আমরা নীচের কোডটি কেন আউটপুট তৈরি করে না কেন সমাধানটি ব্যাখ্যা করতে পারি:

(echo "stdout"; echo "stderror" >&2) >/dev/null 2>&1

সত্যই এটি বোঝার জন্য, আমি আপনাকে উচ্চারণের জন্য ফাইলের বিবরণী টেবিলগুলিতে এই ওয়েবপৃষ্ঠাটি পড়ার পরামর্শ দিচ্ছি । ধরে নিই যে আপনি এই পড়াটি করেছেন, আমরা এগিয়ে যেতে পারি। নোট করুন যে বাশ প্রক্রিয়াগুলি বাম থেকে ডানে; এইভাবে বাশ >/dev/nullপ্রথমে দেখতে (যা একইরকম 1>/dev/null) এবং ফাইল বিবরণী 1 সেট করে stdout এর পরিবর্তে / dev / নলের দিকে নির্দেশ করে। এটি সম্পন্ন করার পরে বাশ ডানদিকের দিকে এগিয়ে যায় এবং দেখে 2>&1। এটি ফাইল বর্ণনাকারী 2 সেট করে ফাইল বর্ণনাকারী 1 হিসাবে একই ফাইলের দিকে নির্দেশ করে (এবং 1 নিজেই বিবরণকারী ফাইল না !!!!) ( এই সংস্থানটি পয়েন্টারে দেখুন)আরও তথ্যের জন্য)) . যেহেতু ফাইল বর্ণনাকারী 1 পয়েন্ট / dev / নাল, এবং ফাইল বিবরণকারী 2 ফাইল ফাইল বর্ণনাকারী 1 হিসাবে একই ফাইলটিতে 2 পয়েন্ট, ফাইল বর্ণনাকারী 2 এখন / dev / নাল পয়েন্ট। সুতরাং উভয় ফাইল বর্ণনাকারী / dev / নালকে নির্দেশ করে এবং এ কারণেই কোনও আউটপুট রেন্ডার করা হয় না।


আপনি যদি ধারণাটি সত্যিই বুঝতে পেরেছেন তা পরীক্ষা করতে, আমরা পুনর্নির্দেশের আদেশটি স্যুইচ করলে আউটপুট অনুমান করার চেষ্টা করুন:

(echo "stdout"; echo "stderror" >&2)  2>&1 >/dev/null

stderror

এখানে যুক্তিটি হ'ল বাম থেকে ডানে বামে মূল্যায়ন করা, ব্যাশ 2> ও 1 দেখায় এবং এইভাবে ফাইল বর্ণনাকারী 2 সেট করে ফাইল বর্ণনাকারী 1, অর্থাৎ স্টাডআউট হিসাবে একই জায়গায় নির্দেশ করে। এরপরে এটি ফাইল ডিস্ট্রিপ্টর 1 সেট করে (মনে রাখবেন </ dev / null = 1> / dev / নাল)> / dev / নালকে নির্দেশ করে, এইভাবে যা মানকে পাঠানো হয় তা মুছে দেয়। এইভাবে আমরা যা বাকী ছিল তা হ'ল সাবসেলের স্ট্যান্ডআউটে পাঠানো হয়নি (প্যারেন্টেসিসের কোড) - "স্টারডার"। মজার বিষয়টি এখানে লক্ষণীয় যে 1 টি স্টডআউটের কেবল পয়েন্টার হলেও পয়েন্টার 2 থেকে 1 এর মাধ্যমে পুনর্নির্দেশ 2>&1পয়েন্টার 2 -> 1 -> স্টাডাউটের শৃঙ্খলা তৈরি করে না। যদি এটি হয়, 1 / dev / নালকে কোডটি পুনর্নির্দেশের ফলস্বরূপ2>&1 >/dev/null পয়েন্টার শৃঙ্খলটি 2 -> 1 -> / dev / নাল দিয়ে দেবে, এবং সুতরাং কোডটি কিছুই দেখায় না, আমরা উপরে যা দেখেছি তার বিপরীতে।


পরিশেষে, আমি লক্ষ করব যে এটি করার সহজ উপায় রয়েছে:

এখানে বিভাগ 3...4.৪ থেকে আমরা দেখতে পাচ্ছি যে আমরা অপারেটরটি &>স্টাডআউট এবং স্টডার উভয়ই পুনর্নির্দেশ করতে ব্যবহার করতে পারি । সুতরাং, যে কোনও কমান্ডের stderr এবং stdout আউটপুট উভয়ই পুনঃনির্দেশ করতে \dev\null(যা আউটপুট মুছে ফেলে), আমরা কেবল টাইপ করি $ command &> /dev/null বা আমার উদাহরণের ক্ষেত্রে:

$ (echo "stdout"; echo "stderror" >&2) &>/dev/null

কী Takeaways:

  • ফাইল বর্ণনাকারীরা পয়েন্টারগুলির মতো আচরণ করে (যদিও ফাইল বর্ণনাকারী ফাইল পয়েন্টারগুলির মতো নয়)
  • একটি ফাইল বর্ণনাকারী "a" কে একটি ফাইল বর্ণনাকারী "বি" তে পুনর্নির্দেশ করা যা ফাইল "এফ" নির্দেশ করে, ফাইল বিবরণকারী "এ" ফাইল বর্ণনাকারী বি - ফাইল "এফ" হিসাবে একই জায়গায় নির্দেশ করে। এটি পয়েন্টারগুলির একটি -> বি -> চ এর শৃঙ্খলা তৈরি করে না
  • কারণ উপরে, যাতে বিষয়ে, 2>&1 >/dev/null= হয়! >/dev/null 2>&1। একটি আউটপুট উত্পন্ন এবং অন্য না!

অবশেষে এই দুর্দান্ত সংস্থানগুলি দেখুন:

পুনঃ দিকনির্দেশ উপর ব্যাশ ডকুমেন্টেশন , ফাইল বর্ণনাকারী টেবিল একটি ব্যাখ্যা , ভূমিকা পয়েন্টার থেকে


ফাইল বর্ণনাকারী (0, 1, 2) কেবল একটি টেবিলের অফসেট। যখন 2> এবং 1 ব্যবহার করা হয় তখন প্রভাবটি স্লট এফডি হয় [2] = ডুপ (1) সুতরাং যেখানেই এফডি [1] এফডি দেখায় [2] এখন নির্দেশ করে। আপনি যখন এফডি পরিবর্তন করেন [1] / dev / নালকে নির্দেশ করেন, তখন এফডি [1] পরিবর্তন করা হয় তবে এটি এফডি [2] স্লট পরিবর্তন করে না (যা স্টাডআউটকে নির্দেশ করে)। আমি ডুপ শব্দটি ব্যবহার করি (কারণ) এটি সেই সিস্টেম কল যা ফাইল বিবরণীর নকল করতে ব্যবহৃত হয়।
প্যাটস

11
LOG_FACILITY="local7.notice"
LOG_TOPIC="my-prog-name"
LOG_TOPIC_OUT="$LOG_TOPIC-out[$$]"
LOG_TOPIC_ERR="$LOG_TOPIC-err[$$]"

exec 3>&1 > >(tee -a /dev/fd/3 | logger -p "$LOG_FACILITY" -t "$LOG_TOPIC_OUT" )
exec 2> >(logger -p "$LOG_FACILITY" -t "$LOG_TOPIC_ERR" )

এটি সম্পর্কিত: স্টাইলআউট ও স্ট্ডার সিস্লগ-এ লেখা।

এটি প্রায় কাজ করে, তবে জিন্টেড থেকে নয়; (


আমি অনুমান করছি "/ dev / fd / 3 এর অনুমতি অস্বীকার করা হয়েছে" এর কারণে এটি কার্যকর হয় না। > & 3 এ পরিবর্তন করা সাহায্য করতে পারে।
ক্যুইজাক

6

আমি একটি সমাধান চেয়েছিলাম stdout প্লাস stderr থেকে আউটপুট একটি লগ ফাইলে লেখা এবং stderr এখনও কনসোলে আছে। সুতরাং আমি টি মাধ্যমে স্ট্যাডার আউটপুট নকল করা প্রয়োজন।

এটিই আমি পেয়েছি সমাধান:

command 3>&1 1>&2 2>&3 1>>logfile | tee -a logfile
  • প্রথম অদলবদল stdr এবং stdout
  • তারপরে লগ ফাইলটিতে স্টাডাউট যুক্ত করুন
  • পাইপ stderr টি করতে এবং লগ ফাইল এ এটি সংযোজন

বিটিডাব্লু, এটি আমার পক্ষে কাজ করে না (লগফিল খালি রয়েছে)। | টি এর কোনও প্রভাব নেই। পরিবর্তে আমি এটি স্ট্যাকওভারফ্লো
ইয়ারোস্লাভ বুলাটোভ

4

পরিস্থিতির জন্য, যখন "পাইপিং" প্রয়োজনীয় হয় আপনি ব্যবহার করতে পারেন:

| &

উদাহরণ স্বরূপ:

echo -ne "15\n100\n"|sort -c |& tee >sort_result.txt

অথবা

TIMEFORMAT=%R;for i in `seq 1 20` ; do time kubectl get pods |grep node >>js.log  ; done |& sort -h

এই বাশ-ভিত্তিক সমাধানগুলি STDOUT এবং STDERR আলাদাভাবে পাইপ করতে পারে ("सॉर्ट-সি" এর STDERR থেকে বা STDERR থেকে "সাজানোর -h")।


1

"সহজ" উপায় (শুধুমাত্র bash4): ls * 2>&- 1>&-


1

টগলিং আউটপুট বিটউইন স্টডআউট / স্টার্ডার এবং একটি লগফাইলে প্রক্রিয়াটি স্বয়ংক্রিয় করতে নিম্নলিখিত ফাংশনগুলি ব্যবহার করা যেতে পারে।

#!/bin/bash

    #set -x

    # global vars
    OUTPUTS_REDIRECTED="false"
    LOGFILE=/dev/stdout

    # "private" function used by redirect_outputs_to_logfile()
    function save_standard_outputs {
        if [ "$OUTPUTS_REDIRECTED" == "true" ]; then
            echo "[ERROR]: ${FUNCNAME[0]}: Cannot save standard outputs because they have been redirected before"
            exit 1;
        fi
        exec 3>&1
        exec 4>&2

        trap restore_standard_outputs EXIT
    }

    # Params: $1 => logfile to write to
    function redirect_outputs_to_logfile {
        if [ "$OUTPUTS_REDIRECTED" == "true" ]; then
            echo "[ERROR]: ${FUNCNAME[0]}: Cannot redirect standard outputs because they have been redirected before"
            exit 1;
        fi
        LOGFILE=$1
        if [ -z "$LOGFILE" ]; then
            echo "[ERROR]: ${FUNCNAME[0]}: logfile empty [$LOGFILE]"

        fi
        if [ ! -f $LOGFILE ]; then
            touch $LOGFILE
        fi
        if [ ! -f $LOGFILE ]; then
            echo "[ERROR]: ${FUNCNAME[0]}: creating logfile [$LOGFILE]"
            exit 1
        fi

        save_standard_outputs

        exec 1>>${LOGFILE%.log}.log
        exec 2>&1
        OUTPUTS_REDIRECTED="true"
    }

    # "private" function used by save_standard_outputs() 
    function restore_standard_outputs {
        if [ "$OUTPUTS_REDIRECTED" == "false" ]; then
            echo "[ERROR]: ${FUNCNAME[0]}: Cannot restore standard outputs because they have NOT been redirected"
            exit 1;
        fi
        exec 1>&-   #closes FD 1 (logfile)
        exec 2>&-   #closes FD 2 (logfile)
        exec 2>&4   #restore stderr
        exec 1>&3   #restore stdout

        OUTPUTS_REDIRECTED="false"
    }

স্ক্রিপ্টের ভিতরে ব্যবহারের উদাহরণ:

echo "this goes to stdout"
redirect_outputs_to_logfile /tmp/one.log
echo "this goes to logfile"
restore_standard_outputs 
echo "this goes to stdout"

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

আপনার স্ক্রিপ্টটিতে কাজ করার জন্য আমাকে এই লাইনগুলি সম্পর্কে মন্তব্য করতে হয়েছিল এবং আমি ক্রমটি পরিবর্তন করেছি: #exec 1> & - # ক্লাস এফডি 1 (লগফিল) # এক্সেক 2> & # ক্লোজ এফডি 2 (লগফিল); এক্সিকিউট 1> & 3 # রিস্টোর স্টেডআউট এক্সিকিউটিউট 2> & 4 # পূর্ব স্টোরার
থম স্কুমাচার

শুনে দুঃখিত হলাম. সেন্টোস 7, ব্যাশ 4.2.46 এ চলার সময় আমি কোনও ত্রুটি পাই না। আমি সেই নির্দেশগুলি যেখানে পেয়েছি তা উল্লেখ করেছি। এটি: রেফ: লগান.টিডব্লু
ফার্নান্দো ফাব্রেতি

আমি এআইএক্স-এ এই কমান্ডগুলি চালিয়ে যাচ্ছি সম্ভবত সে কারণেই। আমি তৈরি করা ফিক্সের জন্য একটি পোস্ট যুক্ত করেছি।
থম স্কুমাচার

1

@ ফার্নান্দো-fabreti

আপনি যা করেছেন তাতে যুক্ত করে আমি ফাংশনগুলি সামান্য পরিবর্তন করেছি এবং & - বন্ধটি সরিয়ে ফেলেছি এবং এটি আমার পক্ষে কাজ করে।

    function saveStandardOutputs {
      if [ "$OUTPUTS_REDIRECTED" == "false" ]; then
        exec 3>&1
        exec 4>&2
        trap restoreStandardOutputs EXIT
      else
          echo "[ERROR]: ${FUNCNAME[0]}: Cannot save standard outputs because they have been redirected before"
          exit 1;
      fi
  }

  # Params: $1 => logfile to write to
  function redirectOutputsToLogfile {
      if [ "$OUTPUTS_REDIRECTED" == "false" ]; then
        LOGFILE=$1
        if [ -z "$LOGFILE" ]; then
            echo "[ERROR]: ${FUNCNAME[0]}: logfile empty [$LOGFILE]"
        fi
        if [ ! -f $LOGFILE ]; then
            touch $LOGFILE
        fi
        if [ ! -f $LOGFILE ]; then
            echo "[ERROR]: ${FUNCNAME[0]}: creating logfile [$LOGFILE]"
            exit 1
        fi
        saveStandardOutputs
        exec 1>>${LOGFILE}
        exec 2>&1
        OUTPUTS_REDIRECTED="true"
      else
        echo "[ERROR]: ${FUNCNAME[0]}: Cannot redirect standard outputs because they have been redirected before"
          exit 1;
      fi
  }
  function restoreStandardOutputs {
      if [ "$OUTPUTS_REDIRECTED" == "true" ]; then
      exec 1>&3   #restore stdout
      exec 2>&4   #restore stderr
      OUTPUTS_REDIRECTED="false"
     fi
  }
  LOGFILE_NAME="tmp/one.log"
  OUTPUTS_REDIRECTED="false"

  echo "this goes to stdout"
  redirectOutputsToLogfile $LOGFILE_NAME
  echo "this goes to logfile"
  echo "${LOGFILE_NAME}"
  restoreStandardOutputs 
  echo "After restore this goes to stdout"

1

আপনি যখন পরিস্থিতিগুলিতে exec 2>&1ব্যাশ ফাংশন ব্যবহার করে পুনরায় লেখার জন্য কোডটি পড়তে সহজ মনে করেন তবে এই জাতীয় জিনিসগুলি ব্যবহার করার বিষয়টি বিবেচনা করুন :

function myfunc(){
  [...]
}

myfunc &>mylog.log

0

Tcsh এর জন্য আমাকে নিম্নলিখিত কমান্ডটি ব্যবহার করতে হবে:

command >& file

যদি command &> fileএটি ব্যবহার করে তবে এটি "অবৈধ নাল কমান্ড" ত্রুটি দেবে।

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