Tải bản đầy đủ (.pdf) (37 trang)

Tìm hiểu ngôn ngữ shell script

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (633.1 KB, 37 trang )

Đề tài: Tìm hiểu ngôn ngữ Shell Script
Lời nói đầu
Ngày nay công nghệ thông tin đã có những bước tiến vượt bậc. Lập trình máy tính
điện tử, viết nên các chương trình ứng dụng đang ngày một gần gũi với con người. Điều
đó tạo nên sự phát triển mạnh mẽ của các ngôn ngữ lập trình. Có những ngôn ngữ không
phụ thuộc hệ điều hành, nhưng bên cạnh đó cũng có những ngôn ngữ gắn liền với hệ
điều hành, phát triển trên nền hệ điều hành và tác động trực tiếp đến các quá trình quản
lý cũng như xử lý của hệ điều hành.
Shell là ngôn ngữ chính của hệ điều hành Linux – hệ điều hành mã nguồn mở, hay
trước đây còn được biết đến là hệ điều hành chế độ dòng lệnh. Có thể thấy shell đóng
vai trò quan trọng và có tầm ảnh hưởng to lớn đến hệ điều hành này. Tất cả các thao tác
quản trị cũng như xử lý của hệ điều hành đều thông qua shell. Với sự phát triển mạnh
mẽ của Linux, việc tìm hiểu shell là hết sức cần thiết. Với nhu cầu đó, nhóm chúng em
đã chọn đề tài tiểu luận “Tìm hiểu ngôn ngữ Shell Script”. Tuy đã rất cố gắng nhưng do
thời gian có hạn, báo cáo của chúng em không tránh khỏi những thiếu sót.
Chúng em xin chân thành cảm ơn thầy đã tạo điều kiện và giúp đỡ chúng em hoàn
thành tiểu luận này.
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 1
Đề tài: Tìm hiểu ngôn ngữ Shell Script
Mục lục
Chương 1-Sơ lược về Shell 3
1.1 Kernel là gì? 3
1.2 Shell là gì? 4
1.3 Phân loại Shell 5
1.3.1 Bourne Shell 5
1.3.2 C Shell 5
1.3.3 Korn Shell 6
1.3.4 Bash Shell 6
Chương 2-Cú pháp ngôn ngữ shell script 8
2.1 Chương trình Hello World 8
2.2 Sử dụng biến 9


2.3 Phân biệt dấu nháy kép (“), dấu nháy đơn (') và dấu thực thi (`) 11
2.3.1 Dấu thực thi (`) 11
2.3.2 Dấu nháy kép (“) và nháy đơn (') 11
2.4 Cấu trúc trong ngôn ngữ shell script 12
2.4.1 Cấu trúc điều kiện 12
2.4.1.1 Cấu trúc if 12
2.4.1.2 Cấu trúc case 13
2.4.2 Cấu trúc điều khiển 15
2.4.2.1 Vòng lặp for 15
2.4.2.2 Vòng lặp while và until 17
Chương 3-Chuyển hướng xuất nhập 18
3.1 Làm việc với dòng vào chuẩn và dòng ra chuẩn 18
3.2 Chuyển hướng xuất nhập 19
3.3 Chuyển hướng stderr (dòng lỗi chuẩn) 20
3.4 Chuyển hướng đồng thời stdout và stderr 21
3.5 Kỹ thuật pipeline 22
Chương 4-Kỹ thuật debug trong shell script 28
4.1 Giải mã thông báo lỗi 28
4.1.1 Tìm lỗi cú pháp 28
4.1.2 Kỹ thuật chia để trị 32
4.2 Chế độ Debug 33
4.2.1 Disabling the Shell 33
4.2.2 Dò lỗi thực thi 34
4.3 Tránh lỗi bằng thói quen lập trình 35
4.3.1 Script sáng sủa 35
4.3.2 Chú thích 36
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 2
Đề tài: Tìm hiểu ngôn ngữ Shell Script
Chương 1- Sơ lược về Shell
Để đi vào tìm hiểu về shell cũng như ngôn ngữ shell script, chúng ta hãy cùng

xem xét kernel là gì?
1.1 Kernel là gì?
Ngày nay, một ví dụ điển hình về phần mềm tự do và phát triển mã nguồn mở đó
chính là hệ điều hành Linux. Phiên bản đầu tiên của Linux được Linux Torvalds phát
triển vào năm 1991 khi ông còn đang là sinh năm thứ 2 đại học Hensinki – Phần Lan và
hoàn thành bản 1.0 vào năm 1994. Bộ phận này được phát triển và tung ra thị trường
dưới bản quyền GNU GPL (đây là giấy phép phần mềm tự do phổ biến nhất do Richard
Stallman viết cho dự án GNU). Do đó bất cứ ai cũng có thể tải về và xem mã nguồn của
Linux.
Kernel là trái tim của hệ điều hành Linux. Nó quản lý các tài nguyên hệ thống.
Các tài nguyên này chính là các thiết bị trong Linux, ví dụ như: thiết bị lưu trữ dữ liệu,
máy in, bộ nhớ, hệ thống quản lý file Kernel sẽ quyết định user nào sẽ sử dụng hệ
thống, trong thời gian bao lâu và khi nào. Nó sẽ chạy các chương trình của bạn (hoặc là
cài đặt các file nhị phân). Kernel cũng chính là một bộ nhớ thường trú của Linux và thực
hiện các tác vụ sau:
➢ Quản lý vào ra
➢ Quản lý tiến trình
➢ Quản lý thiết bị
➢ Quản lý hệ thống file
➢ Quản lý bộ nhớ
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 3
Đề tài: Tìm hiểu ngôn ngữ Shell Script
1.2 Shell là gì?
Như chúng ta đã biết, máy tính sử dụng ngôn ngữ nhị phân bao gồm 0 và 1. Trước
đây để giao tiếp với máy tính, ta buộc lòng phải sử dụng ngôn ngữ nhị phân, điều này rất
khó khăn, phức tạp và dễ gây nhầm lẫn. Hệ điều hành cung cấp cho chúng ta một
chương trình được biến đến dưới tên gọi Shell. Shell tiếp nhận những câu lệnh, cấu trúc
viết bằng tiếng Anh và dịch nó sang ngôn ngữ nhị phân.
Mô hình shell hoạt động có thể hiểu như sau:
Có thể nói Shell chính là môi trường để người dùng tương tác với máy. Shell cũng

chính là một trình biên dịch ngôn ngữ lệnh và thực thi các lệnh truyền vào từ đầu vào
chuẩn (bàn phím) hay một file. Trong MS-DOS Shell chính là COMMAND.COM
nhưng nó không linh hoạt và mạnh mẽ như Shell trong Linux.
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 4
Đề tài: Tìm hiểu ngôn ngữ Shell Script
1.3 Phân loại Shell
Không có sự độc quyền trong shell, do đó bạn có thể tự do lựa chọn shell phù hợp
với mình. Đó có thể là một lợi thế nhưng cũng dẫn đến bất lợi nếu như lựa chọn một
shell mà ta không biết gì về nó. Dưới đây sẽ chỉ ra một số shell chính
1.3.1 Bourne Shell
Shell UNIX đầu tiên được biết đến chính là sh, viết tắt cho shell hoặc Bourne
shell, được đặt theo tên người sáng lập ra sh: Steven Bourne. Bourne shell đã trở thành
một phần chuẩn trong UNIX trong vài thập kỷ. Vì vậy, sh xuất hiện trên hầu hết các hệ
thống hỗ trợ UNIX hoặc các tập lệnh tương tự UNIX bao gồm Linux, Mac OS X.
Một số đặc điểm của Bourne shell:
➢ Các đoạn script có thể thực thi như một lệnh thông qua tên file
➢ Cho phép cả đồng bộ và không đồng bộ khi thực thi các lệnh
➢ Hỗ trợ chuyển hướng xuất nhập và pipeline
➢ Cung cấp điều khiển luồng, các dấu nháy và hàm
➢ Không định kiểu đối với biến
➢ Cung cấp biến địa phương và biến toàn cục
➢ Các đoạn script không đòi hỏi phải được biên dịch trước khi thực thi
1.3.2 C Shell
C Shell được thiết kế bởi Bill Joy trường đại học California, nó có tên như vậy là
do rất nhiều các cú pháp tương tự với ngôn ngữ lập trình C. Tuy nhiên thật khó có thể
tìm ra được các điểm tương đồng, vì vậy đừng hy vọng các kỹ năng lập trình C có thể áp
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 5
Đề tài: Tìm hiểu ngôn ngữ Shell Script
dụng hoàn toàn vào C Shell. Điều đó là đúng, nhưng cũng có rất nhiều các lập trình viên
C sử dụng C Shell.

C Shell phát triển rất nhanh và trở thành shell mặc định của distro BSD (Berkely
Software Distribution) – một distro nổi tiếng của UNIX.
Ngoài những đặc điểm thừa kế từ Bourne Shell, C Shell (viết tắt là csh) cũng có
những đặc điểm rất riêng, đặc biệt là khả năng triệu gọi các lệnh trước đó hoặc một phần
của lệnh trước đó để tạo ra các lệnh mới.
1.3.3 Korn Shell
Korn Shell đã phát triển và trở thành một phần không thể thiếu trong hệ thống
BSD UNIX. Khi AT&T (phòng thí nghiệm nổi tiếng có trụ sở chính tại đồi Murray –
bang New Jersey) phát triển hệ thống UNIX V, các lập trình viên mới nhận ra rằng họ
cần có một shell mới có thể đối chọi được với khả năng của C Shell. Do C Shell phát
triển theo hướng riêng và dần tách biệt với Bourne Shell nên C Shell buộc phải tạo
những cầu nối mới có thể liên lạc được với những lệnh mới của Bourne. Còn Korn Shell
(viết tắt là ksh) có thể hỗ trợ được điều đó.
1.3.4 Bash Shell
Qua quá trình sử dụng, người sử dụng muốn phải có một shell không những tương
thích các đoạn script viết bằng Bourne Shell mà còn phải có đầy đủ các tính năng edit
bằng dòng lệnh. Ngoài ra người sử dụng cũng muốn có sự tự do trong vấn đề bản quyền.
Bash Shell (viết tắt của Bourne Again Shell) đáp ứng được tất cả những điều đó.
Có thể thấy Bash là sự kết tinh những ưu điểm nổi bật của Korn Shell và C Shell.
Đó là khả năng edit bằng dòng lệnh ở Korn Shell và khả năng tự hoàn thành lệnh của C
Shell. Đó chính là lý do mà Korn Shell chỉ phát triển ở những hệ thống UNIX V. Hiện
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 6
Đề tài: Tìm hiểu ngôn ngữ Shell Script
nay thì Bash Shell đã trở thành shell mặc định của các distro Linux cũng như của Mac
OS X.
Trong khuôn khổ bài luận này, chúng ta chỉ tiến hành nghiên cứu Shell script trên
Bash Shell. Tuy nhiên ngay trong tên của Shell cũng đã cho thấy là một sự kế thừa từ
Bourne nên các kiến thức này cũng là kiến thức chung của shell script.
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 7
Đề tài: Tìm hiểu ngôn ngữ Shell Script

Chương 2- Cú pháp ngôn ngữ shell script
2.1 Chương trình Hello World
Chúng ta hãy xem file Hello.sh dưới đây:
#!/bin/sh
# This is a short script to display “Hello” to
# screen
echo “Hello World”
exit 0
Khi thực thi file Hello.sh sẽ được kết quả:
# chmod +x Hello.sh
# ./Hello.sh
Hello World
Chúng ta hãy cùng phân tích ví dụ này. Trong shell, dấu # bắt đầu một dòng
comment. Ở đây dòng 2 và dòng 3 là các dòng comment, tuy vậy dòng đầu tiên không
phải comment dù nó cũng bắt đầu bằng dấu #. Dòng đầu tiên là quy ước thông báo cho
shell biết sử dụng shell sh để biên dịch file này. Dòng 5 dùng để hiển thị một xâu ký tự
sau echo ra màn hình. Lệnh exit đảm bảo rằng script sau khi thực thi sẽ trả về mã lỗi,
đây là cách mà hầu hết các chương trình nên làm. Mặc dù mã lỗi trả về ít khi được dùng
đến trong trường hợp thực hiện tương tác trực tiếp từ dòng lệnh. Tuy nhiên, nhận biết mã
trả về của một đoạn script sau khi thực thi lại thường rất có ích nếu triệu gọi scrit từ
trong một kịch bản script khác. Trong đoạn chương trình trên, lệnh exit trả về giá trị 0
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 8
Đề tài: Tìm hiểu ngôn ngữ Shell Script
cho biết script thực thi thành công và thoát khỏi shell gọi nó. Ta không cố tình bắt các
lỗi xảy ra của những lệnh hệ thống trong trường hợp này.
Mặc dù chúng ta lưu tập tin với đuôi mở rộng là .sh nhưng điều này là không bắt
buộc. Linux thường không sử dụng phần đuôi mở rộng của tập tin làm dấu hiện nhận
dạng, vì vậy chúng ta có thể đặt đuôi mở rộng là bất kỳ tên nào, hoặc có thể không cần
đuôi mở rộng (các script hệ thống thường làm theo cách này). Shell chỉ quan tâm đến
dòng đầu tiên của file ( #!/bin/sh) để quyết định đó là file gì.

2.2 Sử dụng biến
Trong hệ thống unix có 3 loại biến:
➢ Biến hệ thống (System Variable): biến được tạo bởi bản thân hệ điều hành,
các biến này được viết hoa hoàn toàn. Một số biến hệ thống quan trọng
được chỉ ra như bảng dưới đây:
Một số biến ở trên có thể sẽ thay đổi trên từng PC, ví dụ như biến
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 9
Đề tài: Tìm hiểu ngôn ngữ Shell Script
$USERNAME – biến này trả về tên của tài khoản đang truy cập vào PC.
Đặc biệt lưu ý hạn chế thay đổi biến môi trường vì nó có thể gây ra một số
tác hại không mong muốn.
➢ Biến người dùng tự định nghĩa:
Thông thường không cần phải khai báo biến trước khi sử dụng mà thay vào đó
biến sẽ được tự động tạo và khai báo khi làn đầu tiên tên biến xuất hiện, chẳng hạn như
trong phép gán. Mặc định, tất cả các biến đều được khởi tạo và chứa giá trị kiểu chuỗi.
Ngay cả dữ liệu liệu đưa vào biến là một con số thì nó cũng được xem là định dạng
chuỗi. Shell và một vài lệnh tiện ích sẽ tự động chuyển chuỗi thành số để thực hiện phép
tính khi có yêu cầu. Bản thân hệ điều hành unix là hệ điều hành phân biệt chữ hoa chữ
thường nên trong tên biến cũng có sự phân biệt đó.
Bên trong các script của shell có thể lấy về nội dung của biến bằng cách dùng dấu
$ trước tên biến. Tuy nhiên khi gán nội dung cho biến chúng ta không sử dụng ký tự $
trước tên biến. Một đoạn ví dụ sau đây sẽ minh họa cho điều đó:
~> str=”Hello world”
~> echo $str
Hello world
Trong ngôn ngữ shell có quy định chặt chẽ về dấu cách trong các câu lệnh, đặc
biệt trong phép gán không được có dấu cách.
➢ Biến tham số (parameter variable):
Các biến tham số do shell tự quy định để lưu trữ giá trị các tham số truyền vào
cho một lệnh. Ví dụ: $1, $2 là các tham số truyền vào cho lệnh theo thứ tự từ trái sang

phải. Đặc biệt $0 trả về tên lệnh và $@ trả về danh sách các tham số truyền vào dưới
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 10
Đề tài: Tìm hiểu ngôn ngữ Shell Script
dạng chuỗi. Biến $# lưu danh sách tham số truyền vào dưới dạng 1 chuỗi, các tham số
phân cách với nhau bởi biến $IFS, nếu $IFS=null thì biến $# tương đương với biến $@.
2.3 Phân biệt dấu nháy kép (“), dấu nháy đơn (') và dấu thực thi (`)
2.3.1 Dấu thực thi (`)
Dấu này dùng để thông báo shell cần phải thực hiện lệnh trong cặp dấu ` và `. Nó
tương đương với cấu trúc $(command). Ví dụ sau sẽ chỉ rõ điều đó:
~> echo `pwd`
/home/banhbaochay
~> echo $(pwd)
/home/banhbaochay
2.3.2 Dấu nháy kép (“) và nháy đơn (')
Khác với dấu huyền ( ‘ ), những thông tin giữa hai dấu nháy (nháy đơn hoặc nháy
kép) được coi là thông tin được sử dụng trong lệnh echo và sẽ được in ra màn hình hay
được gán vào biến dạng xâu. Như vậy, không thể viết các lệnh hệ thống giữa hai dấu
nháy mà chỉ các để các xâu ký tự hay các biến. Chúng ta xem xét những dòng ví dụ sau:
~> str=”World”
~> echo “Hello $str”
Hello World
~> echo 'Hello $str'
Hello $str
Có thể dễ thấy sự khác biệt của hai dấu nháy đơn và nháy kép qua những dòng
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 11
Đề tài: Tìm hiểu ngôn ngữ Shell Script
lệnh trên, đối với nháy kép (“), khi in ra sẽ được thực hiện với giá trị của biến sau dấu $.
Đối với dấu nháy đơn (') thì sẽ in ra y nguyên như trong dòng văn bản. Thông thường
dấu nháy đơn ít được sử dụng nhưng lại rất tiện lợi khi muốn in y nguyên một dòng văn
bản, đặc biệt là khi có các ký tự đặc biệt nh- $, \.

2.4 Cấu trúc trong ngôn ngữ shell script
2.4.1 Cấu trúc điều kiện
2.4.1.1 Cấu trúc if
Nền tảng cơ bản trong tất cả ngôn ngữ lập trình đó là khả năng kiểm tra điều kiện
và đưa ra quyết định rẽ nhánh thích hợp tùy theo điều kiện logic đúng hay sai. Thực tế,
các script sử dụng lệnh [ và lệnh test để kiểm tra điều kiện logic rất nhiều. Trong hầu
hết các hệ thống UNIX và LINUX, hai lệnh này là tương đương. Tuy nhiên lệnh [ hay
được sử dụng hơn do tính đơn giản và gần gũi với các ngôn ngữ lập trình khác.
Cấu trúc điều kiện trong shell cũng tương tự như trong các ngôn ngữ bậc cao
khác, tức là cũng có các cấu trúc if, if else và if elif
if [ condition ]
then
#script when result is true
fi
hoặc
if [ condition ]
then
#script when result is true
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 12
Đề tài: Tìm hiểu ngôn ngữ Shell Script
else
#script when result is false
fi
hoặc
if [ condition1 ]
then
#script 1
elif [ condition2 ]
#script 2
fi

Biểu thức condition có thể rơi vào 1 trong 3 kiểu dưới đây:
➢ Biểu thức so sánh chuỗi
➢ Biểu thức so sánh toán học
➢ Biểu thức kiểm tra tệp tin: do là ngôn ngữ chủ yếu can thiệp vào thư mục
và file trên hệ thống nên shell đã cung cấp sẵn các tùy chọn kiểm tra như
-d, -e, -f, -g
2.4.1.2 Cấu trúc case
Cấu trúc lệnh case như sau:
case variable in
pattern statements;;
pattern statements;;
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 13
Đề tài: Tìm hiểu ngôn ngữ Shell Script

esac
Cấu trúc case rất linh hoạt, nó cho phép người dùng so khớp nội dung của biến
với một mẫu chuỗi pattern nào đó. Nếu đúng sẽ thực hiện câu lệnh statements tương
ứng. Chúng ta hãy cùng xem xét ví dụ sau:
#!/bin/sh
echo “Is it morning? Please answer yes or no”
read timeofday
case $timeofday in
“yes” ) echo “Good morning” ;;
“no” ) echo “Good afternoon” ;;
“y” ) echo “Good morning” ;;
“n” ) echo “Good afternoon” ;;
* ) echo “Sorry, answer not recognised” ;;
esac
exit 0
Cách chương trình làm việc như sau: Sau khi người dùng nhập câu trả lời, lệnh

case sẽ lấy nội dung của biến $timeofday so sánh vời từng chuỗi. Điểm đặc biệt đó là khi
gặp chuỗi thích hợp nó thực hiện lệnh sau dấu ( rồi kết thúc. Nó tương tự như các ngôn
ngữ khác nhưng luôn có lệnh break ở trong case. Ký tự đại diện * cho phép so khớp với
mọi loại chuỗi. * thường được xem như trường hợp so sánh đúng cuối cùng nếu tất cả
các mẫu so sánh trước đó thất bại. Như vậy * giống như khóa default trong các ngôn ngữ
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 14
Đề tài: Tìm hiểu ngôn ngữ Shell Script
khác. Một phiên bản khác của ví dụ trên được chỉ ra dưới đây:
#!/bin/sh
echo “Is it morning? Please answer yes or no”
read timeofday
case $timeofday in
“yes” | “y” | “YES” | “Yes” ) echo “Good
morning” ;;
“n*” | “N*” ) echo “Good afternoon” ;;
* ) echo “Sorry, answer not recognised” ;;
esac
exit 0
Đoạn script sử dụng nhiều mẫu so khớp trên cùng một dòng lệnh. Trên thực tế
điều này thường hay được sử dụng do làm code trở nên dễ đọc hơn.
2.4.2 Cấu trúc điều khiển
Shell cũng như các ngôn ngữ khác cung cấp các cấu trúc điều khiển luồng như:for,
while, until. Bên cạnh sự khác biệt về mặt cú pháp, shell còn mang một đặc điểm rất
riêng của mình.
2.4.2.1 Vòng lặp for
Cấu trúc lệnh for như sau:
for variable in values
do
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 15
Đề tài: Tìm hiểu ngôn ngữ Shell Script

#statements
done
Như đã nêu, biến variable sẽ nhận tập hợp các giá trị được nêu ra trong values.
Values có thể là một tập các giá trị hoặc là kết quả trả về của một lệnh.
Ta có 2 ví dụ để minh họa cho điều đó:
Ví dụ:
~> for i in 1 2 3 4 5 6
~> do
~> echo -n $i,
~> done
1,2,3,4,5,6,
Ví dụ:
~> for i in `ls`
~> do
~> echo $i
~> done
Documents
downloads
myfolder
Trong ví dụ đầu tiên, tập hợp các giá trị sau từ khóa in phải được ngăn cách nhau
bằng dấu cách. Còn trong ví dụ thứ hai, shell sẽ thực hiện lệnh ls trước rồi chèn kết quả
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 16
Đề tài: Tìm hiểu ngôn ngữ Shell Script
vào vị trí lệnh ls. Lúc đó câu lệnh shell sẽ thành thế này:
~> for i in Documents downloads myfolder
2.4.2.2 Vòng lặp while và until
Hoàn toàn tương tự shell cũng cung cấp cấu trúc while như sau:
while condition
do
#statements

done
Cấu trúc until:
until condition
do
#statements
done
Cấu trúc while và cấu trúc until có một điểm khác biệt căn bản, đó là while thực
thi statements khi condition trả về true, còn until dừng lại khi condition trả về true.
Một trong những ưu điểm nổi bật của shell đó chính là nó cho phép nối nhiều lệnh
và kết quả xuất ra theo nhiều cách khác nhau. Bằng cách gõ các lệnh, chúng ta có thể
thực hiện các tác vụ phức tạp bao gồm nhiều bước hoặc tinh chế kết quả kết xuất cho
các tình huống đặc biệt. Kỹ thuật phục vụ cho mục đích này chính là kỹ thuật pipeline
trong shell sẽ được nhắc đến dưới đây.
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 17
Đề tài: Tìm hiểu ngôn ngữ Shell Script
Chương 3- Chuyển hướng xuất nhập
Các nhà thiết kế UNIX đã xây dựng nên một hệ thống với các đặc điểm sau:
➢ Mọi thứ trong hệ thống đều là file. Các thiết bị đều được biểu diễn như là các
file đặc biệt
➢ Mỗi một tiến trình chạy trong một môi trường riêng. Môi trường đó bao gồm
các file chuẩn cho input, output và error
➢ UNIX có rất nhiều các lệnh nhỏ, mỗi lệnh này được thiết kế để làm tốt nhất
một tác vụ nào đấy. Ưu điểm của nó là tiết kiệm bộ nhớ và giảm yêu cầu xử lý
lên CPU
➢ Các lệnh này được thiết kế để xử lý dữ liệu từ dòng vào chuẩn stdin và đưa kết
quả ra stdout
➢ Người dùng có thể kết hợp linh hoạt các lệnh này bằng cách tạo ra các lệnh
pipelines
3.1 Làm việc với dòng vào chuẩn và dòng ra chuẩn
Tất cả mọi tiến trình trên UNIX hoặc hệ thống tương tự UNIX đều được cung cấp

với 3 dòng chuẩn: stdin (dòng vào chuẩn), stdout (dòng ra chuẩn) và stderr (dòng lỗi
chuẩn). Mặc định sẽ là:
➢ Standard input: đó là bàn phím hoặc là các file đối với script
➢ Standard output: đó là cửa sổ shell hoặc terminal khi chạy script
➢ Standard error: cũng giống như dòng ra chuẩn (cửa sổ shell hoặc
terminal)
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 18
Đề tài: Tìm hiểu ngôn ngữ Shell Script
Ví dụ khi trong đoạn script gọi lệnh read thì nó sẽ đọc dữ liệu từ stdin và khi đoạn
script gọi lệnh echo thì nó sẽ gửi kết quả ra stdout. Để tiện cho việc gọi lệnh và xử lý, hệ
thống quy định 0 cho stdin, 1 cho stdout và 2 cho stderr.
3.2 Chuyển hướng xuất nhập
Vì trong UNIX, bàn phím hay cửa sổ shell cũng chỉ là một loại file đặc biệt nên
rất dễ dàng để chuyển hướng xuất hoặc nhập của 1 script. Chúng ta có thể gửi đầu ra của
một lệnh hoặc một script tới một file thay vì tới cửa sổ shell. Hoàn toàn tương tự, ta
cũng có thể đặt đầu vào của một lệnh hay script là file thay cho bàn phím. Để làm được
điều đó, ta sử dụng cú pháp đặc biệt < và >.
Một lệnh cơ bản thường có cấu trúc như sau:
Để chuyển hướng xuất của lệnh tới một file, cú pháp như sau:
Và để chuyển hướng nhập từ một file, cú pháp như sau:
Mặt khác ta cũng có thể kết hợp chuyển hướng xuất nhập như sau:
Chúng ta hãy cùng xem xét trực tiếp qua ví dụ sau:
Và file commands.txt có nội dung:
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 19
Đề tài: Tìm hiểu ngôn ngữ Shell Script
Trong ví dụ chúng ta đã liệt kê các file có trong thư mục /usr/bin, nếu như
bình thường kết quả sẽ hiển thị trên màn hình. Nhưng với cấu trúc chuyển hướng xuất
nên kết quả được lưu vào file commands.txt tại thư mục hiện hành. Toán tử > đã nói cho
shell biết rằng đầu ra sẽ chuyển vào file commands.txt, nếu file này đã tồn tại thì nó sẽ
xóa file cũ và tạo một file mới. Mỗi dòng trong file commands.txt lưu tên một file trong

thư mục /usr/bin.
Ví dụ dưới đây lại sử dụng toán tử < để chuyển hướng nhập cho lệnh wc:
Lệnh wc (viết tắt của word count) có thể đếm số dòng, số byte, số ký tự và số từ
của một file. Trong lệnh trên, shell được yêu cầu đưa đầu vào là file commands.txt cho
lệnh wc và trả kết quả ra màn hình là số dòng trong file commands.txt.
3.3 Chuyển hướng stderr (dòng lỗi chuẩn)
Mặc định, stderr và stdout đều gửi kết quả ra cửa số shell hoặc terminal nhưng
trong nhiều trường hợp cần phải tách biệt dòng ra của chúng. Lý do chính là khi chuyển
hướng xuất cho một lệnh hoặc script thì chúng ta không thể biết được lệnh đó có xuất
hiện lỗi hay không. Chuyển hướng stderr giải quyết được vấn đề này. Cấu trúc chung để
sử dụng như sau:
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 20
Đề tài: Tìm hiểu ngôn ngữ Shell Script
Số 2 để biểu diễn cho stderr.
3.4 Chuyển hướng đồng thời stdout và stderr
Trong Bash shell, có thể chuyển hướng stderr tới cùng vị trí với stdout theo một số
cách.
Nếu chuyển hướng stdout tới một file thì ta có thể sử dụng cú pháp 2>&1 để
chuyển hướng stderr tới cùng vị trí với stdout:
Lệnh trên gồm 3 phần chính:
➢ ls /usr/bin là lệnh để hiển thị các file trong thư mục /usr/bin
➢ > commands.txt chuyển hướng xuất của lệnh ls tới file commands.txt
➢ 2>&1 sẽ chuyển hướng stderr tới cùng nơi với stdout, do stdout đã chuyển
hướng vào file commands.txt nên stderr cũng chuyển vào file này.
Ta có thể thấy rõ hơn nếu lệnh ls xuất hiện lỗi:
Lưu ý phải hết sức cẩn thận khi gõ tổ hợp 2>&1 bởi vì dấu & đi một mình có
nghĩa là chạy lệnh đó trong chế độ ẩn, nên nhớ không có dấu cách trong tổ hợp 2>&1.
Ta cũng có thể sử dụng cú pháp &> để thực hiện việc này:
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 21
Đề tài: Tìm hiểu ngôn ngữ Shell Script

Mặt khác, nếu ta không chuyển hướng stderr thì thông báo lỗi sẽ được hiển thị ở
màn hình:
Một vấn đề nảy sinh là đôi lúc stdout của một lệnh hiển thị quá nhiều thông tin và
không cần thiết, mục đích chính của người sử dụng lại chỉ là cần xem thông báo lỗi khi
chạy lệnh hoặc script. Giải quyết vấn đề này có thể sử dụng phương pháp chuyển hướng
stdout ra một file tạm, sau đó xóa ngay file tạm đó đi. Nhưng việc tạo xóa liên tục lại
ảnh hưởng đến ổ cứng và hiệu năng của máy. Và UNIX cung cấp cho ta một file đặc biệt
/dev/null, nó còn được gọi dưới tên gọi khác là lỗ đen. Nó bỏ qua mọi dữ liệu ghi
lên nó nhưng có báo cáo về việc ghi dữ liệu thành công và không cung cấp bất kỳ dữ
liệu gì khi đọc nó (trả về EOF).
Vậy ví dụ trên có thể được viết lại như sau:
3.5 Kỹ thuật pipeline
Kỹ thuật pipeline phát triển từ ý tưởn chuyển hướng xuất nhập cho một chương
trình. Nếu chúng ta có thể chuyển hướng xuất của một lệnh và chuyển hướng nhập của
một lệnh khác, tại sao không kết nối trực tiếp đầu ra của lệnh này thành đầu vào của lệnh
kia? Đó chính là điều mà kỹ thuật pipeline giải quyết.
Cú pháp cơ bản được đưa ra như hình dưới:
Ký tự | sẽ nối 2 lệnh, shell sẽ chuyển đầu ra của lệnh thứ nhất thành đầu vào của
lệnh thứ 2. Kỹ thuật pipeline chính là cách viết ngắn gọn của chuyển hướng đã nói ở
trên. Ví dụ, ta có thể đặt stdin của lệnh wc là một file
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 22
Đề tài: Tìm hiểu ngôn ngữ Shell Script
hoặc sử dụng kỹ thuật pipeline với lệnh cat và wc:
Kỹ thuật này cũng có thể áp dụng phối hợp nhiều lệnh:
Cấu trúc trên hoạt động như sau: kết quả lệnh command1 trở thành đối số cho
lệnh command2, sau khi thực hiện xong sẽ đưa kết quả thành đối số cho lệnh
command3, kết quả trả về lại là đầu vào cho command4, kết thúc sẽ lưu kết quả của
command4 vào file output.txt
Ví dụ sau sẽ minh họa rõ ràng cho kỹ thuật pipeline, lệnh spell sẽ trả về danh
sách tất cả các từ không đúng chính tả trong một file text. Lệnh sort cho phép sắp xếp

thứ tự trong một file theo từng dòng và theo tiêu chuẩn lựa chọn. Lệnh uniq sẽ xóa tất
cả những dòng trùng nhau. Chúng ta có thể kết hợp tất cả những lệnh này để tạo nên một
lệnh kiểm tra chính tả đơn giản như sau:
Và dưới đây là kết quả các từ sai lỗi chính tả trong file filename.txt:
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 23
Đề tài: Tìm hiểu ngôn ngữ Shell Script
Quá trình hoạt động của chuỗi lệnh như sau: lệnh spell sẽ tìm ra tất cả các từ
có trong file filename.txt mà bị sai chính tả rồi đưa ra stdout mỗi từ một dòng. Lưu ý
rằng spell là sử dụng khả năng kiểm tra chính tả quá cũ, phiên bản mới nhất của lệnh
này được tích hợp trong module spell-checking của openoffice. Tuy vậy spell vẫn
còn hữu dụng trong việc thử nghiệm cấu trúc pipeline. Tất cả dữ liệu trong stdout của
lệnh spell sẽ trở thành stdin của lệnh sort. Lệnh sort không tham số sẽ sắp xếp
theo thứ tự ABC. Lệnh pipeline sẽ lại chuyển stdout của lệnh sort sang stdin của lệnh
unq. Lệnh unq sẽ thực hiện rà soát stdin và loại bỏ các dòng bị trùng trong stdin. Cuối
cùng stdout của lệnh unq sẽ được ghi vào file suspect_word.txt.
Các khái niệm dưới đây đúng với bất cứ lệnh pipeline nào chúng ta cần tạo.
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 24
Đề tài: Tìm hiểu ngôn ngữ Shell Script
Việc tạo các lệnh pipeline thực sự rất phức tạp. Cách tốt nhất là phải thực hiện
từng bước, phải đảm bảo được từng lệnh trong pipeline phải hoạt động tốt. Chúng ta có
thể tạo ra một chuỗi lệnh xác định chính xác những user nào được sử dụng trong hệ
thống LINUX. Trong hệ thống LINUX, thông tin user thường được lưu trữ trong file
/etc/passwd, đây là file đặc biệt lưu trữ mỗi user trên một dòng. Một file /etc/passwd
trong hệ thống LINUX có thể thấy như dưới đây:
Mỗi dòng trong file này có cấu trúc như sau:
Thông tin này chỉ ra rằng user tên username có password là password (tuy nhiên
password này luôn được mã hóa để không thể đọc bằng trình soạn thảo thông thường).
Ngoài ra còn có những thông tin như ID của user này là userID và ID của group là
groupID (LINUX không cho phép một user không thuộc một group nào vì lý do bảo
mật). Thư mục chính của user là home_directory và shell khởi động của user này là

starting_shell (thông thường là bash shell). Bây giờ ta sẽ tạo ra cấu trúc pipeline để trích
Lê Anh Dũng – Đinh Xuân Thọ – Bùi Hữu Cường – Nguyễn Quang Điệp Trang 25

×