ফাইল বর্ণনাকারী স্থানান্তর করার জন্য ব্যবহারিক ব্যবহার


16

বাশ ম্যান পৃষ্ঠা অনুসারে:

পুনঃনির্দেশ অপারেটর

   [n]<&digit-

ফাইল বর্ণনাকারীকে digitফাইল বর্ণনাকারী nবা স্ট্যান্ডার্ড ইনপুট (ফাইল বর্ণনাকারী 0) এ সরিয়ে দেয় যদি nনির্দিষ্ট না করা হয়। digitদুপলি হওয়ার পরে বন্ধ হয়ে গেছে n

ফাইল বিবরণকারীকে অন্য একটিতে "সরানো" এর অর্থ কী? এই ধরনের অনুশীলনের জন্য সাধারণ পরিস্থিতিগুলি কী কী?

উত্তর:


14

3>&4-একটি ksh93 এক্সটেনশান এছাড়াও বাশ দ্বারা সমর্থিত এবং এটি সংক্ষিপ্ত 3>&4 4>&-, এটি এখন 3 যেখানে 4 ব্যবহৃত হয় এখন নির্দেশ করে, এবং 4 এখন বন্ধ, সুতরাং 4 দ্বারা চিহ্নিত করা এখন 3 এ চলে গেছে।

সাধারণ ব্যবহার আপনি নকল করেছেন stdinবা এর stdoutঅনুলিপি সংরক্ষণ করতে এবং এটি পুনরুদ্ধার করতে চান এমন ক্ষেত্রে যেমন:

ধরুন আপনি কোনও ভেরিয়েবলের একা একা রেখে কমান্ডের স্টডারার (এবং কেবল স্টডার) ক্যাপচার করতে চান।

কমান্ড প্রতিস্থাপন var=$(cmd), একটি পাইপ তৈরি করে। পাইপের লেখার cmdপ্রান্তটি স্ট্যাডআউট (ফাইলের বর্ণনাকারী 1) হয়ে যায় এবং অন্য প্রান্তটি ভেরিয়েবলটি পূরণ করার জন্য শেলটি দিয়ে পড়ে।

এখন, আপনি যদি চান stderrপরিবর্তনশীল যেতে, আপনি কি পারে: var=$(cmd 2>&1)। এখন fd 1 (stdout) এবং 2 (stderr) উভয় পাইপ (এবং অবশেষে পরিবর্তনশীল) এ যান, যা আমরা যা চাই তার অর্ধেক মাত্র।

যদি আমরা var=$(cmd 2>&1-)(সংক্ষেপে var=$(cmd 2>&1 >&-) করি cmd, তবে কেবলমাত্র স্টাডার পাইপে যায় তবে fd 1 বন্ধ থাকে। যদি cmdকোনও আউটপুট লেখার চেষ্টা করা হয়, এটি একটি EBADFত্রুটি দিয়ে ফিরে আসবে , যদি এটি কোনও ফাইল খোলায়, এটি প্রথম ফ্রি এফডি পাবে stdoutএবং কমান্ড তার বিরুদ্ধে রক্ষিত না হলে খোলা ফাইলটিকে নির্ধারিত করা হবে ! আমরা যা চাই তা নয় Not

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

{
  var=$(cmd)
} 3>&1

কোনটি পরিষ্কার লেখার উপায়:

exec 3>&1
var=$(cmd)
exec 3>&-

(এটি শেষ পর্যন্ত বন্ধ করার পরিবর্তে এফডি 3 পুনরুদ্ধার করার সুবিধাও রয়েছে)।

তারপরে {(বা exec 3>&1) এবং }সর্বোপরি, উভয় এফডি 1 এবং 3 একই উত্সটির দিকে নির্দেশ করে fd 1 প্রাথমিকভাবে নির্দেশ করে। কমান্ড সাবস্টিটিউশনের ভিতরে এইচডি 3 টি সেই সংস্থানটির দিকেও ইঙ্গিত করবে (কমান্ড সাবস্টিটিউশন কেবলমাত্র fd 1, stdout পুনর্নির্দেশ করে)। উপরে তাই, জন্য cmd, আমরা এফডিএস 1, 2, 3 পেয়েছি:

  1. পাইপটি ভারে
  2. অস্পৃষ্ট
  3. কমান্ড প্রতিস্থাপনের বাইরে 1 পয়েন্ট হিসাবে একই

যদি আমরা এটিকে পরিবর্তন করি:

{
  var=$(cmd 2>&1 >&3)
} 3>&1-

তারপরে এটি হয়ে যায়:

  1. কমান্ড প্রতিস্থাপনের বাইরে 1 পয়েন্ট হিসাবে একই
  2. পাইপটি ভারে
  3. কমান্ড প্রতিস্থাপনের বাইরে 1 পয়েন্ট হিসাবে একই

এখন, আমরা যা চেয়েছিলাম তা পেয়েছি: স্টার্ডার পাইপের কাছে যায় এবং স্টাডআউটটি অদৃশ্য হয়ে যায়। তবে আমরা সেই এফডি 3 থেকে ফাঁস করছি cmd

কমান্ডগুলি (কনভেনশন অনুসারে) fds 0 থেকে 2 টি উন্মুক্ত এবং মানক ইনপুট, আউটপুট এবং ত্রুটি হিসাবে ধরে নেয়, তারা অন্যান্য এফডিএসের কিছুই গ্রহণ করে না। সম্ভবত তারা এফডি 3 টি ছেড়ে চলে যাবে। তাদের যদি অন্য কোনও ফাইল বর্ণনাকারীর প্রয়োজন হয় তবে তারা কেবল এমনটি করবেন open()/dup()/socket()...যা প্রথম উপলব্ধ ফাইল বিবরণী ফিরিয়ে দেবে। যদি (শেল স্ক্রিপ্টের মতো এটি exec 3>&1) তাদের fdবিশেষভাবে এটি ব্যবহারের প্রয়োজন হয় তবে তারা প্রথমে এটি কোনও কিছুতে অর্পণ করবে (এবং সেই প্রক্রিয়াতে, আমাদের এফডি 3 দ্বারা পরিচালিত সংস্থানটি সেই প্রক্রিয়াটি প্রকাশ করবে)।

এফডি 3 বন্ধ করার পক্ষে এটি ভাল অনুশীলন যেহেতু cmdএটি ব্যবহার করে না, তবে এটি কল করার আগে যদি আমরা এটি নির্ধারিত ত্যাগ করি তবে এটি কোনও বড় কথা cmd। সমস্যাগুলি হতে পারে: এটি cmd(এবং অন্যান্য সম্ভাব্য প্রসেসগুলি যা এটি তৈরি করে) এর কাছে এটির তুলনায় আরও কিছু কম পরিমাণে এফডি পাওয়া যায়। একটি সম্ভাব্য আরও গুরুতর সমস্যা হ'ল যদি এইচডি পয়েন্ট যে সংস্থানটি cmdব্যাকগ্রাউন্ডে তৈরি হওয়া কোনও প্রক্রিয়া দ্বারা শেষ হতে পারে । এটি উদ্বেগের কারণ হতে পারে যদি সেই সংস্থানটি কোনও পাইপ বা অন্য আন্ত-প্রক্রিয়া যোগাযোগের চ্যানেল হয় (যেমন আপনার স্ক্রিপ্টটি যখন চালিত হয় script_output=$(your-script)), এর অর্থ অন্য প্রান্ত থেকে প্রক্রিয়াটি পড়া কখনই ফাইলের শেষের দিকে দেখবে না পটভূমি প্রক্রিয়া সমাপ্ত।

সুতরাং এখানে, এটি লিখতে ভাল:

{
  var=$(cmd 2>&1 >&3 3>&-)
} 3>&1

যা দিয়ে bashসংক্ষিপ্ত করা যেতে পারে:

{
  var=$(cmd 2>&1 >&3-)
} 3>&1

এটি খুব কম ব্যবহৃত হয়েছে তার কারণগুলি সংক্ষেপে:

  1. এটি অ-মানক এবং কেবল সিনট্যাকটিক চিনি। আপনার স্ক্রিপ্টটি কম পোর্টেবল এবং সেই অস্বাভাবিক বৈশিষ্ট্যটির সাথে ব্যবহার না করা লোকের কাছে কম সুস্পষ্ট করে তুলতে আপনার কয়েকটি কীস্ট্রোক সংরক্ষণের ভারসাম্য বজায় রাখতে হবে।
  2. আসল এফডিটিকে ডুপ্লিকেট করার পরে বন্ধ করার প্রয়োজনীয়তাটি প্রায়শই উপেক্ষা করা হয় কারণ বেশিরভাগ সময় আমরা ফলাফলটি ভোগ করি না, তাই আমরা কেবল এর >&3পরিবর্তে >&3-বা করি >&3 3>&-

প্রমাণ যে এটি খুব কমই ব্যবহার করা হয়েছে, যেমন আপনি আবিষ্কার করেছেন যে এটি ব্যাশে বোগাস । ব্যাশে compound-command 3>&4-বা any-builtin 3>&4-পাতার 4 বন্ধ পরেও FD compound-commandবা any-builtinফিরে এসেছে। সমস্যা সমাধানের জন্য একটি প্যাচ এখন (2013-02-19) উপলভ্য।


ধন্যবাদ, এখন আমি জানি যে এফডি কি সরানো। আমার ২ য় স্নিপেট (এবং সাধারণভাবে এফডিএস) সম্পর্কিত 4 ​​টি প্রাথমিক প্রশ্ন রয়েছে: 1) সেন্টিমিডি 1-তে আপনি 2 (স্ট্ডার) 3 টির অনুলিপি করেন, যদি আদেশটি অভ্যন্তরীণভাবে এই 3 এফডি ব্যবহার করে? 2) 3> & 1 এবং 4> & 1 কেন কাজ করে? 3 এবং 4 এর সদৃশটি কেবল সেই দুটি সেন্টিমিটারে কার্যকর হয়, বর্তমান শেলটিও ক্ষতিগ্রস্ত হয়? 3) কেন আপনি 4 সেন্টিমিডি 1 এবং 3 সেন্টিমিডি 2 বন্ধ করবেন? এই আদেশগুলি উল্লিখিত এফডিএস ব্যবহার করে না, তাই না? 4) শেষ স্নিপেটে, যদি কোনও fd কোনও অস্তিত্বহীন (সেন্টিমিডি 1 এবং সেমিডি 2 তে) নকল হয় তবে আমার অর্থ যথাক্রমে 3 এবং 4 হবে?
কুইন্টিন

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

{ var=$(cmd 2>&1 >&3) ; } 3>&1-এটি কি 1 টি বন্ধ করার টাইপো নয়?
কোয়ান্টিন

@ কেন্টিন, এটি এমন একটি টাইপ যা আমি মনে করি না যে আমি এটি অন্তর্ভুক্ত করেছিলাম, তবে এটির কোনও তাত্পর্য নেই কারণ ধনুর্বন্ধনীগুলির অভ্যন্তরের কিছুই এফডি 1 ব্যবহার করে না (এটি এফডি 3 তে নকল করার পুরো বিষয় ছিল: কারণ আসল 1 অন্যথায় ভিতরে প্রবেশযোগ্য হবে না $(...))।
স্টাফেন চেজেলাস

1
@ কন্টিন প্রবেশের পরে {...}, এফডি 3 পয়েন্টটি কীভাবে নির্দেশ করে এবং এফডি 1 বন্ধ হয় তার দিকে 3 পয়েন্ট বন্ধ করে, তারপরে প্রবেশের পরে $(...), এফডি 1 টি পাইপগুলিতে সেট করা থাকে যা ফিডগুলি সরবরাহ করে $var, তারপরে cmd2 তেও, এবং তারপরে 1 থেকে কোন 3 পয়েন্টে to, এটি বাহ্যিক ১. পরে 1 টি বন্ধ থাকার বিষয়টি ব্যাশ-এ থাকা একটি বাগ, আমি এটি রিপোর্ট করব। ksh93 যেখানে বৈশিষ্ট্যটি আসে সেটিতে সেই বাগ নেই।
স্টাফেন চেজেলাস

4

এর অর্থ এটি অন্য ফাইল ডেস্ক্রিপ্টর একই জায়গায় নির্দেশ করে to আপনি দূরে মান ত্রুটি বর্ণনাকারী এর সুস্পষ্ট পৃথক হ্যান্ডলিং থেকে খুব কমই এই কাজ করতে, হবে ( stderr, fd 2, /dev/stderr -> /proc/self/fd/2)। এটি কিছু জটিল ক্ষেত্রে কার্যকর হতে পারে।

অ্যাডভান্সড বাশ স্ক্রিপ্টিং গাইডটির লগ স্তরের এই দীর্ঘ উদাহরণ এবং এই স্নিপেট রয়েছে:

# Redirecting only stderr to a pipe.
exec 3>&1                              # Save current "value" of stdout.
ls -l 2>&1 >&3 3>&- | grep bad 3>&-    # Close fd 3 for 'grep' (but not 'ls').
#              ^^^^   ^^^^
exec 3>&-                              # Now close it for the remainder of the script.

উত্স Mage এর যাদুবিদ্যায় আমরা উদাহরণস্বরূপ একই কোড ব্লক থেকে বিভিন্ন আউটপুট সনাক্ত করতে এটি ব্যবহার করি:

  (
    # everything is set, so run the actual build infrastructure
    run_build
  ) 3> >(tee -a $C_LOG >> /dev/stdout) \
    2> >(tee -a $C_LOG 1>&2 > $VOYEUR_STDERR) \
     > >(tee -a $C_LOG > $VOYEUR_STDOUT)

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


0

ইউনিক্সে ফাইলগুলি ফাইল বর্ণনাকারী দ্বারা পরিচালিত হয় (ছোট্ট পূর্ণসংখ্যাগুলি, উদাহরণস্বরূপ স্ট্যান্ডার্ড ইনপুট 0 হয়, স্ট্যান্ডার্ড আউটপুট 1 হয়, স্ট্যান্ডার্ড ত্রুটি 2 হয়; আপনি অন্যান্য ফাইলগুলি খোলার সাথে সাথে তারা সাধারণত সর্বনিম্ন অব্যবহৃত বর্ণনাকারী হিসাবে নির্ধারিত হয়)। সুতরাং যদি আপনি প্রোগ্রামটির অন্তর্গত বিষয়গুলি জানেন, এবং আপনি স্ট্যান্ডার্ড আউটপুটে বর্ণনাকারী 5 ফাইল করতে যে আউটপুটটি প্রেরণ করতে চান, আপনি বর্ণনাকারী 5 থেকে 1 এ স্থানান্তরিত করতে চান, এখান থেকেই 2> errorsআসে, এবং 2>&1নির্মাণগুলি ত্রুটির অনুলিপি করতে পছন্দ করে আউটপুট স্ট্রিম।

সুতরাং, খুব কমই কখনও ব্যবহার করা হয় (আমার প্রায় 25+ বছরের একচেটিয়া ইউনিক্স ব্যবহারের সময় আমি ক্রোধে একবার বা দু'বার ব্যবহার করা অস্পষ্টভাবে মনে করি), তবে যখন একেবারে প্রয়োজনীয়।


তবে নীচের উপায়ে ফাইল বর্ণনাকারী 1টিকে কেন নকল করবেন না: 5> & 1? কার্নেলটি ঠিক পরে এটি বন্ধ করতে চলেছে বলে এফডি স্থানান্তরকরণের কী ব্যবহার তা আমি বুঝতে পারি না ...
কোয়ান্টিন

এটি 5 কে 1 তে নকল করে না, এটি 5 কোথায় পাঠাচ্ছে যেখানে 1 যাচ্ছে। এবং জিজ্ঞাসার আগে; হ্যাঁ, বিভিন্ন পূর্ববর্তী শেল থেকে নেওয়া বিভিন্ন আলাদা স্বরলিপি রয়েছে।
ভনব্র্যান্ড

তবুও পাবে না। যদি 5>&15 কে পাঠায় যেখানে 1 যাচ্ছে, তবে 1>&5-5 টি বন্ধ করার সাথে সাথে ঠিক কী করবে ?
কোয়ান্টিন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.