Một system admin thường viết script Bash, một số ngắn và một số khá dài, để hoàn thành các tác vụ khác nhau.
Bạn đã bao giờ nhìn vào script cài đặt do nhà cung cấp phần mềm cung cấp? Chúng thường thêm nhiều hàm và logic để đảm bảo cài đặt hoạt động đúng và không gây hại cho hệ thống khách hàng. Qua nhiều năm, tác giả tích lũy bộ sưu tập các kỹ thuật nâng cao script Bash, và muốn chia sẻ một số hy vọng chúng giúp người khác. Đây là bộ sưu tập các script nhỏ được tạo để minh họa các ví dụ đơn giản này.
Khởi đầu
Khi mới bắt đầu, script Bash của tác giả chỉ là một chuỗi lệnh, thường nhằm tiết kiệm thời gian với các thao tác shell tiêu chuẩn như triển khai nội dung web. Một tác vụ như vậy là giải nén nội dung tĩnh vào thư mục home của web server Apache. Script trông như thế này:
cp january_schedule.tar.gz /usr/apache/home/calendar/
cd /usr/apache/home/calendar/
tar zvxf january_schedule.tar.gz
Mặc dù điều này tiết kiệm một chút thời gian và gõ phím, nhưng chắc chắn không phải script thú vị hay hữu ích trong dài hạn. Theo thời gian, tác giả học cách khác dùng script Bash để hoàn thành tác vụ thách thức hơn, như tạo gói phần mềm, cài đặt phần mềm, hoặc backup file server.
1. Câu lệnh điều kiện (Conditional statement)
Giống như nhiều ngôn ngữ lập trình khác, câu lệnh điều kiện là tính năng mạnh mẽ và phổ biến. Điều kiện là thứ cho phép logic được thực hiện bởi chương trình máy tính. Hầu hết ví dụ của tác giả dựa trên logic điều kiện.
Điều kiện cơ bản dùng câu lệnh "if". Điều này cho phép chúng ta kiểm tra một số điều kiện mà sau đó có thể dùng để thao tác cách script thực hiện. Ví dụ, chúng ta có thể kiểm tra sự tồn tại của thư mục bin Java, điều đó chỉ ra Java đã được cài đặt. Nếu tìm thấy, đường dẫn thực thi có thể được cập nhật với vị trí để cho phép gọi bởi ứng dụng Java.
if [ -d "$JAVA_HOME/bin" ] ; then
PATH="$JAVA_HOME/bin:$PATH"
2. Giới hạn thực thi (Limit execution)
Bạn có thể muốn giới hạn script chỉ được chạy bởi một user cụ thể. Mặc dù Linux có quyền tiêu chuẩn cho user và group, cũng như SELinux cho loại bảo vệ này, bạn có thể chọn đặt logic trong script. Có thể bạn muốn chắc chắn chỉ chủ sở hữu của một ứng dụng web cụ thể mới có thể chạy script khởi động của nó. Bạn thậm chí có thể dùng code để giới hạn script cho user root. Linux có một vài biến môi trường chúng ta có thể kiểm tra trong logic này. Một trong số đó là $USER, cung cấp tên user. Cái khác là $UID, cung cấp số nhận dạng user (UID) và, trong trường hợp script, UID của user thực thi.
User
Ví dụ đầu tiên cho thấy cách tác giả có thể giới hạn script cho user jboss1 trong môi trường multi-hosting với nhiều instance application server. Câu lệnh điều kiện "if" thực chất hỏi: "User thực thi có phải không phải là jboss1?" Khi điều kiện được tìm thấy là true, câu lệnh echo đầu tiên được gọi, theo sau là exit 1, kết thúc script.
if [ "$USER" != 'jboss1' ]; then
echo "Sorry, this script must be run as JBOSS1!"
exit 1
fi
echo "continue script"
Root
Ví dụ script tiếp theo đảm bảo chỉ user root mới có thể thực thi nó. Vì UID cho root là 0, chúng ta có thể dùng tùy chọn -gt trong câu lệnh if điều kiện để cấm tất cả UID lớn hơn 0.
if [ "$UID" -gt 0 ]; then
echo "Sorry, this script must be run as ROOT!"
exit 1
fi
echo "continue script"
3. Sử dụng đối số (Use arguments)
Giống như bất kỳ chương trình thực thi nào, script Bash có thể nhận đối số làm đầu vào. Dưới đây là một vài ví dụ. Nhưng trước hết, bạn nên hiểu rằng lập trình tốt có nghĩa là chúng ta không chỉ viết ứng dụng làm những gì chúng ta muốn; chúng ta phải viết ứng dụng không thể làm những gì chúng ta không muốn. Tác giả thích đảm bảo script không làm gì phá hoại trong trường hợp không có đối số. Do đó, đây là kiểm tra đầu tiên. Điều kiện kiểm tra số lượng đối số, $#, cho giá trị 0 và kết thúc script nếu true.
if [ $# -eq 0 ]; then
echo "No arguments provided"
exit 1
fi
echo "arguments found: $#"
Nhiều đối số (Multiple arguments)
Bạn có thể truyền nhiều hơn một đối số cho script. Biến nội bộ script dùng để tham chiếu mỗi đối số đơn giản là tăng dần, như $1, $2, $3, v.v. Tác giả chỉ mở rộng ví dụ trên với dòng sau để echo ba đối số đầu tiên. Rõ ràng, logic bổ sung sẽ cần thiết để xử lý đối số đúng dựa trên tổng số. Ví dụ này đơn giản cho mục đích demo.
echo $1 $2 $3
Trong khi thảo luận về các biến đối số này, bạn có thể thắc mắc, "Anh ấy có bỏ qua số 0 không?"
Vâng, có, nhưng tác giả có lý do tuyệt vời! Có thực sự biến $0, và nó rất hữu ích. Giá trị của nó đơn giản là tên script đang được thực thi.
echo $0
Một lý do quan trọng để tham chiếu tên script trong thực thi là tạo file log bao gồm tên script trong tên của chính nó. Dạng đơn giản nhất có thể chỉ là câu lệnh echo.
echo test >> $0.log
Tuy nhiên, bạn có thể muốn thêm một chút code để đảm bảo log được ghi vào vị trí với tên và thông tin bạn thấy hữu ích cho trường hợp dùng của mình.
4. Đầu vào người dùng (User input)
Một tính năng hữu ích khác dùng trong script là khả năng chấp nhận đầu vào trong quá trình thực thi. Cách đơn giản nhất là cung cấp cho người dùng một số đầu vào.
echo "enter a word please:"
read word
echo $word
Điều này cũng cho phép bạn cung cấp lựa chọn cho người dùng.
read -p "Install Software ?? [Y/n]: " answ
if [ "$answ" == 'n' ]; then
exit 1
fi
echo "Installation starting..."
5. Thoát khi thất bại (Exit on failure)
Một vài năm trước, tác giả viết script cài đặt phiên bản mới nhất Java Development Kit (JDK) trên máy tính. Script giải nén archive JDK vào thư mục cụ thể, cập nhật symbolic link, và dùng tiện ích alternatives để làm cho hệ thống nhận ra phiên bản mới. Nếu giải nén archive JDK thất bại, tiếp tục có thể làm hỏng Java system-wide. Vì vậy, tác giả muốn script abort trong tình huống đó. Tác giả không muốn script thực hiện tập thay đổi hệ thống tiếp theo trừ khi archive được giải nén thành công. Dưới đây là trích đoạn từ script đó:
tar kxzmf jdk-8u221-linux-x64.tar.gz -C /jdk --checkpoint=.500; ec=$?
if [ $ec -ne 0 ]; then
echo "Installation failed - exiting."
exit 1
fi
Một cách nhanh để bạn demo việc dùng biến $? là với one-liner ngắn này:
ls T; ec=$?; echo $ec
Trước hết, chạy touch T theo sau bằng lệnh này. Giá trị ec sẽ là 0. Sau đó, xóa T, rm T, và lặp lại lệnh. Giá trị ec giờ sẽ là 2 vì ls báo lỗi điều kiện vì T không tìm thấy.
Bạn có thể tận dụng báo cáo lỗi này để đưa logic, như tác giả làm trên, để kiểm soát hành vi script của bạn.
Kết luận (Takeaway)
Chúng ta có thể giả định rằng cần dùng ngôn ngữ như Python, C, hoặc Java cho chức năng cao hơn, nhưng không nhất thiết đúng. Ngôn ngữ script Bash rất mạnh mẽ. Có nhiều thứ để học để tối đa hóa sự hữu ích của nó. Tác giả hy vọng những ví dụ ít này sẽ làm sáng tỏ tiềm năng của coding với Bash.