কীভাবে পসিক্স শেলের সমস্ত আউটপুট `লগার` এ প্রেরণ করবেন?


10

আমি .xprofileব্যবহারের ক্ষেত্রে স্ট্যান্ডার্ড আউটপুট এবং স্ট্যান্ডার্ড ত্রুটি আলাদাভাবে লগ করতে চাই logger। বাশে আমি মনে করি এটি দেখতে এরকম কিছু হবে:

exec 1> >(logger --priority user.notice --tag $(basename $0)) \
     2> >(logger --priority user.error --tag $(basename $0))

আমি কীভাবে এটি পসিক্সের সাথে /bin/sh সামঞ্জস্যপূর্ণভাবে করব?

উত্তর:


10

এখানে কোনও পসিক্স সমতুল্য নেই। আপনি কেবল execকাঁটাচামচ নয়, দিয়ে একটি পুনর্নির্দেশ সম্পাদন করতে পারেন । একটি পাইপের জন্য কাঁটাচামচ প্রয়োজন, এবং শেলটি সন্তানের সমাপ্তির জন্য অপেক্ষা করে।

একটি সমাধান হ'ল কোনও ফাংশনে আপনার সমস্ত কোড স্থাপন করা।

all_my_code () {
  
}
{ all_my_code |
  logger --priority user.notice --tag "$(basename "$0")"; } 2>&1 | 
  logger --priority user.error --tag "$(basename "$0")"

(এটি স্টার্ডার দৃষ্টান্ত থেকে স্টার্ডারের উদাহরণ থেকে কোনও ত্রুটি লগ করে more আপনি আরও ফাইল বর্ণনাকারী এলোমেলো করে এড়াতে পারবেন))

loggerপ্রক্রিয়াগুলি এখনও চলমান থাকলেও আপনি যদি পিতামাত শেলটি প্রস্থান করতে চান &তবে loggerআমন্ত্রণগুলির শেষে রাখুন ।

{ all_my_code |
  logger --priority user.notice --tag "$(basename "$0")" & } 2>&1 | 
  logger --priority user.error --tag "$(basename "$0")" &

বিকল্পভাবে, আপনি নামযুক্ত পাইপ ব্যবহার করতে পারেন।

pipe_dir=$(mktemp -d)
mkfifo "$pipe_dir/out" "$pipe_dir/err"
<"$pipe_dir/out" logger --priority user.notice --tag "$(basename "$0")" &
<"$pipe_dir/err" logger --priority user.error --tag "$(basename "$0")" &
exec >"$pipe_dir/out" 2>"$pipe_dir/err" 

rm -r "$pipe_dir"

এটি পুরো স্ক্রিপ্টের জন্য দু'টি এন্ট্রি (আউট এবং এরআর) হিসাবে সিসলগে প্রদর্শিত হবে। প্রশ্নের উদাহরণটিতে প্রতিটি কমান্ডের জন্য একটি (বা দুটি) প্রবেশ থাকবে।
ডার্কহার্ট

@ ডার্কহার্ট আমি আপনার মন্তব্যটি বুঝতে পারি না। প্রশ্নের কোড এবং উভয় সমাধানের প্রস্তাব আমি একই সংখ্যার উদাহরণগুলি চালনা করি loggerএবং তাদের প্রতিটিটিতে একই ইনপুটটি পাস করি।
গিলস 'অশুভ হওয়া বন্ধ করুন'

দুঃখিত, আমার ভুল
ডার্কহার্ট

1
এটি সহজ বলে মনে হচ্ছে , তাই আমি আপনার নামযুক্ত পাইপ সমাধান নিয়ে যাচ্ছি।
l0b0

9

POSIX কমান্ড / প্রক্রিয়া বিকল্প


_log()( x=0
    while  [ -e "${TMPDIR:=/tmp}/$$.$((x+=1))" ]
    do     continue; done        &&
    mkfifo -- "$TMPDIR/$$.$x"    &&
    printf %s\\n "$TMPDIR/$$.$x" || exit
    exec >&- >/dev/null
    {  rm -- "$TMPDIR/$$.$x"
       logger --priority user."$1" --tag "${0##*/}"
    }  <"$TMPDIR/$$.$x" &
)   <&- </dev/null

আপনার এটির মতো ব্যবহার করতে সক্ষম হওয়া উচিত:

exec >"$(_log notice)" 2>"$(_log error)"

mktempকমান্ডটি ব্যবহার করে এমন একটি সংস্করণ এখানে দেওয়া হয়েছে :

_log()( p=
    mkfifo "${p:=$(mktemp -u)}"    &&
    printf %s "$p"                 &&
    exec  <&- >&- <>/dev/null >&0  &&
    {   rm "$p"
        logger --priority user."$1" --tag "${0##*/}"
    }   <"$p" &
)

... যা এটির mktempজন্য আপনার ফাইল ফাইল নির্বাচন করার অনুমতি দেয় সেগুলি ব্যতীত একই কাজ করে। এটি কাজ করে কারণ প্রক্রিয়া প্রতিস্থাপন কোনওভাবেই যাদুকরী নয় এবং প্রতিস্থাপনের আদেশের ক্ষেত্রে খুব অনুরূপভাবে কাজ করে । কমান্ড সাবস্টিটিউশন যেমন কমান্ডের সাথে চালিত কমান্ডের মান দিয়ে প্রসারণের পরিবর্তে পরিবর্তিত হয়, প্রক্রিয়া প্রতিস্থাপন এটির পরিবর্তে একটি ফাইল সিস্টেম লিঙ্কের নাম দেয় যেখানে আউটপুট পাওয়া যায়।

যদিও পসিক্স শেল এই জাতীয় কোনও সরাসরি করোলারি সরবরাহ করে না, তবে এটি অনুকরণকারী খুব সহজভাবে সম্পন্ন হয়। আপনাকে যা করতে হবে তা হ'ল একটি ফাইল তৈরি করা, একটি নাম কমান্ড প্রতিস্থাপনের বাইরে তার নামটি প্রিন্ট করা এবং একই কমান্ডের পটভূমিতে যা আপনার ফাইলটি আউটপুট দেয়। প্রক্রিয়া প্রতিস্থাপনের সাথে আপনি যেমন করেন ঠিক তেমন আপনি এখন সেই প্রসারণের মানটিতে পুনর্নির্দেশ করতে পারেন । এবং সুতরাং পসিক্স শেলটি আপনাকে অবশ্যই প্রয়োজনীয় সমস্ত সরঞ্জাম সরবরাহ করে - যা প্রয়োজন তা হ'ল আপনি সেগুলি এমনভাবে ব্যবহার করতে পারেন যা আপনার পক্ষে উপযুক্ত।

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


আর একটি উপায় এটি মোড়ানো হয়। এটি স্ক্রিপ্টের মধ্যে থেকে করা যেতে পারে।

x=${x##*[!0-9]*}
_log(){ 
    logger --priority user."$1" --tag "${0##*/}"
}   2>/dev/null >&2

cd ../"$PPID.$x" 2>/dev/null &&
trap 'rm -rf -- "${TMPDIR:-/tmp}/$PPID.$x"' 0 || 
{   until cd -- "${TMPDIR:=/tmp}/$$.$x"
    do    mkdir -- "$TMPDIR/$$.$((x+=1))"
    done  && 
    x=$x "$0" "$@" | _log notice
    exit
}   2>&1 | _log error

এটি মূলত আপনার স্ক্রিপ্টটিকে কল করার অনুমতি দেয় যদি এটি এখনও না পেয়ে থাকে এবং আপনাকে বুট করার জন্য অস্থায়ীভাবে একটি ডিরেক্টরি ডিরেক্টরি পেতে পারে।


1
সম্পন্ন , ধন্যবাদ!
l0b0

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

@ l0b0 - আপনি ব্যবহার করতে চেয়েছিলেন mktempএবং অন্যান্য অ-মানক কমান্ড, এটা হতে পারে: _log()( p=; mkfifo "${p:=$(mktemp -u)}"; printf %s "$p"; exec <&- >&- <>/dev/null >&0; { rm "$p"; logger --priority user."$1" --tag "${0##*/}"; } <"$p" &)। আমি আপনার নিজের ব্যাতিক্রম দিয়ে পুরোপুরি পোর্টেবল কমান্ড ভাষা ব্যবহার করে এটি লিখেছিলাম। এছাড়াও, basenameএকটি খুব দরকারী ইউটিলিটি নয়। "${0##*/}"উভয় আরও মজবুত এবং দ্রুত।
মাইকসার্ভ

আমি এটি পরিবর্তন করেছি কারণ আমার কেবল আধুনিক প্ল্যাটফর্মগুলিতে কাজ করা দরকার; প্রধান সমস্যাটি ছিল .xprofile হয়েছে সঙ্গে নিষ্পন্ন করা হবে sh
l0b0

1
@ উইল্ডকার্ড - মাত্র এক মিনিট এবং আমি প্রশ্নের প্রথম অংশটি সাজানোর চেষ্টা করব, তবে দ্বিতীয়টির উত্তর হ্যাঁ: প্রান্তের zshকেসটি ডাব্লু / মাল্টো সক্ষম os প্রথম অংশ হিসাবে: { this; can\'t; happen; before; } < this। এটা কি সাহায্য করে?
মাইকজার্ভ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.