যদিও ইউটিলিটি স্ক্রিপ্টের বাইরে সামান্য একটি লেখা মজাদার, কখনও কখনও আপনাকে ঈশ্বরের কমান্ড-লাইন অ্যাপ্লিকেশনের প্রতি সত্যিকারের সৎ লিখতে হবে। যেটি যুক্তি গ্রহণ করে এবং ইনপুট, আউটপুট, ত্রুটি রিপোর্টিং, ইত্যাদির জন্য ইউনিক্স কনভেনশনগুলির সাথে সুন্দরভাবে খেলে৷
সৌভাগ্যবশত, রুবি আপনাকে মোটামুটি সহজে কমান্ড-লাইন অ্যাপ্লিকেশনের জন্য প্রয়োজনীয় সমস্ত বিল্ডিং ব্লক দেয়। এই পোস্টে আমি সাধারণ "কীভাবে X এর সাথে জেম Y" পদ্ধতির বাইরে যাওয়ার আশা করি, এবং এর পরিবর্তে একটি প্রথম-দরের কমান্ড-লাইন অ্যাপ তৈরির জন্য একসাথে যাওয়া সমস্ত অংশগুলির একটি বিস্তৃত ওভারভিউ করব৷
ইনপুট:এনভায়রনমেন্ট ভেরিয়েবল
এনভায়রনমেন্ট ভেরিয়েবলগুলি সাধারণত সংক্ষিপ্ত কনফিগারেশন মানগুলির জন্য ব্যবহৃত হয় যা আপনি কিছু সময়ের জন্য চারপাশে আটকে রাখতে চান। API কী একটি ভালো উদাহরণ।
পরিবেশ ভেরিয়েবল সেট করা
ব্যবহারকারীরা সাধারণত ব্যাশের মতো শেলের মাধ্যমে পরিবেশের ভেরিয়েবল সেট করে। তারা তাদের একটি নির্দিষ্ট সেশনের জন্য সেট করতে পারে:
$ AWS_ACCESS_KEY_ID=FOO
তারা সেগুলিকে বর্তমান সেশনের জন্য সেট করতে পারে, সাথে যেকোনো নতুন ব্যাশ সেশন:
$ export AWS_ACCESS_KEY_ID=FOO
অথবা তারা একটি একক প্রোগ্রামের জন্য সেট করতে পারে:
$ env AWS_ACCESS_KEY_ID=FOO aws s3 mb s3://mybucket
পরিবেশ ভেরিয়েবল পড়া
ব্যবহারকারী কীভাবে পরিবেশ পরিবর্তনশীল সেট করে না কেন, আপনি এটি রুবির ENV
এর মাধ্যমে পড়তে পারেন হ্যাশ।
key_id = ENV["AWS_ACCESS_KEY_ID"]
পরিবেশ ভার্স কিভাবে হুডের নিচে কাজ করে?
প্রতিটি প্রক্রিয়ার সাথে যুক্ত পরিবেশের ভেরিয়েবলের একটি টেবিল রয়েছে। যখন এটি শিশু প্রক্রিয়ার জন্ম দেয়, তখন তারা সেই টেবিলের একটি কপি পায় এবং অভিভাবক যা কিছু পরিবর্তন করতে চান।
কাদা হিসাবে পরিষ্কার?
আরও পাঠযোগ্য ব্যাখ্যার জন্য, আমার অন্য ব্লগ পোস্টটি দেখুন:পরিবেশের ভেরিয়েবলের জন্য রুবিস্টের গাইড৷
কমান্ড-লাইন আর্গুমেন্ট
কমান্ড-লাইন আর্গুমেন্ট হল এমন কিছু যা আপনি যখন টার্মিনালে একটি প্রোগ্রাম চালান তখন আপনি প্রোগ্রামের নামের পরে রাখেন:
$ echo foo bar baz
উপরের উদাহরণে "foo", "bar" এবং "baz" সব কমান্ড-লাইন আর্গুমেন্ট।
একটি আরো বাস্তবসম্মত উদাহরণ এই মত দেখতে হতে পারে:
$ honeybadger deploy -v --environment staging
কিন্তু এখানেও, কমান্ড-লাইন আর্গুমেন্টগুলি কেবল পাঠ্য। আমরা যদি --environment staging
চাই মানে যাই হোক না কেন, আমাদের নিজেদেরই তা বের করতে হবে।
কমান্ড-লাইন আর্গুমেন্ট পাঠানো হচ্ছে
আমরা ইতিমধ্যে এই মত পাঠানো আর্গুমেন্ট দেখেছি:
$ echo foo bar baz
কিন্তু যেহেতু রুবি একটি ব্যাখ্যা করা ভাষা, আপনি এইরকম কিছু দেখতে পারেন:
$ ruby myprog.rb foo
যতদূর OS উদ্বিগ্ন, আপনি "রুবি" নামে একটি প্রোগ্রাম চালাচ্ছেন এবং এটি দুটি আর্গুমেন্ট পাস করছেন৷
সৌভাগ্যবশত, রুবি যথেষ্ট স্মার্ট এটা জানার জন্য যে আর্গুমেন্ট "foo" আপনার প্রোগ্রামের জন্য, রুবির জন্য নয়। তাই আপনার প্রোগ্রাম একটি আর্গুমেন্ট দেখতে পাবে, "foo"
.
কমান্ড-লাইন আর্গুমেন্ট পড়া
কমান্ড-লাইন আর্গুমেন্টগুলি ARGV
নামে একটি অ্যারেতে সংরক্ষণ করা হয় . এটি একটি গ্লোবাল ভেরিয়েবল, তাই আপনি আপনার প্রোগ্রামের যেকোনো জায়গা থেকে এটি অ্যাক্সেস করতে পারেন।
নীচের উদাহরণে, আমরা ARGV
-এ সবকিছু প্রিন্ট করছি . এটিকে আপনার টার্মিনালে কপি এবং পেস্ট করতে নির্দ্বিধায় এবং এটির সাথে কিছুটা খেলুন।
$ ruby -e "puts ARGV.inspect" foo bar baz
["foo", "bar", "baz"]
অনুগ্রহ করে
ruby -e
দ্বারা নিক্ষিপ্ত হবেন না ব্যবসা আমি এটি শুধুমাত্র এখানে ব্যবহার করছি কারণ এটি আমাকে প্রোগ্রাম এবং এটিকে একটি লাইনে চালানোর ফলাফল দেখাতে দেয়৷
কমান্ড-লাইন আর্গুমেন্ট পার্স করা হচ্ছে
কমান্ড লাইন আর্গুমেন্ট শুধু পাঠ্য. আপনি যদি পাঠ্যটির অর্থ চান কিছু, আপনি এটি পার্স করতে যাচ্ছেন. সৌভাগ্যবশত, পার্সিং এর সাথে আপনাকে সাহায্য করতে পারে এমন বেশ কিছু ভালো লাইব্রেরি আছে।
বছরের পর বছর ধরে, কমান্ড-লাইন আর্গুমেন্টের জন্য কিছুটা আদর্শ সিনট্যাক্স আবির্ভূত হয়েছে। এটা এই মত কিছু দেখায়:
$ program -a --option foo
এই স্টাইলটি আপনাকে -h
এর মত বুলিয়ান পতাকা পেতে দেয় সাহায্য প্রদর্শন করতে। এটি আপনাকে মান সহ বিকল্পগুলি নির্দিষ্ট করতে দেয়৷
প্রবর্তন করা হচ্ছে OptionParser
OptionParser
ক্লাস রুবির স্ট্যান্ডার্ড লাইব্রেরির অংশ। এটি আপনাকে উপরের শৈলীর সাথে মেলে এমন বিকল্পগুলিকে পার্স করার একটি সহজ উপায় দেয়৷
হ্যালো বলে একটি সহজ অ্যাপ্লিকেশন তৈরি করা যাক। এটি আপনাকে কমান্ড-লাইন আর্গুমেন্টের মাধ্যমে নাম উল্লেখ করতে দেবে।
require 'optparse'
# This will hold the options we parse
options = {}
OptionParser.new do |parser|
# Whenever we see -n or --name, with an
# argument, save the argument.
parser.on("-n", "--name NAME", "The name of the person to greet.") do |v|
options[:name] = v
end
end.parse!
# Now we can use the options hash however we like.
puts "Hello #{ options[:name] }" if options[:name]
তারপর যখন আমি এটি চালাই, তখন এটি কাজ করে:
$ ruby hello.rb --name Starr
Hello Starr
$ ruby hello.rb -n Starr
Hello Starr
একটি "হেল্প" স্ক্রীন যোগ করা হচ্ছে
একটি সাহায্য বৈশিষ্ট্য যোগ করা ঠিক যেমন সহজ. আমাদের যা করতে হবে তা হল কিছু পাঠ্য সরবরাহ করা এবং -h
-এর জন্য একটি কমান্ড যোগ করা :
OptionParser.new do |parser|
parser.banner = "Usage: hello.rb [options]"
parser.on("-h", "--help", "Show this help message") do ||
puts parser
end
...
end.parse!
এখন আমরা সাহায্য চাইতে পারি:
$ ruby hello.rb -h
Usage: hello.rb [options]
-h, --help Show this help message
-n, --name NAME The name of the person to greet.
টাইপকাস্টিং আর্গুমেন্ট
সমস্ত কমান্ড-লাইন আর্গুমেন্ট স্ট্রিং, কিন্তু কখনও কখনও আপনি ব্যবহারকারী আপনাকে একটি নম্বর বা একটি তারিখ দিতে চান। হাত দিয়ে রূপান্তর করা ক্লান্তিকর হতে পারে, তাই OptionParser
এটা আপনার জন্য করে।
নীচের উদাহরণে, আমি একটি "গণনা" বিকল্প যোগ করতে যাচ্ছি যা ব্যবহারকারীকে কতবার প্রোগ্রামটিকে হ্যালো বলতে হবে তা নির্দিষ্ট করতে দেয়। আমি OptionParser
কে বলছি একটি Integer
কাস্ট করতে , যা এটি করে।
OptionParser.new do |parser|
...
# Note the `Integer` arg. That tells the parser to cast the value to an int.
# I could have used `Float`, `Date`, or a number of other types.
parser.on("-c", "--count COUNT", Integer, "Repeat the message COUNT times") do |v|
options[:count] = v
end
end.parse!
if options[:name]
options.fetch(:count, 1).times do
puts "Hello #{ options[:name] }"
end
end
এখন, যখন আমি প্রোগ্রামটি চালাই তখন আমাকে একাধিকবার শুভেচ্ছা জানানো হয়:
$ ruby hello.rb -n Starr -c 5
Hello Starr
Hello Starr
Hello Starr
Hello Starr
Hello Starr
নামকরণের নিয়মাবলী
প্রোগ্রামিংয়ের সবচেয়ে কঠিন দিকগুলির মধ্যে একটি হল জিনিসগুলির নাম কী দেওয়া উচিত তা নির্ধারণ করা। কমান্ড লাইন আর্গুমেন্ট কোন ব্যতিক্রম নয়. আপনাকে সাহায্য করার জন্য, আমি সাধারণ যুক্তি এবং তাদের অর্থগুলির একটি সংক্ষিপ্ত সারণী সংকলন করেছি:
পতাকা | সাধারণ অর্থ |
---|---|
-a | সমস্ত, যোগ করুন |
-d | ডিবাগ মোড, বা ডিরেক্টরি নির্দিষ্ট করুন |
-e | কিছু চালান, বা সম্পাদনা করুন |
-f | একটি ফাইল নির্দিষ্ট করুন, অথবা একটি অপারেশন জোর করুন। |
-h | সহায়তা |
-m | একটি বার্তা নির্দিষ্ট করুন |
-o | একটি আউটপুট ফাইল বা ডিভাইস নির্দিষ্ট করুন |
-q | শান্ত মোড |
-v | ভার্বোস মোড। বর্তমান সংস্করণ প্রিন্ট করুন |
-y | যেকোন প্রম্পটে "হ্যাঁ" বলুন |
বিকল্প OptionParser
OptionParser
চমৎকার, কিন্তু এর সীমাবদ্ধতা আছে। স্পষ্টতই, এটি সাম্প্রতিক বছরগুলিতে জনপ্রিয় হওয়া কমান্ড-ভিত্তিক সিনট্যাক্সগুলিকে সমর্থন করে না:
$ myprog command subcommand -V
ভাগ্যক্রমে, একটি টন আছে বিকল্প পার্সিং লাইব্রেরি আছে. আমি নিশ্চিত যে আপনি আপনার পছন্দ মতো একটি খুঁজে পেতে সক্ষম হবেন। এখানে তিনটি আকর্ষণীয় দেখায়:
- GLI - "Git-এর মতো ইন্টারফেস" কমান্ড-লাইন পার্সার আপনাকে সহজেই এমন অ্যাপ্লিকেশন তৈরি করতে দেয় যেগুলি, গিট-এর মতো, একাধিক কমান্ড সহ একক এক্সিকিউটেবল৷
- CRI - নেস্টেড কমান্ডের জন্য সমর্থন সহ কমান্ড-লাইন সরঞ্জাম তৈরির জন্য একটি সহজে ব্যবহারযোগ্য লাইব্রেরি৷
- মেথাডোন - মেথাডোন ডিএসএল পার্সিং এর নিজস্ব বিকল্প প্রদান করে, কিন্তু এটি এর বাইরেও যায়। এটি আপনার জন্য একটি ডিরেক্টরি কাঠামো, একটি পরীক্ষা স্যুট এবং লগিং সেট আপ করবে। এটি আপনার CLI-এর জন্য রেলের মতো।
STDIN-এর মাধ্যমে বেশি পরিমাণে ডেটা ইনপুট করা
কমান্ড-লাইন আর্গুমেন্ট বৃহত্তর পরিমাণে ডেটা ইনপুট করার জন্য উপযুক্ত নয়। এর জন্য, আপনি একটি IO স্ট্রিম ব্যবহার করতে চাইবেন। এবং STDIN হল সবচেয়ে সুবিধাজনক IO স্ট্রীমগুলির মধ্যে একটি৷
৷বেশিরভাগ প্রোগ্রাম অপারেটিং সিস্টেম দ্বারা স্বয়ংক্রিয়ভাবে একটি STDIN বরাদ্দ করা হবে। এটি একটি শুধুমাত্র পঠনযোগ্য ফাইলের মতো যা OS আপনার অ্যাপ ডেটা পাঠাতে ব্যবহার করে। এটি ব্যবহারকারীর কাছ থেকে কীবোর্ড ইনপুট পেতে ব্যবহার করা যেতে পারে। কিন্তু আরও গুরুত্বপূর্ণ, এটি একটি পাইপের মাধ্যমে অন্যান্য প্রোগ্রাম থেকে ডেটা গ্রহণ করতে ব্যবহার করা যেতে পারে।
আপনি STDIN ব্যবহার করেন ঠিক যেমন আপনি একটি পঠনযোগ্য ফাইল ব্যবহার করেন। এখানে, আমি আমার প্রোগ্রামের STDIN এ কিছু পাঠ্য পাইপ করছি। তারপর আমি read
ব্যবহার করি এটি আনার পদ্ধতি৷
$ echo "hello world" | ruby -e "puts STDIN.read.upcase"
HELLO WORLD
রুবিতে, আপনি Enumerable
ব্যবহার করতে পারেন আইও অবজেক্টের বৈশিষ্ট্য। এবং STDIN এর ব্যতিক্রম নয়। তার মানে আপনি সব ধরনের কৌশল করতে পারেন:
# Get the first 20 lines
STDIN.first(20)
# Convert to integers and reject odds
STDIN.map(&:to_i).reject(&:odd)
...etc
ফলাফল STDOUT এ আউটপুট করা
STDOUT হল একটি লেখার জন্য শুধুমাত্র IO স্ট্রিম যা অপারেটিং সিস্টেম আপনার প্রোগ্রামে বরাদ্দ করে৷
STDOUT এ লিখে, আপনি ব্যবহারকারীর টার্মিনালে পাঠ্য পাঠাতে পারেন। ব্যবহারকারী একটি ফাইলে আউটপুট রিডাইরেক্ট করতে পারেন, অথবা অন্য প্রোগ্রামে পাইপ করতে পারেন৷
আপনি STDOUT ব্যবহার করবেন ঠিক যেমন আপনি অন্য কোনো লেখার জন্য ফাইল ব্যবহার করবেন:
STDOUT.write("Hi!\n")
# hi
এবং অবশ্যই, puts
এবং print
উভয় আউটপুট STDOUT.
STDERR-এ স্ট্যাটাস তথ্য পাঠানো হচ্ছে
STDERR হল আরেকটি শুধুমাত্র লেখার IO স্ট্রীম। এটি সাধারণ আউটপুটের জন্য নয়। এটি বিশেষত স্থিতি বার্তাগুলির জন্য - যাতে তারা বাস্তব এর পথে না যায় আউটপুট।
STDERR সাধারণত ব্যবহারকারীর টার্মিনালে প্রদর্শিত হবে, এমনকি তারা STDOUT-কে কোনো ফাইল বা অন্য কোনো প্রোগ্রামে পুনঃনির্দেশ করলেও।
নীচের উদাহরণে আমরা একটি ওয়েবপেজ আনতে কার্ল ব্যবহার করছি। এটি ওয়েবপৃষ্ঠার বিষয়বস্তুকে STDOUT-এ আউটপুট করে, এবং STDERR-এ অগ্রগতির তথ্য প্রদর্শন করে:
$ curl "https://www.google.com/" > /tmp/g.html
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 151k 0 151k 0 0 277k 0 --:--:-- --:--:-- --:--:-- 277k
আপনার নিজস্ব প্রোগ্রাম থেকে STDERR-এ লেখা সহজ। এটিকে IO অবজেক্টের মতই ব্যবহার করুন:
STDERR.write("blah\n")
STDERR.puts("blah")
সুন্দর লাঠি দিয়ে আঘাত করা
আমরা এখন পর্যন্ত যে উদাহরণগুলি দেখেছি সেগুলি কোনও ডিজাইন পুরষ্কার জিততে যাচ্ছে না। কিন্তু কমান্ড-লাইন অ্যাপগুলি কুৎসিত, বা অ-ইন্টারেক্টিভ হওয়া উচিত এমন কোনও কারণ নেই৷
আপনি যদি আপনার অ্যাপটি স্যুপ করার সিদ্ধান্ত নেন, তবে কিছু ভারী উত্তোলন করার জন্য এক টন দুর্দান্ত রত্ন রয়েছে। এখানে আমার পছন্দের তিনটি আছে:
- হাইলাইন - হাইলাইন একটি দুর্দান্ত লাইব্রেরি যা ব্যবহারকারীর ইনপুট সংগ্রহ, যাচাইকরণ এবং টাইপকাস্ট করার জন্য অনেক কাজ করে।
- command_line_reporter - ASCII অগ্রগতি প্রতিবেদন তৈরি করা সহজ করে তোলে।
- পেইন্ট - আপনার বিরক্তিকর পুরানো পাঠ্যকে রঙিন করতে আপনাকে সহজেই ANSI রঙের কোড যোগ করতে দেয়।
আরও সম্পূর্ণ তালিকা দেখুন
প্রস্থান অবস্থা
যদি আপনার প্রোগ্রামটি একটি ত্রুটির সাথে প্রস্থান করে তবে আপনাকে একটি প্রস্থান কোডের মাধ্যমে OS কে জানাতে হবে। এটিই এই ধরনের ব্যাশ কোডের জন্য কাজ করা সম্ভব করে তোলে:
$ prog1 && prog2
আপনি যদি bash এর &&
সাথে পরিচিত না হন অপারেটর, এর সহজ অর্থ হল "প্রোগ2 চালান শুধুমাত্র যদি prog1 সফলভাবে প্রস্থান করে।"
রুবি ডিফল্টরূপে একটি "সফল" কোড এবং ব্যতিক্রম একটি "ব্যর্থতা" কোড সহ প্রস্থান করে। অন্য সবকিছু বাস্তবায়ন করা আপনার উপর নির্ভর করে। ভাগ্যক্রমে, এটা সহজ:
# Any nonzero argument to `exit` counts as failure
exit(1)
আরও তথ্যের জন্য, আমার অন্য পোস্ট দেখুন কিভাবে রুবি প্রোগ্রাম থেকে প্রস্থান করবেন।
প্রক্রিয়ার নাম সেট করা হচ্ছে
যদি আপনার কমান্ড-লাইন প্রোগ্রামটি অল্প সময়ের জন্য চলতে থাকে, তবে এটি গুরুত্বপূর্ণ যে লোকেরা সিস্টেমের প্রক্রিয়াগুলি তালিকাভুক্ত করার সময় এটি কী তা জানা। সাধারনত, একটি রুবি প্রোগ্রাম প্রসেস নাম আপনি প্রোগ্রাম চালানোর জন্য যা টাইপ করেছেন তা নিয়ে গঠিত। তাই যদি আপনি ruby myapp -v
টাইপ করেন , এটি প্রক্রিয়াটির নাম।
আপনার প্রোগ্রামে অনেক আর্গুমেন্ট থাকলে, এটি অপঠনযোগ্য হয়ে উঠতে পারে। তাই আপনি একটি আরো বন্ধুত্বপূর্ণ প্রক্রিয়া নাম সেট করতে চাইতে পারেন. আপনি এটি এভাবে করতে পারেন:
Process.setproctitle("My Awesome Command Line App")
আপনি যদি অভিনব বোধ করেন, তাহলে আপনি প্রসেস শিরোনামটি ব্যবহার করে ব্যবহারকারীকে তথ্য দিতে পারেন যে কোন মুহূর্তে প্রসেসগুলি কী করছে৷
Process.setproctitle("Mail Sender: initializing")
init(...)
Process.setproctitle("Mail Sender: connecting")
connect(...)
Process.setproctitle("Mail Sender: sending")
send(...)
আরও তথ্যের জন্য, আমার পোস্ট দেখুন:টপ এবং পিএস দ্বারা দেখানো হিসাবে আপনার রুবি স্ক্রিপ্টের প্রক্রিয়ার নাম কীভাবে পরিবর্তন করবেন