Trong bài viết đầu tiên trong chuỗi này, bạn tạo một script Bash rất nhỏ, một dòng, và khám phá lý do tạo shell script và tại sao chúng là lựa chọn hiệu quả nhất cho system administrator, thay vì chương trình biên dịch. Trong bài thứ hai, bạn bắt đầu nhiệm vụ tạo một template khá đơn giản bạn có thể dùng như điểm khởi đầu cho các chương trình Bash khác, sau đó khám phá cách test nó.
Bài viết thứ ba trong bốn bài của chuỗi này giải thích cách tạo và dùng một hàm Help đơn giản. Trong khi tạo cơ sở Help của bạn, bạn cũng sẽ học về dùng hàm và cách xử lý tùy chọn dòng lệnh như -h.
Tại sao cần Help?
Ngay cả các chương trình Bash khá đơn giản cũng nên có某种 cơ sở Help, dù nó khá sơ bộ. Nhiều chương trình shell Bash tác giả viết được dùng rất hiếm nên anh ấy quên cú pháp chính xác của lệnh cần thiết. Những cái khác phức tạp đến nỗi anh ấy cần xem lại tùy chọn và đối số ngay cả khi dùng thường xuyên.
Có một hàm Help built-in cho phép bạn xem những điều đó mà không phải kiểm tra chính mã nguồn. Một cơ sở Help tốt và hoàn chỉnh cũng là một phần của tài liệu chương trình.
Về hàm (About functions)
Hàm shell là danh sách câu lệnh chương trình Bash được lưu trong môi trường shell và có thể thực thi, giống như bất kỳ lệnh nào khác, bằng cách gõ tên của chúng tại dòng lệnh. Hàm shell cũng có thể gọi là thủ tục hoặc subroutine, tùy thuộc vào ngôn ngữ lập trình khác bạn đang dùng.
Hàm được gọi trong script hoặc từ giao diện dòng lệnh (CLI) bằng cách dùng tên của chúng, giống như bạn làm cho bất kỳ lệnh nào khác. Trong chương trình CLI hoặc script, các lệnh trong hàm thực thi khi chúng được gọi, sau đó luồng trình tự chương trình trả về thực thể gọi, và chuỗi câu lệnh chương trình tiếp theo trong thực thể đó thực thi.
Cú pháp của một hàm là:
FunctionName(){program statements}
Khám phá điều này bằng cách tạo một hàm đơn giản tại CLI. (Hàm được lưu trong môi trường shell cho instance shell nó được tạo.) Bạn sẽ tạo hàm gọi là hw, viết tắt của "hello world." Nhập mã sau tại CLI và nhấn Enter. Sau đó nhập hw như bạn làm với bất kỳ lệnh shell nào khác:
[student@testvm1 ~]$ hw(){ echo "Hi there kiddo"; }
[student@testvm1 ~]$ hw
Hi there kiddo
[student@testvm1 ~]$
OK, tác giả hơi chán với "Hello world" khởi đầu tiêu chuẩn. Bây giờ, liệt kê tất cả hàm hiện tại đã định nghĩa. Có rất nhiều, nên tác giả chỉ hiển thị hàm hw mới. Khi được gọi từ dòng lệnh hoặc trong chương trình, một hàm thực hiện nhiệm vụ được lập trình và sau đó thoát và trả lại điều khiển cho thực thể gọi, dòng lệnh, hoặc câu lệnh Bash tiếp theo trong script sau câu lệnh gọi:
[student@testvm1 ~]$ declare -f | less
<snip>
hw ()
{
echo "Hi there kiddo"
}
<snip>
Gỡ bỏ hàm đó vì bạn không cần nó nữa. Bạn có thể làm điều đó với lệnh unset:
[student@testvm1 ~]$ unset -f hw ; hw
bash: hw: command not found
[student@testvm1 ~]$
Tạo hàm Help
Mở chương trình hello trong trình soạn thảo và thêm hàm Help dưới đây vào code chương trình hello sau phần copyright nhưng trước câu lệnh echo "Hello world!". Hàm Help này sẽ hiển thị mô tả ngắn về chương trình, sơ đồ cú pháp, và mô tả ngắn các tùy chọn có sẵn. Thêm lời gọi hàm Help để test nó và một số dòng comment cung cấp ranh giới trực quan giữa các hàm và phần chính của chương trình:
################################################################################
# Help #
################################################################################
Help()
{
# Display Help
echo "Add description of the script functions here."
echo
echo "Syntax: scriptTemplate [-g|h|v|V]"
echo "options:"
echo "g Print the GPL license notification."
echo "h Print this Help."
echo "v Verbose mode."
echo "V Print software version and exit."
echo
}
################################################################################
################################################################################
# Main program #
################################################################################
################################################################################
Help
echo "Hello world!"
Các tùy chọn mô tả trong hàm Help này điển hình cho các chương trình tác giả viết, dù chưa có trong code. Chạy chương trình để test nó:
[student@testvm1 ~]$ ./hello
Add description of the script functions here.
Syntax: scriptTemplate [-g|h|v|V]
options:
g Print the GPL license notification.
h Print this Help.
v Verbose mode.
V Print software version and exit.
Hello world!
[student@testvm1 ~]$
Vì bạn chưa thêm logic để hiển thị Help chỉ khi cần, chương trình sẽ luôn hiển thị Help. Vì hàm hoạt động đúng, hãy đọc tiếp để thêm logic hiển thị Help chỉ khi tùy chọn -h được dùng khi gọi chương trình tại dòng lệnh.
Xử lý tùy chọn (Handling options)
Khả năng của script Bash xử lý tùy chọn dòng lệnh như -h cung cấp một số khả năng mạnh mẽ để điều khiển chương trình và sửa đổi nó làm gì. Trong trường hợp tùy chọn -h, bạn muốn chương trình in văn bản Help ra terminal session và sau đó thoát mà không chạy phần còn lại của chương trình. Khả năng xử lý tùy chọn nhập tại dòng lệnh có thể thêm vào script Bash dùng lệnh while (xem Cách lập trình với Bash: Vòng lặp để học thêm về while) kết hợp với lệnh getops và case.
Lệnh getops đọc bất kỳ và tất cả tùy chọn chỉ định tại dòng lệnh và tạo danh sách các tùy chọn đó. Trong code dưới đây, lệnh while lặp qua danh sách tùy chọn bằng cách thiết lập biến $options cho mỗi cái. Câu lệnh case dùng để đánh giá mỗi tùy chọn lần lượt và thực thi câu lệnh trong stanza tương ứng. Câu lệnh while sẽ tiếp tục đánh giá danh sách tùy chọn cho đến khi chúng đã được xử lý hết hoặc nó gặp câu lệnh exit, kết thúc chương trình.
Hãy chắc chắn xóa lời gọi hàm Help ngay trước câu lệnh echo "Hello world!" để thân chính của chương trình trông như thế này:
################################################################################
################################################################################
# Main program #
################################################################################
################################################################################
################################################################################
# Process the input options. Add options as needed. #
################################################################################
# Get the options
while getopts ":h" option; do
case $option in
h) # display Help
Help
exit;;
esac
done
echo "Hello world!"
Lưu ý dấu chấm phẩy kép ở cuối câu lệnh exit trong case option cho -h. Điều này bắt buộc cho mỗi tùy chọn thêm vào câu lệnh case này để phân định cuối của mỗi tùy chọn.
Kiểm thử (Testing)
Test giờ phức tạp hơn một chút. Bạn cần test chương trình với một số tùy chọn khác nhau—và không tùy chọn—để xem nó phản ứng thế nào. Trước hết, test không có tùy chọn để đảm bảo nó in "Hello world!" như nó nên:
[student@testvm1 ~]$ ./hello
Hello world!
Điều đó hoạt động, nên giờ test logic hiển thị văn bản Help:
[student@testvm1 ~]$ ./hello -h
Add description of the script functions here.
Syntax: scriptTemplate [-g|h|t|v|V]
options:
g Print the GPL license notification.
h Print this Help.
v Verbose mode.
V Print software version and exit.
Điều đó hoạt động như mong đợi, nên thử một số test để xem điều gì xảy ra khi bạn nhập một số tùy chọn không mong đợi:
[student@testvm1 ~]$ ./hello -x
Hello world!
[student@testvm1 ~]$ ./hello -q
Hello world!
[student@testvm1 ~]$ ./hello -lkjsahdf
Add description of the script functions here.
Syntax: scriptTemplate [-g|h|t|v|V]
options:
g Print the GPL license notification.
h Print this Help.
v Verbose mode.
V Print software version and exit.
[student@testvm1 ~]$
Chương trình chỉ bỏ qua bất kỳ tùy chọn nào không có phản hồi cụ thể mà không tạo ra bất kỳ lỗi nào. Nhưng lưu ý mục nhập cuối (với -lkjsahdf cho tùy chọn): vì có h trong danh sách tùy chọn, chương trình nhận ra nó và in văn bản Help. Việc test này đã chỉ ra rằng chương trình không có khả năng xử lý đầu vào không đúng và kết thúc chương trình nếu phát hiện.
Bạn có thể thêm stanza case khác vào câu lệnh case để khớp bất kỳ tùy chọn nào không có khớp rõ ràng. Case chung này sẽ khớp bất cứ thứ gì bạn chưa cung cấp khớp cụ thể. Câu lệnh case giờ trông như thế này, với case catch-all \? là case cuối. Bất kỳ case cụ thể bổ sung nào phải đặt trước cái cuối này:
while getopts ":h" option; do
case $option in
h) # display Help
Help
exit;;
\?) # incorrect option
echo "Error: Invalid option"
exit;;
esac
done
Test chương trình lại dùng cùng tùy chọn như trước và xem nó hoạt động như thế nào bây giờ.
Bạn đang ở đâu (Where you are)
Bạn đã hoàn thành một lượng tốt trong bài viết này bằng cách thêm khả năng xử lý tùy chọn dòng lệnh và thủ tục Help. Script Bash của bạn giờ trông như thế này:
#!/usr/bin/bash
################################################################################
# scriptTemplate #
# #
# Use this template as the beginning of a new program. Place a short #
# description of the script here. #
# #
# Change History #
# 11/11/2019 David Both Original code. This is a template for creating #
# new Bash shell scripts. #
# Add new history entries as needed. #
# #
# #
################################################################################
################################################################################
################################################################################
# #
# Copyright (C) 2007, 2019 David Both #
# LinuxGeek46@both.org #
# #
# This program is free software; you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation; either version 2 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program; if not, write to the Free Software #
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #
# #
################################################################################
################################################################################
################################################################################
################################################################################
# Help #
################################################################################
Help()
{
# Display Help
echo "Add description of the script functions here."
echo
echo "Syntax: scriptTemplate [-g|h|t|v|V]"
echo "options:"
echo "g Print the GPL license notification."
echo "h Print this Help."
echo "v Verbose mode."
echo "V Print software version and exit."
echo
}
################################################################################
################################################################################
# Main program #
################################################################################
################################################################################
################################################################################
# Process the input options. Add options as needed. #
################################################################################
# Get the options
while getopts ":h" option; do
case $option in
h) # display Help
Help
exit;;
\?) # incorrect option
echo "Error: Invalid option"
exit;;
esac
done
echo "Hello world!"
Hãy chắc chắn test phiên bản này của chương trình rất kỹ. Dùng đầu vào ngẫu nhiên và xem điều gì xảy ra. Bạn cũng nên thử test tùy chọn hợp lệ và không hợp lệ không dùng dấu gạch ngang (-) ở trước.
Lần sau (Next time)
Trong bài viết này, bạn thêm hàm Help cũng như khả năng xử lý tùy chọn dòng lệnh để hiển thị nó có chọn lọc. Chương trình đang hơi phức tạp hơn, nên test đang trở nên quan trọng hơn và yêu cầu nhiều đường dẫn test hơn để hoàn chỉnh.
Bài viết tiếp theo sẽ xem xét khởi tạo biến và làm một chút sanity checking để đảm bảo chương trình sẽ chạy dưới tập điều kiện đúng.
Tài nguyên (Resources)
- Cách lập trình với Bash: Cú pháp và công cụ
- Cách lập trình với Bash: Toán tử logic và mở rộng shell
- Cách lập trình với Bash: Vòng lặp
Chuỗi bài viết này một phần dựa trên Volume 2, Chapter 10 của khóa tự học Linux ba phần của David Both, Using and Administering Linux—Zero to SysAdmin.