মূল content-এ যাও

DevOps/Linux ও Command Line/Lesson 04

Shell scripting

Command-গুলো একটা file-এ লিখে স্বয়ংক্রিয় করা। Variable, if, for, exit code, set -euo pipefail, আর quoting। আর Python-এ shell-এর মতো একটা command line ভাগ করা।

সময়
26 মিনিট
Exercise
1
Challenge
1
Quiz
3 প্রশ্ন

সহজ ভাষায়

প্রতিদিন server-এ একই কাজ: code নামাও, dependency install করো, test চালাও, restart করো। ১০টা command প্রতিবার হাতে টাইপ করলে একসময় ভুল হবেই। এগুলো একটা file-এ লিখে ফেললে সেটাই shell script:

#!/usr/bin/env bash
set -euo pipefail

echo "🚀 Deploy শুরু"
git pull
pip install -r requirements.txt
python3 -m pytest
sudo systemctl restart model-api
echo "✅ শেষ"
chmod +x deploy.sh    # আগের lesson: execute permission
./deploy.sh           # চালাও

প্রথম লাইন #!/usr/bin/env bash হলো shebang। এটা বলে দেয় কোন program এই file চালাবে।

কেন দরকার?

  • পুনরাবৃত্তি: একই কাজ, প্রতিবার হুবহু একইভাবে
  • CI/CD: GitHub Actions-এর প্রতিটা run: ধাপ আসলে shell command
  • Docker: Dockerfile-এর RUN আর container-এর entrypoint script
  • Server setup: নতুন machine তৈরি করার script

মূল গঠন

#!/usr/bin/env bash
set -euo pipefail

MODEL="student-v2"                     # variable (= এর দুপাশে space নয়!)
EPOCHS="${1:-10}"                      # প্রথম argument, না দিলে 10

echo "Training $MODEL for $EPOCHS epochs"

if [[ -f "models/$MODEL.joblib" ]]; then     # file আছে?
    echo "আগের model আছে, backup নিচ্ছি"
    cp "models/$MODEL.joblib" "backup/"
fi

for split in train valid test; do            # loop
    echo "checking data/$split.csv"
    test -s "data/$split.csv"                # ফাঁকা হলে ব্যর্থ, set -e থামিয়ে দেবে
done

python3 train.py --model "$MODEL" --epochs "$EPOCHS"

Exit code: সাফল্যের ভাষা

প্রতিটা command শেষে একটা সংখ্যা দেয়: 0 = সফল, অন্য যেকোনো সংখ্যা = ব্যর্থ। $?-এ শেষ command-এর code থাকে:

grep -q "ERROR" app.log
echo $?                 # 0 = পাওয়া গেছে, 1 = পাওয়া যায়নি

python3 -m pytest && echo "pass" || echo "fail"     # && সফল হলে, || ব্যর্থ হলে

Python script-ও exit code দেয়:

main.py

এভাবেই একটা Python check CI pipeline থামিয়ে দিতে পারে, যেমন MLOps-এর deploy gate।

set -euo pipefail: নিরাপত্তা বেল্ট

Flagকী করেনা থাকলে কী হয়
-eকোনো command ব্যর্থ হলে থামোTest fail করলেও deploy চলে যায়
-uঅজানা variable হলে থামোrm -rf $DIR/-এ DIR খালি থাকলে rm -rf /
-o pipefailPipe-এর যেকোনো অংশ ব্যর্থ হলে ব্যর্থ ধরোfalse | true সফল বলে ধরা হয়

প্রতিটা script-এর দ্বিতীয় লাইনে এটা লিখে রাখার অভ্যাস করো।

Quoting: সবচেয়ে বেশি bug-এর উৎস

NAME="Riya   Das"
echo $NAME          # Riya Das         ← shell ভাগ করেছে, space হারিয়েছে
echo "$NAME"        # Riya   Das       ← অবিকৃত
touch "my file.txt" # একটা file
touch my file.txt   # দুটো file: "my" আর "file.txt"!

নিয়ম: variable সবসময় "$VAR"। Challenge-এ shell কীভাবে লাইন ভাগ করে, সেটা নিজে বানাবে।

Exercise

Exercise

Exit code আর set -e

+20 XP

প্রতিটা command শেষে একটা exit code দেয়: 0 মানে সফল, অন্য যেকোনো সংখ্যা মানে ব্যর্থ। set -e থাকলে script প্রথম ব্যর্থতাতেই থেমে যায়।

run_steps(steps) লেখো। steps হলো (নাম, function)-এর list, আর প্রতিটা function একটা exit code (int) return করে।

  • ক্রমে চালাও। প্রতিটার পরে "নাম: code" print করো।
  • কোনোটা 0 ছাড়া অন্য কিছু দিলে সেখানেই থামো আর সেই code return করো
  • সব সফল হলে 0 return করো
solution.py

Quiz

  1. Q1Script-এর শুরুতে set -euo pipefail কেন?
  2. Q2rm -rf $DIR/ — DIR variable খালি হলে কী হয়?
  3. Q3echo $NAME আর echo "$NAME"-এর পার্থক্য কী, যখন NAME="Riya Das"?
0/3 answered

Challenge

Challenge

Shell-এর মতো শব্দ ভাগ করা

+50 XP

Shell একটা command line-কে শব্দে (argument) ভাগ করে। কিন্তু quote-এর ভেতরের space ভাগ করে না। split_args(line) লেখো:

  • Quote-এর বাইরের space শব্দ আলাদা করে। একাধিক space মিলে একটা হিসেবে ধরা হবে।
  • "..." বা '...'-এর ভেতরের সবকিছু (space সহ) একই শব্দের অংশ। Quote চিহ্নগুলো নিজে বাদ যায়।
  • Quote শব্দের মাঝেও শুরু হতে পারে: --name="Riya Das" → --name=Riya Das
  • "" (খালি quote) একটা খালি শব্দ তৈরি করে
  • Quote শেষ না হলে ValueError

shlex ব্যবহার করা যাবে না। নিজে character ধরে ধরে করো।

solution.py

বাস্তবে কোথায় ব্যবহার হয়?

একটা ছোট backup script, যেটা প্রতি রাতে চলে (cron দিয়ে):

#!/usr/bin/env bash
set -euo pipefail

BACKUP_DIR="/backups/$(date +%F)"           # যেমন /backups/2026-10-06
mkdir -p "$BACKUP_DIR"
pg_dump "$DATABASE_URL" | gzip > "$BACKUP_DIR/db.sql.gz"
cp -r /srv/models "$BACKUP_DIR/"
find /backups -maxdepth 1 -type d -mtime +7 -exec rm -rf {} +   # ৭ দিনের পুরনো মোছো
echo "backup ঠিকঠাক: $BACKUP_DIR"

Script যখন লম্বা আর জটিল হয়ে যায় (ধরো ১০০ লাইনের বেশি, জটিল logic বা data নিয়ে কাজ), তখন সাধারণত Python-এ লেখা ভালো। Shell সবচেয়ে ভালো command জোড়া লাগাতে।

Interview প্রশ্ন

  • Beginner: Exit code কী? 0 মানে কী?
  • Intermediate: set -euo pipefail কী করে? প্রতিটা flag ব্যাখ্যা করো।
  • Advanced: কখন shell script আর কখন Python বেছে নেবে? Quoting-এর ভুল কীভাবে নিরাপত্তা সমস্যা তৈরি করতে পারে?

এরপর কী?

🎉 Linux আর command line module শেষ: filesystem, permissions, pipes আর scripting। DevOps-এর প্রায় সবকিছু এই ভিত্তির উপর দাঁড়িয়ে।

পরের module: Git আর GitHub। Code-এর version control, branch, merge, আর দলের সাথে কাজ।