কম্পিউটার

রুবির মাধ্যমে শেল কমান্ড থেকে stdout এবং stderr ক্যাপচার করা হচ্ছে

tl;dr আপনি যদি রুবি থেকে একটি শেল কমান্ড চালাতে চান এবং এর stdout, stderr এবং রিটার্ন স্ট্যাটাস ক্যাপচার করতে চান তবে Open3.capture3 দেখুন পদ্ধতি আপনি যদি স্ট্রিমিং ফ্যাশনে stdout এবং stderr ডেটা প্রক্রিয়া করতে চান তবে Open3.popen3 দেখুন .

অনেক খারাপ পছন্দ

রুবি থেকে শেল কমান্ড চালানোর জন্য আক্ষরিকভাবে 492টি উপায় রয়েছে এবং তাদের প্রত্যেকটি কিছুটা আলাদাভাবে কাজ করে। আমি বাজি ধরছি আপনি নীচের পদ্ধতিগুলির মধ্যে একটি ব্যবহার করেছেন৷ আমার যাওয়া সবসময়ই ব্যাক-টিক্স (``)।

exec("echo 'hello world'") # exits from ruby, then runs the command
system('echo', 'hello world') # returns the status code
sh('echo', 'hello world') # returns the status code
`echo "hello world"` # returns stdout
%x[echo 'hello world'] # returns stdout

কিন্তু এই পন্থাগুলি বেশ সীমিত। ধরুন আপনাকে শুধুমাত্র আপনার শেল কমান্ডের stdout নয়, এর stderrও ক্যাপচার করতে হবে। আপনি শুধু ভাগ্যের বাইরে সরল. অথবা ধরুন আপনি একটি স্ট্রীমে stdout ডেটা প্রক্রিয়া করতে চান, এবং কমান্ডটি চলা শেষ হলে একবারে নয়? ভাগ্যের বাইরে।

আরেকটি বিকল্প আছে। যেটি আপনাকে অ্যাসিঙ্ক্রোনাসভাবে কমান্ড চালানোর ক্ষমতা দেয় এবং যা আপনাকে stdout, stderr, এক্সিট কোড এবং PID দেয়। আসুন এটি পরীক্ষা করে দেখি!

ওপেন3

অদ্ভুতভাবে নামের open3 মডিউলটি রুবির স্ট্যান্ডার্ড লাইব্রেরির অংশ। এটা কি করে?

Open3 আপনাকে stdout, stderr, এক্সিট কোড এবং একটি থ্রেডে অ্যাক্সেস দেয় যাতে অন্য একটি প্রোগ্রাম চালানোর সময় চাইল্ড প্রক্রিয়ার জন্য অপেক্ষা করা যায়। আপনি Process.spawn-এর মতোই প্রোগ্রামের বিভিন্ন বৈশিষ্ট্য, পুনঃনির্দেশ, বর্তমান ডিরেক্টরি ইত্যাদি নির্দিষ্ট করতে পারেন। (_সূত্র:[Open3 ডক্স](https://ruby-doc.org/stdlib-2.1.0/libdoc/open3/rdoc/Open3.html))_

এটা কখনো ব্যবহার করেননি? এমনকি শুনেছেন তা কখনও? আমি অনুমান করছি কারণ এটি লাইব্রেরির সবচেয়ে বন্ধুত্বপূর্ণ হিসাবে আসে না। নামটি নিজেই রুবির চেয়ে সি এর মতো শোনাচ্ছে। এবং ডকুমেন্টেশন বেশ হার্ড কোর ঘাড়-দাড়ি. কিন্তু একবার চেষ্টা করে দেখুন, আপনি দেখতে পাবেন যে এটি যতটা ভয়ঙ্কর মনে হয় ততটা ভয়ঙ্কর নয়।

ক্যাপচার3

যদি stdout, stderr এবং স্ট্যাটাস কোড ক্যাপচার করার একটি সহজ উপায় থাকত? ভাল আছে. এই নিবন্ধটির বাকি অংশ পড়ার জন্য আপনার কাছে সময় না থাকলে, শুধু জেনে রাখুন যে আপনি ক্যাপচার 3 নামে একটি পদ্ধতি ব্যবহার করতে পারেন এবং এটিকে একটি দিন কল করতে পারেন৷

চলুন একটি উদাহরণ কটাক্ষপাত করা যাক. ধরুন আপনি আপনার বর্তমান ডিরেক্টরিতে ফাইলগুলির একটি তালিকা পেতে চান। এটি করতে আপনি ls চালাতে পারেন আদেশ৷

আপনি যদি ব্যাক-টিক সিনট্যাক্স ব্যবহার করেন তবে এটি এইরকম দেখায়:

puts(`ls`)

capture3 সহ এটা এরকম দেখাচ্ছে:

require 'open3'
stdout, stderr, status = Open3.capture3("ls")

এটি আপনার কমান্ড চালাবে এবং আপনাকে স্ট্রিং হিসাবে stdout এবং stderr দেবে। কোন ঝামেলা নেই কোন কোলাহল নেই।

নিরাপত্তা

আপনি সাধারণত আপনার ব্যবহারকারীদের আপনার ওয়েব সার্ভারে নির্বিচারে আদেশ চালানোর ক্ষমতা দিতে চান না। তাই identify #{ params[:filename] } এর মত কোড এমন একটি ভয়ঙ্কর ধারণা।

Open3 আপনাকে ডেটা থেকে কমান্ড আলাদা করে এই ধরনের সমস্যা এড়াতে দেয়। এটি সিস্টেম পদ্ধতির মতোই কাজ করে৷

Open3.capture3("identify", params[:filename], other_unsafe_params)

popen3

হুডের নিচে, capture3 একটি অনেক বেশি শক্তিশালী পদ্ধতি ব্যবহার করে যার নাম popen3। এই পদ্ধতিটি সিস্টেম().

এর মত আরো পরিচিত পদ্ধতির চেয়ে একটু ভিন্নভাবে কাজ করে

এটি দেখতে কেমন তা এখানে:

require 'open3'
Open3.popen3("ls") do |stdout, stderr, status, thread|
  puts stdout.read
end

আপনি একটি ফাইল খুলুন এবং পড়া যখন এটা মত ধরনের. আমি নিশ্চিত আপনি এইরকম কোড দেখেছেন:

File.open("my/file/path", "r") do |f|
  puts f.read
end

পাইপ

Open3 এর সাথে, stdout এবং stderr হল সমস্ত পাইপ, যা অনেকটা ফাইল বাফারের মতো আচরণ করে। এবং ফাইলগুলির মতো, আপনি সেগুলি শেষ করার পরে সেগুলিকে বন্ধ করতে হবে৷ যে ব্লক সিনট্যাক্স জন্য কারণ. (একটি নন-ব্লক সিনট্যাক্স আছে, কিন্তু আপনাকে ম্যানুয়ালি ক্লোজ কল করতে হবে stdout, এবং stderr-এ।)

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

এখানে আপনি কিভাবে stderr একবারে একটি লাইন ক্যাপচার করবেন।

require 'open3'
Open3.popen3("sleep 2; ls") do |stdout, stderr, status, thread|
  while line=stderr.gets do 
    puts(line) 
  end
end

থ্রেড

আমরা এখনও কথা বলিনি একটি যুক্তি আছে. এটাই থ্রেড।

থ্রেড আর্গুমেন্ট আপনাকে একটি রুবি থ্রেডের একটি রেফারেন্স দেয় যা আপনার আদেশ শেষ করার জন্য অপেক্ষা করছে। এখন, কমান্ডটি থ্রেডে চলছে না। এটি সম্পূর্ণ আলাদা প্রক্রিয়ায় চলছে। থ্রেডটি কেবল প্রক্রিয়াটি দেখে এবং এটি সম্পন্ন না হওয়া পর্যন্ত অপেক্ষা করে৷

যদিও আপনি সেই থ্রেড রেফারেন্স থেকে কিছু দরকারী তথ্য পেতে পারেন।

  • thread.pid - আপনার শেল কমান্ডের প্রক্রিয়া আইডি রয়েছে। আপনি যদি সেই প্রক্রিয়ার বিরুদ্ধে অতিরিক্ত OS-স্তরের অপারেশন করতে চান তবে আপনার এটির প্রয়োজন হবে৷

  • thread.status - প্রক্রিয়াটির প্রস্থান অবস্থা ধারণ করে। সাফল্য বা ব্যর্থতার জন্য 1 বা 0।

সতর্কতা

Open3 ডক্স থেকে:

অচলাবস্থা এড়াতে আপনার সতর্ক হওয়া উচিত। যেহেতু পাইপগুলি নির্দিষ্ট দৈর্ঘ্যের বাফার,[::popen3](https://ruby-doc.org/stdlib-2.1.0/libdoc/open3/rdoc/Open3.html#method-c-popen3)("prog") {|i, o, e, t| o.read } ডেডলক হয় যদি প্রোগ্রামটি stderr-এ খুব বেশি আউটপুট তৈরি করে। আপনার একই সাথে stdout এবং stderr পড়া উচিত (থ্রেড বা IO.select ব্যবহার করে)। যাইহোক, যদি আপনার stderr আউটপুট প্রয়োজন না হয়, আপনি [::popen2](https://ruby-doc.org/stdlib-2.1.0/libdoc/open3/rdoc/Open3.html#method-c- ব্যবহার করতে পারেন popen2)। একত্রিত করা stdout এবং stderr আউটপুট একটি সমস্যা না হলে, আপনি [::popen2e](https://ruby-doc.org/stdlib-2.1.0/libdoc/open3/rdoc/Open3.html#method-c- ব্যবহার করতে পারেন popen2e)। যদি আপনার সত্যিই আলাদা স্ট্রিং হিসাবে stdout এবং stderr আউটপুট প্রয়োজন হয়, আপনি বিবেচনা করতে পারেন [::capture3](https://ruby-doc.org/stdlib-2.1.0/libdoc/open3/rdoc/Open3.html#method-c -ক্যাপচার৩)।

  1. কিভাবে OTG এর মাধ্যমে মোবাইল থেকে ফাইল ট্রান্সফার করবেন?

  2. Fiddle এর মাধ্যমে রুবি থেকে যেকোন সি লাইব্রেরি ব্যবহার করুন - রুবি স্ট্যান্ডার্ড লাইব্রেরিগুলো সবচেয়ে ভালোভাবে গোপন রাখা হয়।

  3. রুবিতে স্ক্র্যাচ থেকে একটি সাধারণ ওয়েবসকেট সার্ভার তৈরি করা

  4. কিভাবে HTTP শিরোনামগুলি nginx থেকে আপনার রুবি অ্যাপে পাস করা হয়