Bash và shell scripts vẫn chạy các job CI, server và sửa lỗi nhanh. Tìm hiểu nơi chúng phát huy, cách viết script an toàn hơn và khi nào nên dùng công cụ khác.

Khi người ta nói “shell scripting”, thường họ đề cập đến việc viết một chương trình nhỏ chạy trong shell dòng lệnh. Shell đọc các lệnh của bạn và khởi chạy các chương trình khác. Trên hầu hết server Linux, shell đó thường là POSIX sh (một chuẩn cơ bản) hoặc Bash (shell “sh-like” phổ biến nhất với các tính năng bổ sung).
Trong ngôn ngữ DevOps, shell script là lớp glue mỏng nối các công cụ OS, cloud CLI, công cụ build và file cấu hình lại với nhau.
Máy Linux đã có sẵn các tiện ích lõi (như grep, sed, awk, tar, curl, systemctl). Một script shell có thể gọi trực tiếp các công cụ này mà không cần thêm runtime, package hay phụ thuộc—rất hữu dụng trong image tối giản, recovery shell, hoặc môi trường bị khóa.
Shell scripting nổi bật vì hầu hết công cụ tuân theo những hợp đồng đơn giản:
cmd1 | cmd2).0 là thành công; khác 0 là thất bại—rất quan trọng cho tự động hóa.Chúng ta sẽ tập trung vào cách Bash/shell phù hợp với tự động hóa DevOps, CI/CD, container, xử lý sự cố, tính di động và các thực hành an toàn. Chúng ta sẽ không cố biến shell thành framework ứng dụng đầy đủ—khi cần như vậy, tôi sẽ chỉ ra công cụ phù hợp hơn (và cách shell vẫn hỗ trợ xung quanh chúng).
Shell scripting không chỉ là “glue cũ.” Nó là một lớp nhỏ, đáng tin cậy biến chuỗi lệnh thủ công thành hành động có thể lặp lại—đặc biệt khi bạn di chuyển nhanh giữa server, môi trường và công cụ.
Ngay cả khi mục tiêu dài hạn của bạn là hạ tầng quản lý hoàn toàn, thường có lúc bạn cần chuẩn bị host: cài package, thả file config, đặt quyền, tạo user, hoặc lấy secret từ nơi an toàn. Một script shell ngắn là hoàn hảo cho các tác vụ một lần (hoặc “hiếm khi lặp lại”) vì nó chạy ở mọi nơi có shell và SSH.
Nhiều đội lưu runbook như tài liệu, nhưng runbook hữu dụng nhất là script bạn có thể chạy khi cần vận hành:
Biến runbook thành script giảm lỗi con người, làm cho kết quả nhất quán hơn và cải thiện chuyển giao.
Khi sự cố xảy ra, bạn hiếm khi cần một app đầy đủ hay dashboard—bạn cần rõ ràng. Pipeline shell cùng grep, sed, awk, jq vẫn là cách nhanh nhất để cắt log, so sánh output và tìm mẫu qua nhiều node.
Công việc hàng ngày thường là chạy cùng các bước CLI ở dev, staging và prod: gắn tag artifacts, đồng bộ file, kiểm tra trạng thái, hoặc rollout an toàn. Shell script ghi lại các workflow này để chúng nhất quán giữa các môi trường.
Không phải mọi thứ đều tích hợp mượt mà. Shell script có thể kết nối “Tool A xuất JSON” với “Tool B cần biến môi trường”, điều phối các lệnh và thêm kiểm tra/retry thiếu—không cần chờ tích hợp hay plugin mới.
Shell scripting và các công cụ như Terraform, Ansible, Chef, Puppet giải quyết vấn đề liên quan nhưng không thể hoán đổi cho nhau.
Hãy nghĩ IaC/config là hệ thống ghi nhận: nơi trạng thái mong muốn được định nghĩa, review, version và apply nhất quán. Terraform khai báo hạ tầng (mạng, load balancer, DB). Ansible/Chef/Puppet mô tả cấu hình máy và hội tụ liên tục.
Shell script thường là glue code: lớp mỏng kết nối bước, công cụ và môi trường. Một script có thể không “sở hữu” trạng thái cuối cùng, nhưng nó làm cho tự động hóa trở nên thực tế bằng cách điều phối hành động.
Shell rất phù hợp khi bạn cần:
Ví dụ: Terraform tạo resource, nhưng một Bash script xác thực input, đảm bảo backend đúng, và chạy terraform plan + kiểm tra policy trước khi cho phép apply.
Shell triển khai nhanh và gần như không phụ thuộc—lý tưởng cho tự động hóa khẩn cấp và tác vụ phối hợp nhỏ. Nhược điểm là quản trị dài hạn: script có thể trôi thành “mini platform” với pattern không nhất quán, tính idempotency yếu, và thiếu auditing.
Quy tắc thực tế: dùng IaC/config cho hạ tầng trạng thái, có thể lặp lại; dùng shell cho workflow ngắn, có thể ghép nối xung quanh chúng. Khi script trở nên quan trọng với business, chuyển logic cốt lõi vào hệ thống ghi nhận và giữ shell như wrapper.
Hệ thống CI/CD điều phối các bước, nhưng vẫn cần cái gì đó thực sự làm việc. Bash (hoặc POSIX sh) vẫn là glue mặc định vì nó có sẵn trên hầu hết runner, dễ gọi và có thể xâu chuỗi công cụ mà không cần runtime thêm.
Hầu hết pipeline dùng bước shell cho các tác vụ thiết yếu: cài dependency, chạy build, đóng gói output và upload artifact.
Ví dụ thường gặp:
Pipeline truyền cấu hình qua biến môi trường, nên shell script tự nhiên làm bộ định tuyến cho các giá trị đó. Một pattern an toàn:
echo chúng, và tránh ghi ra đĩaƯu tiên:
set +x quanh phần nhạy cảm (để lệnh không bị in ra)CI cần hành vi dự đoán. Script pipeline tốt:
Cache và các bước song song thường do hệ thống CI điều phối, không phải script—Bash không thể quản lý shared cache giữa job một cách tin cậy. Những gì nó có thể làm là làm cho cache key và thư mục nhất quán.
Để script dễ đọc cho đội, coi nó như mã sản phẩm: hàm nhỏ, đặt tên nhất quán, và header sử dụng ngắn. Lưu script chung trong repo (ví dụ dưới /ci/) để thay đổi được review cùng mã nguồn.
Nếu đội bạn liên tục viết “nữa script CI nữa”, workflow hỗ trợ AI có thể giúp—đặc biệt cho boilerplate như phân tích tham số, retry, logging an toàn và rào chắn. Trên Koder.ai, bạn mô tả job pipeline bằng ngôn ngữ tự nhiên và tạo script Bash/sh khởi điểm, rồi lặp trong chế độ lập kế hoạch trước khi chạy. Vì Koder.ai hỗ trợ xuất mã nguồn cùng snapshots và rollback, dễ biến script thành artifact được review hơn là đoạn mã rời rạc bị copy vào YAML CI.
Trong DevOps, một shell script thường là glue code: một chương trình nhỏ nối các công cụ hiện có lại với nhau (tiện ích Linux, cloud CLI, bước CI) bằng pipes, mã thoát và biến môi trường.
Nó phù hợp nhất khi bạn cần tự động hóa nhanh, ít phụ thuộc trên server hoặc runner nơi shell đã có sẵn.
Dùng POSIX sh khi script phải chạy trên nhiều môi trường khác nhau (BusyBox/Alpine, container tối giản, runner CI không xác định).
Dùng Bash khi bạn kiểm soát runtime (image CI của bạn, host ops) hoặc khi bạn cần các tính năng của Bash như [[ ... ]], array, pipefail, hoặc process substitution.
Ghim trình thông dịch bằng shebang (ví dụ #!/bin/sh hoặc #!/usr/bin/env bash) và ghi rõ phiên bản yêu cầu trong tài liệu.
Vì nó đã có sẵn: hầu hết image Linux đều có shell và các tiện ích cốt lõi (grep, sed, awk, tar, curl, systemctl).
Điều này làm cho shell lý tưởng cho:
IaC/công cụ cấu hình thường là hệ thống ghi nhận (desired state, thay đổi có thể review, apply nhất quán). Shell script tốt nhất như một wrapper bổ sung điều phối và rào chắn.
Ví dụ nơi shell bổ trợ IaC:
plan/applyLàm cho chúng dự đoán được và an toàn:
set +x quanh phần nhạy cảmjq thay vì grep bảngNếu bước hay bị flaky (mạng/API), thêm retries có backoff và fail cứng khi hết lần thử.
Giữ entrypoint nhỏ và định nghĩa:
exec tiến trình chính để tín hiệu và exit code được truyền đúngCũng tránh chạy tiến trình nền dài trong entrypoint trừ khi có chiến lược giám sát rõ ràng; nếu không shutdown/restart sẽ không đáng tin cậy.
Các vấn đề phổ biến:
/bin/sh có thể là dash (Debian/Ubuntu) hoặc BusyBox sh (Alpine), không phải Bashecho -e, sed -i, và cú pháp test khác nhau giữa nền tảngMột cơ sở vững chắc là:
set -euo pipefail
Sau đó thêm thói quen:
Để chẩn đoán nhanh, chuẩn hóa một tập lệnh lệnh và thu output kèm timestamp.
Kiểm tra thường gặp:
Hai công cụ phủ nhu cầu hầu hết đội:
Thêm các bài test nhẹ:
Nếu cần di động, hãy test với shell đích (ví dụ dash/BusyBox) và chạy ShellCheck trong CI để phát hiện “bashisms” sớm.
"$var" (ngăn word-splitting/globbing)eval và xây lệnh từ chuỗi-- để kết thúc parsing option (vd: rm -- "$file")mktemp + trap cho file tạm an toàn và cleanupCẩn thận với set -e: xử lý rõ ràng các lệnh có thể thất bại (cmd || true hoặc kiểm tra hợp lý).
df -h, df -iuptime, free -m, vmstat 1 5ss -lntpjournalctl -n 200 --no-pagercurl -fsS -m 2 URLƯu tiên script “chỉ đọc” trước, và biến mọi hành động sửa chữa thành rõ ràng (prompt hoặc --yes).
--dry-run)bats khi cần assertion về exit code, output, fileLưu script ở chỗ dễ tìm (ví dụ scripts/ hoặc ops/) và kèm block --help tối thiểu.