HỌC BẰNG THỰC HÀNH
← Lộ trình học
01 · Linux Administration

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í.

Cốt lõi

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 PATH quyế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, $2Số đố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 -1Lấ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 2Trả 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 = value có dấu cách: shell hiểu là chạy lệnh VAR. 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ưng rm -rf $dir/ với $dir rỗng thì nguy hiểm. Luôn viết "$dir".
  • Script chạy được trong terminal nhưng lỗi trong cron/systemd: PATH và 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ùng EnvironmentFile= quyền 600, 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.

Tài liệu chính thức