Shell, biến môi trường và script đầu tiên
Thực hiện trên server của bạn, rồi kiểm tra từng tiêu chí.
Vì sao cần học
Mọi tiến trình nhận cấu hình qua biến môi trường: database URL, mức log, proxy. Rất nhiều sự cố "chạy tay được, chạy bằng service thì lỗi" đến từ khác biệt môi trường. Script ngắn là công cụ tự động hóa đầu tiên của người vận hành. Script không kiểm tra lỗi sẽ âm thầm làm sai. Module 03 sẽ đi sâu vào Bash; bài này đặt nền móng.
Mục tiêu
- Phân biệt biến shell và biến môi trường, hiểu
export. - Hiểu
PATHquyết định lệnh nào được chạy. - Biết file nào được đọc khi đăng nhập:
/etc/profile.d/,~/.bashrc. - Viết script có tham số, giá trị mặc định, exit code và chế độ an toàn
set -euo pipefail.
Điều kiện tiên quyết
- Bài Tiến trình, signal và độ ưu tiên.
Mental model
Môi trường được copy từ cha sang con. Khi shell chạy một lệnh, tiến trình con nhận bản sao các biến đã export. Con sửa biến thì cha không thấy. Biến không export chỉ tồn tại trong shell hiện tại.
PATH là danh sách thư mục tìm lệnh, theo thứ tự. which và type cho biết lệnh nào sẽ chạy.
Exit code là cách chương trình báo kết quả: 0 là thành công, khác 0 là lỗi. $? chứa exit code của lệnh vừa chạy. systemd, cron, CI và Kubernetes đều dựa vào exit code.
set -euo pipefail: -e dừng khi một lệnh lỗi, -u báo lỗi khi dùng biến chưa đặt, -o pipefail coi cả pipeline là lỗi nếu một lệnh giữa pipeline lỗi.
Thực hành (Guided Lab)
1. Biến shell và biến môi trường
GREETING=xin-chao
bash -c 'echo "con thấy: [$GREETING]"'
export GREETING
bash -c 'echo "con thấy: [$GREETING]"'
env | grep GREETING
echo "$PATH" | tr ':' '\n'
type ls cd systemctl
Giải thích lệnh và tham số
GREETING=xin-chao đặt biến của shell hiện tại; không có dấu cách quanh =. export GREETING truyền biến cho tiến trình con. bash -c mở shell con chạy chuỗi lệnh: lần đầu biến trống, lần sau thấy giá trị. env in biến môi trường. tr ':' '\n' đổi dấu : trong PATH thành xuống dòng; type cho biết một tên là builtin, alias hay executable.
Lần đầu tiến trình con không thấy biến; sau export thì thấy.
2. Biến cho mọi phiên đăng nhập
echo 'export KDC_ENV=lab' | sudo tee /etc/profile.d/kdc-env.sh
Đăng xuất rồi đăng nhập lại, chạy echo $KDC_ENV. Dịch vụ systemd không đọc file này: chúng nhận biến qua Environment= hoặc EnvironmentFile= trong unit. Kiểm tra bằng sudo systemctl show-environment.
3. Script kiểm tra ổ đĩa
sudo tee /usr/local/bin/kdc-diskcheck <<'EOF'
#!/usr/bin/env bash
# kdc-diskcheck: báo mức dùng của một mountpoint.
# Exit 0 = OK, 1 = vượt ngưỡng, 2 = dùng sai.
set -euo pipefail
usage() {
echo "Cách dùng: kdc-diskcheck <thư-mục> [ngưỡng-%]" >&2
exit 2
}
[[ $# -ge 1 ]] || usage
target=$1
limit=${2:-${KDC_DISK_LIMIT:-80}}
[[ -d $target ]] || { echo "Không phải thư mục: $target" >&2; exit 2; }
used=$(df --output=pcent "$target" | tail -1 | tr -dc '0-9')
if (( used >= limit )); then
echo "STATUS=WARN used=${used}% limit=${limit}% target=$target"
exit 1
fi
echo "STATUS=OK used=${used}% limit=${limit}% target=$target"
EOF
sudo chmod 755 /usr/local/bin/kdc-diskcheck
Giải thích lệnh và tham số
| Thành phần | Ý nghĩa |
|---|---|
usage() | Định nghĩa hàm in cách dùng; >&2 gửi thông báo tới stderr. |
$#, $1, $2 | Số đối số, đối số thứ nhất, đối số thứ hai của script. |
[[ $# -ge 1 ]] | Kiểm tra có ít nhất một đối số; -ge nghĩa là lớn hơn hoặc bằng. |
${2:-${KDC_DISK_LIMIT:-80}} | Lấy đối số thứ hai nếu có giá trị; nếu không dùng biến môi trường, cuối cùng mặc định 80. |
[[ -d $target ]] | Kiểm tra đường dẫn là thư mục. -d ở đây là phép kiểm tra của Bash, khác install -d. |
df --output=pcent "$target" | Chỉ lấy cột phần trăm dung lượng đã dùng của filesystem chứa đường dẫn. |
tail -1 | Lấy dòng cuối; dạng đầy đủ là tail -n 1. |
tr -dc '0-9' | -d xóa ký tự, -c đảo tập lựa chọn: chỉ giữ các chữ số. |
(( used >= limit )) | So sánh số trong Bash; nếu đúng thì đi vào nhánh cảnh báo. |
exit 0, exit 1, exit 2 | Trả mã kết quả theo quy ước của script: OK, vượt ngưỡng, dùng sai. |
Đặt biến đường dẫn trong dấu nháy kép như "$target" để một đường dẫn có dấu cách vẫn là một đối số.
${2:-${KDC_DISK_LIMIT:-80}}: dùng tham số thứ hai nếu có, nếu không thì biến môi trường KDC_DISK_LIMIT, cuối cùng là 80.
4. Thử các exit code
kdc-diskcheck /; echo "exit=$?"
kdc-diskcheck / 1; echo "exit=$?"
KDC_DISK_LIMIT=1 kdc-diskcheck /; echo "exit=$?"
kdc-diskcheck; echo "exit=$?"
kdc-diskcheck /khong-ton-tai; echo "exit=$?"
Giải thích lệnh và tham số
$? là mã thoát của lệnh vừa chạy trước đó. ; cho phép in mã này kể cả khi script thất bại. KDC_DISK_LIMIT=1 kdc-diskcheck / đặt biến môi trường chỉ cho lần chạy đó; không đổi biến lâu dài của terminal. / là thư mục gốc filesystem, 1 là ngưỡng phần trăm; các lần gọi thiếu đối số hoặc đường dẫn sai cần trả 2.
KDC_DISK_LIMIT=1 lệnh đặt biến môi trường chỉ cho đúng lệnh đó.
5. Lưu kết quả
mkdir -p ~/kdc-labs/shell
kdc-diskcheck / | tee ~/kdc-labs/shell/diskcheck.txt
Giải thích lệnh và tham số
mkdir -p tạo thư mục cha còn thiếu và cho phép thư mục đã tồn tại. Dấu | đưa kết quả kdc-diskcheck / vào tee; tee vừa hiển thị kết quả vừa ghi vào file báo cáo.
Tự kiểm tra (Verification)
ls -l /usr/local/bin/kdc-diskcheck
cat /etc/profile.d/kdc-env.sh
cat ~/kdc-labs/shell/diskcheck.txt
Giải thích lệnh và tham số
ls -l xem quyền thực thi của script. cat đọc file biến môi trường và báo cáo đã lưu.
Chọn server và bấm Kiểm tra kết quả.
Lỗi thường gặp
VAR = valuecó dấu cách: shell hiểu là chạy lệnhVAR. Gán biến không có dấu cách quanh=.- Không đặt biến trong dấu nháy kép:
[[ -d $target ]]an toàn, nhưngrm -rf $dir/với$dirrỗng thì nguy hiểm. Luôn viết"$dir". - Script chạy được trong terminal nhưng lỗi trong cron/systemd:
PATHvà biến môi trường khác nhau. Dùng đường dẫn tuyệt đối hoặc khai báo môi trường rõ ràng.
Ghi chú production
- Secret không nên nằm trong
/etc/profile.d/: mọi user đăng nhập đều đọc được. DùngEnvironmentFile=quyền600, hoặc công cụ quản lý secret ở các module sau. - Script được dùng trong monitoring phải có exit code ổn định; Module 03 sẽ biến script này thành
server-health.shđầy đủ.
Dọn dẹp
sudo rm -f /usr/local/bin/kdc-diskcheck /etc/profile.d/kdc-env.sh
Giải thích lệnh và tham số
rm -f xóa file và không hỏi xác nhận; -r thêm xóa đệ quy thư mục cùng nội dung, nên -rf gộp hai tùy chọn này.