এটি কি বাশ ম্যানুয়ালটির পুনঃনির্দেশ বিভাগে টাইপো?


13
Note that the order of redirections is significant.  For example, the command

          ls > dirlist 2>&1

   directs both standard output and standard error to the file dirlist, 
   while the command

          ls 2>&1 > dirlist

   directs  only  the  standard  output  to  file  dirlist,  because the 
   standard error was duplicated from the standard output before the standard
   output was redirected to dirlist.

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

দেখে মনে হচ্ছে এটি "বলে রাখা উচিত কারণ স্ট্যান্ডার্ড আউটপুটটি গাড়িচালককে পুনঃনির্দেশিত করার পরে স্ট্যান্ডার্ড ত্রুটিটি স্ট্যান্ডার্ড আউটপুট থেকে নকল করা হয়েছিল"। STDOUT কোনও ফাইলের দিকে পরিচালিত হওয়ার আগে যদি STDERR কে STDOUT এ প্রেরণ করা হত, তবে ফাইলটি STDOUT এবং STDERR থাকতে পারে না?

কেউ দয়া করে আমার জন্য এটি পরিষ্কার করতে পারেন? এটা কি আমার পক্ষে পড়ার দরিদ্র বোধগম্যতা? সদৃশ শব্দের ব্যবহার এই প্রসঙ্গে আমার কাছে কিছুটা অদ্ভুত বলে মনে হয়। সম্ভবত এটি আমাকে ছুড়ে ফেলেছে।



1
মিশ্রণ ক্রিয়াকলাপগুলির একটি সর্বোত্তম কেস যা "মান অনুসারে" বনাম "রেফারেন্স দ্বারা"। আপনি যখন কোনও ফাইল বর্ণনাকারীর সদৃশ করেন তখন এটি একটি মান অপারেশন। প্রোগ্রামিংয়ে, a = 1; b = a; a = 2আপনি a == 2 && b == 1সত্য হওয়ার প্রত্যাশার পরে । পুনঃনির্দেশটি অ্যাসাইনমেন্টের 2>&1অনুরূপ b = a- এটি মান দ্বারা হয়, রেফারেন্স দ্বারা নয়। 2>&1চিরকালের জন্য বর্ণনাকারী 1 ফাইল করার জন্য ফাইল বর্ণনাকারী 2 ফাইল রাখে না - তারা এখনও 2 স্বতন্ত্র ফাইল বর্ণনাকারী, যারা একই ফাইলটিতে নির্দেশ করে।
jw013

উত্তর:


23

সদৃশ এখানে সত্যই গুরুত্বপূর্ণ অংশ।

পুনরায়নির্দেশের আগে ফাইল বর্ণনাকারী কোথায় চলেছে তা দেখুন। এটি সাধারণত বর্তমান টার্মিনাল, যেমন:

STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1

এখন, আমরা যদি ls -lপুনঃনির্দেশ ছাড়াই কল করি তবে আউটপুট এবং ত্রুটি বার্তাগুলি আমার টার্মিনালের নীচে চলে /dev/pts/1

আমরা যদি প্রথমে STDOUTকোনও ফাইলের ( ls -l > dirlist) এ পুনঃনির্দেশ করি , তবে এটির মতো দেখাচ্ছে:

STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1

আমরা যখন তারপর পুনর্নির্দেশ STDERRএকটি থেকে ডুপ্লিকেট এর STDOUT'র ফাইল বর্ণনাকারী ( ls -l > dirlist 2>&1), STDERRসদৃশ যায় /home/bon/dirlist:

STDOUT ---> /home/bon/dirlist
STDERR ---> /home/bon/dirlist

যদি আমরা প্রথমে এর ফাইল বর্ণনাকারীর ( ) STDERRনকলটি পুনর্নির্দেশ করি :STDOUTls -l 2>&1

STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1

এবং তারপরে STDOUT একটি ফাইল ( ls -l 2>&1 > dirlist) এ, আমরা এটি পেয়ে যাব:

STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1

এখানে, STDERRএখনও টার্মিনালে যাচ্ছে।

আপনি দেখতে পাচ্ছেন, ম্যান পেজে ক্রমটি সঠিক।


পুনর্নির্দেশ পরীক্ষা করা হচ্ছে

এখন, আপনি এটি পরীক্ষা করতে পারেন। ব্যবহার করে ls -l /proc/$$/fd/আপনি দেখতে পাবেন যেখানে STDOUT(এফডি 1 সহ) এবং STDERR(এফডি 2 সহ) বর্তমান প্রক্রিয়াটি চলছে:

$ ls -l /proc/$$/fd/
total 0
lrwx------ 1 bon bon 64 Jul 24 18:19 0 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 18:19 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 07:41 2 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 18:19 255 -> /dev/pts/1

আসুন একটি ছোট শেল স্ক্রিপ্ট তৈরি করুন যা দেখায় যে আপনার ফাইল বর্ণনাকারীদের কোথায় নির্দেশ করা হয়েছে। এইভাবে, lsকলিং শেল থেকে কোনও পুনর্নির্দেশ সহ কল করার সময় আমরা সর্বদা রাষ্ট্র পাই get

$ cat > lookfd.sh
#!/bin/sh
ls -l /proc/$$/fd/
^D
$ chmod +x lookfd.sh

(এর সাথে CtrlD, আপনি ফাইলের শেষের দিকে প্রেরণ করুন এবং সুতরাং catআদেশটি পাঠানো বন্ধ করুন STDIN))

পুনঃনির্দেশের বিভিন্ন সংমিশ্রণ সহ এখন এই স্ক্রিপ্টটি কল করুন:

$ ./lookfd.sh 
total 0
lrwx------ 1 bon bon 64 Jul 24 19:08 0 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:08 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:08 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:08 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh > foo.out
$ cat foo.out 
total 0
lrwx------ 1 bon bon 64 Jul 24 19:10 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:10 1 -> /home/bon/foo.out
lrwx------ 1 bon bon 64 Jul 24 19:10 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:10 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh 2>&1 > foo.out
$ cat foo.out 
total 0
lrwx------ 1 bon bon 64 Jul 24 19:10 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:10 1 -> /home/bon/foo.out
lrwx------ 1 bon bon 64 Jul 24 19:10 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:10 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh > foo.out 2>&1
$ cat foo.out 
total 0
lrwx------ 1 bon bon 64 Jul 24 19:11 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:11 1 -> /home/bon/foo.out
l-wx------ 1 bon bon 64 Jul 24 19:11 2 -> /home/bon/foo.out
lr-x------ 1 bon bon 64 Jul 24 19:11 255 -> /home/bon/lookfd.sh

আপনি দেখতে পাচ্ছেন, ফাইল বর্ণনাকারী 1 (for STDOUT) এবং 2 (for STDERR) পৃথক হয়। মজা করার জন্য, আপনি পুনর্নির্দেশ STDINএবং ফলাফল দেখতে পারেন:

$ ./lookfd.sh < /dev/zero
total 0
lr-x------ 1 bon bon 64 Jul 24 19:18 0 -> /dev/zero
lrwx------ 1 bon bon 64 Jul 24 19:18 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:18 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:18 255 -> /home/bon/lookfd.sh

(পাঠকের কাছে প্রশ্ন রেখে গেছে: ফাইল বিবরণকারী 255 পয়েন্টটি কোথায় করবে ?;-))


+1 - দুর্দান্ত উত্তর। অত্যন্ত ভাল লেখা এবং ভয়ঙ্কর উদাহরণ। ধন্যবাদ!!!
slm

আমি দেখতে পাচ্ছি, আমার মনে হয় আমার ভুল বোঝাবুঝিটি ছিল যে নীচের সমস্ত কমান্ডের জন্য পুনঃনির্দেশটি স্থির থাকবে, যাতে বাকী লাইনের জন্য যে কোনও এসটিডিআরআর STDOUT এ যায়।
গ্রেগ লেভেন্টাল

2

না, ম্যানুয়ালটি ঠিক আছে।

যদি প্রথম টার্মিনালটিতে 1 টি এবং টার্মিনালের 2 টিও হয়, তবে:

command  2>&1   1>somewhere

পুনঃনির্দেশ মূল্যায়নটি বাম থেকে ডানে ঘটবে।

সুতরাং এটি FIRST মূল্যায়ন করবে 2>&1এবং এইভাবে FIRST এফডি কীভাবে 1নির্দেশ করবে (যেমন the terminal, সাধারণত / dev / tty এর ফাইল বর্ণনাকারী ) এফডিতে রূপান্তর করে 2

সুতরাং সেই সময়ে এফডি 2এখন নির্দেশ করে যেখানে এফডি 1নির্দেশ করে ( the terminal)

এবং তারপরে 1>somewhereঅংশটি মূল্যায়ন করে এবং এর ফলে somewhereএফডি- র ফাইল বর্ণনাকারীটি অনুলিপি করবে 1(সুতরাং এই মুহুর্তে, এফডি 1এখন পয়েন্ট করবে somewhereএবং এফডি 2এখনও পয়েন্ট করবে the terminal)

সুতরাং এটি প্রকৃতপক্ষে 1 কে "কোথাও" এবং 2 টি টার্মিনালে প্রিন্ট করে, কারণ 2 টি আগে 1 টির আগে 1 থেকে নকল করা হয়েছিল।

অন্য আদেশ:

command  1>somewhere 2>&1

প্রথম পুনর্নির্দেশ FD হবে 1থেকে somewhere, এবং তারপর FD 2 মধ্যে যে একই রেফারেন্স কপি, তাই শেষ 2 এছাড়াও পয়েন্ট এ somewhere। তবে তারা এখন থেকে "সংযুক্ত" নয়। প্রতিটি এখনও আলাদাভাবে পুনঃনির্দেশিত করা যেতে পারে।

উদা:

command  1>somewhere 2>&1
exec 2>/dev/null

এটির শেষে, এফডি 1নির্দেশ করে somewhereএবং এফডি 2নির্দেশিত হয়/dev/null

Fd- 1র সাধারণ নামগুলি STDOUT (স্ট্যান্ডার্ড আউটপুট), এবং fd এর স্বাভাবিক নাম 2STDERR (স্ট্যান্ডার্ড ত্রুটি, কারণ এটি সাধারণত STDOUT এ হস্তক্ষেপ না করে ত্রুটি প্রদর্শন করতে ব্যবহৃত হয়)


@ মাইকেল-মরোজেক: সম্পাদনার জন্য ধন্যবাদ, তবে আমি "অনুলিপি" এর পরিবর্তে "অনুলিপি" না দিয়ে "অনুলিপি" বলার জন্য জোর দিয়েছি যে এখন থেকে উভয়ই "একই জিনিস" বিশ্বাস করতে পারে, যা সত্য নয়। উদাহরণস্বরূপ: cmd 1>somewhere 2>&1 ; exec 2>/dev/nullসম্পাদকের পরে, কেবল 2 টি / dev / নালটিতে পুনঃনির্দেশ করা হয়েছে (1 এখনও "কোথাও" চলছে)। "এফডি 1" এর পরিবর্তে "কী 1 পয়েন্ট" বলার উপায় নিয়ে আসতে আমার সাহায্য দরকার, তবে এটিও বিভ্রান্তিকর ...
অলিভিয়ার ডুলাক

1
আপনি কি বোঝাতে চাচ্ছেন তা আমি নিশ্চিত নই; আপনিই সেই ব্যক্তি যিনি এটিকে "অনুলিপি" থেকে "সদৃশ" হিসাবে পরিবর্তন করেছেন। আমি যা কিছু করেছি সেগুলি মূলধন এবং ফর্ম্যাট করেছিলাম, আমি একটি শব্দও পরিবর্তন করিনি
মাইকেল মরোজেক

দোহ ... ... দুঃখিত আর যা সম্পাদনা করা হয়েছে তাতে আরও সুনির্দিষ্ট করে তুলতে আমি আবারও সম্পাদনা করেছি
অলিভিয়ার ডুলাক

1

আমি মনে করি যে এখানে বিভ্রান্তিকর অংশটি হ'ল স্ট্রডারকে স্ট্রাউডে পুনঃনির্দেশিত করাই আসলে দু'টি প্রবাহকে সংযুক্ত করে।

একটি পুরোপুরি যুক্তিসঙ্গত ধারণা তবে আপনি যখন লেখেন তখন 2>&1স্টেডার কী স্টিডাউট লিখছেন এবং একই জায়গায় লিখেছেন তা একটি পিকুবু নেয়। অতএব আপনি যদি পরবর্তীকালে স্টাডাউটকে অন্য কোথাও লিখতে যেতে বলেন তবে এটি ইতিমধ্যে সরানো স্টাডারের গন্তব্যে কোনও প্রভাব ফেলবে না।

আমি মনে করি এটি আমার কাছে একটি পাল্টা প্রতিরোধী তবে এটি কীভাবে কাজ করে। আপনি যেখানে লিখতে চান সেখানে সেট আপ করুন তারপরে সবাইকে "আমাকে কপি করুন" বলুন। আশা করি তা স্পষ্ট হয়ে গেছে ...


0

অনুলিপি ...

এটি গুরুত্বপূর্ণ, তবে এই অর্থে যে এটি অনেক বিভ্রান্তির উত্স । এটা সত্যিই বেশ সহজ। এই উত্তরটি কেবল একটি "র‌্যাডিক্যাল" চিত্রণ।

গৃহীত উত্তরটি ভাল তবে খুব দীর্ঘ এবং এটি "নকল" জোর দেয়।

প্রশ্নটি বুদ্ধিমানের সাথে শেষ হয়:

শব্দ অনুলিপি ব্যবহার এই প্রেক্ষাপটে আমার কাছে একটু অদ্ভুত মনে হয়। সম্ভবত এটি আমাকে ছুড়ে ফেলেছে।

আমি ব্যাশ স্বরলিপি ব্যবহার করি এবং ভেরিয়েবলগুলি "এক" এবং "দুটি" ফাইলহ্যান্ডেল "1" এবং "2" হিসাবে সংজ্ঞায়িত করি। (আউটপুট) পুনঃনির্দেশ অপারেটর >একটি অ্যাসাইনমেন্ট =&এবং এর $অর্থ "মান"।

ম্যান বাশ উদাহরণ (ডিফল্ট "1" যুক্ত)

ls 1>dirlist 2>&1      # both to dirlist
ls 2>&1 1>dirlist      # 1 to dirlist, 2 stays on tty/screen 

পরিণত:

one=dirlist  two=$one

এবং

two=$one   one=dirlist

এমনকি এটি আমার কাছে অ-স্বয়ংক্রিয় এবং অন্যান্য কিছু আমার ধারণা। প্রথম লাইন পাতার আপনার সাথে $oneএবং $twoউভয় ধারণকারী "dirlist"। অবশ্যই.

দ্বিতীয় লাইনটি অকেজো অ্যাসাইনমেন্ট দিয়ে শুরু হয়। উভয়ই তাদের নির্দেশ হিসাবে "টিটিওয়াই" (কিছুটা প্রতীকী) দিয়ে সংজ্ঞা দিয়ে শুরু করেন ; এই অ্যাসাইনমেন্ট দ্বারা কোনও মান পরিবর্তন হয় না, এবং ফাইলহ্যান্ডলগুলির মতো ভেরিয়েবলগুলির সাথে কোনও কিছুই ম্যাজিকালি লিঙ্কযুক্ত হয় না। পরিবর্তনশীল twoনিম্নলিখিত দ্বারা প্রভাবিত হয় না one=dirlist। অবশ্যই না.

সম্বডি এখানে (years বছর আগে) "কপি" বা "সদৃশ" এর পরিবর্তে "পয়েন্ট টু" পরামর্শ দিয়েছিল এবং পরে বুঝতে পেরেছিল: এটিও বিভ্রান্তিকর হবে।

এই সদৃশ বা পয়েন্টার অর্থপূর্ণ এমনকি প্রয়োজন হয় না। সম্ভবত এটি অ্যাম্পারস্যান্ড যা আরও মনোযোগ প্রয়োজন। অপারেটর / টোকেন / যা কিছু "মান"।

যদি - এবং শুধুমাত্র যদি - আপনি আপনার কনসোলে একটি আশ্চর্যজনক জব নম্বর পাওয়ার উপায় খুঁজছেন , তবে "সম্পন্ন" বার্তা বোনাস হিসাবে "2" নামে একটি ফাইল পাবেন, তারপরে আপনি যান:

ls 1>2& 2>/dev/null

এটি স্বাভাবিকভাবে " অনুলিপি" / "সদৃশ" 1 থেকে 2 হিসাবে পড়ে এবং তারপরে উভয় একসাথে শূন্য হয়ে যায় । তবে ধারণাটি ভুল, এবং সিনট্যাক্সও। (তবে কোনও সিনট্যাক্স ত্রুটি নেই, এটি বৈধ)

এটির পরিকল্পনা করার সঠিক উপায় হ'ল দু'জনের যে কোনও একটিকে বাতিল করে ফেলা, এবং তারপরে অন্যটিকে একই জায়গায় পুনঃনির্দেশ করা:

ls 1>/dev/null 2>&1
# or 
ls 2>/dev/null 1>&2

(নেতৃস্থানীয় "1" রেখে যেতে পারে)

(ঠিক আছে অ্যাক্ট। এ খুব দীর্ঘ নয়, তবে তালিকার অনেক বেশি - বা: খুব ভাল দৃশ্যায়ন, এত ভাল ব্যাখ্যা নয়)

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