কোডটিতে "{এক্সিকিউটিউট> / দেব / নাল; }> / দেব / নাল "হুডের নীচে কী হচ্ছে?


15

যখন আপনি একটি কমান্ডের তালিকা পুনর্নির্দেশ করেন যা এক্সিকিউটি রিডাইরেকশন ধারণ করে, এক্সিকিউটিভ / / দেব / নাল এখনও পরে প্রয়োগ করা হবে বলে মনে হয় না যেমন:

{ exec >/dev/null; } >/dev/null; echo "Hi"

"হাই" ছাপা হয়

আমি এই ছাপে ছিলাম যে {}কমান্ড তালিকাটি যদি পাইপলাইনের অংশ না হয় তবে সাব- exec >/dev/nullশেল হিসাবে বিবেচিত হবে না, সুতরাং এটি এখনও আমার মনের বর্তমান শেল পরিবেশের মধ্যে প্রয়োগ করা উচিত।

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

{ exec >/dev/null; } 2>/dev/null; echo "Hi"

আশানুরূপ কোনও আউটপুট নেই; ফাইল বর্ণনাকারী 1 ভবিষ্যতে কমান্ডের পাশাপাশি / dev / নালকে লক্ষ্য করা যায়। এটি পুনরায় চালনার মাধ্যমে দেখানো হয়েছে:

{ exec >/dev/null; } >/dev/null; echo "Hi"

যা কোনও আউটপুট দেবে না।

আমি একটি স্ক্রিপ্ট তৈরি এবং এটি স্ট্রাক করার চেষ্টা করেছি, তবে আমি এখানে এখনও ঠিক কী ঘটছে তা সম্পর্কে নিশ্চিত নই।

এই স্ক্রিপ্টের প্রতিটি বিন্দুতে STDOUT ফাইল বর্ণনাকারীর কী হচ্ছে?

সম্পাদনা: আমার স্ট্রেস আউটপুট যুক্ত করা হচ্ছে:

read(255, "#!/usr/bin/env bash\n{ exec 1>/de"..., 65) = 65
open("/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
fcntl(1, F_GETFD)                       = 0
fcntl(1, F_DUPFD, 10)                   = 10
fcntl(1, F_GETFD)                       = 0
fcntl(10, F_SETFD, FD_CLOEXEC)          = 0
dup2(3, 1)                              = 1
close(3)                                = 0
close(10)                               = 0
open("/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
fcntl(1, F_GETFD)                       = 0
fcntl(1, F_DUPFD, 10)                   = 10
fcntl(1, F_GETFD)                       = 0
fcntl(10, F_SETFD, FD_CLOEXEC)          = 0
dup2(3, 1)                              = 1
close(3)                                = 0
dup2(10, 1)                             = 1
fcntl(10, F_GETFD)                      = 0x1 (flags FD_CLOEXEC)
close(10)                               = 0
fstat(1, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0
ioctl(1, TCGETS, 0x7ffee027ef90)        = -1 ENOTTY (Inappropriate ioctl for device)
write(1, "hi\n", 3)                     = 3

এটা অদ্ভুত; আমি এর পুনরুত্পাদন করতে পারি না close(10)। আপনি নিজের স্ক্রিপ্টের সম্পূর্ণ লিখিত সামগ্রীও পোস্ট করতে পারেন যার উপর আপনি স্ট্রেস রেখেছিলেন?
ডিপ্রেশনডানিয়েল

: @DepressedDaniel এখানে পূর্ণ স্ক্রিপ্ট এবং strace, হয় স্ক্রিপ্ট strace,
জোয়ি Pabalinas

আপনার ;পরে একটি বিপথগামী হয়েছে }, যা সর্বোপরি > /dev/nullযৌগিক তালিকায় প্রয়োগ না করার অর্থ পরিবর্তন করে {}
ডিপ্রেশনডানিয়েল

ডিপ্রেশনড ডানিয়েল আহ, আপনি পুরোপুরি সঠিক! এখন আউটপুট আমি আশা করি; আপনার উত্তরের জন্য ধন্যবাদ!
জোয় পাবালিনাস

উত্তর:


17

চলুন অনুসরণ করা যাক

{ exec >/dev/null; } >/dev/null; echo "Hi"

ধাপে ধাপে.

  1. দুটি আদেশ আছে:

    ক। { exec >/dev/null; } >/dev/null, অনুসরণ করে

    খ। echo "Hi"

    শেলটি প্রথমে কমান্ড (ক) এবং তারপরে কমান্ড (বি) চালায়।

  2. { exec >/dev/null; } >/dev/nullনিম্নলিখিত হিসাবে আয় কার্যকর করা :

    ক। প্রথমে শেলটি পুনঃনির্দেশ সম্পাদন করে >/dev/null এবং কমান্ড শেষ হয়ে গেলে এটি পূর্বাবস্থায় ফেলার স্মরণ রাখে

    খ। তারপরে, শেলটি কার্যকর করে { exec >/dev/null; }

    গ। অবশেষে, শেলটি স্ট্যান্ডার্ড আউটপুটটি যেখানে ছিল সেখানে ফিরে যায়। (এটি একই মেকানিজম হিসাবে রয়েছে ls -lR /usr/share/fonts >~/FontList.txt- পুনর্নির্দেশগুলি কেবল যে কমান্ডের সাথে সম্পর্কিত সেটির সময়কালের জন্য তৈরি করা হয়))

  3. একবার প্রথম কমান্ডটি সম্পন্ন হয়ে গেলে শেলটি কার্যকর হয় echo "Hi"। স্ট্যান্ডার্ড আউটপুট যেখানেই এটি প্রথম কমান্ডের আগে ছিল is


2 বি এর আগে 2a মৃত্যুদন্ড কার্যকর করার পিছনে কি কোনও কারণ আছে? (ডান থেকে বাম)
জো প্যাবালিনাস

5
পুনর্নির্দেশগুলি অবশ্যই প্রয়োগ করা হবে যে আদেশটি তারা প্রয়োগ করে, না? তারা অন্যথায় কিভাবে কাজ করতে পারে?
অ্যালেক্সপ

আহা, কখনও সেভাবে ভাবিনি! প্রথম দুটি হ'ল বোর্হ দুর্দান্ত উত্তর; আমি কোনও সিদ্ধান্ত নেওয়ার আগে এটিকে কিছুটা দেওয়ার জন্য, তবে আমি উভয়ের ব্যাখ্যাটির প্রশংসা করি!
জোয় পাবালিনাস

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

14

সাব-শেল বা সাব-প্রসেসটি ব্যবহার না করার জন্য, যখন কোনও যৌগিক তালিকার আউটপুট {}পাইপ করা হয় >তখন শেলটি যৌগিক তালিকা চালানোর আগে STDOUT বিবরণী সংরক্ষণ করে এবং এরপরে পুনরুদ্ধার করে। সুতরাং exec >যৌগিক তালিকার অন্তর্ভুক্ত পুরাতন বর্ণনাকারীটিকে STDOUT হিসাবে পুনরুদ্ধার করা বিন্দুটির আগে তার প্রভাব বহন করে না।

আসুন এর প্রাসঙ্গিক অংশটি একবার দেখুন strace bash -c '{ exec >/dev/null; } >/dev/null; echo hi' 2>&1 | cat -n:

   132  open("/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
   133  fcntl(1, F_GETFD)                       = 0
   134  fcntl(1, F_DUPFD, 10)                   = 10
   135  fcntl(1, F_GETFD)                       = 0
   136  fcntl(10, F_SETFD, FD_CLOEXEC)          = 0
   137  dup2(3, 1)                              = 1
   138  close(3)                                = 0
   139  open("/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
   140  fcntl(1, F_GETFD)                       = 0
   141  fcntl(1, F_DUPFD, 10)                   = 11
   142  fcntl(1, F_GETFD)                       = 0
   143  fcntl(11, F_SETFD, FD_CLOEXEC)          = 0
   144  dup2(3, 1)                              = 1
   145  close(3)                                = 0
   146  close(11)                               = 0
   147  dup2(10, 1)                             = 1
   148  fcntl(10, F_GETFD)                      = 0x1 (flags FD_CLOEXEC)
   149  close(10)                               = 0

আপনি দেখতে পাচ্ছেন কীভাবে ১৩৪ লাইনে, ডেস্ক্রিপ্টরকে 1( STDOUT) কমপক্ষে অন্য বর্ণনাকারীর সাথে অনুলিপি করে অনুলিপি করা হয়েছে 10( F_DUPFDএটিই হয়; এটি সেই বর্ণনাকারীর উপরে নকল করার পরে প্রদত্ত সংখ্যায় শুরু হওয়া সর্বনিম্ন উপলব্ধ বর্ণনাকারী ফেরত দেয়)। এছাড়াও কিভাবে, লাইন 137 উপর, ফল open("/dev/null")(বর্ণনাকারী 3) বর্ণনাকারী সম্মুখের অনুলিপি করা হয়েছে 1( STDOUT)। পরিশেষে, লাইনে 147, বিবরণীতে পুরানো STDOUTসংরক্ষিতগুলি 10আবার বিবরণীতে 1( STDOUT) এ অনুলিপি করা হয় । নেট এফেক্টটি হ'ল পরিবর্তনটি STDOUTঅন ​​লাইনে অন্তরক করা 144(যা অভ্যন্তরের সাথে মিলে যায় exec >/dev/null)।


যেহেতু এফডি 1 টি 137 লাইনে এফডি 3 দ্বারা ওভাররাইট করা হয়েছে, 141 লাইনটি 10 ​​থেকে / দেব / নালকে কেন নয়?
জোয় পাবালিনাস

@ জোপ্যাবালিনাস লাইন 141 10 এর পরে পরবর্তী উপলব্ধ বর্ণনাকারী এফডি 1 (অর্থাত্ স্টডআউট) ডুপ্লিকেট করছে , যা 11 হিসাবে দেখা যাচ্ছে, কারণ আপনি সেই সিস্টেম কলটি থেকে রিটার্ন মানটি দেখতে পাচ্ছেন। 10 টি কেবলমাত্র হার্ড-কোডিং করা হয়েছে যাতে ব্যাশের বর্ণনাকারী সংরক্ষণটি একক-অঙ্কের বর্ণনাকারীর সাথে হস্তক্ষেপ না করে যাতে আপনি আপনার স্ক্রিপ্টে ম্যানিপুলেট করতে পারেন exec
ডিপ্রেশনডানিয়েল

তাহলে fcntl (1, F_DUPFD, 10) সর্বদা STDOUT উল্লেখ করবে যেখানে এফডি 1 বর্তমানে নির্দেশ করছে?
জোয় পাবালিনাস

@ জোয়েপাবলিনাস আপনার প্রশ্ন কী তা নিশ্চিত নয়। এফডি 1 IS stdout- এ। তারা একই জিনিস।
ডিপ্রেশনডানিয়েল

আমার মূল পোস্টে সম্পূর্ণ স্ট্রেস আউটপুট যুক্ত হয়েছে।
জোয়ে পাবালিনাস

8

{ exec >/dev/null; } >/dev/null; echo "Hi"এবং এর মধ্যে পার্থক্য { exec >/dev/null; }; echo "Hi"হ'ল dup2(10, 1);fd 10 বন্ধ করার আগে ডাবল পুনর্নির্দেশটি করে যা stdoutপরবর্তী কমান্ড চালানোর আগে আসলটির অনুলিপি হয় echo

এটি সেভাবে ঘটে কারণ বাহ্যিক পুনর্নির্দেশটি প্রকৃতপক্ষে অভ্যন্তরীণ পুনঃনির্দেশকে ওভারলেল করছে। এ কারণেই stdoutএটি সম্পূর্ণ হয়ে গেলে মূল এফডিটি অনুলিপি করে ।


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