Vì sao biến môi trường quan trọng trong Bash
Ở bài trước chúng ta đã tách logic thành function để script dễ tái sử dụng hơn. Khi script bắt đầu chạy trong nhiều môi trường — local, staging, production, CI/CD runner — vấn đề tiếp theo là: cấu hình lấy từ đâu và truyền vào như thế nào?
Biến trong Bash giúp lưu giá trị tạm thời trong script. Biến môi trường giúp truyền cấu hình cho process con như docker, kubectl, aws, curl hoặc ứng dụng mà script khởi chạy. Nếu quản lý biến không rõ ràng, script rất dễ deploy nhầm môi trường, lộ secret, hoặc chạy sai vì thiếu config.
Biến cục bộ và cách gán giá trị
Cú pháp gán biến trong Bash không có khoảng trắng quanh dấu =:
| |
Khi đọc biến, dùng $VAR hoặc ${VAR}. Trong script thực tế, ${VAR} thường rõ ràng hơn khi nối chuỗi:
| |
Một lỗi rất phổ biến là thêm khoảng trắng:
| |
Khi giá trị có khoảng trắng hoặc ký tự đặc biệt, luôn quote biến:
| |
Không quote biến có thể làm path bị tách thành nhiều argument, gây lỗi khó đoán trong script vận hành.
export: khi nào biến trở thành environment variable
Biến Bash bình thường chỉ tồn tại trong shell hiện tại. Process con không tự thấy biến đó:
| |
Muốn process con đọc được, dùng export:
| |
Trong DevOps, export thường dùng khi gọi CLI hoặc chạy ứng dụng:
| |
Bạn cũng có thể truyền biến chỉ cho một command:
| |
Cách này gọn và an toàn hơn nếu biến chỉ cần tồn tại cho đúng một lệnh.
Xem, đặt và xóa biến với env, set, unset
Một vài command hữu ích khi debug môi trường chạy script:
| |
env phù hợp để kiểm tra process con sẽ thấy gì. set chi tiết hơn, nhưng output dài và có thể chứa dữ liệu nhạy cảm, nên hạn chế paste nguyên output vào ticket hoặc log.
Ví dụ kiểm tra biến bắt buộc:
| |
Cú pháp ${!name} là indirect expansion: nếu name="APP_ENV", Bash sẽ đọc giá trị của biến APP_ENV.
Đọc cấu hình từ file .env
File .env giúp tách config khỏi code:
| |
Cách đơn giản để load file:
| |
set -a làm các biến được gán sau đó tự động export, nên process con có thể đọc được.
Tuy nhiên, source .env sẽ thực thi nội dung file như Bash code. Vì vậy chỉ dùng với file bạn kiểm soát, không source file upload từ user hoặc nguồn không tin cậy.
Một pattern an toàn hơn cho script deploy:
| |
Dòng : "${VAR:?message}" khiến script dừng ngay nếu biến chưa được set hoặc rỗng. Đây là cách fail-fast rất hữu ích trước khi chạy deploy.
Nhận tham số CLI bằng getopts
Không phải cấu hình nào cũng nên nằm trong .env. Những giá trị thay đổi theo lần chạy, như môi trường đích hoặc chế độ dry-run, nên nhận qua flag:
| |
Chạy thử:
| |
getopts phù hợp cho option ngắn như -e production, -n. Nếu cần long option như --environment, bạn có thể tự parse bằng case, nhưng nên giữ format đơn giản để script dễ bảo trì.
$IFS: kiểm soát cách Bash tách chuỗi
IFS là Internal Field Separator — tập ký tự Bash dùng để tách word khi xử lý một số expansion và lệnh read. Mặc định gồm space, tab và newline.
Khi đọc file từng dòng, dùng pattern này để giữ nguyên khoảng trắng đầu/cuối và không xử lý backslash đặc biệt:
| |
Khi tách chuỗi CSV đơn giản:
| |
Tránh đổi IFS global nếu không cần. Nếu phải đổi, hãy giới hạn trong một dòng hoặc một scope nhỏ để không làm hỏng phần khác của script.
Các biến đặc biệt thường gặp
Bash có nhiều biến đặc biệt rất hữu ích khi viết script vận hành:
| Biến | Ý nghĩa |
|---|---|
$0 | Tên script đang chạy |
$1, $2 | Tham số vị trí |
$@ | Toàn bộ tham số, nên dùng "$@" |
$# | Số lượng tham số |
$? | Exit code của command vừa chạy |
$$ | PID của shell hiện tại |
$! | PID của background process gần nhất |
${BASH_SOURCE[0]} | Đường dẫn file script hiện tại trong Bash |
Ví dụ dùng $! và wait để theo dõi background job:
| |
Ví dụ lấy thư mục chứa script, không phụ thuộc bạn chạy script từ đâu:
| |
Pattern này rất hữu ích khi script cần load file config hoặc thư viện nằm cạnh nó.
Ví dụ DevOps: script deploy đọc .env, nhận flag và validate biến
Ví dụ dưới đây mô phỏng một script deploy nhỏ. Script nhận môi trường qua -e, hỗ trợ dry-run bằng -n, load file .env.<environment>, validate biến bắt buộc rồi chạy lệnh deploy.
| |
File .env.staging có thể như sau:
| |
Điểm quan trọng trong ví dụ:
- Không hardcode host/image tag trong script.
- Validate môi trường hợp lệ trước khi source file.
- Dùng
set -ađể export config cho process con nếu cần. - Dùng dry-run để kiểm tra lệnh trước khi chạy thật.
- Quote biến khi dựng path và argument.
Sai sót thường gặp
- Gán biến có khoảng trắng quanh
=:NAME = valuelà sai trong Bash. - Không quote biến: Path có khoảng trắng hoặc ký tự glob như
*có thể làm script chạy sai. - Export quá nhiều: Chỉ export biến mà process con cần đọc.
- Source
.envkhông tin cậy:.envlà Bash code khi dùngsource, có thể thực thi lệnh. - Đưa secret vào log: Tránh
set -xquanh đoạn xử lý token/password. - Dùng
$1trực tiếp vớiset -u: Hãy dùng${1:-}hoặc validate trước. - Đổi
IFSglobal: Có thể làm hỏng loop hoặc parse argument ở đoạn sau.
Ghi chú triển khai
- Khi áp dụng vào dự án của bạn, hãy phân loại cấu hình:
- Giá trị cố định theo môi trường →
.env.staging,.env.productionhoặc config file riêng. - Giá trị thay đổi theo lần chạy → flag CLI qua
getopts. - Secret → biến môi trường từ CI/CD secret store hoặc vault, không commit vào git.
- Giá trị cố định theo môi trường →
- Best practices:
- Bật
set -uđể phát hiện biến chưa khai báo, nhưng dùng${VAR:-}khi biến optional. - Validate biến bắt buộc sớm bằng
: "${VAR:?message}". - Dùng
printenv VARđể debug một biến thay vì in toàn bộ environment. - Prefix biến theo app, ví dụ
BLOG_APP_ENV, để tránh trùng tên. - Không commit file
.envchứa secret; chỉ commit.env.example.
- Bật
- Troubleshooting:
- Process con không thấy biến? → Kiểm tra bạn đã
exportchưa. - Script chạy đúng local nhưng sai cron/CI? → Kiểm tra
PATH, working directory và biến môi trường runner cung cấp. .envkhông load đúng? → Kiểm tra file có syntax Bash hợp lệ, không có khoảng trắng quanh=.
- Process con không thấy biến? → Kiểm tra bạn đã
🎯 Lời kết
Quản lý biến tốt giúp Bash script chạy ổn định hơn giữa nhiều môi trường. Hãy giữ code và config tách biệt, validate biến bắt buộc trước khi thao tác thật, quote biến khi dùng trong command, và chỉ export những gì process con cần.
Ở bài tiếp theo, chúng ta sẽ đi vào cron job với Bash: cú pháp lịch chạy, crontab, @daily, @reboot, log cron, vấn đề PATH và ví dụ backup/healthcheck tự động. 🚀
Tài liệu tham khảo
- GNU Bash Manual — Shell Parameters — Tài liệu chính thức về positional parameters và special parameters.
- GNU Bash Manual — Bourne Shell Builtins — Tham khảo
export,set,unset,getopts,source. - GNU Bash Manual — Word Splitting — Giải thích vai trò của
IFStrong word splitting. - The Open Group — Shell Command Language — Tham khảo chuẩn POSIX shell về biến, quoting và expansion.
