এক্সিকিউট ব্যবহার করে পরবর্তী সমস্ত কমান্ডের স্টার্ডারকে পুনঃনির্দেশ করুন


43

আমার একটি বাশ ফাইল রয়েছে যা আমার সমস্ত আউটপুটকে একটি ফাইলে, ডিবাগ লগের পাশাপাশি টার্মিনালে পুনর্নির্দেশ করতে হবে। আমাকে stdout এবং stderr উভয়ই ডিবাগে পুনঃনির্দেশ করা এবং স্ক্রিপ্টের সমস্ত কমান্ডের জন্য এটি লগ করতে হবে।

আমি 2>&1 | tee -a $DEBUGফাইলের প্রতিটি একক কমান্ডের জন্য যুক্ত করতে চাই না । আমি সাথে থাকতে পারে | tee -a $DEBUG

আমার মনে আছে এটির মতো কিছু করার একটি উপায় ছিল exec 2>&1

বর্তমানে আমি নিম্নলিখিতগুলির মতো কিছু ব্যবহার করছি:

#!/bin/bash
DEBUGLOG=/tmp/debug
exec 2>&1
somecommand | tee -a $DEBUGLOG
somecommand2 | tee -a $DEBUGLOG
somecommand3 | tee -a $DEBUGLOG

কিন্তু এটা কাজ করে না. কারও কি সমাধান আছে / এর কারণ ব্যাখ্যা করতে পারে?


1
কিছু শেলগুলিতে |&শর্টকাট হিসাবে কাজ করে 2>&1 |এটি কমপক্ষে কিছুটা সুবিধাজনক।
কেভিন

উত্তর:


39

একবারে প্রচুর কমান্ড পুনঃনির্দেশ করার সমাধান হিসাবে:

#!/bin/bash
{
    somecommand 
    somecommand2
    somecommand3
} 2>&1 | tee -a $DEBUGLOG

আপনার আসল সমাধানটি কেন কাজ করে না: এক্সিকিউটিভ 2> & 1 স্ট্যান্ডার্ড ত্রুটি আউটপুটটিকে আপনার শেলের স্ট্যান্ডার্ড আউটপুটে পুনর্নির্দেশ করবে, যা আপনি যদি কনসোল থেকে আপনার স্ক্রিপ্টটি চালান, তবে এটি আপনার কনসোল হবে। কমান্ডগুলিতে পাইপ পুনর্নির্দেশ কেবল কমান্ডের স্ট্যান্ডার্ড আউটপুটটিকে পুনর্নির্দেশ করবে।

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

এটি ব্যাখ্যা করার জন্য একটি আসল উপায় হ'ল সত্যটি কী ঘটে তা দেখা হচ্ছে:

আপনি যদি টার্মিনাল থেকে চালনা করেন তবে আপনার শেলের আসল পরিবেশটি দেখতে দেখতে এটি দেখতে পারা যায়:

stdin -> /dev/pts/42
stdout -> /dev/pts/42
stderr -> /dev/pts/42

আপনি স্ট্যান্ডার্ড ত্রুটিটিকে স্ট্যান্ডার্ড আউটপুট ( exec 2>&1) এ রূপান্তরিত করার পরে , আপনি ... মূলত কিছুই পরিবর্তন করেন না। তবে আপনি যদি স্ক্রিপ্টের স্ট্যান্ডার্ড আউটপুট কোনও ফাইলে পুনর্নির্দেশ করেন তবে আপনি এমন পরিবেশের সাথে শেষ করবেন:

stdin -> /dev/pts/42
stdout -> /your/file
stderr -> /dev/pts/42

তারপরে শেল স্ট্যান্ডার্ড ত্রুটিটিকে স্ট্যান্ডার্ড আউটপুটে পুনঃনির্দেশ করা শেষ হবে:

stdin -> /dev/pts/42
stdout -> /your/file
stderr -> /your/file

একটি কমান্ড চালানো এই পরিবেশের উত্তরাধিকারী হবে। আপনি যদি কোনও কমান্ড চালনা করেন এবং এটি টিপতে পাইপ করেন তবে কমান্ডের পরিবেশটি হবে:

stdin -> /dev/pts/42
stdout -> pipe:[4242]
stderr -> /your/file

সুতরাং আপনার কমান্ডের স্ট্যান্ডার্ড ত্রুটিটি এখনও শেলটিকে তার স্ট্যান্ডার্ড ত্রুটি হিসাবে ব্যবহার করে into

আপনি আসলে একটি কমান্ডের পরিবেশ সন্ধান করে দেখতে পারেন /proc/[pid]/fd: ls -lপ্রতীকী লিঙ্কের বিষয়বস্তু তালিকাভুক্ত করতেও ব্যবহার করুন। 0ফাইল এখানে স্ট্যান্ডার্ড ইনপুট হয়, 1মান আউটপুট এবং 2মান ত্রুটি। যদি কমান্ডটি আরও ফাইল খুলবে (এবং বেশিরভাগ প্রোগ্রামগুলি করে), আপনি সেগুলিও দেখতে পাবেন। একটি প্রোগ্রাম এছাড়াও পুনর্নির্দেশ বা তার মান ইনপুট / আউটপুট এবং পুনরায় ব্যবহার বন্ধ করা চয়ন করতে পারেন 0, 1এবং 2


41

আপনি আপনার স্ক্রিপ্টের শীর্ষে এই জাতীয় নির্বাহক ব্যবহার করতে পারেন:

exec > >(tee "$HOME/somefile.log") 2>&1

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

#!/bin/bash -

exec > >(tee "$HOME/somefile.log") 2>&1

echo "$HOME"
echo hi
date
date +%F
echo bye 1>&2

আমাকে ফাইল $HOME/somefile.logএবং টার্মিনালটিতে এভাবে আউটপুট দেয় :

/home/saml
hi
Sun Jan 20 13:54:17 EST 2013
2013-01-20
bye

2
মনে রাখবেন যে এটি বাশিজম ব্যবহার করে - এটি অন্যান্য শেলগুলিতে (যেমন, ড্যাশ) কাজ নাও করতে পারে। তবে প্রশ্নটি বাশকে নির্দিষ্ট করেছে, +1।
রিচার্ড হ্যানসেন

8
রিচার্ডহানসেন, প্রক্রিয়া প্রতিস্থাপন এমন একটি বৈশিষ্ট্য যা ksh দ্বারা প্রবর্তিত হয়েছিল, বাশ নয় এবং zsh দ্বারা সমর্থিতও তাই আমি এটিকে বাশিজম বলব না ।
স্টাফেন চেজেলাস

6
@ স্টাফেনচাজেলাস: আপনি ভাল বক্তব্য রেখেছেন। আমি কেবল এটি উল্লেখ করতে চেয়েছিলাম যে সিনট্যাক্সটি পসিক্স স্ট্যান্ডার্ড দ্বারা সমর্থিত নয় এবং এটি সর্বজনীনভাবে /bin/shস্ক্রিপ্টগুলিতে কাজ করবে না (অনেক লোক স্ক্রিপ্টগুলিতে ভুলক্রমে ব্যাশ সিনট্যাক্স ব্যবহার করে /bin/sh)।
রিচার্ড হ্যানসেন

আমার জন্য এটি /dev/fd/62: Operation not supportedকোন ক্লু দেয় ?
Eun

1
লগ ফাইল বাদে স্ট্যাডারকে পুনঃনির্দেশ না করার কোনও উপায় আছে? যদি মূল স্ক্রিপ্টটি হয় myscriptএবং আমি চালিত হয় তবে ./myscript > /dev/nullআমার এখনও দেখা উচিত byeযা থেকে এসেছে echo bye >&2
মার্টিন জাম্বন

0

স্টার্ডার লিখুন এবং একটি ফাইলে স্টডআউট করুন, স্ক্রিনে স্ট্যাডার প্রদর্শন করুন (স্টাডআউটে)

exec 2> >(tee -a -i "$HOME/somefile.log")
exec >> "$HOME/somefile.log"

ক্রোনগুলির জন্য দরকারী, যাতে আপনি মেল দ্বারা ত্রুটিগুলি (এবং কেবল ত্রুটিগুলি) পেতে পারেন

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