Bash ও শেল স্ক্রিপ্ট এখনও CI জব, সার্ভার ও দ্রুত ফিক্স চালায়। কী সময় এগুলো ভালো লাগে, নিরাপদ স্ক্রিপ্ট কিভাবে লিখবেন, এবং কখন অন্য টুল ব্যবহার করা উচিত জানুন।

যখন কেউ “শেল স্ক্রিপ্টিং” বলে, তারা সাধারণত এমন একটি ছোট প্রোগ্রামের কথা বলেন যা কমান্ড-লাইন শেলে চালানো হয়। শেল আপনার কমান্ডগুলো পড়ে এবং অন্যান্য প্রোগ্রাম লঞ্চ করে। বেশিরভাগ লিনাক্স সার্ভারে সেই শেল হয় POSIX sh (স্ট্যান্ডার্ডায়েজড বেসলাইন) বা Bash (সবচেয়ে সাধারণ "sh-লাইক" শেল, অতিরিক্ত সুবিধাসহ)।
ডেভঅপস পরিভাষায়, শেল স্ক্রিপ্টগুলো হলো পাতলা glue লেয়ার যা OS টুল, ক্লাউড CLI, বিল্ড টুল এবং কনফিগ ফাইলগুলো একসাথে বেঁধে দেয়।
লিনাক্স মেশিনগুলো ইতিমধ্যে কোর ইউটিলিটি (যেমন grep, sed, awk, tar, curl, systemctl) সহ আসে। একটি শেল স্ক্রিপ্ট সরাসরি এই টুলগুলো কল করতে পারে, কোনো অতিরিক্ত রানটাইম/প্যাকেজ/ডিপেনডেন্সি ছাড়াই—এটি মিনিমাল ইমেজ, রিকভারি শেল বা লকড-ডাউন পরিবেশে বিশেষভাবে কাজে দেয়।
শেল স্ক্রিপ্টিং তখনই উজ্জ্বল কারণ বেশিরভাগ টুল সহজ কনট্রাক্ট ফলো করে:
cmd1 | cmd2)।0 মানে সাফল্য; নন-জিরো মানে ব্যর্থতা—অটোমেশনের জন্য জরুরি।আমরা ফোকাস করব কিভাবে Bash/শেল ডেভঅপস অটোমেশনে, CI/CD, কনটেইনার, ট্রাবলশুটিং, পোর্টেবিলিটি এবং সেফটি প্র্যাকটিসে ফিট করে। আমরা শেলকে পূর্ণ অ্যাপ ফ্রেমওয়ার্কে পরিণত করার চেষ্টা করব না—যখন তা দরকার, আমরা অন্য ভাল অপশনগুলো উল্লেখ করব (আর কীভাবে শেল তাদের চারপাশে সাহায্য করে)।
শেল স্ক্রিপ্টিং শুধু "লিগ্যাসি glue" নয়। এটি ছোট, নির্ভরযোগ্য লেয়ার যা ম্যানুয়াল কমান্ড সিকোয়েন্সগুলোকে রিপিটেবল অ্যাকশনে পরিণত করে—বিশেষ করে যখন আপনি দ্রুত সার্ভার, পরিবেশ এবং টুলগুলোর মধ্যে কাজ করছেন।
আপনার লক্ষ্য যদি সম্পূর্ণভাবে ম্যানেজড ইনফ্রাস্ট্রাকচার হয়, তবুও প্রায়ই এমন একটি মুহূর্ত থাকে যখন হোস্ট প্রস্তুত করতে হবে: একটি প্যাকেজ ইনস্টল করা, কনফিগ ফাইল রাখানো, পারমিশন সেট করা, ইউজার তৈরী করা বা সিক্রেট ফেচ করা। ছোট শেল স্ক্রিপ্ট এই একবারের (বা বিরল) কাজের জন্য উপযুক্ত কারণ এটি সেখানে চালানো যায় যেখানে শেল ও SSH আছে।
অনেক দল রানবুক ডকুমেন্ট হিসেবে রাখে, কিন্তু সবচেয়ে কার্যকর রানবুকগুলো হল স্ক্রিপ্ট যা রুটিন অপসে চালানো যায়:
রানবুককে স্ক্রিপ্টে পরিণত করা মানবীয় ত্রুটি কমায়, ফলাফলকে ধারাবাহিক করে এবং হ্যান্ডঅফ উন্নত করে।
একটি ইনসিডেন্ট হলে, সাধারণত পূর্ণ অ্যাপ বা ড্যাশবোর্ড নয়—আপনি স্পষ্টতা চাইবেন। grep, sed, awk, এবং jq মতো টুল দিয়ে শেল পাইপলাইনগুলো লগ কাটা, আউটপুট তুলনা এবং নোডগুলোর মধ্যে প্যাটার্ন দেখা সবচেয়ে দ্রুত উপায়।
দৈনন্দিন কাজ প্রায়ই একই CLI ধাপগুলো চালানো: আর্টিফ্যাক্ট ট্যাগিং, ফাইল সিঙ্ক, স্ট্যাটাস চেক বা সেফ রোলআউট। শেল স্ক্রিপ্ট এই ওয়ার্কফ্লো ধরে রাখে যাতে তারা বিভিন্ন পরিবেশে কনসিস্টেন্ট থাকে।
সবকিছুই সুন্দরভাবে ইন্টিগ্রেট হয় না। শেল স্ক্রিপ্ট “টুল A JSON আউটপুট করে” কে “টুল B expects env vars” এ রূপান্তর করতে পারে, কলগুলো অর্কেস্ট্রেট করে এবং অনুপস্থিত চেক/রিট্রাই যোগ করে—নতুন ইন্টিগ্রেশন বা প্লাগইনের জন্য অপেক্ষা না করে।
শেল স্ক্রিপ্টিং এবং Terraform, Ansible, Chef, Puppet ইত্যাদি জিনিসগুলো সম্পর্কিত সমস্যাগুলো সমাধান করে, কিন্তু এগুলো একে অপরের বিকল্প নয়।
IaC/কনফিগ ম্যানেজমেন্টকে ভাবুন সিস্টেম অফ রেকর্ড হিসেবে: যেখানে ইচ্ছাকৃত অবস্থা ব্যাখ্যা, রিভিউ, ভার্সন এবং কনসিস্টেন্টভাবে প্রয়োগ করা হয়। Terraform ইনফ্রাস্ট্রাকচার ঘোষণা করে (নেটওয়ার্ক, লোড ব্যাল্যান্সার, ডাটাবেস)। Ansible/Chef/Puppet মেশিন কনফিগ ও ongoing convergence বর্ণনা করে।
শেল স্ক্রিপ্ট সাধারণত গ্লু কোড: পাতলা লেয়ার যা ধাপ, টুল এবং পরিবেশ সংযুক্ত করে। একটি স্ক্রিপ্ট হয়তো চূড়ান্ত স্টেট “অকুপাই” করে না, কিন্তু এটি অটোমেশনকে ব্যবহারযোগ্য করে তোলে।
শেল ভালো সঙ্গী যখন আপনি প্রয়োজন:
উদাহরণ: Terraform রিসোর্স তৈরি করে, কিন্তু একটি Bash স্ক্রিপ্ট ইনপুট যাচাই করে, সঠিক ব্যাকএন্ড নিশ্চিত করে এবং terraform plan + পলিসি চেক চালায় apply-এর আগে।
শেল দ্রুত ইমপ্লিমেন্ট করার জন্য ভালো এবং ডিপেনডেন্সি কম—জরুরি অটোমেশন ও ছোট সমন্বয় কাজের জন্য আদর্শ। কিন্তু দীর্ঘমেয়াদি গভর্ন্যান্সের দুর্বলতা আছে: স্ক্রিপ্টগুলো ছোট-খাটো প্ল্যাটফর্মে পরিণত হতে পারে, অনিয়মিত প্যাটার্ন, দুর্বল আইডেমপো-টেন্সি এবং সীমিত অডিটিং থাকে।
একটি বাস্তবিক নিয়ম: stateful, পুনরাবৃত্তি ইনফ্রাস্ট্রাকচার/কনফিগের জন্য IaC/কনফিগ টুল ব্যবহার করুন; তাদের চারপাশে ছোট, কম্পোজেবল কাজের জন্য শেল ব্যবহার করুন। যখন একটি স্ক্রিপ্ট ব্যবসার-নির্ভরীয় হয়ে যায়, তখন মূল লজিক সিস্টেম-অফ-রেকর্ড টুলে মাইগ্রেট করুন এবং শেলকে র্যাপার রাখুন।
CI/CD সিস্টেম ধাপগুলো অর্কেস্ট্রেট করে, কিন্তু এগুলোকে কাজ করতে কাউকে লাগবে। Bash (বা POSIX sh) ডিফল্ট গ্লু হিসেবে থেকে যায় কারণ এটি বেশিরভাগ রানারে আছে, সহজে ইনভোক করা যায় এবং অতিরিক্ত রানটাইম ছাড়াই টুলগুলো চেইন করতে পারে।
অধিকাংশ পাইপলাইন শেল ধাপ ব্যবহার করে নিচের রুটিন কাজগুলোর জন্য: ডিপেনডেন্সি ইনস্টল, বিল্ড চালানো, আউটপুট প্যাকেজ করা, আর্টিফ্যাক্ট আপলোড করা।
টিপিক্যাল উদাহরণ:
পাইপলাইন কনফিগ সাধারনত env ভ্যারিয়েবলে পাস করে, তাই শেল স্ক্রিপ্টগুলিই প্রাকৃতিকভাবে সেই মানগুলো রাউট করে। নিরাপদ প্যাটার্ন:
set +x ব্যবহার করুন (কমান্ড প্রিন্ট নাহোয়া নিশ্চিত করতে)CI-র জন্য পূর্বানুমানযোগ্য আচরণ দরকার। ভালো পাইপলাইন স্ক্রিপ্টগুলোঃ
ক্যাশিং ও প্যারালেল ধাপ সাধারণত CI সিস্টেম নিয়ন্ত্রণ করে; শেল শেয়ার্ড ক্যাশ across জব ভালোভাবে ম্যানেজ করতে পারে না। কিন্তু শেল ক্যাশ কি ও ডিরেক্টরি কনসিস্টেন্ট রাখতে সাহায্য করে।
টিমে স্ক্রিপ্টগুলি পড়ার মতো রাখতে, এগুলোকে প্রোডাক্ট কোডের মত আচরণ করুন: ছোট ফাংশন, ধারাবাহিক নামকরণ, সংক্ষিপ্ত usage হেডার। শেয়ার্ড স্ক্রিপ্টগুলো রেপোতে রাখুন (যেমন /ci/) যাতে কোড পরিবর্তনের সঙ্গে রিভিউ হয়।
যদি আপনার দল বারবার “আরেকটি CI স্ক্রিপ্ট” লিখে, AI-সহায্যক ওয়ার্কফ্লো সহায়তা করতে পারে—বিশেষ করে বয়লারপ্লেটের জন্য: আর্গ পার্সিং, রিট্রাই, নিরাপদ লগিং, গার্ডরেইল। Koder.ai তে আপনি প্লেইন ভাষায় পাইপলাইন কাজ বর্ণনা করে একটি স্টার্টার Bash/sh স্ক্রিপ্ট জেনারেট করতে পারবেন, তারপর প্ল্যানিং মোডে ইটারেট করতে পারবেন। Koder.ai সোর্স কোড এক্সপোর্ট, স্ন্যাপশট ও রোলব্যাক সাপোর্ট করে, যার ফলে স্ক্রিপ্টগুলো অ্যাড-হক স্নিপেট নয়—রিভিউ করা আর্টিফ্যাক্ট হিসেবে ট্রিট করা সহজ।
অনেক টুল প্রথমে CLI এক্সপোজ করে—এই কারণে কনটেইনার ও ক্লাউড ওয়ার্কফ্লোতে শেল প্র্যাকটিকাল গ্লু লেয়ারের মতো থাকে। ইনফ্রাস্ট্রাকচার অন্য কোথাও ডিফাইন করা হোক না কেন, আপনাকে লঞ্চ, ভ্যালিডেট, কালেক্ট এবং রিকভার করার জন্য ছোট, নির্ভরযোগ্য অটোমেশন দরকার।
কনটেইনার entrypoint-এ আপনি ছোট শেল স্ক্রিপ্ট পাবেন যেগুলো:
কিন্তু এন্ট্রি-স্ক্রিপ্টগুলো সংক্ষিপ্ত ও পূর্বানুমানযোগ্য রাখুন—সেটআপ করুন এবং তারপর exec দিয়ে মেইন প্রসেস চালান যাতে সিগন্যাল ও exit কোড সঠিকভাবে চলে।
দৈনন্দিন Kubernetes কাজের জন্য লাইটওয়েট হেল্পারগুলো উপকারী: kubectl র্যাপার যা কনটেক্সট/নেমস্পেস ঠিক আছে কি না নিশ্চিত করে, একাধিক পড থেকে লগ সংকলন করে, অথবা ইনসিডেন্টে সাম্প্রতিক ইভেন্ট নিয়ে আসে।
উদাহরণ: একটি স্ক্রিপ্ট প্রোডাকশনে পয়েন্ট করলে চলবে না, বা লগগুলো একক আর্টিফ্যাক্টে বানিয়ে টিকিটে যোগ করে।
AWS/Azure/GCP CLI ব্যাচ টাস্কে উপযুক্ত: রিসোর্স ট্যাগ করা, সিক্রেট রোটেট করা, ইনভেন্টরি এক্সপোর্ট করা, বা রাতের বেলা নন-প্রোড এনভায়রনমেন্ট বন্ধ করা। শেল এই কাজে বেশ দ্রুত—এই অ্যাকশনগুলো চেইন করে রিপিটেবল কমান্ড বানাতে।
দুইটি সাধারণ ব্যর্থতা হল ভঙ্গুর পার্সিং ও অনবিশ্বস্থ API। সম্ভাব্য structured আউটপুট প্রাধান্য দিন:
--output json) এবং jq দিয়ে পার্স করুন, মানব-ফরম্যাটেড টেবিল grep না করেএকটি ছোট পরিবর্তন—JSON + jq এবং বেসিক রিট্রাই লজিক—“ল্যাপটপে কাজ করে” স্ক্রিপ্টকে বারবার চালানোর মতো নির্ভরযোগ্য অটোমেশন বানায়।
কোথাও ভাঙলে, সাধারণত আপনাকে নতুন টুলচেইন দরকার হয় না—আপনি মিনিটের মধ্যে উত্তর চাইবেন। শেল ইনসিডেন্ট রেসপন্সের জন্য উপযুক্ত কারণ এটি হোস্টেই থাকে, দ্রুত চালানো যায়, এবং ছোট, নির্ভরযোগ্য কমান্ডগুলোকে একত্র করে একটি স্পষ্ট চিত্র তৈরি করে।
আউটেজের সময় সাধারণত কয়েকটি বেসিক যাচাই করা হয়:
df -h, df -i)free -m, vmstat 1 5, uptime)ss -lntp, ps aux | grep ...)getent hosts name, dig +short name)curl -fsS -m 2 -w '%{http_code} %{time_total}\n' URL)শেল স্ক্রিপ্ট এখানে ভালো কারণ আপনি এই চেকগুলো স্ট্যান্ডার্ডাইজ করে হোস্ট জুড়ে চালাতে পারেন এবং আউটপুট ইনসিডেন্ট চ্যানেলে পেস্ট করতে পারেন।
একটি ভালো ইনসিডেন্ট স্ক্রিপ্ট একটি স্ন্যাপশট সংগ্রহ করে: টাইমস্ট্যাম্প, হোস্টনেম, কার্নেল ভার্সন, সাম্প্রতিক লগ, বর্তমান কানেকশন এবং রিসোর্স ব্যবহার। সেই "স্টেট বান্ডেল" পরে রুট-কজ বিশ্লেষণে সাহায্য করে।
#!/usr/bin/env bash
set -euo pipefail
out="incident_$(hostname)_$(date -u +%Y%m%dT%H%M%SZ).log"
{
date -u
hostname
uname -a
df -h
free -m
ss -lntp
journalctl -n 200 --no-pager 2>/dev/null || true
} | tee "$out"
ইনসিডেন্ট অটোমেশন প্রথমে রিড-অনলি হওয়া উচিত। “ফিক্স” অ্যাকশনগুলোকে স্পষ্ট ওনলি করুন—কনফার্মেশন প্রম্পট বা --yes ফ্ল্যাগ দিয়ে এবং কি পরিবর্তন হবে তা স্পষ্টভাবে দেখান। এতে রেসপন্ডারগুলো দ্রুত কাজ করতে পারে—বিনা অতিরিক্ত ইনসিডেন্ট তৈরি করে।
পোর্টেবিলিটি গুরুত্বপূর্ণ যখন আপনার অটোমেশন সেই "যেটাই রানের আছে" পরিবেশে চলবে: মিনিমাল কন্টেইনার (Alpine/BusyBox), বিভিন্ন লিনাক্স ডিসট্রো, CI ইমেজ, বা ডেভেলপার ল্যাপটপ (macOS)। বড় ব্যথার কারণ হচ্ছে প্রত্যেক মেশিনে একই শেল আছে ধরে নেওয়া।
POSIX sh সর্বনিম্ন সাধারণ লেভেল: বেসিক ভ্যারিয়েবল, case, for, if, পাইপলাইন, এবং সিম্পল ফাংশন। সর্বত্র চলার মতো স্ক্রিপ্ট লিখতে চাইলে এটিকে টার্গেট করুন।
Bash ফিচার-সমৃদ্ধ: অ্যারে, [[ ... ]] টেস্ট, process substitution (<(...)), set -o pipefail, এক্সটেন্ডেড globbing এবং উন্নত স্ট্রিং হ্যান্ডলিং। এই ফিচারগুলো ডেভঅপস অটোমেশন দ্রুত করে—কিন্তু /bin/sh যদি Bash না হয়, তাহলে ব্রেক করতে পারে।
sh টার্গেট করুন (Alpine's ash, Debian dash, BusyBox)macOS-এ ডিফল্ট Bash 3.2 থাকতে পারে, লিনাক্স CI ইমেজে Bash 5.x—তাই “Bash স্ক্রিপ্ট” লেখলেও ভার্সন ডিফারেন্সে সমস্যা হতে পারে।
সাধারণ bashisms: [[ ... ]], অ্যারে, source (পোর্টেবল হলে . ব্যবহার করুন), এবং echo -e আচরণ। যদি POSIX চান, তাহলে প্রকৃত POSIX শেলে (উদাহরণ: dash বা BusyBox sh) লিখে টেস্ট করুন।
আপনার ইচ্ছা মেনেই শিব্যাং ব্যবহার করুন:
#!/bin/sh
অথবা:
#!/usr/bin/env bash
তারপর রেপোতে প্রয়োজনীয় চাহিদা (উদাহরণ: “requires Bash ≥ 4.0”) লিখে রাখুন যাতে CI, কনটেইনার এবং টিম মিলে থাকে।
CI-তে shellcheck চালান যাতে bashisms, কোটিং ভুল ও অন-নিরাপদ প্যাটার্ন ধরা পড়ে। এটি "ওয়ার্কস অন মাই মেশিন" শেল ত্রুটি রোধ করার দ্রুত উপায়। আরও আইডিয়া ও সেটআপের জন্য একটি অন্তর্দল গাইড দেখান: /blog/shellcheck-in-ci
শেল স্ক্রিপ্ট সাধারণত প্রোডাকশন সিস্টেম, ক্রেডেনশিয়াল ও সংবেদনশীল লগস অ্যাক্সেস করে। কিছু প্রতিরক্ষামূলক অভ্যাস "হ্যান্ডি অটোমেশন" এবং একটি ইনসিডেন্টের মধ্যে পার্থক্য তৈরি করে।
অনেক দল স্ক্রিপ্টের শুরুতে রাখে:
set -euo pipefail
-e ত্রুটিতে থামায়, কিন্তু if কন্ডিশন, while টেস্ট এবং কিছু পাইপলাইনে আপনাকে অপ্রত্যাশিত আচরণ দিতে পারে। প্রত্যাশিত ব্যর্থতা স্পষ্টভাবে হ্যান্ডল করুন।-u আনসেট ভ্যারিয়েবলকে ত্রুটি মনে করে—টাইপো ধরার জন্য খুব ভাল।pipefail নিশ্চিত করে পাইপলাইনের ভেতরের কোনো কমান্ড ব্যর্থ করলে পুরো পাইপলাইন ব্যর্থ হবে।যখন আপনি ইচ্ছাকৃতভাবে একটি কমান্ড ব্যর্থ হতে দেবেন, সেটা হয়তো command || true বা স্পষ্ট চেক দিয়ে দেখান।
কোট ছাড়া ভ্যারিয়েবল ব্যবহার করলে word-splitting ও wildcard expansion ঘটতে পারে:
rm -rf $TARGET # ঝুঁকিপূর্ণ
rm -rf -- "$TARGET" # নিরাপদ
প্রয়োজনে Bash-এ অ্যারে ব্যবহার করুন যখন আর্গুমেন্টগুলো বানাতে হবে।
eval এড়ানো, লিস্ট প্রিভিলেজপ্যারাম, এনভি ভ্যার, ফাইলনাম ও কমান্ড আউটপুটকে অনট্রাস্টেড হিসেবে বিবেচনা করুন।
eval এড়ান এবং শেল কোড স্ট্রিং হিসেবে বানাবেন নাsudo নয়, নির্দিষ্ট কমান্ডে sudo ব্যবহার করুনecho, ডিবাগ ট্রেস বা verbose curl)।set -x সংবেদনশীল অংশে নিষ্ক্রিয় করুন; ট্রেসিং অস্থায়ীভাবে বন্ধ করুনঅস্থায়ী ফাইলের জন্য mktemp ব্যবহার করুন এবং ক্লিনআপে trap দিন:
tmp="$(mktemp)"
trap 'rm -f "$tmp"' EXIT
-- ব্যবহার করে অপশন পার্সিং শেষ করুন (rm -- "$file") এবং সংবেদনশীল ডেটা ফাইল তৈরিতে স্ট্রিকট umask সেট করুন।
শেল স্ক্রিপ্ট প্রায়ই দ্রুত একটি ফিক্স হিসেবে শুরু করে, পরে ধীরে ধীরে প্রোডাকশনে চলে যায়। মেইনটেনেবলিটি তা যেন রহস্যময় ফাইল না হয় সেটা নিশ্চিত করে।
কিছু স্ট্রাকচার দ্রুত ফল দেয়:
scripts/ (বা ops/) ফোল্ডারে রাখুন যাতে খুঁজে পাওয়া সহজ হয়backup-db.sh, rotate-logs.sh, release-tag.sh)—ইন-জোক নাম এড়ানস্ক্রিপ্টের ভিতরে ছোট, single-purpose ফাংশন এবং ধারাবাহিক লগিং প্যাটার্ন (যেমন log_info/log_warn/log_error) ব্যবহার করুন।
-h/--help সাপোর্ট করুন—এটা স্ক্রিপ্টকে এমন একটি টুল বানায় যা টিম সহজে চালাতে পারে।
শেল টেস্ট করা কঠিন নয়—কিন্তু সহজে বাদ পড়ে। হালকা উদ্যোগ:
--dry-run) দিয়ে স্ক্রিপ্ট চালায় এবং আউটপুট যাচাই করেটেস্টগুলোর ফোকাস রাখুন ইনপুট/আউটপুট: আর্গুমেন্ট, exit স্ট্যাটাস, লগ লাইন, এবং সাইড-ইফেক্ট (ফাইল তৈরি, কমান্ড কল)।
দুটি টুল অনেক সমস্যা ধরবে:
দুটোকেই CI-তে চালান যাতে স্ট্যান্ডার্ড কেউ মনে করে চালায় না—প্রতি PR-এ বাধ্যতামূলক হয়।
অপারেশনাল স্ক্রিপ্ট ভার্সন কন্ট্রোল, কোড রিভিউ এবং চেঞ্জ ম্যানেজমেন্টের আওতায় রাখুন। পরিবর্তনের জন্য PR বাধ্যতামূলক রাখুন, বিহেভিয়র পরিবর্তন কমিট মেসেজে ডকুমেন্ট করুন, এবং যখন স্ক্রিপ্ট একাধিক রেপো বা টিম দ্বারা ব্যবহৃত হয় তখন সিম্পল ভার্সন ট্যাগ বিবেচনা করুন।
নির্ভরযোগ্য ইনফ্রা স্ক্রিপ্টগুলো predictable, safe to re-run, এবং চাপের মধ্যে পড়লে পড়ার মতো হয়। কিছু প্যাটার্ন “ওয়ার্কস অন মাই মেশিন” কে টিম-ট্রাস্টেড বানায়।
ধরি স্ক্রিপ্টটি দুইবার চালানো হবে—মানব, cron বা রিট্রাইং CI জবের কারণে। “স্টেট নিশ্চিত করা” প্রাধান্য দিন—“করণ” করার পরিবর্তে।
mkdir -p ব্যবহার করুন, শুধুমাত্র mkdir নয়নিয়ম: যদি প্রয়োজনীয় শেষ অবস্থা ইতিমধ্যে থাকে, স্ক্রিপ্ট সফলভাবে বের হয়ে উল্টে আসা উচিত।
নেটওয়ার্ক ব্যর্থ হয়। রেজিস্ট্রি রেট-লিমিট করে। API টাইমআউট হয়। ফ্ল্যাকি অপারেশনগুলো রিট্রাই ও বাড়তে থাকা বিলম্ব সহ র্যাপ করুন।
retry() {
n=0; max=5; delay=1
while :; do
"$@" && break
n=$((n+1))
[ "$n" -ge "$max" ] && return 1
sleep "$delay"; delay=$((delay*2))
done
}
(উপরের ব্লকে ডাবল কোটিং লক্ষ্য করুন—আর্গুমেন্টগুলো সঠিকভাবে ফরওয়ার্ড করা হচ্ছে)।
অটোমেশনে HTTP স্ট্যাটাসকে ডেটা হিসেবে বিবেচনা করুন। curl -fsS ব্যবহার করুন (নন-2xx এ ফেল করে, ত্রুটি দেখায়) এবং প্রয়োজনে স্ট্যাটাস ক্যাপচার করুন:
resp=$(curl -sS -w "\n%{http_code}" -H "Authorization: Bearer $TOKEN" "$URL")
body=${resp%$'\n'*}; code=${resp##*$'\n'}
[ "$code" = "200" ] || { echo "API failed: $code" >&2; exit 1; }
JSON পার্স করতে হলে jq ব্যবহার করুন—নরমাল grep পাইপলাইনগুলো ভঙ্গুর।
একই রিসোর্স নিয়ে দুই কপি স্ক্রিপ্ট লড়াই করলে সমস্যা হয়। flock যখন আছে ব্যবহার করুন, অথবা PID চেকসহ লকফাইল প্যাটার্ন ব্যবহার করুন।
লগ স্পষ্ট রাখুন (টাইমস্ট্যাম্প, কী করা হলো), কিন্তু মেশিন-রিডেবল মোড (JSON)ও অফার করুন যাতে ড্যাশবোর্ড ও CI আর্টিফ্যাক্টগুলো স্বয়ংক্রিয়ভাবে ব্যবহার করতে পারে। একটি ছোট --json ফ্ল্যাগ প্রায়ই কাজে লাগবে।
শেল গ্লু ল্যাঙ্গুয়েজ হিসেবে চমৎকার: এটি কমান্ড চেইন করে, ফাইল মুভ করে এবং ইতিমধ্যে বক্সে থাকা টুলগুলোকে কুড়িয়ে ব্যবহার করে। কিন্তু সব ধরণের অটোমেশনের জন্য এটি সেরা নয়।
নিচের লক্ষণগুলো দেখলেই শেল ছেড়ে গিয়ে অন্য ভাষা বিবেচনা করুন:
if, টেম্পোরারি ফ্ল্যাগ, স্পেশাল কেস)Python ভাল যখন আপনি API-র সাথে ইন্টিগ্রেট করছেন (ক্লাউড, টিকিটিং), JSON/YAML নিয়ে কাজ করছেন, অথবা ইউনিট টেস্ট ও পুনঃব্যবহারযোগ্য মডিউল দরকার। যদি আপনার স্ক্রিপ্ট বাস্তবে রিচ্-হ্যান্ডলিং, উন্নত লগিং এবং স্ট্রাকচার্ড কনফিগ লাগে, Python সাধারণত ভঙ্গুর পার্সিং কমায়।
Go ডিস্ট্রিবিউটেবল টুলিংয়ের জন্য ভালো: একক স্ট্যাটিক বাইনারি, পূর্বানুমানযোগ্য পারফরম্যান্স, এবং কঠোর টাইপিং। যদি আপনি একটি ইন্টারনাল CLI টুল বানাতে চান যা মিনিমাল কনটেইনার বা লকড-ডাউন হোস্টে চলবে, Go উপযুক্ত।
প্রায়শই বাস্তবিক প্যাটার্ন: শেল কে পাতলা র্যাপার হিসেবে রাখা:
এটাই যেখানে Koder.ai সহায়তা করতে পারে: ওয়ার্কফ্লো প্রোটোটাইপ পুরুত্থ ভাবে পাতলা Bash র্যাপার হিসেবে তৈরি করুন, তারপর যখন লজিক গ্র্যাজুয়েট করে এক্সপোর্ট করে ভার্সন কন্ট্রোল ও রিভিউ-র মধ্যে নিয়ে আসুন।
শেল বেছে নিন যদি এটা প্রাথমিকভাবে: কমান্ড অর্কেসট্রেট করা, সংক্ষিপ্ত, এবং টার্মিনালে সহজে টেস্ট করা যায়।
অন্য ভাষা বেছে নিন যদি দরকার: লাইব্রেরি, স্ট্রাকচার্ড ডেটা, ক্রস-প্ল্যাটফর্ম সাপোর্ট, বা টেস্ট সহ রক্ষণযোগ্য কোড যা সময়ের সাথে বাড়বে।
Bash শিখা সবচেয়ে ভালো যখন আপনি এটাকে একটি টুলবেল্ট হিসেবে দেখেন—একবারে পুরো ভাষা মাস্টার করতে হবে না। সেই ২০% শিখুন যা আপনি সাপ্তাহিক ব্যবহার করবেন, আর কষ্ট হলে নতুন ফিচার যোগ করুন।
বেসিক কমান্ড ও নিয়মগুলোর ওপর ফোকাস করুন:
ls, find, grep, sed, awk, tar, curl, jq (হ্যাঁ, এটা শেল নয়—কিন্তু অপরিহার্য)|, >, >>, 2>, 2>&1, here-strings$?, set -e ট্রেড-অফ, এবং স্পষ্ট চেক cmd || exit 1"$var", অ্যারে, এবং কখন word-splitting সমস্যা করেfoo() { ... }, $1, $@, ডিফল্ট মানছোট স্ক্রিপ্ট লিখুন যা টুলগুলো গ্লু করে—বড় অ্যাপ বানানোর চেস্টা করবেন না।
প্রতি সপ্তাহে একটি সংক্ষিপ্ত প্রকল্প নিন এবং ফ্রেশ টার্মিনাল থেকে রানেবল রাখুন:
প্রতিটি স্ক্রিপ্ট প্রথমে ~100 লাইন রাখুন। বড় হলে ফাংশনে ভাগ করুন।
প্রাইমারি সোর্স ব্যবহার করুন:
man bash, help set, এবং man testএকটি ছোট স্টার্টার টেমপ্লেট ও রিভিউ চেকলিস্ট তৈরি করুন:
set -euo pipefail (অথবা ডকুমেন্ট করা বিকল্প)trap ক্লিনআপশেল স্ক্রিপ্ট সবচেয়ে বেশি মূল্য দেয় যখন আপনাকে দ্রুত, পোর্টেবল গ্লু দরকার: বিল্ড চালানো, সিস্টেম ইন্সপেকশন, এবং সামান্য ডিপেনডেন্সির সাথে রিপিটেবল অ্যাডমিন কাজ করা।
কয়েকটি সেফটি ডিফল্ট (কোটিং, ইনপুট ভ্যালিডেশন, রিট্রাই, লিন্টিং) স্ট্যান্ডার্ড করলে শেল আপনার অটোমেশন স্ট্যাকের নির্ভরযোগ্য অংশ হয়ে ওঠে—নতুন ঝুঁকিপূর্ণ বিন্যাস নয়। এবং যখন আপনি “স্ক্রিপ্ট” থেকে “প্রোডাক্ট” এ যেতে চান, Koder.ai-এর মতো টুলগুলো সেই অটোমেশনকে একটি রক্ষণযোগ্য অ্যাপ বা ইন্টারনাল টুলে রূপান্তর করতে সাহায্য করতে পারে, সোর্স কন্ট্রোল, রিভিউ এবং রোলব্যাক বজায় রেখে।
DevOps-এ একটি শেল স্ক্রিপ্ট সাধারণত গ্লু কোড — ছোট একটি প্রোগ্রাম যা বিদ্যমান টুলগুলোকে pipes, exit codes এবং environment variables ব্যবহার করে একসাথে বেঁধে দেয় (লিনাক্স ইউটিলিটি, ক্লাউড CLI, CI ধাপ ইত্যাদি)।
যখনই আপনাকে দ্রুত, ডিপেন্ডেন্সি-কম অটোমেশন চাই যা সার্ভার বা রান্নারের শেলে সরাসরি চালানো যাবে, তখন শেল সবথেকে কার্যকর।
যদি আপনার স্ক্রিপ্ট বিভিন্ন পরিবেশে চলবে (BusyBox/Alpine, মিনিমাল কন্টেইনার, অজানা CI রানার), তাহলে POSIX sh ব্যবহার করুন।
আপনি যদি রানটাইম কন্ট্রোল করেন (আপনার CI ইমেজ, অপস হোস্ট) অথবা Bash-এর বিশেষ ফিচার দরকার (যেমন [[ ... ]], arrays, pipefail, process substitution), তখন Bash ব্যবহার করুন।
শেবাং দিয়ে ইন্টারপ্রেটার পিন করুন (উদাহরণ: #!/bin/sh বা #!/usr/bin/env bash) এবং প্রয়োজনীয় ভার্সন ডকুমেন্ট করুন।
কারণ এটা সরাসরি থাকে: বেশিরভাগ লিনাক্স ইমেজে শেল ও মূল ইউটিলিটি আছে (grep, sed, awk, tar, curl, systemctl)।
এটি উপযুক্ত:
IaC/কনফিগ টুলগুলো সাধারণত সিস্টেম অফ রেকর্ড — সেখানে ইচ্ছাকৃত কাঠামো নির্ধারণ, রিভিউ, ভার্সনিং এবং কনসিস্টেন্ট অ্যাপ্লাই করা হয়। Shell স্ক্রিপ্টগুলো ভালোভাবে কাজ করে র্যাপার বা অর্কেস্ট্রেটরের মতো: ধাপগুলো সংযুক্ত করা, ভ্যারিয়েবল ভ্যালিডেশন, এবং ক্লাউড/CI CLI-গুলোর মধ্যে ইন্টিগ্রেশন।
উদাহরণস্বরূপ: Terraform রিসোর্স তৈরি করে, কিন্তু একটি Bash স্ক্রিপ্ট ইনপুট যাচাই, সঠিক ব্যাকএন্ড নিশ্চয়তা এবং terraform plan + পলিসি চেক চালাতে পারে আগে apply করার আগে।
নির্ভরযোগ্য ও পূর্বানুমানযোগ্য রাখুন:
set +x ব্যবহার করুনjq দিয়ে JSON পার্স করুন, টেবিল grep-এ ভরসা করবেন নাএকটি ফ্ল্যাকি ধাপ থাকলে (নেটওয়ার্ক/API), ব্যাকঅফ সহ রিট্রাই যোগ করুন এবং সর্বোচ্চ চেষ্টা ব্যর্থ হলে কঠোরভাবে ব্যর্থ করুন।
এনট্রিপয়েন্ট স্ক্রিপ্টগুলো ছোট ও নির্ধারিত রাখুন:
exec দিয়ে মেইন প্রসেস চালান যাতে সিগন্যাল ও exit কোড সঠিকভাবে চলেএন্ট্রি-স্ক্রিপ্টে ব্যাকগ্রাউন্ডে দীর্ঘসময়ের প্রসেস রাখবেন না যদি না আপনার সুপারভিশন কৌশল পরিষ্কার থাকে—নাহলে শাটডাউন ও রিস্টার্ট অসততা জন্মাতে পারে।
সাধারণ সমস্যা:
/bin/sh হতে পারে dash (Debian/Ubuntu) বা BusyBox sh (Alpine), Bash নয়echo -e, sed -i, এবং টেস্ট সিনট্যাক্স প্ল্যাটফর্মভিত্তিকভাবে ভিন্ন হতে পারেএকটি ভালো বেসলাইন:
set -euo pipefail
আর কিছু অভ্যাস:
দ্রুত, কনসিস্টেন্ট ডায়াগনস্টিক্সের জন্য কিছু কমাণ্ড স্ট্যান্ডার্ডাইজ করুন এবং টাইমস্ট্যাম্পসহ আউটপুট সংগ্রহ করুন।
সাধারণ চেকগুলো:
দুটি টুল বেশিরভাগ সমস্যা ধরবে:
হালকা টেস্টিং:
পোর্টেবিলিটি জরুরি হলে টার্গেট শেল (উদাহরণ: dash/BusyBox) দিয়ে টেস্ট করুন এবং CI-তে ShellCheck চালান যাতে bashisms দ্রুত ধরা পড়ে।
"$var" (word-splitting/globbing প্রতিরোধ করে)eval এড়ান এবং স্ট্রিং থেকে শেল কোড বানাবেন না-- ব্যবহার করুন (উদাহরণ: rm -- "$file")mktemp এবং ক্লিনআপে trap ব্যবহার করুনset -e নিয়ে সতর্ক হবেন: প্রত্যাশিত ব্যর্থতা আলাদা করে হ্যান্ডল করুন (cmd || true বা উপযুক্ত চেক)।
df -h, df -iuptime, free -m, vmstat 1 5ss -lntpjournalctl -n 200 --no-pagercurl -fsS -m 2 URLপ্রথমে read-only চেক রাখুন; যে কোন ফিক্স/রাইট অ্যাকশন স্পষ্টভাবে আলাদা (প্রম্পট বা --yes) রাখুন।
--dry-run মোডসহ)স্ক্রিপ্টগুলো scripts/ বা ops/-এ রাখুন এবং মিনিমাল --help ব্লক রাখুন।