Shell script là công cụ mạnh mẽ giúp tự động hóa các tác vụ trong hệ thống Linux. Dưới đây là tổng hợp các kiến thức nền tảng, được sắp xếp từ khai báo script, biến, mảng, đến các cấu trúc điều khiển và xử lý đầu vào.
1. Cấu trúc cơ bản của Shell Script
Một tập tin script thường bắt đầu với dòng shebang để chỉ định trình thông dịch:
#!/bin/bash
# Mô tả chức năng của script
Dòng đầu tiên cho hệ thống biết sử dụng shell nào (ví dụ: /bin/bash), dòng thứ hai là chú thích.
2. Biến và Mảng
Biến
Để gán giá trị cho biến, sử dụng cú pháp tên_biến=giá_trị (không có khoảng trắng quanh dấu =). Để truy cập giá trị, thêm dấu $ trước tên biến. Sử dụng $() để lấy kết quả của lệnh.
so_ngay=10
khach="Katie"
echo "$khach đã check-in cách đây $so_ngay ngày"
# Lấy kết quả từ lệnh
thoi_gian=$(date)
echo "Thời gian hiện tại: $thoi_gian"
Mảng một chiều
Mảng được khai báo với các phần tử cách nhau bằng khoảng trắng, truy cập bằng chỉ số. Sử dụng * hoặc @ để lấy tất cả phần tử.
mang_cua_toi=(A B C D)
echo "Các phần tử: ${mang_cua_toi[*]}"
echo "Số lượng phần tử: ${#mang_cua_toi[@]}"
3. Chuyển hướng (Redirection) và Đường ống (Pipe)
Chuyển hướng đầu ra
# Ghi đè lên file
ls -l > output.txt
# Ghi thêm vào cuối file
echo "Dòng mới" >> output.txt
Chuyển hướng đầu vào
# Đếm số dòng, từ, ký tự từ file
wc < file1
Đường ống (Pipe)
Kết nối đầu ra của lệnh này thành đầu vào của lệnh khác:
rpm -qa | sort > danh_sach_rpm.txt
4. Các Lệnh Cơ Bản: echo, read, printf
# In văn bản
echo "Đây là một dòng"
echo "\"Đây là dòng có dấu ngoặc kép\""
# Đọc dữ liệu từ bàn phím
read ten
echo "Xin chào, $ten"
# In với định dạng
printf "%-10s %-8s %-4.2f\n" "Nguyễn" "Nam" 66.12
5. Cấu Trúc Điều Khiển
Vòng lặp for
# Duyệt qua danh sách
for gia_tri in 1 2 3 4 5; do
echo "Giá trị: $gia_tri"
done
# Sử dụng seq
for i in `seq 1 5`; do
echo "Số thứ tự: $i"
done
Vòng lặp while
dem=1
while [ $dem -le 5 ]; do
echo "Lần lặp thứ $dem"
dem=$((dem + 1))
done
Cấu trúc if-else
# Kiểm tra lệnh thành công
if grep "nguoidung" /etc/passwd; then
echo "Người dùng tồn tại"
else
echo "Không tìm thấy người dùng"
fi
# Sử dụng test hoặc [ ]
if [ -f /etc/hosts ]; then
echo "File /etc/hosts tồn tại"
fi
So sánh số học
Sử dụng các toán tử: -eq (bằng), -ne (khác), -gt (lớn hơn), -lt (nhỏ hơn), -ge (lớn hơn hoặc bằng), -le (nhỏ hơn hoặc bằng).
a=10
b=20
if [ $a -lt $b ]; then
echo "$a nhỏ hơn $b"
fi
So sánh chuỗi
chuoi1="hello"
chuoi2="world"
if [ "$chuoi1" = "$chuoi2" ]; then
echo "Hai chuỗi bằng nhau"
fi
# Kiểm tra độ dài
if [ -n "$chuoi1" ]; then
echo "Chuỗi không rỗng"
fi
So sánh file
if [ -d /home ]; then
echo "/home là một thư mục"
fi
if [ -f /etc/passwd ]; then
echo "File /etc/passwd tồn tại"
fi
Cấu trúc case
case $user in
root)
echo "Chào root"
;;
admin)
echo "Chào admin"
;;
*)
echo "Người dùng không xác định"
;;
esac
6. Xử Lý Tham Số Dòng Lệnh
Tham số vị trí
# $0: tên script, $1, $2,...: tham số thứ 1, thứ 2
echo "Script: $0"
echo "Tham số 1: $1"
echo "Tổng số tham số: $#"
echo "Tất cả tham số: $*"
Đọc dữ liệu từ người dùng
# Đọc với prompt
read -p "Nhập tên của bạn: " ten
echo "Xin chào, $ten"
# Đọc ẩn mật khẩu
read -s -p "Nhập mật khẩu: " mat_khau
# Đọc với timeout
if read -t 5 -p "Nhập tên (5 giây): " ten; then
echo "Xin chào $ten"
else
echo "Hết thời gian"
fi
Đọc dữ liệu từ file
so_dong=1
cat file.txt | while read dong; do
echo "Dòng $so_dong: $dong"
so_dong=$((so_dong + 1))
done
7. Chuyển Hướng Nâng Cao
Các bộ mô tả file (File Descriptor)
Ba bộ mô tả mặc định: 0 (stdin), 1 (stdout), 2 (stderr).
# Chuyển hướng lỗi
echo "Lỗi xảy ra" >&2
# Chuyển hướng tất cả đầu ra
exec 1>log.txt
echo "Dòng này sẽ được ghi vào log.txt"
Chuyển hướng đầu vào vĩnh viễn
exec 0< input.txt
while read dong; do
echo "Đã đọc: $dong"
done