Tùy Biến Tham Số Shell
Một trong những sức mạnh lớn nhất của bash nằm ở khả năng thao tác với chuỗi và biến thông qua các cú pháp mở rộng tham số. Dưới đây là các trường hợp sử dụng phổ biến.
Hình thức ${parameter:+expression} thực hiện việc kiểm tra nếu parameter tồn tại và không phải là rỗng, hệ thống sẽ trả về giá trị của expression.
#!/bin/bash
# Ví dụ thay thế ký tự trong biến
filename="backup/data_report%202023.txt"
# Thay thế tất cả ký tự '%' bằng ký tự '_'
clean_name="${filename/%/_}"
echo "$clean_name"
Các toán tử như % và # hoạt động dựa trên cơ chế khớp mẫu theo quy tắc không tham lam (non-greedy) hoặc tham lam (greedy).
- Mô tả ngắn gọn:
${VAR%pattern}xóa phần phù hợp với pattern từ phía bên phải của biến VAR và giữ lại phần còn lại. - Gấp đôi (%):
${VAR%%pattern}loại bỏ chuỗi dài nhất khớp với pattern tính từ phía sau về trước. - Tương tự cho #:
${VAR#pattern}xóa từ bên trái sang phải theo mô hình không tham lam, trong khi${VAR##pattern}tìm kiếm tối đa từ trái sang phải.
path="/usr/local/lib/module.so"
# Lấy tên file gốc, bỏ phần đường dẫn
basename_file="${path##*/}"
# Lấy phần đuôi file
extension="${path##*.}"
echo "Tên: $basename_file, Phần mở rộng: $extension"
Để trích xuất một đoạn con hoặc độ dài biến, bạn có thể sử dụng chỉ số:
text="Hello World"
# Cắt từ ký tự thứ 2 đến 4 ký tự (bắt đầu từ index 1, độ dài 5)
sub_text="${text:1:5}"
# Độ dài tổng cộng của chuỗi
len=${#text}
echo "Chuỗi con: $sub_text, Tổng chiều dài: $len"
Quản Lý Người Dùng Và Nhóm
Các công cụ dòng lệnh dưới đây hỗ trợ admin trong việc cấu hình tài khoản hệ thống.
# Thêm người dùng 'devuser' vào nhóm 'developers'
usermod -aG developers devuser
# Xóa thành viên khỏi nhóm
gpasswd -d devuser developers
# Thay đổi shell mặc định cho tài khoản
chsh -s /bin/bash devuser
# Thiết lập ngày hết hạn cho tài khoản (format: YYYY-MM-DD)
chage -E 2024-12-31 devuser
# Xem thông tin hạn sử dụng tài khoản
chage -l devuser
# Khóa và mở khóa tài khoản
usermod -L devuser # Khóa
usermod -U devuser # Mở khóa
Toán Học Với BC
Đối với các phép tính số học phức tạp hơn integer, utility bc là lựa chọn tiêu chuẩn.
# Chuyển đổi hệ cơ số (từ thập phân sang nhị phân)
number=100
echo "obase=2; $number" | bc
# Chuyển ngược lại (nhị phân sang thập phân)
echo "obase=10; ibase=2; 1100100" | bc
# Tính toán số thập phân với độ chính xác được định nghĩa (scale)
echo "scale=4; 22/7" | bc
# Căn bậc hai và luỹ thừa
echo "sqrt(144)" | bc
echo "2^10" | bc
Định Danh Tập Tin Tùy Chỉnh
Command exec cho phép tạo các file descriptor mới để quản lý luồng dữ liệu độc lập, hữu ích trong việc đọc/ghi song song hoặc xử lý log.
# Khởi tạo file descriptor số 3 để đọc tập tin input_data
exec 3<input_data.txt
# Gửi dữ liệu ra màn hình
cat <&3
# Khởi tạo file descriptor số 4 để ghi đè (truncation mode)
exec 4>>output_log.txt
echo "Starting process..." >&4
# Đóng file descriptor khi hoàn tất
exec 3<&-
exec 4>&-
Mảng Và Mảng Liên Kết
Bash hỗ trợ cả mảng tuần tự (dùng index số) và mảng liên kết (associative array, dùng key string).
# Định nghĩa mảng thường
numbers=(10 20 30 40)
echo "Giá trị tại index 1: ${numbers[1]}"
echo "Toàn bộ nội dung: ${numbers[@]}"
echo "Số lượng phần tử: ${#numbers[@]}"
# Định nghĩa mảng liên kết (cần declare -A)
declare -A user_info
user_info["admin"]="Alice"
user_info["guest"]="Bob"
# Truy cập và lặp qua mảng liên kết
echo "${user_info[admin]}"
for key in "${!user_info[@]}"; do
echo "Key: $key, Value: ${user_info[$key]}"
done
Lưu ý Về Alias Và Test Điều Kiện
Khi cần thực thi lệnh gốc mà không bị alias ảnh hưởng, hãy thêm dấu \ trước tên lệnh hoặc sử dụng đường dẫn tuyệt đối. Ngoài ra, các test điều kiện giúp script đưa ra quyết định dựa trên trạng thái filesystem.
# Kiểm tra tính hợp lệ của file/directory
if [ -f "$filepath" ]; then
echo "File tồn tại"
fi
if [ -d "$dirpath" ]; then
echo "Là thư mục"
fi
if [ -r "$filepath" ]; then
echo "Có quyền đọc"
fi
Các tệp cấu hình shell kích hoạt khi login phụ thuộc vào kiểu tương tác:
- Login Interactive: Đọc
/etc/profile,~/.bash_profile, hoặc~/.profile. - Non-login Interactive: Đọc
/etc/bashrcvà~/.bashrc.
Hướng Dẫn Tìm Kiếm Với Find
Công cụ find cực kỳ linh hoạt, hỗ trợ các toán tử logic và giới hạn độ sâu đệ quy.
# Tìm file .log nhưng loại trừ thư mục cache
find /var/www -type f -name "*.log" -prune -o -print
# Giới hạn tìm kiếm ở độ sâu tối đa 3 cấp
find /home -maxdepth 3 -name "*.txt"
# Tìm file truy cập trong vòng 7 phút qua
find . -amin -7
Biến đặc biệt trong find bao gồm:
-atime n: Thời gian truy cập gần đây nhất.-mtime n: Thời gian sửa đổi nội dung gần đây nhất.-ctime n: Thời gian sửa đổi metadata (permission/ownership) gần đây nhất.
Thao Tác Với Văn Bản (Xargs, Split, Csplit)
xargs dùng để chuyển đầu vào thành đối số dòng lệnh. Cú pháp -I rất hữu ích để thay thế vị trí placeholder.
# Tìm file mã nguồn và đếm dòng chứa từ main
find . -name "*.c" | xargs -I {} sh -c "echo 'File: {}; grep -n main {}'"
Chia nhỏ file lớn (Split) sử dụng dd tạo dữ liệu giả lập, rồi dùng split.
# Tạo file thử nghiệm 1MB
dd if=/dev/zero of=testdata bs=1M count=1
# Chia thành nhiều file nhỏ
split -b 100k testdata part_
# Nối lại các phần file
cat part_* > merged_testdata
csplit chia file dựa trên mẫu regex hoặc vị trí dòng. Ví dụ tách log theo máy chủ:
csplit server.log '/SERVER/' {*} -z -f "server_"
Sử Dụng Diff Và Patch
So sánh sự khác biệt giữa các phiên bản và áp dụng bản vá.
# Tạo diff dạng unified
diff -u config.old config.new > backup.patch
# Áp dụng patch
patch -p1 < backup.patch
# Đảo ngược thay đổi (nếu đã áp dụng nhầm)
patch -R -p1 < backup.patch
Để tìm giao điểm giữa hai danh sách file đã sắp xếp, dùng comm.
# Chỉ hiển thị dòng giống nhau (loại bỏ cột 1 và 2)
comm listA listB -1 -2
Xử Lý Dòng (Cut, Sed, Awk)
Cut: Trích xuất trường theo cột hoặc byte.
cut -d':' -f1 /etc/passwd
Sed: Thay thế văn bản nâng cao. Sử dụng & để giữ nguyên chuỗi khớp ban đầu trong kết quả thay thế.
# Thêm dấu ngoặc vuông quanh mỗi từ
echo "hello world" | sed 's/\w*/[\&]/g'
Awk: Ngôn ngữ xử lý văn bản mạnh mẽ.
#!/bin/bash
# Đếm số dòng chứa từ "error" trong logs
awk 'BEGIN { count=0 } /error/ { count++ } END { print "Total errors: " count }' /var/log/syslog
Biến hệ thống trong awk:
NR: Số dòng hiện tại.$NF: Trường cuối cùng của dòng.FS: Ký tự phân cách trường (mặc định là khoảng trắng).
Truyền biến môi trường vào awk qua tùy chọn -v:
limit=10
awk -v max="$limit" '{ if ($1 <= max) print }' data.txt
Quyền Hạn Đặc Biệt
Có các bit đặc biệt như Sticky Bit (t) ngăn chặn xóa file bởi người dùng khác trong thư mục chung (ví dụ /tmp). Setuid (s) cho phép chạy chương trình với quyền của chủ sở hữu.
# Đặt sticky bit
chmod +t /shared_folder
# Thiết lập setuid cho binary
chmod u+s /usr/bin/passwd
Chống biến đổi file vĩnh viễn bằng chattr:
# Ghi bất biến (immutable)
chattr +i important_config.conf
# Cho phép chỉ thêm dữ liệu (append-only)
chattr +a app_log.txt
Giám Sát Tài Nguyên
Để debug hiệu năng hệ thống, tổ hợp các công cụ sau là bắt buộc:
| Tài Nguyên | Dụng Cụ |
|---|---|
| CPU | top, htop, mpstat, pidstat -u |
| I/O | iostat, iotop, dstat --top-bio |
| Mạng | ss, netstat, nload, iptraf |
| Trace | strace (syscall), ltrace (library calls) |
Ví dụ theo dõi quá trình tiêu tốn CPU cao nhất bằng dstat:
dstat --top-cpu -n 1 --top-mem
Log Rotate
Cấu hình /etc/logrotate.d/custom giúp tự động cắt và nén log files.
/var/log/myapp/*.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
postrotate
/usr/bin/systemctl reload myapp.service
endscript
}
Điều Hướng Thư Mục Linh Hoạt
Thay vì liên tục dùng cd, hãy dùng stack của pushd và popd để quay lui nhanh chóng.
pushd /project/src
# Đang làm việc tại /project/src
popd
# Quay trở lại thư mục trước đó