Chuẩn bị kỳ thi LPI 101: Các lệnh GNU và UNIX

Chủ đề 103 (LPIC-1) Quản trị trình độ sơ cấp

Các giao diện người dùng đồ họa (GUI) là tốt, nhưng để giải phóng sức mạnh thực sự của Linux, thì không có gì thay thế được dòng lệnh. Tìm hiểu về kỳ thi LPI® 101 và học về các luồng và các bộ lọc, quản lý tập tin và tiến trình, các biểu thức chính quy và trình soạn thảo vi. Trong hướng dẫn thứ ba này của loạt năm bài hướng dẫn, Ian Shields giới thiệu cho bạn về dòng lệnh Linux® và một số các lệnh GNU và UNIX. Đến cuối hướng dẫn này, bạn sẽ cảm thấy thoải mái sử dụng các lệnh trên một hệ thống Linux.

Ian Shields, Lập trình viên cao cấp, IBM

Ian Shields làm việc cho rất nhiều dự án Linux trên vùng Linux của developerWorks. Ông là một lập trình viên cao cấp của IBM tại Khu vực Tam giác nghiên cứu (Research Triangle Park - RTP), bang Bắc Carolina (NC). Ông đã đến với IBM ở Canberra, Úc, như là một kỹ sư hệ thống vào năm 1973, và từ đó đã làm việc về các hệ thống thông tin liên lạc và điện toán mọi nơi tại Montreal, Canada, và RTP, NC. Ông đã có một số bằng sáng chế và đã xuất bản một số bài báo. Ông tốt nghiệp đại học ngành toán học thuần tuý và triết học tại Đại học Quốc gia Úc. Ông có bằng thạc sĩ và tiến sĩ khoa học máy tính của Đại học Bắc Carolina.



20 08 2010

Trước khi bạn bắt đầu

Tìm hiểu xem các hướng dẫn có thể dạy cho bạn những gì và làm thế nào để bạn có thể tiếp thu được nhiều nhất từ các hướng dẫn đó.

Về loạt bài này

Viện Linux chuyên nghiệp (LPI-Linux Professional Institute) cấp chứng chỉ nhà quản trị hệ thống Linux ở hai trình độ: trình độ sơ cấp (còn gọi là "chứng chỉ cấp 1") và trình độ trung cấp (còn gọi là "chứng chỉ cấp 2"). Để đạt được chứng chỉ cấp 1, bạn phải vượt qua kỳ thi 101 và 102; để đạt được chứng chỉ cấp 2, bạn phải vượt qua kỳ thi 201 và 202.

developerWorks cung cấp các hướng dẫn để giúp bạn chuẩn bị cho từng kỳ thi trong bốn kỳ thi đó. Mỗi bài thi bao gồm một số chủ đề và mỗi chủ đề có một hướng dẫn tự học tương ứng trên developerWorks. Đối với kỳ thi LPI 101, có năm chủ đề và các hướng dẫn tương ứng trên developerWorks là:

Bảng 1. Kỳ thi LPI 101: Các hướng dẫn và các chủ đề
Chủ đề của kỳ thi LPI 101Hướng dẫn trên developerWorksTóm tắt hướng dẫn
Chủ đề 101Chuẩn bị cho kỳ thi LPI 101: (Chủ đề 101):
Phần cứng và kiến trúc.
Tìm hiểu cách cấu hình phần cứng hệ thống của bạn với Linux. Đến cuối hướng dẫn này, bạn sẽ biết cách Linux cấu hình phần cứng có trong một máy tính cá nhân (PC) hiện đại như thế nào và bạn sẽ phải xem xét ở đâu khi có trục trặc.
Chủ đề 102Chuẩn bị cho kỳ thi LPI 101:
Cài đặt Linux và quản lý gói.
Giới thiệu về cài đặt Linux và quản lý gói. Đến cuối hướng dẫn này, bạn sẽ biết cách Linux sử dụng các phân vùng đĩa, cách Linux khởi động và cách cài đặt và quản lý các gói phần mềm như thế nào.
Chủ đề 103Chuẩn bị cho kỳ thi LPI 101:
Các lệnh GNU và UNIX.
(Hướng dẫn này). Giới thiệu về các lệnh GNU và UNIX thường dùng. Đến cuối hướng dẫn này, bạn sẽ biết cách sử dụng các lệnh trong bash shell, bao gồm cách sử dụng các lệnh và các bộ lọc xử lý văn bản, cách tìm kiếm các tập tin và các thư mục và cách quản lý các tiến trình.
Chủ đề 104Chuẩn bị cho kỳ thi LPI 101:
Các thiết bị, các hệ thống tập tin Linux và tiêu chuẩn dạng cây của hệ thống tập tin.
Học cách tạo các hệ thống tập tin trên các phân vùng đĩa, cũng như cách cho phép người dùng truy cập chúng, quản lý quyền chủ sở hữu tập tin và các hạn ngạch của người dùng và sửa chữa các hệ thống tập tin khi cần thiết. Bạn cũng được học về liên kết cứng và liên kết biểu tượng và cách để xác định vị trí các tập tin trong hệ thống tập tin của bạn và nơi đặt các tập tin.
Chủ đề 110Chuẩn bị cho kỳ thi LPI 101:
Hệ thống Window X.
Tìm hiểu cách cài đặt và duy trì Hệ thống Window X, bao gồm cả việc cấu hình và cài đặt một máy chủ font X. Bạn cũng tìm hiểu cách thiết lập và tùy biến một trình quản lý hiển thị và tùy chỉnh một môi trường màn hình nền toàn hệ thống và trình quản lý cửa sổ, bao gồm cả các trình đơn quản lý cửa sổ và các trình đơn bàn điều khiển màn hình nền.

Để vượt qua kỳ thi 101 và 102 (và đạt được chứng chỉ cấp 1), bạn cần có khả năng:

  • Làm việc với các dòng lệnh Linux.
  • Thực hiện các nhiệm vụ bảo trì đơn giản: trợ giúp những người dùng, thêm những người dùng vào một hệ thống lớn hơn, sao lưu và phục hồi, tắt và khởi động lại.
  • Cài đặt và đặt cấu hình một máy trạm (bao gồm cả X) và kết nối nó với một mạng LAN hoặc kết nối một máy tính độc lập qua modem tới mạng Internet.

Để tiếp tục chuẩn bị cho chứng chỉ cấp 1, hãy xem hướng dẫn của developerWorks cho kỳ thi LPI 101. Đọc thêm trọn bộ các hướng dẫn LPI của developerWorks.

LPI không chứng thực bất kỳ tài liệu hay kỹ thuật luyện thi riêng biệt nào của một bên thứ ba. Để biết thêm chi tiết, xin vui lòng liên hệ với info@lpi.org.

Về hướng dẫn này

Chào mừng bạn đến với "Các lệnh GNU và UNIX", hướng dẫn thứ ba trong năm hướng dẫn được thiết kế để chuẩn bị cho bạn về kỳ thi LPI 101. Trong hướng dẫn này, bạn sẽ tìm hiểu về cách sử dụng các lệnh GNU và UNIX.

Hướng dẫn này được cấu tạo theo các mục tiêu của LPI đối với chủ đề này. Nói chung, hãy chờ đợi sẽ có nhiều câu hỏi hơn trong kỳ thi dành cho các mục tiêu có trọng số cao hơn.

Table 2. GNU and UNIX commands: ExaBảng 2. Các lệnh GNU và UNIX: Các mục tiêu của kỳ thi được trình bày trong hướng dẫn nàym objectives covered in this tutorial
Mục tiêu của kỳ thi LPITrọng số của mục tiêuTóm tắt mục tiêu
1.103.1
Làm việc trên dòng lệnh
Trọng số 5Tương tác với các trình shell và các lệnh bằng cách sử dụng dòng lệnh. Mục tiêu này bao gồm cách gõ các lệnh và các dãy lệnh hợp lệ, định nghĩa, tham khảo và xuất khẩu các biến môi trường, sử dụng lược sử lệnh và các phương tiện chỉnh sửa, gọi các lệnh trong đường dẫn và ngoài đường dẫn, sử dụng phép thay thế lệnh, áp dụng các lệnh đệ quy xuyên qua một cây thư mục và sử dụng hướng dẫn sử dụng để tìm hiểu về các lệnh.
1.103.2
Xử lý luồng văn bản bằng cách sử dụng các bộ lọc
Trọng số 6Áp dụng các bộ lọc cho các luồng văn bản. Mục tiêu này bao gồm việc gửi các tập tin văn bản và các luồng kết quả đầu ra qua các bộ lọc tiện ích văn bản để sửa đổi kết quả đầu ra, sử dụng các lệnh UNIX tiêu chuẩn có trong gói các công cụ tiện ích văn bản (textutil) của GNU.
1.103.3
Thực hiện quản lý tập tin cơ bản
Trọng số 3Sử dụng các lệnh UNIX cơ bản để sao chép, di chuyển và xóa các tập tin và thư mục. Nhiệm vụ bao gồm các hoạt động quản lý tập tin nâng cao như sao chép nhiều tập tin một cách đệ quy, gỡ bỏ các thư mục một cách đệ quy và di chuyển các tập tin đáp ứng một mẫu ký tự đại diện. Mục tiêu này bao gồm việc sử dụng các đặc tả ký tự đại diện đơn giản và nâng cao để tham chiếu các tập tin, cũng như sử dụng lệnh tìm kiếm để định vị và hành động trên tập tin dựa vào kiểu, độ lớn hoặc thời gian.
1.103.4
Sử dụng các luồng, các đường ống và các chuyển hướng
Trọng số 5Chuyển hướng các luồng và kết nối chúng để xử lý hiệu quả dữ liệu văn bản. Các nhiệm vụ bao gồm chuyển hướng đầu vào tiêu chuẩn, đầu ra tiêu chuẩn và báo báo lỗi tiêu chuẩn, đặt đường ống cho đầu ra của một lệnh thành đầu vào của lệnh khác, sử dụng đầu ra của một lệnh làm các đối số cho lệnh khác và gửi đầu ra tới cả luồng đầu ra tiêu chuẩn (stdout) lẫn một tập tin.
1.103.5
Tạo, theo dõi và tắt các tiến trình
Trọng số 5Quản lý các tiến trình. Mục tiêu này bao gồm hiểu biết cách chạy các công việc ở mặt trước và nền sau, đưa một công việc từ nền sau tới mặt trước và ngược lại, bắt đầu một tiến trình sẽ chạy mà không được kết nối tới một thiết bị đầu cuối và báo hiệu cho một chương trình tiếp tục chạy sau khi đăng xuất. Ngoài ra các nhiệm vụ còn bao gồm theo dõi tiến trình tích cực, lựa chọn và sắp xếp tiến trình để hiển thị, gửi các tín hiệu đến các tiến trình , tắt tiến trình và nhận biết và tắt các ứng dụng X còn chưa kết thúc sau khi phiên X đã đóng.
1.103.6
Sửa đổi các ưu tiên thực hiện tiến trình
Trọng số 3Quản lý các mức ưu tiên thực hiện tiến trình. Các nhiệm vụ bao gồm chạy một chương trình với mức ưu tiên cao hơn hoặc thấp hơn, xác định mức ưu tiên của một tiến trình và thay đổi mức ưu tiên của một tiến trình đang chạy.
1.103.7
Tìm kiếm các tập tin văn bản bằng cách sử dụng biểu thức chính quy
Trọng số 3Thao tác các tập tin và dữ liệu văn bản bằng cách sử dụng các biểu thức chính quy. Mục tiêu này bao gồm việc tạo ra các biểu thức chính quy đơn giản, có chứa một số phần tử ký hiệu. Ngoài ra nó còn bao gồm cách sử dụng các công cụ biểu thức chính quy để thực hiện các việc tìm kiếm qua nội dung của hệ thống tập tin hoặc tập tin.
1.103.8
Thực hiện các hoạt động chỉnh sửa tập tin cơ bản bằng cách sử dụng vi
Trọng số 1Chỉnh sửa các tập tin văn bản bằng cách sử dụng vi. Mục tiêu này bao gồm chuyển hướng vi, các nút vi cơ bản, chèn, chỉnh sửa, xóa, sao chép và tìm văn bản.

Điều kiện cần có trước

Để thu nhận được nhiều nhất từ hướng dẫn này, bạn cần phải có một kiến thức cơ bản về Linux và một hệ thống Linux đang hoạt động, trên hệ thống đó bạn có thể thực hành các lệnh được trình bày trong hướng dẫn này. Đôi khi các phiên bản khác nhau của một chương trình có thể định dạng kết quả đầu ra khác nhau, do đó kết quả của bạn có thể trông không chính xác như các liệt kê và các hình trong hướng dẫn này.


Sử dụng dòng lệnh

Phần này trình bày tư liệu cho chủ đề 1.103.1 cho kỳ thi quản trị trình độ sơ cấp (LPIC-1) 101. Chủ đề này có trọng số 5.

Trong phần này, bạn tìm hiểu về các chủ đề sau đây:

  • Tương tác với các shell và các lệnh bằng cách sử dụng dòng lệnh.
  • Sử dụng các lệnh và các dãy lệnh hợp lệ.
  • Định nghĩa, sửa đổi, tham khảo và xuất khẩu các biến môi trường.
  • Truy cập lược sử lệnh và các tiện ích chỉnh sửa.
  • Gọi các lệnh trong đường dẫn và ngoài đường dẫn.
  • Sử dụng phép thay thế lệnh.
  • Áp dụng đệ quy các lệnh xuyên qua một cây thư mục.
  • Sử dụng các trang hướng dẫn (man) để tìm hiểu về các lệnh.

Phần này cung cấp cho bạn một giới thiệu ngắn gọn về một số tính năng chính của bash shell, tập trung vào các tính năng quan trọng cho chứng chỉ. Nhưng shell là một môi trường rất phong phú và chúng tôi khuyến khích bạn tiếp tục khám phá nó. Nhiều cuốn sách tuyệt vời dành cho các trình shell UNIX và Linux và bash shell nói riêng.

bash shell

bash shell là một trong nhiều shell có sẵn cho Linux. Nó còn được gọi là shell dựa theo Bourne (Bourne-again shell), sau khi Stephen Bourne, người sáng tạo ra một shell trước đó (/bin/sh). Về cơ bản bash tương thích với sh, nhưng nó cung cấp nhiều cải tiến về cả chức năng lẫn khả năng lập trình. Nó kết hợp các tính năng từ Korn shell (ksh) và C shell (csh) và được dự kiến là một shell tuân thủ theo POSIX.

Trước khi chúng ta xoáy sâu hơn vào bash, hãy nhớ lại rằng một shell là một chương trình chấp nhận và thi hành các lệnh. Nó cũng hỗ trợ các cấu trúc lập trình, cho phép xây dựng các lệnh phức tạp từ các phần nhỏ hơn. Các lệnh phức tạp này, còn gọi là các kịch bản lệnh scripts (script), có thể được lưu như các tập tin để trở thành các lệnh mới, với tư cách riêng. Thật vậy, nhiều lệnh trên một hệ thống Linux điển hình thực sự các kịch bản lệnh.

Các shell có một số lệnh dựng sẵn, chẳng hạn như cd, break, and exec. Các lệnh khác là lệnh ngoài.

Các shell cũng sử dụng ba luồng (streams) vào/ra (I/O) tiêu chuẩn:

  • stdinluồng đầu vào tiêu chuẩn, cung cấp đầu vào cho các lệnh.
  • stdoutluồng đầu ra tiêu chuẩn, hiển thị đầu ra từ các lệnh.
  • stderrluồng lỗi tiêu chuẩn, hiển thị đầu ra lỗi từ các lệnh.

Các luồng đầu vào cung cấp đầu vào cho các chương trình, thường từ việc gõ phím trên bàn phím. Các luồng đầu ra in các ký tự văn bản, thường là tới một đầu cuối. Thiết bị đầu cuối ban đầu là một máy đánh chữ ASCII hoặc màn hình hiển thị, nhưng bây giờ nó thường là một cửa sổ trên màn hình nền đồ họa. Chi tiết hơn nữa về cách chuyển hướng các luồng I/O tiêu chuẩn này sẽ được trình bày trong phần sau của hướng dẫn này, phần Các luồng, các đường ống và các chuyển hướng. Phần còn lại của phần này tập trung vào việc chuyển hướng ở một mức cao.

Đối với phần còn lại của bài viết này, chúng tôi sẽ giả định bạn biết cách để có được một dấu nhắc shell. Nếu bạn chưa biết, bài viết "Các nhiệm vụ cơ bản cho các nhà phát triển Linux mới của developerWorks sẽ cho bạn biết cách thực hiện được điều này và nhiều hơn nữa.

Nếu bạn đang sử dụng một hệ thống Linux không có một màn hình nền đồ họa hoặc nếu bạn mở một cửa sổ đầu cuối trên một màn hình nền đồ họa, bạn sẽ được chào đón bằng một dấu nhắc, có lẽ giống như dấu nhắc được hiển thị trong Liệt kê 1.

Liệt kê 1. Một số dấu nhắc của người dùng điển hình
[db2inst1@echidna db2inst1]$ 
ian@lyrebird:~> 
$

Nếu bạn đăng nhập như là người dùng root (chủ) (hay siêu người dùng-superuser), dấu nhắc của bạn có thể trông giống như một dấu nhắc được hiển thị trong Liệt kê 2.

Liệt kê 2. Các ví dụ về dấu nhắc của người dùng root hay siêu người dùng
[root@echidna root]# 
lyrebird:~ # 
#

Người dùng root có quyền lực lớn, vì vậy hãy sử dụng nó cẩn thận. Khi bạn có các đặc quyền chủ, thì hầu hết các dấu nhắc có một dấu (#) ở đuôi. Các đặc quyền của người dùng bình thường luôn được mô tả bằng một kí tự khác, thường là một dấu đô la ($). Thực tế dấu nhắc của bạn có thể trông khác so với các ví dụ trong bài viết này. Dấu nhắc của bạn có thể bao gồm tên người dùng, tên máy chủ của bạn, thư mục hiện tại, ngày tháng hoặc thời gian dấu nhắc đó được in ra và v.v.

Các quy ước trong hướng dẫn này

Các hướng dẫn này của developerWorks cho các kỳ thi LPI 101 và 102 có các ví dụ mã được cắt và dán từ các hệ thống Linux thực bằng cách sử dụng các dấu nhắc mặc định cho các hệ thống đó. Dấu nhắc root của chúng tôi có một dấu # ở cuối, do đó bạn có thể phân biệt chúng với dấu nhắc của người dùng thông thường có dấu $ ở cuối. Quy ước này phù hợp với nhiều cuốn sách về đề tài này. Lưu ý cẩn thận với dấu nhắc trong bất kỳ các ví dụ nào.

Các lệnh và các dãy lệnh

Vậy là bây giờ bạn có một dấu nhắc, chúng ta hãy xem bạn có thể làm gì với nó. Chức năng chính của shell là để thông dịch các lệnh của bạn sao cho bạn có thể tương tác với hệ thống Linux của mình. Trên các hệ thống Linux (và UNIX), các lệnh có một tên lệnh và sau đó là các tùy chọncác tham số. Một số lệnh không có các tùy chọn và cũng không có các tham số và một số lệnh có các tùy chọn nhưng không có các tham số, trong khi những lệnh khác không có tùy chọn nào nhưng có các tham số.

Nếu một dòng chứa một ký tự #, thì tất cả các ký tự còn lại trên dòng đó được bỏ qua. Vì vậy, một ký tự # có thể biểu thị một nhận xét cũng như một dấu nhắc root. Nó là cái gì sẽ rõ ràng từ ngữ cảnh.

Lệnh echo

Lệnh echo in lại (hay dội trả lại) các đối số của nó ra đầu cuối như trong Liệt kê 3.

Liệt kê 3. Các ví dụ về lệnh echo
[ian@echidna ian]$ echo Word 
Word 
[ian@echidna ian]$ echo A phrase 
A phrase 
[ian@echidna ian]$ echo Where are my spaces? 
Where are my spaces? 
[ian@echidna ian]$ echo "Here are my spaces." # plus comment 
Here are my spaces.

Trong ví dụ thứ ba của Liệt kê 3, tất cả các khoảng trống thừa được nén thành một khoảng trống duy nhất ở đầu ra. Để tránh điều này, bạn cần phải đặt trong dấu nháy các chuỗi ký tự, bằng cách dấu nháy kép (") hoặc dấu nháy đơn ('). Bash sử dụng khoảng trống, ví dụ như ký tự để trống, dấu tab và ký tự xuống dòng mới, để tách dòng đầu vào của bạn thành các thẻ (token), rồi chuyển tới lệnh của bạn. Việc đặt các chuỗi ký tự trong cặp dấu nháy sẽ bảo tồn khoảng trống dư thừa và làm cho toàn bộ chuỗi ký tự thành một thẻ duy nhất. Trong ví dụ trên, mỗi thẻ sau tên lệnh là một tham số, do đó chúng ta lần lượt có các tham số 1, 2, 4 và 1.

Lệnh echo có một vài tùy chọn. Thông thường lệnh echo sẽ nối thêm một ký tự xuống dòng mới vào đuôi của kết quả đầu ra. Sử dụng tùy chọn -n để loại bỏ điều này. Sử dụng tùy chọn -e để cho phép một số ký tự nhất định được áp mã thoát là dấu gạch chéo ngược có ý nghĩa riêng đặc biệt. Một số trong các ký tự này được hiển thị trong Bảng 3.

Bảng 3. Các ký tự có mã thoát và lệnh echo
Dãy lệnh thoátChức năng
\aCảnh báo (chuông)
\bLùi một vị trí
\cLoại bỏ ký tự xuống dòng mới ở đuôi (cùng chức năng như tùy chọn -n)
\fIn ra và bắt đầu một trang mới (xóa màn hình trên màn hiển thị video)
\nDòng mới
\rXuống dòng
\tDấu tab ngang

Mã thoát và tiếp tục dòng

Có một vấn đề nhỏ nảy sinh ra khi sử dụng các dấu gạch chéo ngược trong bash. Khi ký tự dấu gạch chéo ngược (\) không đặt trong cặp dấu nháy, nó có tác dụng như một lệnh thoát để báo hiệu cho chính bash giữ nguyên ý nghĩa nguyên văn của ký tự tiếp theo. Điều này là cần thiết cho các siêu ký tự (metacharacter) của shell đặc biệt mà chúng ta sẽ trình bày ngay sau đây. Có một trường hợp ngoại lệ với quy tắc này: một dấu gạch chéo ngược tiếp theo là một dấu dòng mới làm cho bash nuốt cả hai ký tự và xử lý dãy như một yêu cầu tiếp tục dòng. Điều này rất tiện dụng để ngắt các dòng dài, đặc biệt là trong các kịch bản lệnh của shell.

Để cho các dãy mô tả trên được xử lý đúng bởi lệnh echo hay các lệnh khác có sử dụng các ký tự điều khiển với mã thoát tương tự, bạn phải đưa dãy mã thoát vào trong cặp dấu nháy hoặc là một phần của một chuỗi ký tự được đặt trong cặp dấu nháy, trừ khi bạn sử dụng một dấu gạch chéo ngược thứ hai để buộc shell giữ nguyên nó dành cho lệnh xử lý. Liệt kê 4 cho thấy một số ví dụ về cách sử dụng khác nhau của dấu \.

Liệt kê 4. Thêm các ví dụ về lệnh echo
[ian@echidna ian]$ echo -n No new line 
No new line
[ian@echidna ian]$ echo -e "No new line\c" 
No new line
[ian@echidna ian]$ echo "A line with a typed > return" 
A line with a typed return 
[ian@echidna ian]$ echo -e "A line with an escaped\nreturn" 
A line with an escaped return 
[ian@echidna ian]$ echo "A line with an escaped\nreturn but no -e option" 
A line with an escaped\nreturn but no -e option 
[ian@echidna ian]$ echo -e Doubly escaped\\n\\tmetacharacters 
Doubly escaped metacharacters 
[ian@echidna ian]$ echo Backslash \ 
> followed by newline \ 
> serves as line continuation. 
Backslash followed by newline serves as line continuation.

Lưu ý rằng bash hiển thị một dấu nhắc đặc biệt (>) khi bạn gõ một dòng với các dấu nháy không khớp. Chuỗi đầu vào của bạn tiếp tục ở trên dòng thứ hai và bao gồm ký tự dòng mới.

Các siêu ký tự bash shell và các toán tử điều khiển

Bash có một vài siêu ký tự (metacharacter), khi không được đặt trong dấu nháy, siêu ký tự này cũng dùng để chia đầu vào thành các từ. Ngoài khoảng trống, chúng là '|', '&', ';', '(', ')', '<' và '>'. Chúng ta sẽ thảo luận một số trong các siêu ký tự này chi tiết hơn trong các phần khác của hướng dẫn này. Bây giờ, lưu ý rằng nếu bạn muốn có một siêu ký tự như là một phần văn bản của bạn, nó phải được đặt trong dấu nháy hoặc có đặt mã thoát bằng cách sử dụng một dấu gạch chéo ngược (\) như trong Liệt kê 4.

Dấu dòng mới và một số siêu ký tự hoặc cặp siêu ký tự nhất định cũng dùng như là các toán tử điều khiển. Đó là '||', '&&', '&', ';', ';;', '|'' '(', và ')'. Một số các toán tử điều khiển này cho phép bạn tạo các dãy lệnh hoặc các danh sách của các lệnh.

Dãy lệnh đơn giản nhất chỉ là hai lệnh được phân cách nhau bằng dấu chấm phẩy (;). Mỗi lệnh được thi hành theo thứ tự. Trong bất kỳ môi trường lập trình nào, các lệnh trả về một chỉ báo thành công hay thất bại; các lệnh Linux thường trả về một giá trị bằng không khi thành công và một giá trị khác không cho trường hợp thất bại. Bạn có thể đưa vào thêm một số xử lý có điều kiện trong danh sách của bạn bằng cách sử dụng các toán tử điều khiển && và ||. Nếu bạn tách hai lệnh bằng toán tử điều khiển && thì lệnh thứ hai được thực hiện khi và chỉ khi lệnh thứ nhất trả về mã kết thúc (exit) bằng không. Nếu bạn tách các lệnh bằng ||, thì lệnh thứ hai được thực hiện chỉ khi lệnh thứ nhất trả về một mã kết thúc khác không. Liệt kê 5 cho thấy một số dãy lệnh khi sử dụng lệnh echo. Các dãy này chưa thực sự thú vị do lệnh echo trả về 0, nhưng bạn sẽ thấy nhiều ví dụ sau này, khi chúng ta có thêm vài lệnh để sử dụng.

Liệt kê 5. Các dãy lệnh
[ian@echidna ian]$ echo line 1;echo line 2; echo line 3 
line 1 
line 2 
line 3 
[ian@echidna ian]$ echo line 1&&echo line 2&&echo line 3 
line 1 
line 2 
line 3 
[ian@echidna ian]$ echo line 1||echo line 2; echo line 3 
line 1 
line 3

Lệnh exit

Bạn có thể kết thúc một shell bằng cách sử dụng lệnh exit (thoát ra). Bạn có thể tùy ý đưa ra một mã exit như là một tham số. Nếu bạn đang chạy shell của mình trong một cửa sổ đầu cuối trên một màn hình nền đồ họa, cửa sổ của bạn sẽ đóng. Tương tự như vậy, nếu bạn đã kết nối tới một hệ thống từ xa bằng cách sử dụng ssh hoặc telnet (ví dụ thế), kết nối của bạn sẽ chấm dứt. Trong bash shell, bạn cũng có thể giữ phím Ctrl và nhấn phím d để thoát ra.

Hãy xem một toán tử điều khiển khác. Nếu bạn bao bọc một lệnh hoặc một danh sách lệnh trong các dấu ngoặc đơn, thì lệnh hay trình tự đó được thực thi trong shell con, để cho lệnh exit thoát ra khỏi shell con chứ không phải thoát khỏi shell bạn đang làm việc với nó. Liệt kê 6 cho thấy một ví dụ đơn giản liên quan đến && và ||.

Liệt kê 6. Các shell con và các trình tự
[ian@echidna ian]$ (echo In subshell; exit 0) && echo OK || echo Bad exit 
In subshell 
OK 
[ian@echidna ian]$ (echo In subshell; exit 4) && echo OK || echo Bad exit 
In subshell Bad 
exit

Hãy tiếp tục để biết nhiều dãy lệnh hơn nữa ở phần sau trong bài viết này.

Các biến môi trường

Khi bạn đang chạy trong một bash shell, có nhiều thứ tạo nên môi trường của bạn, chẳng hạn như hình dạng của dấu nhắc của bạn, thư mục nhà của bạn, thư mục làm việc của bạn, tên của shell của bạn, các tập tin bạn đã mở, các chức năng mà bạn đã xác định và v.v. Môi trường của bạn bao gồm nhiều biến. Các biến này có thể do bash hay do bạn thiết lập. Bash shell cũng cho phép bạn có các biến shell và bạn có thể xuất khẩu các biến đó sang môi trường của bạn để cho các tiến trình khác đang chạy trong shell sử dụng hoặc cho các shell khác do bạn có thể tạo ra từ shell hiện hành sử dụng.

Cả các biến môi trường lẫn các biến shell có một tên. Bạn tham khảo giá trị của một biến bằng cách thêm dấu '$' vào trước tên của nó. Bạn sẽ bắt gặp một số trong các biến môi trường bash chung được chỉ ra trong Bảng 4.

Bảng 4. Một số biến môi trường bash chung
TênChức năng
USERTên của người dùng đã đăng nhập.
UIDSố nhận dạng người dùng của người dùng đã đăng nhập.
HOMEThư mục nhà của người dùng.
PWDThư mục làm việc hiện tại.
SHELLTên của shell.
$Số nhận dạng tiến trình (hay PID của tiến trình bash shell (hoặc tiến trình khác) đang chạy.
PPIDSố nhận dạng tiến trình của tiến trình đã bắt đầu tiến trình này (tức là, số nhận dạng của tiến trình cha mẹ).
?Mã exit của lệnh cuối cùng.

Liệt kê 7 hiển thị bạn có thể thấy những gì trong một số biến bash chung này.

Liệt kê 7. Môi trường và các biến shell
[ian@echidna ian]$ echo $USER $UID 
ian 500
[ian@echidna ian]$ echo $SHELL $HOME $PWD 
/bin/bash /home/ian/home/ian 
[ian@echidna ian]$ (exit 0);echo $?;(exit 4);echo $? 
0 
4
[ian@echidna ian]$ echo $$ $PPID 
30576 30575

Không sử dụng bash?

Bash shell là shell mặc định trong hầu hết các bản phân phối Linux. Nếu bạn không chạy trong bash shell, bạn có thể muốn xem xét một trong những cách sau đây để thực hành với bash shell.

  • Sử dụng
    chsh -s /bin/bash
    lệnh để thay đổi shell mặc định của bạn. Shell mặc định này sẽ có hiệu lực trong lần tới khi bạn đăng nhập.
  • Sử dụng
    su - $USER -s /bin/bash
    lệnh để tạo ra một tiến trình khác như một shell con trong shell hiện tại của bạn. Tiến trình mới sẽ là một shell đăng nhập, sử dụng bash.
  • Tạo một mã nhận dạng (id) với mặc định là của một bash shell để sử dụng cho việc chuẩn bị kỳ thi LPI.

Bạn có thể tạo hoặc thiết lập một biến shell bằng cách gõ tên, ngay sau đó là một dấu bằng (=). một biến shell bằng cách gõ tên, ngay sau đó là một dấu bằng (=). Các biến có phân biệt dạng chữ hoa chữ thường, do đó var1 và VAR1 là các biến khác nhau. Theo quy ước, các biến, đặc biệt là các biến xuất khẩu, là biến chữ hoa, nhưng đây không phải là một yêu cầu bắt buộc. Về mặt kỹ thuật, $$ và $? là các tham số shell hơn là các biến. Chúng chỉ có thể được tham chiếu; bạn không thể gán một giá trị cho chúng.

Khi bạn tạo một biến shell, bạn thường sẽ muốn xuất khẩu nó đến môi trường để cho nó sẽ sẵn dùng cho các tiến trình khác mà bạn khởi đầu các tiến trình ấy từ shell này. Các biến mà bạn xuất khẩu không sẵn dùng đối với một shell cha mẹ. Bạn sử dụng lệnh export (xuất khẩu) để xuất khẩu một tên biến. Như một phím tắt trong bash, bạn có thể gán một giá trị và xuất khẩu một biến trong một bước.

Để minh họa việc gán và xuất khẩu, chúng ta hãy chạy lệnh bash khi ở trong bash shell và sau đó chạy Korn shell (ksh) từ bash shell mới. Chúng ta sẽ sử dụng lệnh ps để hiển thị thông tin về lệnh đang chạy. Chúng ta sẽ tìm hiểu thêm về ps khi chúng ta tìm hiểu về phần trạng thái tiến trình sau trong loạt bài này.

Liệt kê 8. Thêm các biến môi trường và các biến shell
[ian@echidna ian]$ ps -p $$ -o "pid ppid cmd" 
  PID PPID CMD 
30576 30575 -bash 
[ian@echidna ian]$ bash
[ian@echidna ian]$ ps -p $$ -o "pid ppid cmd" 
  PID PPID CMD 16353 30576 bash 
[ian@echidna ian]$ VAR1=var1 
[ian@echidna ian]$ VAR2=var2
[ian@echidna ian]$ export VAR2 
[ian@echidna ian]$ export VAR3=var3
[ian@echidna ian]$ echo $VAR1 $VAR2 $VAR3 
var1 var2 var3 
[ian@echidna ian]$ echo $VAR1 $VAR2 $VAR3 $SHELL 
var1 var2 var3 /bin/bash
[ian@echidna ian]$ ksh 
$ ps -p $$ -o "pid ppid cmd" 
  PID PPID CMD 
16448 16353 ksh 
$ export VAR4=var4 
$ echo $VAR1 $VAR2 $VAR3 $VAR4 $SHELL
var2 var3 var4 /bin/bash 
$ exit 
$ [ian@echidna ian]$ echo $VAR1 $VAR2 $VAR3 $VAR4 $SHELL 
var1 var2 var3 /bin/bash 
[ian@echidna ian]$ ps -p $$ -o "pid ppid cmd" 
  PID PPID CMD 
16353 30576 bash 
[ian@echidna ian]$ exit 
[ian@echidna ian]$ ps -p $$ -o "pid ppid cmd" 
  PID PPID CMD 
30576 30575 -bash 
[ian@echidna ian]$ echo $VAR1 $VAR2 $VAR3 $VAR4 $SHELL 
/bin/bash

Lưu ý:

  1. Khi bắt đầu dãy lệnh này, bash shell có PID 30576.
  2. Bash shell thứ hai có PID 16353 và shell cha mẹ của nó là PID 30576, đó là bash shell ban đầu.
  3. Chúng ta tạo ra các biến VAR1, VAR2 và VAR3 trong bash shell thứ hai, nhưng chỉ xuất khẩu biến VAR2 và VAR3.
  4. Trong Korn shell, chúng ta tạo ra biến VAR4. Lệnh echo chỉ hiển thị các giá trị cho biến VAR2, VAR3 và VAR4, điều này xác nhận rằng biến VAR1 đã không được xuất khẩu. Bạn có ngạc nhiên không khi thấy rằng giá trị của biến SHELL đã không thay đổi, mặc dù dấu nhắc đã thay đổi? Bạn không thể luôn dựa vào biến SHELL để cho bạn biết bạn đang chạy trong shell nào, nhưng lệnh ps sẽ nói cho bạn biết lệnh hiện tại. Lưu ý rằng ps đặt một dấu nối (-) ở phía trước của bash shell đầu tiên để báo hiệu rằng đây là shell đăng nhập.
  5. Quay lại bash shell thứ hai, chúng ta có thể nhìn thấy các biến VAR1, VAR2 và VAR3.
  6. Và cuối cùng, khi chúng ta quay trở lại shell ban đầu, không có biến nào trong số các biến mới của chúng ta còn tồn tại.

Các cuộc thảo luận trước đó về việc đặt các dấu nháy nói rằng bạn có thể sử dụng hoặc dấu nháy đơn hoặc dấu nháy kép. Có một sự khác biệt quan trọng giữa chúng. Shell chỉ khai triển các biến shell nằm giữa các dấu nháy kép ($quot;), nó không khai triển nếu sử dụng dấu nháy đơn ('). Trong ví dụ trước, chúng ta bắt đầu một shell khác bên trong shell của chúng ta và chúng ta đã nhận được một mã nhận dạng tiến trình mới. Khi sử dụng tùy chọn -c, bạn có thể chuyển một lệnh tới shell khác để nó thực hiện lệnh và trả về. Nếu bạn chuyển một chuỗi ký tự đặt trong dấu nháy như là một lệnh, shell bên ngoài của bạn sẽ loại bỏ các dấu nháy và chuyển tiếp chuỗi ký tự đi. Nếu dấu nháy kép được sử dụng, các biến được khai triển trước khi chuỗi ký tự được chuyển đi, nên kết quả có thể không được như bạn mong đợi. Shell và lệnh sẽ chạy trong tiến trình khác nên chúng sẽ có một mã nhận dạng tiến trình (PID) khác. Liệt kê 9 minh họa các khái niệm này. PID của bash shell cấp cao nhất được tô đậm.

Liệt kê 9. Đặt dấu nháy và các biến shell
[ian@echidna ian]$ echo "$SHELL" '$SHELL' "$$" '$$' 
/bin/bash $SHELL 19244 $$ 
[ian@echidna ian]$ bash -c "echo Expand in parent $$ $PPID" 
Expand in parent 19244 19243
[ian@echidna ian]$ bash -c 'echo Expand in child $$ $PPID' 
Expand in child 19297 19244

Cho đến nay, mọi tham khảo biến của chúng ta đã kết thúc bằng khoảng trống, vì thế tên biến kết thúc ở đâu là rõ ràng. Thực vậy, các tên biến chỉ gồm các chữ cái, chữ số hoặc ký tự gạch dưới. Shell biết rằng một tên biến kết thúc ở nơi tìm thấy ký tự khác. Đôi khi bạn cần sử dụng các biến trong các biểu thức mà ở đó ý nghĩa có thể mập mờ. Trong trường hợp này, bạn có thể sử dụng các dấu ngoặc ôm ({}) để phân định tên biến như trong Liệt kê 10.

Liệt kê 10. Sử dụng dấu ngoặc ôm với các tên biến
[ian@echidna ian]$ echo "-$HOME/abc-" 
-/home/ian/abc- 
[ian@echidna ian]$ echo "-$HOME_abc-" 
-- 
[ian@echidna ian]$ echo "-${HOME}_abc-" 
-/home/ian_abc-

Lệnh Env

Lệnh env không có bất kỳ tuỳ chọn hoặc các tham số nào sẽ hiển thị các biến môi trường hiện tại. Bạn cũng có thể sử dụng nó để thực thi một lệnh trong một môi trường tùy chỉnh. Tùy chọn -i (hoặc chỉ cần -) xóa môi trường hiện tại trước khi chạy lệnh, trong khi tùy chọn -u bỏ thiết lập biến môi trường mà bạn không muốn chuyển đi.

Liệt kê 11 cho thấy một phần kết quả đầu ra của lệnh env không có bất kỳ tham số nào và sau đó là ba ví dụ về cách gọi các shell khác nhau không có môi trường cha mẹ. Hãy xem xét cẩn thận những điều này trước khi chúng ta thảo luận về chúng.

Liệt kê 11. Lệnh env
[ian@echidna ian]$ env 
HOSTNAME=echidna 
TERM=xterm 
SHELL=/bin/bash
HISTSIZE=1000 
SSH_CLIENT=9.27.89.137 4339 22 
SSH_TTY=/dev/pts/2
USER=ian 
... 
_=/bin/env OLDPWD=/usr/src 
[ian@echidna ian]$ env -i bash -c 'echo $SHELL; env' 
/bin/bash 
PWD=/home/ian 
SHLVL=1 _=/bin/env
[ian@echidna ian]$ env -i ksh -c 'echo $SHELL; env' 
_=/bin/env
PATH=/bin:/usr/bin 
[ian@echidna ian]$ env -i tcsh -c 'echo $SHELL; env' 
SHELL: Undefined variable.

Nhận thấy rằng bash đã đặt biến SHELL, nhưng không xuất khẩu nó đến môi trường, mặc dù có ba biến khác do bash đã tạo ra trong môi trường đó. Trong ví dụ ksh, chúng ta có hai biến môi trường, nhưng sự nỗ lực của chúng ta để nhận lại giá trị của biến SHELL chỉ cho một dòng trống. Cuối cùng, tcsh đã không tạo ra bất kỳ biến môi trường nào và đưa ra một lỗi khi ta cố gắng tham khảo giá trị của SHELL.

Bỏ thiết lập và thiết lập

Liệt kê 11 cho thấy hành vi khác nhau trong cách các shell xử lý các biến và các môi trường. Trong khi bài viết này tập trung vào bash, nên biết rằng không phải tất cả shell hành xử theo cùng một cách giống nhau. Hơn nữa, các shell hành xử theo một cách khác nhau tùy theo chúng có là một shell đăng nhập hay không. Bây giờ, chúng ta sẽ chỉ có thể nói rằng một shell đăng nhập là shell mà bạn nhận được khi bạn đăng nhập vào hệ thống; bạn có thể bắt đầu các shell khác để vận hành như shell đăng nhập nếu bạn muốn. Ba shell bắt đầu ở trên bằng cách sử dụng env -i không phải là các shell đăng nhập. Hãy thử thêm tùy chọn -l vào chính lệnh shell để thấy những sự khác nhau mà bạn sẽ nhận được với một shell đăng nhập.

Vì vậy, chúng ta hãy xem xét nỗ lực của chúng ta để hiển thị giá trị của biến SHELL trong các shell không đăng nhập:

  1. Khi bash bắt đầu, nó thiết lập biến SHELL, nhưng nó đã không tự động xuất khẩu biến này tới môi trường.
  2. Khi ksh bắt đầu, nó đã không thiết lập biến SHELL. Tuy nhiên, việc tham khảo một biến môi trường chưa được định nghĩa là tương đương với việc tham khảo một biến có một giá trị rỗng.
  3. Khi tcsh bắt đầu, nó đã không thiết lập biến SHELL. Trong trường hợp này, hành vi mặc định khác với ksh (và bash) ở chỗ là có thông báo một lỗi khi chúng ta cố gắng sử dụng một biến.

Bạn có thể sử dụng lệnh unset để bỏ thiết lập một biến và loại nó khỏi danh sách biến shell. Nếu biến đó đã được xuất khẩu đến môi trường, lệnh này cũng sẽ loại bỏ biến đó khỏi môi trường. Bạn có thể sử dụng lệnh set để kiểm soát nhiều khía cạnh về cách làm việc của bash (hoặc các shell khác). Lệnh set là một lệnh shell dựng sẵn, do đó các tùy chọn khác nhau là đặc thù riêng của shell. Trong bash, tùy chọn -u làm cho bash thông báo một lỗi với các biến chưa được định nghĩa chứ không xử lý chúng như là các biến đã định nghĩa nhưng rỗng. Bạn có thể bật các tùy chọn khác nhau của lệnh set bằng một dấu - và tắt chúng bằng một dấu +. Bạn có thể hiển thị tùy chọn set hiện tại bằng cách sử dụng lệnh echo $-.

Liệt kê 12. Bỏ thiết lập và thiết lập
[ian@echidna ian]$ echo $- 
himBH 
[ian@echidna ian]$ echo $VAR1 
[ian@echidna ian]$ set -u;echo $- 
himuBH 
[ian@echidna ian]$ echo $VAR1 
bash: VAR1: unbound variable 
[ian@echidna ian]$ VAR1=v1 
[ian@echidna ian]$ VAR1=v1;echo $VAR1 
v1 
[ian@echidna ian]$ unset VAR1;echo $VAR1 
bash: VAR1: unbound variable 
[ian@echidna ian]$ set +u;echo $VAR1;echo $- 
himBH

Nếu bạn sử dụng lệnh set không có bất cứ tùy chọn nào, thì lệnh này sẽ hiển thị tất cả các biến shell của bạn và các giá trị của chúng (nếu có). Ngoài ra còn có lệnh khác, declare (khai báo), mà bạn có thể sử dụng lệnh đó để tạo, xuất khẩu và hiển thị các giá trị của các biến shell. Bạn có thể khảo sát tỉ mỉ nhiều tùy chọn set còn lại và lệnh declare bằng cách sử dụng các trang hướng dẫn sử dụng (man pages). Chúng ta sẽ thảo luận về các trang hướng dẫn sử dụng sau trong bài viết này.

Lệnh Exec

Một lệnh cuối cùng được trình bày là exec. Bạn có thể sử dụng lệnh exec để chạy một chương trình khác thay thế shell hiện hành. Liệt kê 13 bắt đầu một bash shell con và sau đó sử dụng lệnh exec để thay thế nó bằng một Korn shell. Khi thoát khỏi Korn shell, bạn quay trở lại ở bash shell ban đầu (trong ví dụ này là PID 22985).

Liệt kê 13. Sử dụng lệnh exec
[ian@echidna ian]$ echo $$ 
22985 
[ian@echidna ian]$ bash 
[ian@echidna ian]$ echo $$ 
25063 
[ian@echidna ian]$ exec ksh 
$ echo $$ 
25063 
$ exit 
[ian@echidna ian]$ echo $$ 
22985

Lược sử lệnh

Nếu bạn đang gõ vào các lệnh như bạn đọc, bạn có thể nhận thấy rằng bạn thường sử dụng một lệnh nhiều lần hoặc giống hệt nhau hoặc với những thay đổi nhỏ. Một tin tốt là bash shell có thể duy trì một lược sử của các lệnh của bạn. Theo mặc định, lược sử luôn được bật lên. Bạn có thể tắt nó đi bằng cách sử dụng lệnh set +o history và bật lên lại bằng cách sử dụng lệnh set -o history. Một biến môi trường được gọi là HISTSIZE báo cho bash biết có thể lưu giữ bao nhiêu dòng lược sử. Một số các thiết lập khác điều khiển cách lược sử hoạt động và được quản lý như thế nào. Xem các trang hướng dẫn sử dụng bash để biết các chi tiết đầy đủ.

Một số các lệnh giúp bạn có thể sử dụng chức năng lược sử là:

history (lược sử)
Hiển thị toàn bộ lược sử.
history N
Hiển thị N dòng lược sử gần nhất của bạn.
history -d N
Xóa dòng thứ N của lược sử của bạn; bạn có thể làm điều này nếu dòng đó có chứa một mật khẩu, ví dụ
!!
Lệnh gần đây nhất của bạn.
!N
Lệnh thứ Ntrong lược sử.
!-N
Lùi lại N lệnh trong lược sử (!-1 tương đương với !!).
!#
Lệnh hiện tại bạn đang gõ.
!string
Lệnh gần đây nhất bắt đầu với chuỗi ký tự (string).
!?string?
Lệnh gần đây nhất có chứa chuỗi ký tự.

Bạn cũng có thể sử dụng một dấu hai chấm (:) tiếp theo là một giá trị nhất định để truy cập hoặc sửa đổi một phần hoặc một lệnh từ lược sử của bạn. Liệt kê 16 minh họa một số tính năng lược sử.

Liệt kê 14. Thao tác lược sử lệnh
[ian@echidna ian]$ echo $$ 
22985
[ian@echidna ian]$ env -i bash -c 'echo $$' 
1542 
[ian@echidna ian]$ !! 
env -i bash -c 'echo $$' 
1555 
[ian@echidna ian]$ !ec 
echo $$ 22985 
[ian@echidna ian]$ !en:s/$$/$PPID/ 
env -i bash -c 'echo $PPID' 
22985
[ian@echidna ian]$ history 6 
1097 echo $$ 
1098 env -i bash -c 'echo $$' 
1099 env -i bash -c 'echo $$' 
1100 echo $$ 
1101 env -i bash -c 'echo $PPID' 
1102 history 6 
[ian@echidna ian]$ history -d1100

Các lệnh trong Liệt kê 16 làm những việc sau:

  1. Dội trả lại mã nhận dạng tiến trình PID của shell hiện tại.
  2. Chạy một lệnh echo trong shell mới và dội trả lại PID của shell đó.
  3. Chạy lại lệnh gần nhất vừa qua.
  4. Chạy lại lệnh gần nhất bắt đầu bằng 'ec'; Ở đây sẽ chạy lại lệnh đầu tiên trong ví dụ này.
  5. Chạy lại lệnh gần nhất bắt đầu bằng 'en', nhưng thay thế '$PPID' vào chỗ '$$', sao cho PID cha mẹ được hiển thị thay thế.
  6. Hiển thị 6 lệnh gần nhất vừa qua của lược sử.
  7. Xoá mục 1100 của lược sử, đó là lệnh echo gần nhất.

Bạn cũng có thể chỉnh sửa lược sử một cách tương tác. Bash shell sử dụng thư viện readline để quản lý việc chỉnh sửa lệnh và lược sử. Theo mặc định, các phím và tổ hợp phím được sử dụng để di chuyển qua lược sử hoặc chỉnh sửa các dòng tương tự như nhưng phím và tổ hợp phím được sử dụng trong trình soạn thảo GNU Emacs. Các tổ hợp gõ phím Emacs thường được thể hiện như là C-x hoặc M-x, trong đó x là một phím thông thường , còn CM là phím Control và phím Meta, tương ứng. Trên hệ thống máy tính cá nhân (PC) điển hình, phím Ctrl dùng như phím Control cho Emacs và phím Alt dùng như phím Meta. Bảng 3 tóm tắt một số chức năng chỉnh sửa lược sử sẵn có. Ngoài các tổ hợp phím được hiển thị trong Bảng 3, các phím dịch chuyển con chạy như các phím mũi tên phải, trái, lên, xuống và phím Home và End thường được thiết lập để hoạt động một cách hợp lý. Các chức năng bổ sung cũng như cách làm thế nào để tùy chỉnh các tùy chọn này bằng cách sử dụng một tập tin khởi tạo readline (thường là inputrc trong thư mục nhà của bạn) có thể được tìm thấy trong các trang hướng dẫn sử dụng.

Bảng 5. Chỉnh sửa lược sử bằng các lệnh emacs
LệnhPhím PC thường dùngMô tả
C-fRight arrowDi chuyển sang phải một khoảng trống.
C-bLeft arrowDi chuyển sang trái một khoảng trống.
M-fAlt-fDi chuyển đến đầu từ tiếp theo; các môi trường GUI thường nhận tổ hợp phím này để mở trình đơn File của cửa sổ đó.
M-bAlt-bDi chuyển đến đầu của từ trước đó.
C-aHomeDi chuyển tới đầu dòng.
C-eEndDi chuyển tới cuối dòng.
BackspaceBackspaceXóa ký tự trước con trỏ.
C-dDelXóa ký tự trong con trỏ (các chức năng Del và Backspace có thể được đặt cấu hình theo nghĩa ngược lại).
C-kCtrl-kXóa (loại bỏ) tới cuối dòng và lưu lại văn bản đã bị xóa để sử dụng sau này.
M-dAlt-dXóa (loại bỏ) tới cuối từ và lưu lại văn bản đã bị xóa để sử dụng sau này.
C-yCtrl-yLấy lại văn bản đã loại bỏ bằng một lệnh xóa nói trên.

Nếu bạn muốn thao tác lược sử bằng cách sử dụng một chế độ chỉnh sửa giống như -vi, thì bạn sử dụng lệnh set -o vi để chuyển sang chế độ vi. Sử dụng lệnh set -o emacs. để chuyển về chế độ emacs. Khi bạn gọi một lệnh trong chế độ vi, ban đầu bạn đang ở chế độ chèn của vi. Nhiều chi tiết hơn về trình soạn thảo vi có trong phần Chỉnh sửa tập tin bằng vi.

Các đường dẫn

Một số lệnh bash được dựng sẵn, trong khi các lệnh khác ở bên ngoài. Bây giờ chúng ta hãy xem các lệnh bên ngoài và cách để chạy chúng và cách để biết một lệnh có là lệnh bên trong không.

Shell tìm thấy các lệnh ở đâu?

Các lệnh ngoài chỉ là các tập tin trong hệ thống tập tin của bạn. Phần Quản lý tập tin cơ bản sau đây trong hướng dẫn này và hướng dẫn cho Chủ đề 104 sẽ trình bày chi tiết hơn. Trên các hệ thống Linux và UNIX, tất cả các tập tin được truy cập như một phần của một cây lớn duy nhất có gốc ở /. Trong ví dụ của chúng ta, cho đến nay, thư mục hiện tại của chúng ta đã là thư mục nhà của người dùng. Những người dùng không phải là root thường có một thư mục nhà trong thư mục /home, ví dụ như /home/ian, trong trường hợp của tôi. Thư mục nhà của root luôn là /root. Nếu bạn gõ một tên lệnh, thì bash sẽ tìm lệnh này trên đường dẫn của bạn, đó là một danh sách các thư mục được phân tách bằng dấu hai chấm trong biến môi trường PATH.

Nếu bạn muốn biết lệnh nào sẽ được thực hiện khi bạn gõ một chuỗi ký tự cụ thể, hãy sử dụng lệnh which hay type. Liệt kê 15 hiển thị đường dẫn mặc định của tôi cùng với các vị trí của một số lệnh.

Liệt kê 15. Tìm các vị trí lệnh
[ian@echidna ian]$ echo $PATH
/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/home/ian/bin 
[ian@echidna ian]$ which bash env zip xclock echo set ls 
alias ls='ls --color=tty'
         /bin/ls 
/bin/bash 
/bin/env 
/usr/bin/zip 
/usr/X11R6/bin/xclock
/bin/echo 
/usr/bin/which: no set in (/usr/local/bin:/bin:/usr/bin:/usr/X11R6/b 
in:/home/ian/bin)
[ian@echidna ian]$ type bash env zip xclock echo set ls 
bash is /bin/bash 
env is /bin/env 
zip is /usr/bin/zip 
xclock is /usr/X11R6/bin/xclock 
echo is a shell builtin 
set is a shell builtin
ls is aliased to `ls --color=tty'

Lưu ý rằng các thư mục trong đường dẫn chủ yếu kết thúc ở /bin. Đây là một quy ước chung, nhưng không phải là một yêu cầu. Lệnh which đã thông báo rằng lệnh ls là một alias (bí danh) và không thể tìm thấy lệnh set. Trong trường hợp này, chúng ta diễn giải điều đó có nghĩa là lệnh không tồn tại hay đó là một lệnh dựng sẵn. Lệnh type thông báo rằng lệnh ls là một alias, nhưng nó xác nhận lệnh set như là một lệnh shell dựng sẵn. Nó cũng thông báo rằng có một lệnh echo dựng sẵn cũng như một lệnh trong /bin được which đã tìm thấy. Hai lệnh cũng tạo ra kết quả đầu ra theo các thứ tự khác nhau.

Chúng ta thấy rằng lệnh ls được sử dụng để liệt kê các nội dung thư mục, là một alias (bí danh). Các bí danh là một cách tiện dụng để cấu hình một số lệnh để sử dụng các tập hợp mặc định khác nhau hoặc để cung cấp một tên thay thế cho một lệnh. Trong ví dụ của chúng ta, tùy chọn --color=tty làm cho danh sách liệt kê thư mục phân biệt kiểu tập tin hoặc thư mục theo các màu sắc khác nhau. Hãy thử chạy dircolors --print-database để xem các mã màu được kiểm soát như thế nào và màu nào được sử dụng cho loại tập tin nào.

Mỗi một trong số các lệnh này có các tùy chọn bổ sung. Tùy thuộc vào nhu cầu của bạn, bạn có thể sử dụng cả hai lệnh. Tôi có xu hướng sử dụng lệnh which khi tôi khá chắc chắn tôi sẽ tìm thấy một tập tin thi hành được và tôi chỉ cần đặc tả đường dẫn đầy đủ của nó. Tôi thấy rằng lệnh type cho tôi biết thêm nhiều thông tin chính xác, mà đôi khi tôi cần trong một kịch bản lệnh shell.

Chạy các lệnh khác

Chúng ta đã thấy trong Liệt kê 15 rằng các tập tin có thể thi hành được có một đường dẫn đầy đủ bắt đầu bằng /, tức là thư mục gốc. Ví dụ, chương trình xclock thực sự là /usr/bin/xclock, một tập tin nằm trong thư mục /usr/bin. Nếu một lệnh không có trong đặc tả PATH (đường dẫn) của bạn, bạn vẫn có thể chạy nó bằng cách chỉ rõ đường dẫn cùng với tên lệnh. Bạn có thể sử dụng hai loại đường dẫn:

  • Các đường dẫn tuyệt đối (absolute) là những đường dẫn bắt đầu bằng /, như là những đường dẫn chúng ta đã thấy trong Liệt kê 15 (/bin/bash, /bin/env, v.v).
  • Các đường dẫn tương đối (relative) là tương đối so với thư mục làm việc hiện tại của bạn, như lệnh pwd thông báo. Những lệnh này không bắt đầu bằng /, mà chứa ít nhất một /.

Bạn có thể sử dụng các đường dẫn tuyệt đối bất kể thư mục làm việc hiện tại của bạn ở đâu, nhưng nhiều khả năng bạn sẽ có thể sử dụng các đường dẫn tương đối chỉ khi một lệnh nằm ở rất gần với thư mục hiện tại của bạn. Giả sử bạn đang phát triển một phiên bản mới của chương trình "Hello World!" kinh điển trong một thư mục con của thư mục nhà của bạn tên là mytestbin. Bạn có thể sử dụng đường dẫn tương đối để chạy lệnh của bạn dưới dạng mytestbin/hello. Có hai tên đặc biệt bạn có thể sử dụng trong một đường dẫn; một dấu chấm duy nhất (.) dùng để chỉ thư mục hiện tại và một cặp dấu chấm (..) để chỉ thư mục cha mẹ của thư mục hiện hành. Vì thư mục nhà của bạn thường không có trên PATH của bạn (và nói chung không nên có), bạn sẽ cần phải cung cấp rõ ràng một đường dẫn cho bất kỳ tệp thi hành được nào mà bạn muốn chạy từ thư mục nhà của bạn. Ví dụ, nếu bạn đã có một bản sao của chương trình hello của bạn trong thư mục nhà của bạn, bạn có thể chạy nó bằng lệnh ./hello. Bạn có thể sử dụng cả dấu . và dấu .. như một phần của một đường dẫn tuyệt đối, mặc dù một dấu chấm đơn không có ích lợi gì trong trường hợp này. Bạn cũng có thể sử dụng một dấu ngã (~) có nghĩa là thư mục nhà của bạn và ~username có nghĩa là thư mục nhà của người dùng có tên username. Một số ví dụ được hiển thị trong Liệt kê 16.

Liệt kê 16. Các đường dẫn tuyệt đối và tương đối
[ian@echidna ian]$ /bin/echo Use echo command rather than builtin 
Use echo command rather than builtin
[ian@echidna ian]$ /usr/../bin/echo Include parent dir in path 
Include parent dir in path 
[ian@echidna ian]$ /bin/././echo Add a couple of useless path components 
Add a couple of useless path components
[ian@echidna ian]$ pwd # See where we are 
/home/ian 
[ian@echidna ian]$ ../../bin/echo Use a relative path to echo 
Use a relative path to echo
[ian@echidna ian]$ myprogs/hello # Use a relative path with no dots
-bash: myprogs/hello: No such file or directory 
[ian@echidna ian]$ mytestbin/hello # Use a relative path with no dots 
Hello World!
[ian@echidna ian]$ ./hello # Run program in current directory 
Hello World! 
[ian@echidna mytestbin]$ ~/mytestbin/hello # run hello using ~
Hello World! 
[ian@echidna ian]$ ../hello # Try running hello from parent 
-bash: ../hello: No such file or directory

Thay đổi thư mục làm việc của bạn

Cũng giống như bạn có thể thi hành các chương trình từ các thư mục khác nhau trong hệ thống, bạn có thể thay đổi thư mục làm việc hiện tại của bạn bằng cách sử dụng lệnh cd. Đối số của cd phải là đường dẫn tuyệt đối hay tương đối tới một thư mục. Cũng giống như với các lệnh, bạn có thể sử dụng dấu ., dấu .., dấu ~ và ~username trong đường dẫn. Nếu bạn sử dụng cd mà không có tham số nào, đó sẽ là chuyển tới thư mục nhà của bạn. Một gạch nối duy nhất (-) là tham số dùng để chuyển đến thư mục làm việc trước đó. Thư mục nhà của bạn được lưu trữ trong biến môi trường HOME và thư mục trước đó được lưu trữ trong biến OLDPWD, do đó một mình cd tương đương với cd $HOMEcd - tương đương với cd $OLDPWD. Thông thường chúng ta nói thay đổi thư mục thay cho toàn văn thay đổi thư mục làm việc hiện tại.

Cũng giống như đối với các lệnh, thư mục cũng có một biến môi trường, CDPATH, chứa một tập hợp các thư mục được phân tách bằng dấu hai chấm cần được tìm kiếm (ngoài thư mục làm việc hiện tại) khi phân giải các đường dẫn tương đối. Nếu việc phân giải đã sử dụng một đường dẫn từ CDPATH, thì cd sẽ in đường dẫn đầy đủ của thư mục kết quả làm đầu ra. Thông thường, nếu chuyển đổi thư mục thành công không dẫn đến kết quả đầu ra nào khác hơn là một dấu nhắc mới, có thể đổi khác. Một số ví dụ được hiển thị trong Liệt kê 17.

Liệt kê 17. Thay đổi các thư mục
[ian@echidna home]$ cd /;pwd 
/ 
[ian@echidna /]$ cd /usr/X11R6;pwd 
/usr/X11R6 
[ian@echidna X11R6]$ cd ;pwd 
/home/ian
[ian@echidna ian]$ cd -;pwd 
/usr/X11R6 
/usr/X11R6 
[ian@echidna X11R6]$ cd ~ian/..;pwd 
/home 
[ian@echidna home]$ cd ~;pwd 
/home/ian
[ian@echidna ian]$ export CDPATH=~ 
[ian@echidna mytestbin]$ cd /;pwd 
/
[ian@echidna /]$ cd mytestbin 
/home/ian/mytestbin

Áp dụng đệ quy các lệnh

Nhiều lệnh Linux có thể được áp dụng đệ quy cho tất cả các tập tin trong một cây thư mục. Ví dụ, lệnh ls có tùy chọn -R để liệt kê đệ quy các thư mục và tất cả các lệnh cp, mv, rmdiff đều có tùy chọn -r để áp dụng đệ quy chúng. Phần Quản lý tập tin cơ bản trình bày chi tiết về ứng dụng đệ quy các lệnh.

Thay thế lệnh

bash shell có khả năng vô cùng mạnh mẽ cho phép các kết quả của một lệnh được sử dụng như là đầu vào cho lệnh khác; điều này được gọi là phép thay thế lệnh. Phép thay thế này có thể được thực hiện bằng cách bao bọc lệnh mà bạn muốn sử dụng kết quả của nó trong các dấu kiểm ngược (`). Điều này vẫn còn phổ biến, nhưng một cách dễ dàng hơn để sử dụng với nhiều lệnh lồng nhau là bao bọc chúng giữa $( và ).

Trong hướng dẫn trước, "Chuẩn bị kỳ thi LPI 101 (chủ đề 102): cài đặt Linux và quản lý gói," chúng ta đã thấy rằng rpm có thể nói cho bạn biết một lệnh đến từ gói nào; chúng ta đã sử dụng khả năng thay thế lệnh như là một kỹ thuật tiện dụng. Bây giờ bạn biết chúng ta thực sự đã làm gì.

Thay thế lệnh là một công cụ vô giá trong các kịch bản lệnh shell và cũng có ích trên dòng lệnh. Liệt kê 18 cho thấy một ví dụ về cách nhận được đường dẫn tuyệt đối của một thư mục từ một đường dẫn tương đối, cách tìm kiếm RPM nào cung cấp lệnh /bin/echo và cách (với quyền root) liệt kê các nhãn của ba phân vùng trên một ổ đĩa cứng. Phần cuối cùng sử dụng lệnh seq để tạo một dãy các số nguyên.

Liệt kê 18. Thay thế lệnh
[ian@echidna ian]$ echo '../../usr/bin' dir is $(cd ../../usr/bin;pwd)
../../usr/bin dir is /usr/bin 
[ian@echidna ian]$ which echo 
/bin/echo
[ian@echidna ian]$ rpm -qf `which echo` 
sh-utils-2.0.12-3 
[ian@echidna ian]$ su - 
Password: 
[root@echidna root]# for n in $(seq 7 9); do echo p$n `e2label /dev/hda$n`;done 
p7 RH73 
p8 SUSE81 
p9 IMAGES

Các trang hướng dẫn sử dụng

Chủ đề cuối cùng của chúng ta trong phần này của hướng dẫn nói cho bạn biết cách nhận được tài liệu hướng dẫn về các lệnh Linux thông qua các trang hướng dẫn sử dụng và các nguồn tài liệu tham khảo khác.

Các trang và các phần hướng dẫn sử dụng

Nguồn tài liệu chính (và truyền thống) là các trang hướng dẫn sử dụng, bạn có thể truy cập chúng bằng cách sử dụng lệnh man. Hình 1 minh họa trang hướng dẫn sử dụng cho chính lệnh man. Sử dụng lệnh man man để hiển thị thông tin này.

Hình 1. Trang hướng dẫn sử dụng cho lệnh man
Trang hướng dẫn sử dụng cho lệnh man

Hình 1 cho thấy một số mục tiêu biểu trong các trang hướng dẫn sử dụng:

  • Một phần đầu có tên của các lệnh tiếp theo bằng số phần của nó trong dấu ngoặc đơn.
  • Tên của lệnh và các lệnh có liên quan bất kỳ được mô tả trong cùng một trang hướng dẫn sử dụng.
  • Một bản tóm tắt các tùy chọn và các tham số áp dụng cho lệnh này.
  • Một mô tả ngắn gọn về lệnh này.
  • Thông tin chi tiết trên mỗi một trong tùy chọn.

Bạn có thể tìm thấy các phần khác về cách sử dụng, làm thế nào để thông báo các lỗi, thông tin tác giả và một danh sách các lệnh có liên quan. Ví dụ, trang hướng dẫn sử dụng cho lệnh man nói cho chúng ta biết rằng các lệnh liên quan (và các phần hướng dẫn sử dụng của chúng) là:

apropos(1), whatis(1), less(1), groff(1), and man.conf(5).

Có tám nhóm trang hướng dẫn sử dụng thường gặp. Các trang hướng dẫn sử dụng thường được cài đặt khi bạn cài đặt một gói, vì vậy nếu bạn chưa cài đặt một gói phần mềm, nhiều khả năng bạn sẽ không có trang hướng dẫn sử dụng cho nó. Tương tự, một số phần hướng dẫn sử dụng của bạn có thể rỗng hoặc gần như rỗng. Dưới đây là những phần hướng dẫn sử dụng thường gặp và một số nội dung ví dụ:

  1. Các lệnh của người dùng (env, ls, echo, mkdir, tty).
  2. Các cuộc gọi hệ thống hoặc các chức năng nhân (link, sethostname, mkdir).
  3. Các thường trình thư viện (acosh, asctime, btree, locale, XML::Parser).
  4. Thông tin liên quan đến thiết bị (isdn_audio, mouse, tty, zero).
  5. Mô tả định dạng tập tin (keymaps, motd, wvdial.conf).
  6. Các trò chơi (lưu ý rằng nhiều trò chơi hiện nay có đồ họa và có trợ giúp đồ họa ngoài hệ thống trang hướng dẫn sử dụng).
  7. Các nhóm linh tinh (arp, boot, regex, unix utf8).
  8. Quản trị hệ thống (debugfs, fdisk, fsck, mount, renice, rpm).

Các nhóm linh tinh khác mà bạn có thể tìm thấy bao gồm 9 cho tài liệu của nhân Linux, n cho tài liệu mới, o cho tài liệu cũ, và l cho tài liệu hướng dẫn nội bộ.

Một số mục xuất hiện trong nhiều phần. Ví dụ chúng ta cho thấy mkdir có trong phần 1 và 2 và tty trong phần 1 và 4. Bạn có thể chỉ rõ một nhóm cụ thể, ví dụ, man 4 tty hoặc man 2 mkdir, hoặc bạn có thể chỉ rõ tùy chọn -a để liệt kê tất cả các phần hướng dẫn sử dụng có thể có.

Bạn có thể nhận thấy trong hình minh họa là man có nhiều tùy chọn cho bạn tự khám phá. Bây giờ, chúng ta hãy xem nhanh một số các lệnh "Xem thêm" có liên quan đến man.

Xem thêm

Hai lệnh quan trọng liên quan đến manwhatisapropos. Lệnh whatis tìm kiếm các trang hướng dẫn sử dụng theo tên mà bạn đưa ra và hiển thị các thông tin tên từ các trang hướng dẫn sử dụng thích hợp. Lệnh apropos thực hiện tìm kiếm từ khoá của các trang hướng dẫn sử dụng và liệt kê các trang có chứa từ khóa của bạn. Liệt kê 19 minh họa các lệnh này.

Liệt kê 19. Ví dụ về lệnh whatis và apropos
[ian@lyrebird ian]$ whatis man 
man            (1) - format and display the on-line manual pages 
man            (7) - macros to format man pages 
man [manpath]  (1) - format and display the on-line manual pages 
man.conf [man] (5) - configuration data for man 
[ian@lyrebird ian]$ whatis mkdir 
mkdir          (1) - make directories 
mkdir          (2) - create a directory 
[ian@lyrebird ian]$ apropos mkdir 
mkdir          (1) - make directories 
mkdir          (2) - create a directory 
mkdirhier      (1x) - makes a directory hierarchy

Nhân đây, nếu bạn không thể tìm thấy trang hướng dẫn sử dụng cho man.conf, hãy thử chạy lệnh man man.config để thay thế.

Lệnh man đánh số trang đầu ra trên màn hiển thị của bạn khi sử dụng một chương trình phân trang. Trên phần lớn các hệ thống Linux, đây có thể sẽ là chương trình less. Một sự lựa chọn khác có thể là chương trình more cũ hơn. Nếu bạn muốn in trang, hãy chỉ rõ tùy chọn -t để định dạng trang cho việc in ấn khi sử dụng chương trình groff hay troff.

Trình phân trang less có một số lệnh giúp bạn tìm kiếm các chuỗi trong kết quả đầu ra đã hiển thị. Sử dụng lệnh man less để tìm hiểu thêm về / (tìm kiếm xuôi), ? (tìm kiếm ngược về trước) và n (lặp lại tìm kiếm cuối cùng), trong số rất nhiều các lệnh khác.

Các nguồn tài liệu tham khảo khác

Ngoài các trang hướng dẫn sử dụng có thể truy cập từ một dòng lệnh, Quỹ phần mềm miễn phí (Free Software Foundation) đã tạo ra một số các tập tin info (thông tin) được xử lý bằng chương trình info. Các tập tin này cung cấp các phương tiện chuyển hướng rộng rãi bao gồm khả năng để chuyển đến các phần khác. Hãy thử lệnh man info hay info info để biết thêm thông tin. Không phải tất cả các lệnh đều có tài liệu hướng dẫn bằng info, do đó, bạn sẽ nhận thấy mình sử dụng cả hai lệnh man và info nếu bạn trở thành một người sử dụng info.

Cũng có một số giao diện đồ họa cho các trang hướng dẫn sử dụng, chẳng hạn như xman (từ Dự án XFree86) và yelp (trình duyệt trợ giúp Gnome 2.0).

Nếu bạn không thể tìm thấy sự trợ giúp cho một lệnh, hãy thử chạy lệnh đó với tùy chọn --help. Lệnh này có thể cung cấp sự trợ giúp của lệnh hoặc nó có thể nói cho bạn biết cách nhận được sự trợ giúp mà bạn cần.

Phần tiếp theo xem xét xử lý các luồng văn bản bằng các bộ lọc.


Các luồng văn bản và các bộ lọc

Phần này trình bày tư liệu cho chủ đề 1.103.2 cho kỳ thi quản trị trình độ sơ cấp (LPIC-1) 101. Chủ đề này có trọng số 6.

Trong phần này, bạn tìm hiểu về các chủ đề sau đây:

  • Gửi các tập tin văn bản và các luồng đầu ra thông qua các bộ lọc để sửa đổi đầu ra.
  • Sử dụng các lệnh tiêu chuẩn UNIX có trong gói các tiện ích văn bản (textutils) GNU.

Lọc văn bản

Lọc văn bản là quá trình nhận một luồng văn bản đầu vào và thực hiện một số chuyển đổi trên văn bản đó trước khi gửi nó đến một luồng đầu ra. Mặc dù cả luồng đầu vào lẫn luồng đầu ra có thể đến từ một tập tin, trong các môi trường Linux và UNIX, việc lọc hầu như thường được thực hiện bằng cách xây dựng một đường ống của các lệnh, ở đó luồng đầu ra từ một lệnh được dẫn bằng ống (piped) hay được chuyển hướng để được sử dụng như luồng đầu vào cho lệnh kế tiếp. Các ống và chuyển hướng được trình bày đầy đủ hơn trong phần Các luồng, các ống và các chuyển hướng, nhưng bây giờ, hãy xem xét các ống và chuyển hướng luồng đầu ra cơ bản khi sử dụng các toán tử | và >.

Tạo đường ống bằng toán tử |

Nhớ lại từ phần trước là các trình shell sử dụng ba luồng vào/ra (I/O):

  • stdinluồng đầu vào tiêu chuẩn, cung cấp đầu vào cho các lệnh.
  • stdoutluồng đầu ra tiêu chuẩn, hiển thị đầu ra từ các lệnh.
  • stderrluồng lỗi tiêu chuẩn, hiển thị đầu ra lỗi từ các lệnh.

Cho đến nay trong hướng dẫn này, luồng đầu vào đến từ các tham số mà chúng ta cung cấp cho các lệnh và luồng đầu ra đã được hiển thị trên thiết bị đầu cuối của chúng ta. Nhiều lệnh xử lý văn bản (các bộ lọc) có thể lấy đầu vào hoặc từ luồng đầu vào tiêu chuẩn hoặc từ một tập tin. Để sử dụng đầu ra của một lệnh, ví dụ command1, làm đầu vào cho một bộ lọc, ví dụ command2, bạn kết nối các lệnh bằng cách sử dụng toán tử ống (|) như trong Liệt kê 20.

Liệt kê 20. Tạo đường ống cho đầu ra từ command1 tới đầu vào của command2
 command1 | command2

Cả hai lệnh này có thể có các tùy chọn hoặc các đối số, như bạn sẽ thấy sau trong phần này. Bạn cũng có thể sử dụng toán tử | để chuyển hướng đầu ra của command2 trong đường ống này tới một lệnh khác, ví dụ command3. Việc xây dựng các đường ống dài của các lệnh, mỗi lệnh có khả năng hạn chế là một cách Linux và UNIX thường dùng để thực hiện các nhiệm vụ. Đôi khi bạn cũng sẽ thấy một dấu nối ngang (-) được sử dụng thay cho tên tập tin như là một đối số cho một lệnh, nghĩa là đầu vào phải đến từ luồng đầu vào tiêu chuẩn (stdin) chứ không phải từ một tập tin.

Chuyển hướng đầu ra bằng toán tử >

Thật tốt đẹp khi có thể tạo ra một đường ống của một số lệnh và xem đầu ra trên thiết bị đầu cuối của bạn, nhưng có những lúc bạn muốn lưu đầu ra vào một tập tin. Bạn làm điều này bằng toán tử chuyển hướng đầu ra (>).

Đối với phần còn lại của phần này, chúng ta sẽ sử dụng một số tập tin nhỏ, vì vậy hãy tạo một thư mục gọi là lpi103 và sau đó di chuyển (bằng lệnh cd) vào thư mục này. Chúng ta sẽ sử dụng toán tử > để chuyển hướng đầu ra của lệnh echo vào một tập tin gọi là text1. Tất cả việc này được hiển thị trong Liệt kê 21. Chú ý rằng đầu ra không hiển thị trên thiết bị đầu cuối, vì nó đã được chuyển đến tập tin.

Liệt kê 21. Tạo đường ống cho đầu ra từ command 1 vào một tập tin
[ian@echidna ian]$ mkdir lpi103 
[ian@echidna ian]$ cd lpi103 
[ian@echidna lpi103]$ echo -e "1 apple\n2 pear\n3 banana">text1

Bây giờ chúng ta có một vài công cụ cơ bản để tạo đường ống và chuyển hướng, hãy xem xét một số các lệnh và các bộ lọc xử lý văn bản UNIX và Linux thường dùng. Phần này cho bạn thấy một số khả năng cơ bản; hãy đọc các trang hướng dẫn sử dụng thích hợp để tìm hiểu thêm về các lệnh này.

Các lệnh cat, tac, od và split

Bây giờ bạn đã tạo ra tập tin text1, bạn có thể muốn kiểm tra những gì có trong đó. Hãy sử dụng lệnh cat (viết tắt của catenate (tạo thành chuỗi)) để hiển thị nội dung của một tập tin trên luồng đầu ra tiêu chuẩn (stdout). Liệt kê 22 kiểm tra các nội dung của tập tin được tạo ra ở trên.

Liệt kê 22. Hiển thị các nội dung tập tin bằng lệnh cat
[ian@echidna lpi103]$ cat text1 
1 apple 
2 pear 
3 banana

Lệnh cat lấy đầu vào từ luồng đầu vào tiêu chuẩn (stdin) nếu bạn không chỉ định một tên tệp (hoặc nếu bạn chỉ định - làm tên tập tin). Hãy sử dụng lệnh này cùng với việc chuyển hướng đầu ra để tạo ra một tập tin văn bản như trong Liệt kê 23.

Liệt kê 23. Tạo một tập tin văn bản bằng lệnh cat
[ian@echidna lpi103]$ cat>text2 
9 plum 
3 banana 
10 apple

Trong Liệt kê 23, lệnh cat duy trì đọc từ luồng đầu vào tiêu chuẩn (stdin) cho đến cuối tập tin. Sử dụng tổ hợp phím Ctrl-d (giữ phím Ctrl và nhấn phím d) để báo hiệu kết thúc tập tin. Đây cũng chính là tổ hợp phím để thoát ra khỏi bash shell. Cũng lưu ý rằng phím tab giúp dóng thẳng các tên trái cây trong một cột.

Đôi khi, bạn có thể muốn hiển thị một tập tin theo thứ tự ngược lại. Đương nhiên, có một bộ lọc văn bản để làm việc này, được gọi là tac (đảo ngược của cat). Liệt kê 24 hiển thị tập tin text2 mới cũng như tập tin text1 cũ theo thứ tự ngược. Lưu ý cách hiển thị chỉ để nối hai tập tin.

Liệt kê 24. Hiển thị đảo ngược bằng lệnh tac
[ian@echidna lpi103]$ tac text2 text1 
10 apple 
3 banana 
9 plum 
3 banana 
2 pear 
1 apple

Bây giờ, giả sử bạn hiển thị hai tập tin văn bản bằng cách sử dụng lệnh cat hoặc tac và lưu ý sự dóng hàng khác nhau. Để tìm hiểu cái gì gây ra điều này, bạn cần phải xem xét các ký tự điều khiển có trong tập tin đó. Vì chúng tác động vào đầu ra hiển thị văn bản chứ không có dạng hiển thị của ký tự điều khiển, chúng ta cần phải xổ ra tập tin theo một định dạng cho phép bạn tìm thấy và diễn giải những ký tự đặc biệt này. Các tiện ích văn bản GNU bao gồm một lệnh od (hay Octal D - xổ ra số đếm cơ số 8) cho mục đích này.

Có vài tùy chọn cho lệnh od, chẳng hạn như tùy chọn -A để điều khiển cơ số dịch bít (offsets) của tập tin và -t để điều khiển khuôn dạng các nội dung tập tin được hiển thị. Cơ số có thể được quy định là o, (octal - cơ số 8 là mặc định), d (hệ thập phân), x (hệ mười sáu) hoặc n (không có sự dịch chuyển nào được hiển thị). Bạn có thể hiển thị kết quả đầu ra như cơ số 8, cơ số 16, thập phân, dấu phẩy động, ASCII với các mã thoát dấu gạch chéo ngược hoặc các ký tự có tên (nl là dòng mới, ht là dấu tab theo chiều ngang, v.v.) Liệt kê 25 cho thấy một số các định dạng có sẵn để xổ ra tập tin ví dụ text2.

Liệt kê 25. Xổ ra các tập tin bằng lệnh od
[ian@echidna lpi103]$ od text2 
0000000 004471 066160 066565 031412 061011 067141 067141 005141 
0000020 030061 060411 070160 062554 000012 
0000031 
[ian@echidna lpi103]$ od -A d -t c text2
0000000 9 \t p l u m \n 3 \t b a n a n a \n 
0000016 1 0 \t a p p l e \n 
0000025 
[ian@echidna lpi103]$ od -A n -t a text2 
9 ht p l u m nl 3 ht b a n a n a nl 
1 0 ht a p p l  e nl

Lưu ý:

  1. Tùy chọn -A của lệnh cat cung cấp một cách thay thế khác để xem các dấu tab và các dấu kết thúc dòng của bạn ở đâu. Xem trang hướng dẫn sử dụng để biết thêm thông tin.
  2. Nếu bạn có hệ thống nền máy tính lớn (mainframe), bạn có thể quan tâm đến tiện ích hexdump, là một phần của một tập hợp các tiện ích khác nhau. Nó không được trình bày ở đây, vì vậy hãy xem các trang hướng dẫn sử dụng.

Các tập tin mẫu của chúng tôi là rất nhỏ, nhưng đôi khi bạn sẽ có các tập tin lớn mà bạn cần phải chia tách ra thành những đoạn nhỏ hơn. Ví dụ, bạn có thể muốn ngắt một tập tin lớn thành những đoạn có kích thước đĩa CD để bạn có thể ghi nó vào đĩa CD gửi qua bưu điện cho ai đó, người có thể tạo ra một đĩa DVD cho bạn. Lệnh split sẽ làm điều này theo cách mà có thể sử dụng lệnh cat để tạo lại tập tin dễ dàng. Theo mặc định, các tập tin kết quả từ lệnh split có một tiền tố trong tên của chúng là 'x' tiếp theo bằng một hậu tố là 'aa', 'ab', 'ac', ..., 'ba', 'bb', v.v . Các tùy chọn cho phép bạn thay đổi những mặc định này. Bạn cũng có thể kiểm soát độ lớn của các tập tin đầu ra và quy định liệu các tập tin có chứa toàn bộ các dòng hay chỉ số đếm byte. Liệt kê 26 minh họa việc chia tách hai tập tin văn bản của chúng ta với các tiền tố khác nhau cho các tập tin đầu ra. Chúng ta chia tách tập tin text1 thành các tập tin chứa nhiều nhất là hai dòng và tập tin text2 thành các tập tin có chứa nhiều nhất là 18 byte. Sau đó chúng ta sử dụng lệnh cat để hiển thị một số các đoạn riêng biệt cũng như để hiển thị tập tin hoàn chỉnh bằng cách sử dụng globbing, sẽ được trình bày trong phần về các kí tự đại diện và globbing trong hướng dẫn này. (Globbing là quá trình khai triển một tên tập tin không cụ thể chứa một ký tự đại diện trong một tập hợp các tập tin cụ thể tồn tại trong thiết bị lưu trữ trên một máy tính, máy chủ hoặc mạng. –ND).

Liệt kê 26. Chia tách và kết hợp lại bằng lệnh split và cat
[ian@echidna lpi103]$ split -l 2 text1 
[ian@echidna lpi103]$ split -b 18 text2 y 
[ian@echidna lpi103]$ cat yaa 
9 plum 
3 banana 
10
[ian@echidna lpi103]$ cat yab 
apple
[ian@echidna lpi103]$ cat y* 
9 plum 
3 banana 
10 apple

Lưu ý rằng tập tin chia tách có tên yab đã không kết thúc bằng một ký tự dòng mới, do đó dấu nhắc của chúng ta đã bị dịch đi sau khi chúng ta sử dụng lệnh cat để hiển thị nó.

Lệnh wc, head và tail

Lệnh Cattac hiển thị toàn bộ tập tin. Lệnh đó là tốt cho các tập tin nhỏ như các ví dụ của chúng ta, nhưng giả sử bạn có một tập tin lớn. Vâng, đầu tiên bạn có thể muốn sử dụng lệnh wc (Word Count đếm từ) để xem tập tin này lớn như thế nào. Lệnh wc hiển thị số dòng, số từ và số byte trong một tập tin. Bạn cũng có thể tìm thấy số byte bằng cách sử dụng lệnh ls -l. Liệt kê 27 hiển thị danh sách thư mục với định dạng dài cho hai tập tin văn bản của chúng ta, cũng như kết quả đầu ra từ lệnh wc.

Liệt kê 27. Sử dụng lệnh wc với các tập tin văn bản
[ian@echidna lpi103]$ ls -l text*
-rw-rw-r-- 1 ian ian 24 Sep 23 12:27 text1 
-rw-rw-r-- 1 ian ian 25 Sep 23 13:39 text2 
[ian@echidna lpi103]$ wc text* 
3 6 24 text1 
3 6 25 text2 
6 12 49 total

Các tùy chọn cho phép bạn điều khiển đầu ra từ lệnh wc hoặc để hiển thị thông tin khác như độ dài dòng tối đa. Xem trang hướng dẫn sử dụng để biết chi tiết.

Hai lệnh cho phép bạn hiển thị hoặc phần (đầu - head) hoặc phần (cuối - tail). Các lệnh này là các lệnh headtail. Chúng có thể được sử dụng như các bộ lọc hoặc chúng có thể nhận một tên tập tin làm đối số. Theo mặc định, chúng sẽ hiển thị 10 dòng đầu tiên (hoặc cuối cùng) của tập tin hoặc luồng. Liệt kê 28 sử dụng lệnh dmesg để hiển thị thông báo khởi động, kết hợp với các lệnh wc, tailhead để phát hiện ra rằng có 177 thông báo, sau đó để hiển thị 10 thông báo mới nhất trong số này và cuối cùng để hiển thị 6 thông báo bắt đầu từ thông báo 15 từ dưới lên. Một số các dòng đã bị cắt ngắn trong kết quả đầu ra này (được biểu thị bằng dấu ba chấm ...).

Liệt kê 28. Sử dụng lệnh wc, head và tail để hiển thị các thông báo khởi động
[ian@echidna lpi103]$ dmesg | wc 
177 1164 8366 
[ian@echidna lpi103]$ dmesg | tail
i810: Intel ICH2 found at IO 0x1880 and 0x1c00, MEM 0x0000 and ...
i810_audio: Audio Controller supports 6 channels. 
i810_audio: Defaulting to base 2 channel mode. 
i810_audio: Resetting connection 0
ac97_codec: AC97 Audio codec, id: ADS98 (Unknown) 
i810_audio: AC'97 codec 0 Unable to map surround DAC's (or ... 
i810_audio: setting clocking to 41319 
Attached scsi CD-ROM sr0 at scsi0, channel 0, id 0, lun 0 
sr0: scsi3-mmc drive: 0x/32x writer cd/rw xa/form2 cdda tray
Uniform CD-ROM driver Revision: 3.12 
[ian@echidna lpi103]$ dmesg | tail -n15 | head -n 6 
agpgart: Maximum main memory to use for agp memory: 941M 
agpgart: Detected Intel i845 chipset a
gpgart: AGP aperture is 64M @ 0xf4000000 
Intel 810 + AC97 Audio, version 0.24, 13:01:43 Dec 18 2003 
PCI: Setting latency timer of device 00:1f.5 to 64 
i810: Intel ICH2 found at IO 0x1880 and 0x1c00, MEM 0x0000 and ...

Một cách dùng thông dụng khác của tailtiếp tục một tập tin bằng cách sử dụng tùy chọn -f thường với một số đếm dòng là 1. Bạn có thể sử dụng lệnh này khi bạn có một quá trình nền sau đang tạo đầu ra trong một tập tin và bạn muốn kiểm tra và xem nó đang làm thế nào. Trong chế độ này, lệnh tail sẽ chạy cho đến khi bạn hủy bỏ nó (bằng cách sử dụng Ctrl-c), hiển thị các dòng khi chúng được ghi vào tập tin.

Lệnh expand (khai triển), unexpand (không khai triển) và tr

Khi chúng ta tạo ra các tập tin text1 và text2, chúng ta tạo text2 có các ký tự tab. Đôi khi bạn có thể muốn tráo đổi các tab để lấy khoảng trống hoặc ngược lại. Các lệnh expandunexpand làm điều này. Tùy chọn -t cho cả hai lệnh cho phép bạn thiết lập các điểm dừng tab. Một giá trị duy nhất sẽ thiết lập các tab lặp lại ở khoảng cách đó. Liệt kê 29 cho thấy cách khai triển các tab trong tập tin text2 chỉ thành các khoảng trống đơn và một dãy thay đổi của các lệnh expandunexpand phá hỏng việc dóng hàng văn bản trong text2.

Liệt kê 29. Sử dụng lệnh expand và unexpand
[ian@echidna lpi103]$ expand -t 1 text2 
9 plum 
3 banana 
10 apple 
[ian@echidna lpi103]$ expand -t8 text2|unexpand -a -t2|expand -t3 
9 plum 
3 banana 
10 apple

Thật không may, bạn không thể sử dụng lệnh unexpand để thay thế các khoảng trống trong text1 bằng các tab do lệnh unexpand cần ít nhất hai khoảng trống để chuyển đổi thành tab. Tuy nhiên, bạn có thể sử dụng lệnh tr , chuyển dịch các ký tự trong một bộ (set1) thành các ký tự tương ứng trong một bộ khác (set2). Liệt kê 30 chỉ ra cách sử dụng lệnh tr để chuyển dịch khoảng trống thành các tab. Do lệnh tr chỉ là một bộ lọc, nên bạn tạo đầu vào cho nó bằng cách sử dụng lệnh cat. Ví dụ này cũng minh họa việc sử dụng dấu - để biểu thị đầu vào tiêu chuẩn cho lệnh cat.

Liệt kê 30. Sử dụng lệnh expand and unexpand
[ian@echidna lpi103]$ cat text1 |tr ' ' '\t'|cat - text2 
1 apple 
2 pear 
3 banana 
9 plum 
3 banana 
10 apple

Nếu bạn không chắc chắn những gì đang xảy ra trong hai ví dụ vừa qua, hãy thử sử dụng lệnh od để kết thúc lần lượt từng giai đoạn của đường ống, ví dụ,
cat text1 |tr ' ' '\t' | od -tc

Lệnh pr, nl và fmt

Lệnh pr được sử dụng để định dạng các tập tin cho việc in ấn. Tiêu đề mặc định bao gồm tên tập tin và ngày giờ tạo tập tin, cùng với số trang và hai dòng cuối trang để trống. Khi đầu ra được tạo từ nhiều tập tin hoặc luồng đầu vào tiêu chuẩn, ngày tháng và thời gian hiện tại được sử dụng thay cho tên tập tin và ngày tạo tập tin. Bạn có thể in các tập tin cạnh nhau trong các cột và điều khiển nhiều khía cạnh về định dạng thông qua các tùy chọn. Như thường lệ, hãy tham khảo trang hướng dẫn sử dụng để biết chi tiết.

Lệnh nl đánh số các dòng, có thể thuận tiện khi in các tập tin. Bạn cũng có thể đánh số các dòng bằng tùy chọn -n của lệnh cat. Liệt kê 31 cho thấy cách in tập tin text1 của chúng ta và sau đó làm thế nào để đánh số tập tin text2 và in bên cạnh với tập tin.

Liệt kê 31. Đánh số và định dạng cho việc in ấn
[ian@echidna lpi103]$ pr text1 | head

2005-09-23 12:27               text1               Page 1 

1 apple 
2 pear 
3 banana 

[ian@echidna lpi103]$ nl text2 | pr -m - text1 | head 

2005-09-26 11:48                                    Page 1 

1 9  plum                      1 apple 
2 3 banana                     2 pear 
3 10 apple                     3 banana

Một lệnh có ích khác cho việc định dạng văn bản là lệnh fmt. Lệnh này định dạng văn bản sao cho nó vừa khít trong các lề. Bạn có thể nối một vài dòng ngắn cũng như chia tách các dòng dài. Trong Liệt kê 32, chúng ta tạo text3 với chỉ một dòng văn bản dài bằng cách sử dụng các biến !#:* của tính năng lược sử để tiết kiệm việc gõ câu của chúng ta bốn lần. Chúng ta cũng tạo text4 mỗi dòng chỉ có một từ. Sau đó, chúng ta sử dụng lệnh cat để hiển thị các tập tin này chưa định dạng bao gồm cả một ký tự '$' được hiển thị để chỉ ra các kết thúc dòng. Cuối cùng, chúng ta sử dụng lệnh fmt để định dạng chúng tới chiều rộng tối đa là 60 ký tự. Một lần nữa, hãy tham khảo trang hướng dẫn sử dụng để biết chi tiết về các tùy chọn bổ sung.

Liệt kê 32. Định dạng tới một độ dài dòng tối đa
[ian@echidna lpi103]$ echo "This is a sentence. " !#:* !#:1-$>text3 
echo "This is a sentence. " "This is a sentence. " "This is a sentenc 
e. " "This is a sentence. ">text3
[ian@echidna lpi103]$ echo -e "This\nis\nanother\nsentence.">text4
[ian@echidna lpi103]$ cat -et text3 text4
This is a sentence. This is a sentence. This is a sentence. This i 
s a sentence. $ 
This$ 
is$
another$ 
sentence.$ 
[ian@echidna lpi103]$ fmt -w 60 text3 text4 
This is a sentence. This is a sentence. This is a 
sentence. This is a sentence. 
This is another sentence.

Lệnh sort và uniq

Lệnh sort sắp xếp đầu vào bằng cách sử dụng thứ tự sắp xếp (collating sequence) cho nơi diễn ra (LC_COLLATE) của hệ thống. Lệnh sort cũng có thể hợp nhất các tập tin đã sắp xếp và kiểm tra xem một tập tin đã được sắp xếp hay không.

Liệt kê 33 minh họa cách sử dụng lệnh sort để sắp xếp theo thứ tự hai tập tin văn bản của chúng ta sau khi chuyển các khoảng trống thành các tab trong tập tin text1. Vì thứ tự sắp xếp là theo ký tự, bạn có thể bị bất ngờ về các kết quả. May mắn thay, lệnh sort có thể sắp xếp theo các giá trị số hoặc giá trị ký tự. Bạn có thể xác định sự lựa chọn này cho toàn bộ bản ghi hoặc cho từng trường. Trừ khi bạn xác định một dấu phân tách trường khác đi, các trường được định giới bằng các khoảng trống hoặc các tab. Ví dụ thứ hai trong Liệt kê 33 cho thấy việc sắp xếp trường đầu tiên theo giá trị số và trường thứ hai theo dãy sắp xếp (theo bảng chữ cái). Nó cũng minh họa việc sử dụng tùy chọn -u để loại bỏ bất kỳ các dòng giống hệt nhau nào và chỉ giữ các dòng duy nhất.

Liệt kê 33. Sắp xếp ký tự và số
[ian@echidna lpi103]$ cat text1 | tr ' ' '\t' | sort - text2 
10 apple 
1 apple 
2 pear 
3 banana 
3 banana 
9 plum
[ian@echidna lpi103]$ cat text1|tr ' ' '\t'|sort -u -k1n -k2 - text2 
1 apple 
2 pear 
3 banana 
9 plum 
10 apple

Chú ý rằng chúng ta vẫn còn có hai dòng có chứa quả "apple" (táo). Một lệnh khác gọi là uniq cung cấp cho chúng ta thêm quyền kiểm soát việc loại bỏ dòng trùng lặp. Lệnh uniq thường hoạt động trên các tập tin đã sắp xếp, nhưng gỡ bỏ các dòng giống hệt nhau liên tiếp khỏi bất kỳ tập tin nào, dù đã sắp xếp hay chưa. Lệnh uniq cũng có thể bỏ qua một số trường. Liệt kê 34 sắp xếp hai tập tin văn bản của chúng ta bằng cách sử dụng trường thứ hai (tên trái cây) và sau đó loại bỏ các dòng giống hệt nhau, bắt đầu từ trường thứ hai (có nghĩa là, chúng ta bỏ qua trường đầu tiên khi kiểm tra bằng uniq).

Liệt kê 34. Sử dụng lệnh uniq
[ian@echidna lpi103]$ cat text1|tr ' ' '\t'|sort -k2 - text2|uniq -f1 
10 apple 
3 banana 
2 pear 
9 plum

Việc sắp xếp của chúng ta theo thứ tự sắp xếp, do đó lệnh uniq cung cấp cho chúng ta dòng "10 apple" (10 quả táo) thay cho dòng "1 apple". Hãy thử thêm vào lệnh sắp xếp theo số cho trường khóa 1 để xem cách thay đổi sắp xếp như thế nào.

Lệnh cut, paste và join

Bây giờ hãy xem xét thêm ba lệnh nữa xử lý các trường trong dữ liệu văn bản. Các lệnh này đặc biệt có ích cho việc xử lý dữ liệu dạng bảng. Đầu tiên là lệnh cut trong đó trích xuất các trường khỏi các tập tin văn bản. Dấu phân tách trường mặc định là ký tự tab. Liệt kê 35 sử dụng lệnh cut để phân tách hai cột của tập tin text2 và sau đó sử dụng một khoảng trống làm dấu phân tách đầu ra. Đây là một cách khá kỳ cục để chuyển đổi tab trong mỗi dòng thành một khoảng trống.

Liệt kê 35. Sử dụng lệnh cut
[ian@echidna lpi103]$ cut -f1-2 --output-delimiter=' ' text2 
9 plum 
3 banana 
10 apple

Lệnh paste dán các dòng từ hai hoặc nhiều tập tin cạnh nhau, tương tự như cách mà lệnh pr kết hợp các tập tin bằng cách sử dụng tùy chọn -m của nó. Liệt kê 36 cho thấy kết quả của việc dán hai tập tin văn bản của chúng ta.

Liệt kê 36. Dán các tập tin
[ian@echidna lpi103]$ paste text1 text2 
1 apple 9 plum 
2 pear 3 banana
3 banana 10 apple

Các ví dụ này cho thấy việc dán đơn giản, nhưng lệnh paste có thể dán dữ liệu từ một hoặc nhiều tập tin theo một số cách khác nhau. Tham khảo trang hướng dẫn sử dụng để biết chi tiết.

Lệnh thao tác trường cuối cùng là join, để nối các tập tin dựa vào một trường so khớp. Các tập tin cần được sắp xếp theo trường nối. Do tập tin text2 không được sắp xếp theo thứ tự số, chúng ta có thể sắp xếp nó và sau đó lệnh join sẽ nối hai dòng có trường nối khớp nhau (là 3 trong trường hợp này). Ngoài ra chúng ta hãy tạo một tập tin mới, text5, bằng cách sắp xếp text 1 theo trường thứ hai (tên trái cây) và sau đó thay thế các khoảng trống bằng các tab. Nếu sau đó chúng ta sắp xếp text2 và nối nó với text 5 bằng cách sử dụng trường thứ hai, thì chúng ta sẽ có hai dòng khớp nhau (apple và banana). Liệt kê 37 minh họa cả hai phép nối này.

Liệt kê 37. Nối các tập tin bằng các trường nối
[ian@echidna lpi103]$ sort -n text2|join -1 1 -2 1 text1 - 
3 banana banana 
[ian@echidna lpi103]$ sort -k2 text1|tr ' ' '\t'>text5 
[ian@echidna lpi103]$ sort -k2 text2 | join -1 2 -2 2 text5 - 
apple 1 10 
banana 3 3

Trường sử dụng để nối được xác định riêng cho mỗi tập tin. Ví dụ, bạn có thể nối dựa vào trường số 3 của một tập tin và trường số 10 của tập tin kia.

Sed

Sed (là từ stream editor) là trình soạn thảo luồng. Đã có một số bài viết của developerWorks, cũng như nhiều cuốn sách và các chương sách viết về sed (xem Tài nguyên). Sed là vô cùng mạnh mẽ và những việc mà nó có thể làm được chỉ bị hạn chế bởi trí tưởng tượng của bạn mà thôi. Mục giới thiệu nhỏ này sẽ kích thích sự khao khát tìm hiểu sed của bạn, hoàn toàn không có tham vọng trình bày đầy đủ hay mở rộng.

Cũng như nhiều lệnh văn bản mà chúng ta đã xem xét cho đến nay, sed có thể làm việc như một bộ lọc hoặc nhận đầu vào của nó từ một tập tin. Kết quả đưa tới luồng đầu ra tiêu chuẩn. Sed nạp các dòng từ đầu vào vào vùng mẫu (pattern space), áp dụng các lệnh chỉnh sửa của sed cho các nội dung của vùng mẫu và sau đó viết vùng mẫu tới đầu ra tiêu chuẩn. Sed có thể kết hợp nhiều dòng trong vùng mẫu và nó có thể viết ra một tập tin, chỉ viết những kết quả đầu ra đã chọn lọc hoặc không viết ra tí nào

Sed sử dụng cú pháp biểu thức chính quy (xem phần Tìm kiếm với các biểu thức chính quy ở phần sau trong hướng dẫn này) để tìm kiếm và thay thế có chọn loc văn bản trong vùng mẫu cũng như kiểm soát các dòng văn bản nào cần được vận hành bằng một bộ các lệnh chỉnh sửa. Một bộ đệm lưu giữ (hold buffer) cung cấp lưu trữ tạm thời cho văn bản. Bộ đệm lưu giữ có thể thay thế vùng mẫu, được thêm vào vùng mẫu hoặc được trao đổi với vùng mẫu. Sed có một bộ lệnh hạn chế, nhưng bộ lệnh này kết hợp với cú pháp biểu thức chính quy và bộ đệm lưu giữ tạo ra một số khả năng năng tuyệt vời. Một bộ lệnh sed thường được gọi là một kịch bản lệnh sed.

Liệt kê 38 cho thấy ba kịch bản lệnh sed đơn giản. Trong kịch bản lệnh đầu tiên, chúng ta sử dụng lệnh s (substitute - thay thế) để thay thế một chữ ‘A’ hoa vào chỗ chữ 'a' thường trên mỗi dòng. Ví dụ này chỉ thay thế chữ 'a' đầu tiên, do đó trong ví dụ thứ hai, chúng ta thêm cờ 'g' (global - toàn cầu) để làm cho sed thay đổi tất cả các trường hợp chữ ‘a’. Trong kịch bản lệnh thứ ba, chúng ta đưa vào lệnh d (delete - xóa) để xóa một dòng. Trong ví dụ của chúng ta, chúng ta sử dụng một địa chỉ là 2 để chỉ thị rằng chỉ có dòng 2 cần phải xóa. Chúng ta phân tách các lệnh bằng cách sử dụng một dấu chấm phẩy (;) và sử dụng cùng một phép thay thế toàn cầu giống như đã sử dụng trong kịch bản lệnh thứ hai để thay thế 'a' bằng 'A'.

Liệt kê 38. Bắt đầu các kịch bản lệnh sed
[ian@echidna lpi103]$ sed 's/a/A/' text1 
1 Apple 
2 peAr 
3 bAnana 
[ian@echidna lpi103]$ sed 's/a/A/g' text1 
1 Apple 
2 peAr
3 bAnAnA 
[ian@echidna lpi103]$ sed '2d;$s/a/A/g' text1 
1 apple 
3 bAnAnA

Ngoài hoạt động trên từng dòng riêng lẻ, sed có thể hoạt động trên một dải các dòng. Đầu và cuối của dải này được phân cách bởi một dấu phẩy (,) và có thể được xác định bằng một con số là số dòng, một dấu mũ (^) là từ đầu tập tin hoặc một dấu đô la ($) là đến cuối tập tin. Khi đã cho một địa chỉ hoặc một dải địa chỉ, bạn có thể nhóm một số lệnh giữa cặp dấu ngoặc nhọn ({ và }) để làm cho các lệnh này hoạt động chỉ trên các dòng trong dải đã chọn. Liệt kê 39 minh họa hai cách để làm cho phép thay thế toàn cầu của chúng ta được áp dụng cho chỉ hai dòng cuối của tập tin của chúng ta. Liệt kê 39 cũng minh họa việc sử dụng tùy chọn -e để bổ sung thêm các lệnh vào vùng mẫu. Khi sử dụng dấu ngoặc nhọn, chúng ta phải phân tách các lệnh theo cách này.

Liệt kê 39. Các địa chỉ sed
[ian@echidna lpi103]$ sed -e '2,${' -e 's/a/A/g' -e '}' text1 
1 apple
2 peAr 
3 bAnAnA 
[ian@echidna lpi103]$ sed -e '/pear/,/bana/{' -e 's/a/A/g' -e '}' text1 
1 apple 
2 peAr 
3 bAnAnA

Các kịch bản lệnh sed cũng có thể được lưu trữ trong các tập tin. Trong thực tế, bạn sẽ có thể muốn làm điều này cho các kịch bản lệnh thường được sử dụng. Hãy nhớ rằng ở trên chúng ta sử dụng lệnh tr để thay đổi các khoảng trống trong text1 thành các tab. Bây giờ chúng ta hãy làm điều đó với một kịch bản lệnh sed được lưu giữ trong một tập tin. Chúng ta sẽ sử dụng lệnh echo để tạo tập tin. Các kết quả được hiển thị trong Liệt kê 40.

Liệt kê 40. Một lệnh sed hay hay
[ian@echidna lpi103]$ echo -e "s/ /\t/g">sedtab
[ian@echidna lpi103]$ cat sedtab 
s/ / /g 
[ian@echidna lpi103]$ sed -f sedtab text1 
1 apple 
2 pear 
3 banana

Có rất nhiều lệnh sed tiện dụng như Liệt kê 40. Xem Tài nguyên để tìm các liên kết đến một số ví dụ.

Ví dụ sed cuối cùng của chúng ta sử dụng lệnh = để in các số dòng và sau đó lọc kết quả đầu ra thông qua sed một lần nữa để bắt chước tác động của lệnh nl để đánh số dòng. Liệt kê 41 sử dụng = để in các số dòng, sau đó sử dụng lệnh N để đọc một dòng đầu vào thứ hai vào trong vùng mẫu và cuối cùng loại bỏ các ký tự dòng mới (\n) giữa hai dòng trong vùng mẫu.

Liệt kê 41. Đánh số các dòng bằng sed
[ian@echidna lpi103]$ sed '=' text2 
1 
9 plum 
2 
3 banana 
3 
10 apple 
[ian@echidna lpi103]$ sed '=' text2|sed 'N;s/\n//'
19 plum 
23 banana 
310 apple

Không hoàn toàn là những gì chúng ta đã mong muốn! Những gì chúng ta thực sự muốn là dóng thẳng các số của chúng ta trong một cột với một vài khoảng trống trước các dòng từ tập tin. Trong Liệt kê 42, chúng ta nhập vào một vài dòng lệnh (chú ý dấu nhắc thứ cấp >). Hãy nghiên cứu ví dụ và tham khảo lời giải thích dưới đây.

Liệt kê 42. Đánh số các dòng với sed - vòng hai
[ian@echidna lpi103]$ cat text1 text2 text1 text2>text6 
[ian@echidna lpi103]$ ht=$(echo -en "\t")
[ian@echidna lpi103]$ sed '=' text6|sed "N
> s/^/ / 
> s/^.*\(......\)\n/\1$ht/"
 1 1 apple
 2 2 pear
 3 3 banana
 4 9 plum
 5 3 banana
 6 10 apple
 7 1 apple
 8 2 pear
 9 3 banana
 10 9 plum
 11 3 banana
 12 10 apple

Dưới đây là các bước chúng ta đã thực hiện:

  1. Đầu tiên chúng ta đã sử dụng lệnh cat để tạo ra một tập tin mười hai dòng từ hai bản sao tập tin text1 và text2 của chúng ta. Không có trò vui nào trong việc định dạng các con số trong các cột nếu chúng ta không có các số chữ số khác nhau.
  2. bash shell sử dụng phím tab để hoàn thành lệnh, do đó thật tiện dụng để có một ký tự tab bắt giữ mà bạn có thể sử dụng khi bạn cần một tab thực. Chúng ta sử dụng lệnh echo để thực hiện việc này và lưu ký tự đó trong biến shell 'ht'.
  3. Chúng ta tạo một luồng có chứa các số dòng tiếp sau bởi các dòng dữ liệu như chúng ta đã làm trước và lọc nó qua một bản sao thứ hai của sed.
  4. Chúng ta đọc một dòng thứ hai trong vùng mẫu.
  5. Chúng ta thêm vào phần đầu số dòng của chúng ta ở chỗ bắt đầu của vùng mẫu (đánh dấu bằng ^) với sáu khoảng trống.
  6. Chúng ta sau đó thay thế tất cả dòng cho tới dấu dòng mới bằng sáu ký tự cuối cùng trước dấu dòng mới cộng với một ký tự tab. Lưu ý rằng một phần bên trái của lệnh 's' sử dụng '\(' và '\)' để đánh dấu các ký tự mà chúng ta muốn sử dụng ở phần bên phải. Trong phần bên phải, chúng ta tham chiếu đến tập hợp ký tự đầu tiên được đánh dấu như thế (và chỉ một tập hợp ấy trong ví dụ này) như là \1. Lưu ý rằng lệnh của chúng ta được đặt trong dấu nháy kép (") để cho sự thay thế sẽ xảy ra với $ht.

Các phiên bản gần đây (phiên bản 4) của sed chứa tài liệu tham khảo theo định dạng info (thông tin) và bao gồm nhiều ví dụ tuyệt vời. Các tài liệu này không có trong phiên bản cũ hơn 3.02. GNU sed sẽ chấp nhận lệnh sed --version để hiển thị phiên bản này.


Quản lý tập tin cơ bản

Phần này trình bày tư liệu cho chủ đề 1.103.3 cho kỳ thi quản trị trình độ sơ cấp (LPIC-1) 101. Chủ đề này có trọng số 3.

Trong phần này, bạn tìm hiểu về các chủ đề sau đây:

  • Liệt kê các nội dung thư mục.
  • Sao chép, di chuyển và gỡ bỏ các tập tin và các thư mục.
  • Thao tác đệ quy nhiều tập tin và thư mục.
  • Sử dụng các mẫu ký tự đại diện cho việc thao tác tập tin.
  • Sử dụng lệnh find để định vị và hành động trên các tập tin dựa vào kiểu, độ lớn hoặc thời gian.

Liệt kê các thư mục

Như chúng ta đã nói ở trên trong cuộc thảo luận của chúng ta về các đường dẫn trong phần sử dụng dòng lệnh,tất cả các tập tin trên các hệ thống Linux và UNIX® được truy cập như là một phần của một hệ thống tập tin có cấu trúc cây lớn duy nhất bắt nguồn tại /.

Liệt kê các mục trong thư mục

Nếu bạn đã tìm hiểu qua các phần trước với chúng tôi, bạn đã tạo ra một thư mục, đó là lpi103, trong thư mục nhà của bạn. Các tên tập tin và tên thư mục hoặc là tuyệt đối nghĩa là chúng bắt đầu bằng một / hoặc chúng là tương đối so với thư mục làm việc hiện tại, nghĩa là chúng không bắt đầu bằng một /. Đường dẫn tuyệt đối cho một tập tin hay thư mục có một / theo sau là một loạt gồm không có hoặc nhiều tên thư mục, mỗi tên tiếp theo bởi dấu / và sau đó là một tên cuối cùng. Khi đã cho một tên tập tin hay tên thư mục tương đối so với thư mục làm việc hiện tại, chỉ cần nối liền tên tuyệt đối của thư mục làm việc, một dấu / và tên tương đối ấy với nhau. Ví dụ, thư mục lpi103 mà chúng ta đã tạo ra trong phần vừa qua đã được tạo ra trong thư mục nhà của tôi, /home/ian, do đó đường dẫn đầy đủ, hay tuyệt đối, của nó là /home/ian/lpi103. Liệt kê 43 cho thấy ba cách khác nhau để sử dụng lệnh ls để liệt kê các tập tin trong thư mục này.

Liệt kê 43. Liệt kê các mục trong thư mục
[ian@echidna lpi103]$ pwd 
/home/ian/lpi103
[ian@echidna lpi103]$ echo $PWD 
/home/ian/lpi103 
[ian@echidna lpi103]$ ls 
sedtab text2 text4 text6 xab yab 
text1  text3 text5 xaa   yaa
[ian@echidna lpi103]$ ls "$PWD" 
sedtab text2 text4 text6 xab yab 
text1  text3 text5 xaa   yaa 
[ian@echidna lpi103]$ ls /home/ian/lpi103 
sedtab text2 text4 text6 xab yab 
text1  text3 text5 xaa   yaa

Như bạn có thể thấy, bạn có thể cung cấp một tên thư mục như là một tham số cho lệnh ls và nó sẽ liệt kê các nội dung của thư mục đó.

Liệt kê các chi tiết

Trên một thiết bị lưu trữ, một tập tin hoặc thư mục được chứa trong một bộ sưu tập các khối. Thông tin về một tập tin được chứa trong một inode để ghi lại các thông tin như là chủ sở hữu, khi nào tập tin đó được truy cập lần cuối cùng, độ lớn của nó, nó có là một thư mục hay không và ai có thể đọc hoặc viết nó. Số inode còn được gọi là số thứ tự tập tin và là duy nhất trong một hệ thống tập tin cụ thể. Chúng ta có thể sử dụng tùy chọn -l (hoặc --format=long) để hiển thị một số thông tin được lưu trữ trong inode.

Theo mặc định, lệnh ls không liệt kê các tập tin đặc biệt, những tập tin có tên bắt đầu bằng một dấu chấm (.). Tất cả thư mục khác ngoài thư mục gốc có ít nhất hai mục đặc biệt, chính thư mục đó (.) và thư mục cha mẹ (..). Thư mục gốc không có thư mục cha mẹ.

Liệt kê 44 sử dụng các tùy chọn -l-a để hiển thị một danh sách định dạng dài về tất cả các tập tin bao gồm cả các mục . và .. của thư mục.

Liệt kê 44. Liệt kê thư mục với định dạng dài
[ian@echidna lpi103]$ ls -al 
total 56
drwxrwxr-x    2  ian  ian     4096   Sep 30 15:01 . 
drwxr-xr-x   94  ian  ian     8192   Sep 27 12:57 .. 
-rw-rw-r--    1  ian  ian        8   Sep 26 15:24 sedtab 
-rw-rw-r--    1  ian  ian       24   Sep 23 12:27 text1 
-rw-rw-r--    1  ian  ian       25   Sep 23 13:39 text2 
-rw-rw-r--    1  ian  ian       84   Sep 25 17:47 text3 
-rw-rw-r--    1  ian  ian       26   Sep 25 22:28 text4 
-rw-rw-r--    1  ian  ian       24   Sep 26 12:46 text5
-rw-rw-r--    1  ian  ian       98   Sep 26 16:09 text6 
-rw-rw-r--    1  ian  ian       15   Sep 23 14:11 xaa 
-rw-rw-r--    1  ian  ian        9   Sep 23 14:11 xab 
-rw-rw-r--    1  ian  ian       18   Sep 23 14:11 yaa 
-rw-rw-r--    1  ian  ian        7   Sep 23 14:11 yab

Trong Liệt kê 44, dòng đầu tiên cho thấy tổng số các khối đĩa (56) được các tập tin đã liệt kê sử dụng. Các trường còn lại cho bạn biết về tập tin đó.

  • Trường đầu tiên (trong trường hợp này là drwxrwxr-x hoặc -rw-rw-r -) cho chúng ta biết tập tin đó là một thư mục (d) hay là một tập tin thông thường (-). Bạn cũng có thể thấy các liên kết biểu tượng (l) mà chúng ta sẽ tìm hiểu sau hoặc các giá trị khác cho một số tập tin đặc biệt (chẳng hạn như các tập tin trong hệ thống tập tin /dev). Tiếp theo kiểu tập tin là ba bộ quyền hạn (chẳng hạn như rwx hoặc r--) dành cho chủ sở hữu, các thành viên trong nhóm của chủ sở hữu và tất cả mọi người. Ba giá trị lần lượt báo hiệu người dùng, nhóm hay tất cả mọi người được phép làm gì, đọc (r), viết (w) hoặc cho chạy (x). Cách sử dụng khác ví dụ như setuid sẽ được trình bày sau.
  • Trường tiếp theo là một số, cho chúng ta biết số của các liên kết cứng đến tập tin. Chúng ta đã nói rằng inode chứa các thông tin về tập tin. Mục tập tin trong thư mục có chứa một liên kết cứng (hoặc con trỏ) tới inode cho tập tin đó, vì vậy mỗi mục được liệt kê phải có ít nhất một liên kết cứng. Các mục ứng với thư mục có thêm một mục . và mỗi thư mục con còn có thêm mục .. nữa. Vì vậy chúng ta có thể nhìn thấy từ liệt kê ở trên là thư mục nhà của tôi có khá nhiều thư mục con
  • Hai trường kế tiếp là chủ sở hữu tập tin và nhóm chính của chủ sở hữu. Một số hệ thống, chẳng hạn như hệ thống Red Hat, mặc định sẽ cung cấp một nhóm riêng cho mỗi người dùng. Trên hệ thống khác, tất cả người dùng có thể ở trong một hoặc có lẽ một vài nhóm.
  • Trường tiếp theo chứa độ dài của tập tin.
  • Trường áp chót chứa dấu thời gian của việc sửa đổi cuối cùng.
  • Và trường cuối cùng chứa tên của tập tin hoặc thư mục.

Tùy chọn -i của lệnh ls sẽ hiển thị các số inode cho bạn. Chúng ta sẽ sử dụng số này sau trong hướng dẫn này và cũng sử dụng khi chúng ta thảo luận về liên kết cứng và liên kết biểu tượng trong hướng dẫn cho Chủ đề 104.

Nhiều tập tin

Bạn cũng có thể xác định nhiều tham số cho lệnh ls, ở đó mỗi tên hoặc là tên của một tập tin hoặc tên của một thư mục. Nếu một tên là tên của một thư mục, thì lệnh ls liệt kê các nội dung của thư mục chứ không phải là thông tin về mục đó. Trong ví dụ của chúng ta, giả sử chúng ta muốn thông tin về mục ứng với thư mục lpi103 giống như khi nó được liệt kê trong thư mục cha mẹ, lệnh ls -l ../lpi103 sẽ cung cấp cho chúng ta một liệt kê giống như ví dụ trước. Liệt kê 45 cho thấy cách sử dụng ls -ld và hơn nữa làm thế nào để liệt kê các mục cho nhiều tập tin hoặc thư mục.

Liệt kê 45. Sử dụng lệnh ls -d
[ian@echidna lpi103]$ ls -ld ../lpi103 sedtab xaa
drwxrwxr-x     2 ian   ian 4096   Oct  2 18:49 ../lpi103 
-rw-rw-r--     1 ian   ian    8   Sep 26 15:24 sedtab 
-rw-rw-r--     1 ian   ian   15   Sep 23 14:11 xaa

Lưu ý rằng thời gian chỉnh sửa cho lpi103 là khác với thời gian đó trong liệt kê trước. Ngoài ra, như trong liệt kê trước, thời gian chỉnh sửa cũng khác với các dấu thời gian (timestamp) của bất kỳ các tập tin nào trong thư mục. Đây có phải là những gì bạn mong đợi không? Thông thường là không. Tuy nhiên, khi viết hướng dẫn này, tôi tạo thêm một số ví dụ và sau đó xóa chúng, do đó các dấu thời gian của thư mục phản ánh thực tế đó. Chúng ta sẽ nói thêm về các thời gian tập tin sau trong phần này khi chúng ta thảo luận về việc tìm kiếm các tập tin.

Sắp xếp đầu ra

Theo mặc định, lệnh ls liệt kê các tập tin theo thứ tự abc. Có một số tùy chọn để sắp xếp đầu ra. Ví dụ, ls -t sẽ sắp xếp theo thời gian sửa đổi (từ mới nhất đến cũ nhất) trong khi ls -lS sẽ tạo ra một danh sách dài được sắp xếp theo độ lớn (lớn nhất đến nhỏ nhất). Thêm -r sẽ đảo ngược thứ tự sắp xếp. Ví dụ, sử dụng ls -lrt để tạo ra một danh sách dài được sắp xếp từ cũ nhất đến mới nhất. Tham khảo trang hướng dẫn sử dụng để tìm các cách sắp xếp khác mà bạn có thể áp dụng khi liệt kê các tập tin và các thư mục.

Lệnh copy (sao chép), move (di chuyển) và delete (xóa)

Chúng ta bây giờ đã tìm hiểu một số cách để tạo ra các tập tin, nhưng giả sử chúng ta muốn tạo các bản sao của các tập tin, đổi tên các tập tin, di chuyển chúng trong hệ thống phân cấp các tập tin hoặc thậm chí xóa chúng. Chúng ta sử dụng ba lệnh ngắn cho các mục đích này.

cp
được sử dụng để tạo một bản sao của một hay nhiều tập tin. Bạn phải cung cấp ít nhất hai tên, một (hoặc nhiều) các tên nguồn (source) và một tên đích (target). Nếu bạn xác định hai tên tập tin, thì tên tập tin đầu tiên được sao chép thành tên tập tin thứ hai. Cả tên tập tin nguồn lẫn tên tập tin đích có thể bao gồm một đặc tả đường dẫn. Nếu bạn xác định một thư mục làm tên cuối cùng, thì bạn có thể xác định nhiều tập tin để được sao chép vào trong nó. Tất cả các tập tin sẽ được sao chép từ các vị trí hiện có của chúng và các bản sao sẽ có tên giống như các tập tin ban đầu. Lưu ý ở đây không có giả thiết mặc định rằng đích là thư mục hiện tại như trong hệ điều hành DOS và Windows.
mv
được sử dụng để di chuyển (move) hay đổi tên ( rename) một hay nhiều tập tin hoặc thư mục. Nói chung, các tên bạn có thể sử dụng theo các quy tắc giống như với việc sao chép bằng lệnh cp; bạn có thể đổi tên một tập tin đơn lẻ hoặc di chuyển một tập hợp các tập tin vào một thư mục mới. Do tên chỉ là một mục thư mục có các liên kết đến một inode, nên đừng ngạc nhiên là số inode không thay đổi trừ khi tập tin được chuyển đến một hệ thống tập tin khác, trong trường hợp đó việc di chuyển tập tin vận hành giống như sao chép, tiếp theo là xóa bản gốc.
rm
được sử dụng để gỡ bỏ (remove) một hay nhiều tập tin. Chúng ta sẽ xem cách gỡ bỏ các thư mục ngay sau đây.

Liệt kê 46 minh họa việc sử dụng lệnh cpmv để tạo một số các bản sao lưu các tập tin văn bản của chúng ta. Chúng ta cũng sử dụng lệnh ls -i để hiển thị các inode cho một số các tập tin của chúng ta.

  1. Đầu tiên chúng ta tạo một bản sao của tập tin text1 của chúng ta như là tập tin text1.bkp.
  2. Sau đó chúng ta quyết định tạo ra một thư mục con sao lưu bằng cách sử dụng lệnh mkdir.
  3. Chúng ta tạo một bản sao lưu thứ hai của text1, lúc này trong thư mục sao lưu và chỉ ra rằng tất cả ba tập tin có các inode khác nhau.
  4. Chúng ta sau đó di chuyển text1.bkp của chúng ta vào thư mục sao lưu và sau đó đổi tên nó cho nhất quán hơn với bản sao lưu thứ hai. Mặc dù chúng ta có thể đã làm điều này bằng một lệnh đơn thì ở đây chúng ta sử dụng hai lệnh để minh họa.
  5. Chúng ta kiểm tra các inode một lần nữa và xác nhận rằng text1.bkp có inode là 2129019 không còn trong thư mục lpi103 của chúng ta, mà bây giờ đó là inode của text1.bkp.1 trong thư mục sao lưu.
Liệt kê 46. Sao chép và di chuyển các tập tin
[ian@echidna lpi103]$ cp text1 text1.bkp
[ian@echidna lpi103]$ mkdir backup 
[ian@echidna lpi103]$ cp text1 backup/text1.bkp.2 
[ian@echidna lpi103]$ ls -i text1 text1.bkp backup
2128984 text1 2129019 text1.bkp 

backup: 
1564497 text1.bkp.2
[ian@echidna lpi103]$ mv text1.bkp backup 
[ian@echidna lpi103]$ mv backup/text1.bkp backup/text1.bkp.1 
[ian@echidna lpi103]$ ls -i text1 text1.bkp backup 
ls: text1.bkp: No such file or directory 
2128984 text1 

backup: 
2129019 text1.bkp.1 1564497 text1.bkp.2

Thông thường, lệnh cp sẽ sao chép một tập tin đè lên một bản sao hiện có, nếu tập tin hiện có cho phép viết được. Mặt khác, lệnh mv sẽ không di chuyển hoặc đổi tên một tập tin nếu đích đó tồn tại. Có nhiều lựa chọn có ích có liên quan đến hành vi này của lệnh cpmv.

-f hoặc --force (bắt buộc)
sẽ làm cho lệnh cp cố gắng gỡ bỏ một tập tin đích đang tồn tại ngay cả khi nó không cho phép viết được.
-i hoặc --interactive (tương tác)
sẽ yêu cầu xác nhận trước khi cố gắng thay thế một tập tin đang tồn tại.
-b hoặc --backup (sao lưu)
sẽ tạo một bản sao lưu của bất kỳ tập tin nào sẽ được thay thế.

Như thường lệ, hãy tham khảo các hướng dẫn sử dụng để biết chi tiết đầy đủ về các tùy chọn này và các tùy chọn khác cho việc sao chép và di chuyển.

Trong Liệt kê 47, chúng tôi minh họa việc sao chép bằng sao lưu dự phòng và sau đó xóa tập tin.

Liệt kê 47. Các bản sao lưu và xóa tập tin
[ian@echidna lpi103]$ cp text2 backup 
[ian@echidna lpi103]$ cp --backup=t text2 backup 
[ian@echidna lpi103]$ ls backup 
text1.bkp.1 text1.bkp.2 text2 text2.~1~ 
[ian@echidna lpi103]$ rm backup/text2 backup/text2.~1~ 
[ian@echidna lpi103]$ ls backup 
text1.bkp.1 text1.bkp.2

Lưu ý rằng lệnh rm cũng chấp nhận các tùy chọn -i (interactive) và -f (force). Một khi bạn xóa một tập tin bằng cách sử dụng lệnh rm, hệ thống tập tin không còn có quyền truy cập vào nó nữa. Một số hệ thống mặc định thiết lập một bí danh alias rm='rm -i' dành cho người dùng root để giúp ngăn chặn việc vô ý xóa tập tin. Điều này cũng là một ý tưởng tốt nếu bạn đang lo lắng về những gì bạn có thể vô tình xóa mất.

Trước khi chúng ta rời khỏi cuộc thảo luận này, cần lưu ý rằng lệnh cp mặc định sẽ tạo một dấu thời gian mới cho tập tin hoặc các tập tin mới. Chủ sở hữu và nhóm cũng được thiết lập là chủ sở hữu và nhóm của người sử dụng đang thực hiện sao chép. Tùy chọn -p có thể được sử dụng để bảo toàn các thuộc tính được chọn. Lưu ý rằng người dùng root có thể là người dùng duy nhất có thể bảo vệ quyền sở hữu. Xem trang hướng dẫn sử dụng để biết các chi tiết.

Lệnh mkdir và rmdir

Chúng ta đã biết cách tạo một thư mục bằng lệnh mkdir. Bây giờ chúng ta sẽ xem xét thêm về lệnh mkdir và giới thiệu lệnh tương tự với nó để gỡ bỏ các thư mục, lệnh rmdir.

Lệnh mkdir

Giả sử chúng ta đang ở trong thư mục lpi103 của chúng ta và chúng ta muốn tạo các thư mục con dir1 và dir2. Lệnh mkdir, giống như các lệnh mà chúng ta vừa xem xét lại, sẽ xử lý các yêu cầu tạo nhiều thư mục chỉ trong một lần như trong Liệt kê 48.

Liệt kê 48. Tạo nhiều thư mục
[ian@echidna lpi103]$ mkdir dir1 dir2

Lưu ý rằng không có đầu ra nào khi thực hiện thành công, mặc dù bạn có thể sử dụng lệnh echo $? để xác nhận rằng mã thoát thực sự là 0.

Nếu thay vào đó, bạn muốn tạo ra một thư mục con lồng nhau, chẳng hạn như d1/d2/d3, điều này sẽ thất bại do các thư mục d1 và d2 không tồn tại. May mắn thay, lệnh, mkdir có một tùy chọn -p cho phép nó tạo ra bất kỳ các thư mục cha mẹ được yêu cầu nào. Liệt kê 49 minh họa điều này.

Liệt kê 49. Tạo các thư mục cha mẹ
[ian@echidna lpi103]$ mkdir d1/d2/d3 
mkdir: cannot create directory `d1/d2/d3': No such file or directory 
[ian@echidna lpi103]$ echo $? 
1 
[ian@echidna lpi103]$ mkdir -p d1/d2/d3
[ian@echidna lpi103]$ echo $? 
0

Lệnh rmdir

Gỡ bỏ các thư mục bằng lệnh rmdir ngược với việc tạo ra các thư mục. Một lần nữa, lại có tùy chọn -p cũng để gỡ bỏ các thư mục cha mẹ. Bạn chỉ có thể gỡ bỏ một thư mục bằng lệnh rmdir nếu nó trống rỗng, như không có tùy chọn để gỡ bỏ cưỡng bức. Chúng ta sẽ thấy một cách khác để hoàn thành thủ thuật đặc biệt này khi chúng ta xem xét phần thao tác đệ quy. Một khi bạn biết rằng bạn có lẽ sẽ ít khi sử dụng lệnh rmdir trên dòng lệnh, tuy vậy biết về nó vẫn tốt.

Để minh họa việc gỡ bỏ thư mục, chúng ta sao chép tập tin text1 của chúng ta vào thư mục d1/d2 để nó không rỗng. Chúng ta sau đó đã sử dụng lệnh rmdir để gỡ bỏ tất cả các thư mục mà chúng ta vừa mới tạo ra bằng lệnh mkdir. Như bạn thấy, d1 và d2 không bị gỡ bỏ vì d2 không rỗng. Các thư mục khác đã được gỡ bỏ. Sau khi chúng ta gỡ bỏ bản sao của text1 trong d2, chúng ta có thể gỡ bỏ d1 và d2 bằng cách sử dụng lệnh rmdir -p.

Liệt kê 50. Gỡ bỏ các thư mục
[ian@echidna lpi103]$ cp text1 d1/d2 
[ian@echidna lpi103]$ rmdir -p d1/d2/d3 dir1 dir2 
rmdir: `d1/d2': Directory not empty 
[ian@echidna lpi103]$ ls . d1/d2 
.: 
backup sedtab text2 text4 text6 xab yab 
d1     text1  text3 text5 xaa   yaa 

d1/d2: 
text1 
[ian@echidna lpi103]$ rm d1/d2/text1 
[ian@echidna lpi103]$ rmdir -p d1/d2

Thao tác đệ quy

Trong một số phần còn lại của phần này chúng ta sẽ xem xét các hoạt động khác nhau để xử lý nhiều tập tin và để thao tác đệ quy một phần của một cây thư mục.

Liệt kê đệ quy

Lệnh ls có một tùy chọn -R (lưu ý 'R' chữ hoa) để liệt kê một thư mục và tất cả các thư mục con của nó. Tùy chọn đệ quy chỉ áp dụng cho các tên thư mục; nó sẽ không tìm thấy tất cả các tập tin có tên chẳng hạn là "text1' trong một cây thư mục. Bạn có thể sử dụng tùy chọn khác mà chúng ta đã thấy với -R. rồi. Một danh sách đệ quy của thư mục của lpi103 của chúng ta, bao gồm cả các số inode, được hiển thị trong Liệt kê 51.

Liệt kê 51. Danh sách thư mục đệ quy
[ian@echidna lpi103]$ ls -iR ~/lpi103
/home/ian/lpi103: 
1564496 backup 2128985 text2 2128982 text5 2128987 xab 
2128991 sedtab 2128990 text3 2128995 text6 2128988 yaa 
2128984 text1  2128992 text4 2128986 xaa   2128989 yab 

/home/ian/lpi103/backup:
2129019 text1.bkp.1 1564497 text1.bkp.2

Sao chép đệ quy

Bạn có thể sử dụng tùy chọn -r (hay -R hay --recursive) để làm cho lệnh cp đi sâu vào trong các thư mục nguồn và sao chép nội dung theo cách đệ quy. Để ngăn chặn một phép đệ qui vô hạn, các thư mục nguồn tự nó có thể không được sao chép. Liệt kê 52 cho thấy làm thế nào để sao chép tất cả mọi thứ trong thư mục lpi103 của chúng ta tới một thư mục con copy1. Chúng ta sử dụng lệnh ls -R để hiển thị cây thư mục kết quả.

Liệt kê 52. Sao chép đệ quy
[ian@echidna lpi103]$ cp -pR . copy1 
cp: cannot copy a directory, `.', into itself, `copy1' 
[ian@echidna lpi103]$ ls -R 
.: 
backup sedtab text2 text4 text6 xab yab 
copy1 text1 text3 text5 xaa yaa 

./backup:
text1.bkp.1 text1.bkp.2 

./copy1: 
backup text1 text3 text5 xaa yaa
sedtab text2 text4 text6 xab yab 

./copy1/backup: 
text1.bkp.1 text1.bkp.2

Xóa đệ quy

Chúng ta đã đề cập ở trên rằng lệnh rmdir chỉ gỡ bỏ các thư mục rỗng. Chúng ta có thể sử dụng tùy chọn -r (hoặc -R hoặc --recursive) để làm cho lệnh rm để gỡ bỏ cả các tập tin cũng như các thư mục như chỉ ra trong Liệt kê 53, ở đây chúng ta gỡ bỏ thư mục copy1 mà chúng ta vừa tạo ra, cùng với các nội dung của nó, bao gồm cả thư mục con sao lưu và các nội dung của nó.

Liệt kê 53. Xóa đệ quy
[ian@echidna lpi103]$ rm -r copy1 
[ian@echidna lpi103]$ ls -R 
.:
backup text1 text3 text5 xaa yaa 
sedtab text2 text4 text6 xab yab
                              
./backup: 
text1.bkp.1 text1.bkp.2

Nếu bạn có các tập tin mà bạn không có khả năng viết vào được, bạn có thể cần phải thêm tùy chọn -f để buộc gỡ bỏ. Điều này thường được người dùng root thực hiện khi xóa dữ liệu, nhưng bạn được cảnh báo rằng bạn có thể bị mất dữ liệu có giá trị nếu bạn không cẩn thận.

Các ký tự đại diện và globbing

Thông thường, bạn có thể cần phải thực hiện một thao tác trên nhiều đối tượng hệ thống tập tin, mà không thao tác trên toàn bộ cây như chúng ta vừa thực hiện với các hoạt động đệ quy. Ví dụ, bạn có thể muốn tìm số lần sửa đổi của tất cả các tập tin văn bản mà chúng ta đã tạo ra trong lpi103, không liệt kê các tập tin chia tách. Mặc dù điều này là dễ dàng với các thư mục nhỏ của chúng ta, nhưng nó sẽ khó khăn hơn nhiều trong một hệ thống tập tin lớn.

Để giải quyết vấn đề này, hãy sử dụng sự hỗ trợ của ký tự đại diện được dựng sẵn trong bash shell. Sự hỗ trợ này còn được gọi là "globbing" (bởi vì ban đầu nó được thực hiện dưới dạng một chương trình gọi là /etc/glob), cho phép bạn xác định nhiều tập tin bằng cách sử dụng mẫu ký tự đại diện.

Một chuỗi có chứa bất kỳ các ký tự '?', '*' hay '[', là một mẫu ký tự đại diện (wildcard pattern). Globbing là quá trình trong đó shell (hoặc có thể là một chương trình khác) khai triển những mẫu ký tự đại diện này thành một danh sách các tên đường dẫn khớp với mẫu đó. Sự so khớp được thực hiện như sau.

?
khớp với bất kỳ ký tự đơn lẻ nào.
*
khớp với bất kỳ chuỗi nào, kể cả một chuỗi rỗng.
[
đưa vào một lớp ký tự. Một lớp ký tự là một chuỗi không rỗng, được kết thúc bằng một ']'. Một sự so khớp có nghĩa là làm khớp với bất kỳ ký tự đơn nào nằm trong cặp dấu ngoặc vuông đó. Có một vài xem xét đặc biệt.
  • Các ký tự '*' và '?' khớp với bản thân chúng. Nếu bạn sử dụng các ký tự này trong các tên tập tin, bạn sẽ cần phải thực sự cẩn thận với việc đặt trong dấu nháy hay hoặc dấu thoát.
  • Vì chuỗi ký tự phải không rỗng và được kết thúc bằng ']', bạn phải đặt ']' đầu tiên trong chuỗi đó nếu bạn muốn làm khớp với nó.
  • Ký tự '-' giữa hai ký tự khác biểu diễn một dải bao gồm hai ký tự khác và mọi ký tự ở giữa theo thứ tự sắp xếp (collating sequence). Ví dụ, ] 0-9a-fA-F [ biểu diễn bất kỳ số hệ đếm 16 chữ hoa hay chữ thường. Bạn có thể làm khớp với một '-' bằng cách đặt nó hoặc là đầu tiên hay cuối cùng trong một dải.
  • Ký tự '!' nếu xuất hiện như là ký tự đầu tiên của một dải sẽ biểu thị phần bù cho dải đó, để cho nó khớp với ký tự bất kỳ các ký tự còn lại nào khác. Ví dụ [!0-9] có nghĩa là ký tự bất kỳ nào, trừ các chữ số 0 đến 9. Một ký tự '!' ở bất kỳ vị trí nào, không phải vị trí đầu tiên, tự khớp với nó. Hãy nhớ rằng '!' cũng được sử dụng với chức năng lược sử của shell, vì vậy bạn cần phải cẩn thận để đặt mã thoát đúng cho nó.

Globbing được áp dụng riêng cho từng thành phần của một tên đường dẫn. Bạn không thể làm khớp với một '/' và cũng không bao gồm một '/' trong một dải. Bạn có thể sử dụng nó bất cứ nơi nào mà bạn có thể xác định nhiều tên tập tin hay tên thư mục, ví dụ trong các lệnh ls, cp, mv hay rm. Trong Liệt kê 54, trước tiên chúng ta tạo một vài tập tin có tên kỳ cục và sau đó sử dụng các lệnh lsrm với các mẫu ký tự đại diện.

Liệt kê 54. Các ví dụ về mẫu ký tự đại diện
[ian@echidna lpi103]$ echo odd1>'text[*?!1]'
[ian@echidna lpi103]$ echo odd2>'text[2*?!]' 
[ian@echidna lpi103]$ ls 
backup text1      text2      text3 text5 xaa yaa 
sedtab text[*?!1] text[2*?!] text4 text6 xab yab 
[ian@echidna lpi103]$ ls text[2-4] 
text2 text3 text4 
[ian@echidna lpi103]$ ls text[!2-4] 
text1 text5 text6
[ian@echidna lpi103]$ ls text*[2-4]* 
text2 text[2*?!] text3 text4
[ian@echidna lpi103]$ ls text*[!2-4]* # Surprise! 
text1 text[*?!1] text[2*?!] text5 text6 
[ian@echidna lpi103]$ ls text*[!2-4] # More surprise! 
text1 text[*?!1] text[2*?!] text5 text6 
[ian@echidna lpi103]$ echo text*>text10 
[ian@echidna lpi103]$ ls *\!* 
text[*?!1] text[2*?!] 
[ian@echidna lpi103]$ ls *[x\!]* 
text1 text2 text3 text5 xaa 
text[*?!1] text[2*?!] text4 text6 xab 
[ian@echidna lpi103]$ ls *[y\!]* 
text[*?!1] text[2*?!] yaa yab 
[ian@echidna lpi103]$ ls tex?[[]* 
text[*?!1] text[2*?!] 
[ian@echidna lpi103]$ rm tex?[[]*
[ian@echidna lpi103]$ ls *b* 
sedtab xab yab 

backup: text1.bkp.1 text1.bkp.2 
[ian@echidna lpi103]$ ls 
backup/*2 backup/text1.bkp.2
[ian@echidna lpi103]$ ls -d .* 
. ..

Lưu ý:

  1. Phần bù liên quan với '*' có thể dẫn đến một số bất ngờ. Mẫu '* [! 2-4]' khớp với phần dài nhất của một tên mà không có 2, 3, hoặc 4 sau nó, nó được khớp với cả hai text[*?!1] và text[2*?!]. Vì vậy bây giờ cả hai điều bất ngờ này là rõ ràng.
  2. Như với ví dụ ở trên về ls, nếu việc khai triển mẫu dẫn đến một tên là một tên thư mục và tùy chọn -d không được xác định, thì các nội dung của thư mục đó sẽ được liệt kê (như trong ví dụ trên cho mẫu '*b*').
  3. Nếu một tên tập tin bắt đầu bằng một dấu chấm (.) thì ký tự đó cần phải được so khớp rõ ràng. Chú ý rằng chỉ có lệnh ls cuối đã liệt kê hai mục thư mục đặc biệt (. và ..).

Hãy nhớ rằng bất kỳ các ký tự đại diện nào trong một lệnh có thể được khai triển bởi trình shell có thể dẫn đến kết quả bất ngờ. Hơn nữa, nếu bạn xác định một mẫu không khớp với bất kỳ đối tượng hệ thống tập tin nào thì POSIX yêu cầu rằng chuỗi mẫu ban đầu được chuyển tới lệnh. Chúng ta minh họa điều này trong Liệt kê 55. Một số phiên bản cũ hơn đã chuyển một danh sách rỗng tới lệnh, do đó bạn có thể rơi vào các kịch bản lệnh cũ, mang đến những hành vi bất thường. Chúng ta minh họa những điểm này trong Liệt kê 55.

Liệt kê 55. Mẫu ký tự đại diện gây bất ngờ
[ian@echidna lpi103]$ echo text* 
text1 text2 text3 text4 text5 text6 
[ian[ian@echidna lpi103]$ echo "text*" 
text*
@echidna lpi103]$ echo text[[\!?]z?? 
text[[!?]z??

Để biết thêm thông tin về globbing, hãy xem man 7 glob. Bạn sẽ cần số phần bởi vì cũng có thông tin glob trong phần 3. Cách tốt nhất để hiểu rõ tất cả các tương tác shell khác nhau là bằng thực hành, do đó hãy thử dùng các ký hiệu đại diện bất cứ khi nào bạn có cơ hội. Hãy nhớ thử lệnh ls để kiểm tra mẫu ký tự đại diện của bạn trước khi thi hành nó với bất kỳ lệnh nào trong các lệnh cp, mv hoặc tồi tệ hơn, lệnh rm vì nó có thể gây bất ngờ cho bạn.

Chạm vào các tập tin

Bây giờ chúng ta sẽ xem xét các lệnh touch (chạm vào) có thể cập nhật số lần truy cập và sửa đổi tập tin hoặc tạo tập tin rỗng. Trong phần tiếp theo chúng ta sẽ xem cách sử dụng thông tin này để tìm các tập tin và thư mục. Chúng ta sẽ sử dụng thư mục lpi103 mà chúng ta đã tạo ra ở trên trong hướng dẫn này. Chúng ta cũng sẽ xem xét nó.

Lệnh touch

Lệnh touch không có tùy chọn nào nhận một hay nhiều tên tập tin làm các tham số đầu vào và cập nhật thời gian sửa đổi các tập tin. Đây chính là dấu thời gian bình thường được hiển thị khi liệt kê nội dung thư mục với định dạng dài (long). Trong Liệt kê 56, chúng ta sử dụng lệnh echo người bạn cũ của chúng ta để tạo một tập tin nhỏ được gọi là f1 và sau đó sử dụng lệnh liệt kê nội dung thư mục với định dạng dài để hiển thị thời gian chỉnh sửa (hoặc mtime). Trong trường hợp này, đây cũng là thời gian tạo tập tin. Sau đó chúng ta sử dụng lệnh sleep để chờ 60 giây và chạy ls một lần nữa. Lưu ý rằng dấu thời gian cho tập tin đó đã lệch đi một phút.

Liệt kê 56. Cập nhật thời gian sửa đổi bằng lệnh touch
[ian@echidna lpi103]$ echo xxx>f1; ls -l f1; sleep 60; touch f1; ls -l f1 
-rw-rw-r--    1 ian ian    4 Nov 4   15:57 f1 
-rw-rw-r--    1 ian ian    4 Nov 4   15:58 f1

Nếu bạn xác định một tên tập tin cho một tập tin chưa tồn tại, thì lệnh touch bình thường sẽ tạo một tập tin rỗng cho bạn, trừ khi bạn chỉ rõ tùy chọn -c hay --no-create. Liệt kê 57 minh họa cả hai lệnh này. Lưu ý rằng chỉ f2 được tạo ra.

Liệt kê 57. Tạo các tập tin rỗng bằng lệnh touch
[ian@echidna lpi103]$ touch f2; touch -c f3; ls -l f* 
-rw-rw-r--    1 ian ian     4 Nov 4 15:58 f1 
-rw-rw-r--    1 ian ian     0 Nov 4 16:12 f2

Lệnh touch cũng có thể đặt thời gian sửa đổi (mtime) của một tập tin tới một ngày giờ cụ thể bằng cách sử các tùy chọn -d hoặc -t. Tùy chọn -d là rất linh hoạt, chấp nhận nhiều định dạng ngày tháng và thời giờ khác nhau, trong khi tùy chọn -t cần ít nhất một giá trị thời gian dạng MMDDhhmm, còn giá trị năm và giá trị giây là tùy chọn. Liệt kê 58 hiển thị một số ví dụ.

Liệt kê 58. Thiết lập mtime bằng lệnh touch
[ian@echidna lpi103]$ touch -t 200511051510.59 f3 
[ian@echidna lpi103]$ touch -d 11am f4 
[ian@echidna lpi103]$ touch -d "lst fortnight" f5 
[ian@echidna lpi103]$ touch -d "yesterday 6am" f6 
[ian@echidna lpi103]$ touch -d "2 days ago 12:00" f7 
[ian@echidna lpi103]$ touch -d "tomorrow 02:00" f8 
[ian@echidna lpi103]$ touch -d "5 Nov" f9 
[ian@echidna lpi103]$ ls -lrt f* 
-rw-rw-r--    1 ian ian 0 Oct 24 12:32 f5 
-rw-rw-r--    1 ian ian 4 Nov  4 15:58 f1 
-rw-rw-r--    1 ian ian 0 Nov  4 16:12 f2 
-rw-rw-r--    1 ian ian 0 Nov  5 00:00 f9 
-rw-rw-r--    1 ian ian 0 Nov  5 12:00 f7 
-rw-rw-r--    1 ian ian 0 Nov  5 15:10 f3
-rw-rw-r--    1 ian ian 0 Nov  6 06:00 f6 
-rw-rw-r--    1 ian ian 0 Nov  7 11:00 f4 
-rw-rw-r--    1 ian ian 0 Nov  8  2005 f8

Nếu bạn không chắc chắn một biểu thức ngày tháng có thể phân giải thành ngày tháng nào, bạn có thể sử dụng lệnh date để tìm ra nó. Lệnh này cũng chấp nhận tùy chọn -d và có thể phân giải cùng kiểu các định dạng ngày mà lệnh touch có thể làm.

Bạn có thể sử dụng tùy chọn -r (hay --reference) cùng với một tên tập tin tham khảo để biểu thị rằng lệnh touch (hay date) cần phải sử dụng dấu thời gian của một tập tin hiện có. Liệt kê 59 hiển thị một số ví dụ.

Liệt kê 59. Các dấu thời gian từ các tập tin tham khảo
[ian@echidna lpi103]$ date 
Mon Nov 7 12:40:11 EST 2005 
[ian@echidna lpi103]$ date -r f1 
Fri Nov 4 15:58:27 EST 2005 
[ian@echidna lpi103]$ touch -r f1 f1a 
[ian@echidna lpi103]$ ls -l f1* 
-rw-rw-r-- 1 ian ian 4 Nov 4 15:58 f1 
-rw-rw-r-- 1 ian ian 0 Nov 4 15:58 f1a

Một hệ thống Linux ghi lại cả thời gian sửa đổi của tập tin lẫn thời gian truy cập. Cả hai dấu thời gian được thiết lập tới cùng một giá trị khi một tập tin được tạo và cả hai được đặt lại khi tập tin được sửa đổi. Nếu một tập tin chỉ được truy cập, thì thời gian truy cập được cập nhật, thậm chí ngay cả khi tập tin không được sửa đổi. Trong ví dụ mới nhất của chúng ta là lệnh touch, chúng ta sẽ xem xét các thời gian truy cập tập tin. Tùy chọn -a (hoặc --time=atime, --time=access hay --time=use) xác định rằng thời gian truy cập cần phải được cập nhật. Liệt kê 60 sử dụng lệnh cat để truy cập tập tin f1 và hiển thị các nội dung của nó. Chúng ta sau đó sử dụng lệnh ls -lls -lu để hiển thị thời gian sửa đổi và thời gian truy cập tương ứng cho f1 và f1a, mà chúng ta đã tạo bằng cách sử dụng f1 như một tập tin tham khảo. Sau đó chúng ta thiết lập lại thời gian truy cập của f1 trùng với thời gian truy cập của f1a bằng lệnh touch -a.

Liệt kê 60. Thời gian truy cập và thời gian sửa đổi
[ian@echidna lpi103]$ cat f1 
xxx
[ian@echidna lpi103]$ ls -lu f1* 
-rw-rw-r-- 1 ian ian 4 Nov 7 14:13 f1
-rw-rw-r-- 1 ian ian 0 Nov 4 15:58 f1a 
[ian@echidna lpi103]$ ls -l f1*
-rw-rw-r-- 1 ian ian 4 Nov 4 15:58 f1 
-rw-rw-r-- 1 ian ian 0 Nov 4 15:58 f1a 
[ian@echidna lpi103]$ cat f1 xxx 
[ian@echidna lpi103]$ ls -l f1* 
-rw-rw-r-- 1 ian ian 4 Nov 4 15:58 f1 
-rw-rw-r-- 1 ian ian 0 Nov 4 15:58 f1a 
[ian@echidna lpi103]$ ls -lu f1* 
-rw-rw-r-- 1 ian ian 4 Nov 7 14:13 f1 
-rw-rw-r-- 1 ian ian 0 Nov 4 15:58 f1a 
[ian@echidna lpi103]$ touch -a -r f1a f1 
[ian@echidna lpi103]$ ls -lu f1*
-rw-rw-r-- 1 ian ian 4 Nov 4 15:58 f1 
-rw-rw-r-- 1 ian ian 0 Nov 4 15:58 f1a

Để có thêm đầy đủ thông tin về nhiều đặc tả thời giờ và ngày tháng cho phép, hãy xem các trang hướng dẫn sử dụng hoặc các trang thông tin cho các lệnh touch và date.

Tìm kiếm các tập tin

Trong chủ đề cuối cùng cho phần này của hướng dẫn, chúng ta sẽ xem xét lệnh find (tìm) được sử dụng để tìm các tập tin trong một hoặc nhiều cây thư mục, dựa trên các tiêu chí như tên, dấu thời gian hoặc độ lớn. Một lần nữa, chúng ta sẽ sử dụng thư mục lpi103 mà chúng ta đã tạo ra trước đó trong hướng dẫn này.

Lệnh find

Lệnh find sẽ tìm kiếm các tập tin hoặc thư mục bằng cách sử dụng tất cả hoặc một phần của tên, hoặc bằng tiêu chí tìm kiếm khác, như độ lớn, kiểu, chủ sở hữu tập tin, ngày tạo hoặc ngày truy cập cuối cùng. Thao tác tìm kiếm cơ bản nhất là tìm theo tên hoặc một phần của một tên. Liệt kê 61 cho thấy một ví dụ từ thư mục lpi103 của chúng ta, ở đây trước tiên chúng ta tìm kiếm tất cả các tập tin có một ký tự '1' hoặc một ký tự 'k' trong tên của chúng, sau đó thực hiện một số tìm kiếm đường dẫn mà chúng tôi sẽ giải thích trong các lưu ý dưới đây.

Liệt kê 61. Tìm kiếm các tập tin theo tên
[ian@echidna lpi103]$ find . -name "*[1k]*"
./text1 
./f1 
./backup 
./backup/text1.bkp.2 
./backup/text1.bkp.1 
./f1a
[ian@echidna lpi103]$ find . -ipath "*ACK*1" 
./backup/text1.bkp.1
[ian@echidna lpi103]$ find . -ipath "*ACK*/*1" 
./backup/text1.bkp.1
[

Lưu ý:

  1. Các mẫu mà bạn có thể sử dụng là các mẫu ký tự đại diện shell giống như các mẫu mà chúng ta đã thấy ở trên khi chúng ta thảo luận trong phần Các kí tự đại diện và globbing.
  2. Bạn có thể sử dụng -path thay cho -name để so khớp với đường dẫn đầy đủ thay vì chỉ dùng tên tập tin cơ sở. Trong trường hợp này, mẫu có thể qua các thành phần đường dẫn.
  3. Nếu bạn muốn tìm kiếm phân biệt dạng chữ hoa chữ thường như được hiển thị trong việc sử dụng ipath ở trên, hãy đặt thêm một ký tự 'i' vào trước các tùy chọn lệnh find để tìm kiếm một chuỗi hoặc mẫu.
  4. Nếu bạn muốn tìm một tập tin hoặc thư mục có tên bắt đầu bằng một dấu chấm, chẳng hạn như .bashrc hoặc thư mục hiện hành (.), thì bạn phải chỉ rõ một dấu chấm đứng đầu như một phần của mẫu. Nếu không, các tìm kiếm tên sẽ bỏ qua các tập tin hoặc thư mục này.

Trong ví dụ đầu tiên ở trên, chúng ta đã tìm thấy cả hai tập tin và một thư mục (./backup). Hãy sử dụng tham số -type cùng với một chữ cái chỉ kiểu để hạn chế tìm kiếm. Hãy sử dụng 'f' cho các tập tin thông thường, 'd' cho thư mục và 'l' cho các liên kết biểu tượng. Xem trang hướng dẫn sử dụng cho lệnh find để tìm các kiểu có khả năng khác. Liệt kê 62 cho thấy kết quả của việc tìm kiếm các thư mục (-type d).

Liệt kê 62. Tìm các tập tin theo kiểu
[ian@echidna lpi103]$ find . -type d 
. 
./backup
[ian@echidna lpi103]$ find . -type d -name "*" 
./backup

Lưu ý rằng đặc tả -type d không có bất kỳ dạng đặc tả tên nào sẽ hiển thị các thư mục có một dấu chấm đứng đầu trong các tên của chúng (chỉ các thư mục hiện tại trong trường hợp này).

Chúng ta cũng có thể tìm kiếm theo kích thước tập tin, hoặc tìm các tập tin có kích thước cụ thể (n) hoặc tìm các tập tin kích thước lớn hơn (n+) hoặc kích thước nhỏ hơn (-n) một giá trị đã cho. Bằng cách sử dụng cả hai giới hạn kích thước lớn hơn và bé hơn, chúng ta có thể tìm ra các tập tin có độ lớn nằm trong dải đã cho. Theo mặc định tùy chọn -size của lệnh find giả định một đơn vị là 'b' cho các khối 512 byte. Trong số các lựa chọn khác, hãy chỉ rõ 'c' cho các byte, hoặc 'k' cho kilobyte. Trong Liệt kê 63 đầu tiên chúng ta tìm thấy tất cả các tập tin có độ lớn bằng 0 và sau đó tất cả các tập tin có kích thước hoặc là 24 hoặc là 25 byte. Lưu ý rằng việc chỉ rõ -empty thay vì -size 0 (kích thước bằng 0) cũng tìm ra các tập tin rỗng.

Liệt kê 63. Tìm các tập tin theo kích thước
[ian@echidna lpi103]$ find . -size 0 
./f2 
./f3
./f4 
./f5 
./f6 
./f7 
./f8 
./f9 
./f1a 
[ian@echidna lpi103]$ find . -size -26c -size +23c -print 
./text1 
./text2 
./text5 
./backup/text1.bkp.2
./backup/text1.bkp.1

Liệt kê 63 giới thiệu tùy chọn -print là một ví dụ về một hành động có thể được thực hiện đối với các kết quả do việc tìm kiếm trả về. Trong bash shell, đây là hành động mặc định nếu không có hành động nào được xác định. Trên một số hệ thống và một số shell, yêu cầu phải chỉ rõ một hành động, nếu không thì không có kết quả đầu ra nào.

Các hành động khác bao gồm lệnh -ls để in các thông tin tương tự như thông tin từ lệnh ls -lids hoặc lệnh -exec sẽ thi hành một lệnh cho mỗi tập tin. Lệnh -exec phải được kết thúc bằng một dấu chấm phẩy và phải được đặt mã thoát nhằm tránh việc trình shell thông dịch nó trước tiên. Hơn nữa hãy chỉ rõ {} bất cứ ở đâu bạn muốn tập tin trả về được dùng trong lệnh đó. Như chúng ta đã thấy ở trên, các dấu ngoặc nhọn cũng có ý nghĩa đối với shell và nên được đặt mã thoát (hoặc dùng cặp dấu nháy) cho nó. Liệt kê 64 cho thấy có thể sử dụng các tùy chọn -ls-exec như thế nào để liệt kê thông tin tập tin.

Liệt kê 64. Tìm và hành động trên các tập tin
[ian@echidna lpi103]$ find . -size -26c -size +23c -ls 
2128984 4 -rw-rw-r-- 1 ian ian 24 Sep 23 12:27 ./text1
2128985 4 -rw-rw-r-- 1 ian ian 25 Sep 23 13:39 ./text2 
2128982 4 -rw-rw-r-- 1 ian ian 24 Sep 26 12:46 ./text5 
1564497 4 -rw-rw-r-- 1 ian ian 24 Oct 4 09:45 ./backup/text1.bkp.2 
2129019 4 -rw-rw-r-- 1 ian ian 24 Oct 4 09:43 ./backup/text1.bkp.1 
[ian@echidna lpi103]$ find . -size -26c -size +23c -exec ls -l '{}' \; 
-rw-rw-r-- 1 ian ian 24 Sep 23 12:27 ./text1 
-rw-rw-r-- 1 ian ian 25 Sep 23 13:39 ./text2
-rw-rw-r-- 1 ian ian 24 Sep 26 12:46 ./text5 
-rw-rw-r-- 1 ian ian 24 Oct  4 09:45 ./backup/text1.bkp.2 
-rw-rw-r-- 1 ian ian 24 Oct  4 09:43 ./backup/text1.bkp.1

Tùy chọn -exec có thể được sử dụng cho nhiều mục đích theo như trí tưởng tượng của bạn có thể tưởng tượng ra. Ví dụ:

find . -empty -exec rm '{}' \;

sẽ gỡ bỏ tất cả các tập tin rỗng trong một cây thư mục, còn lệnh

find . -name "*.htm" -exec mv '{}' '{}l' \;

sẽ đặt lại tên tất cả tập tin .htm thành tập tin .html.

Đối với ví dụ cuối cùng, chúng ta sử dụng các dấu thời gian (timestamp) được mô tả bằng lệnh touch để định vị các tập tin có các dấu thời gian cụ thể. Liệt kê 65 hiển thị ba ví dụ:

  1. Khi được sử dụng với -mtime -2, lệnh find tìm tất cả các tập tin đã sửa đổi trong vòng hai ngày qua. Một ngày trong trường hợp này là một khoảng thời gian 24 giờ so với ngày giờ hiện tại. Lưu ý rằng bạn sẽ sử dụng -atime nếu bạn muốn tìm các tập tin dựa trên thời gian truy cập chứ không phải là thời gian chỉnh sửa.
  2. Thêm tùy chọn -daystart có nghĩa là chúng ta muốn xem xét ngày như các ngày theo lịch, bắt đầu từ lúc nửa đêm. Bây giờ tập tin f3 được loại bỏ ra khỏi danh sách.
  3. Cuối cùng, chúng ta chỉ ra cách sử dụng một khoảng thời gian tính bằng các phút chứ không phải là các ngày để tìm các tập tin được sửa đổi từ một giờ (60 phút) đến 10 giờ (600 phút) trước đây.
Liệt kê 65. Tìm các tập tin bằng dấu thời gian
[ian@echidna lpi103]$ date 
Mon Nov 7 14:59:02 EST 2005 
[ian@echidna lpi103]$ find . -mtime -2 -type f -exec ls -l '{}' \; 
-rw-rw-r-- 1 ian ian 0 Nov 5 15:10 ./f3 
-rw-rw-r-- 1 ian ian 0 Nov 7 11:00 ./f4 
-rw-rw-r-- 1 ian ian 0 Nov 6 06:00 ./f6
-rw-rw-r-- 1 ian ian 0 Nov 8 2005 ./f8 
[ian@echidna lpi103]$ find . -daystart -mtime -2 -type f -exec ls -l '{}' \; 
-rw-rw-r-- 1 ian ian 0 Nov 7 11:00 ./f4 
-rw-rw-r-- 1 ian ian 0 Nov 6 06:00 ./f6 
-rw-rw-r-- 1 ian ian 0 Nov 8 2005 ./f8 
[ian@echidna lpi103]$ find . -mmin -600 -mmin +60 -type f -exec ls -l '{}' \; 
-rw-rw-r-- 1 ian ian 0 Nov 7 11:00 ./f4

Các trang hướng dẫn sử dụng cho lệnh find có thể giúp bạn tìm hiểu phạm vi rộng về các lựa chọn mà chúng ta không thể trình bày trong giới thiệu ngắn gọn này.


Các luồng, các ống dẫn và các chuyển hướng

Phần này trình bày tư liệu cho chủ đề 1.103.4 cho kỳ thi quản trị trình độ sơ cấp (LPIC-1) 101. Chủ đề này có trọng số 5.

Trong phần này, bạn tìm hiểu về các chủ đề sau đây:

  • Chuyển hướng các luồng vào ra tiêu chuẩn: đầu vào tiêu chuẩn, đầu ra tiêu chuẩn và báo báo lỗi tiêu chuẩn.
  • Đặt đường ống cho đầu ra từ một lệnh tới đầu vào của lệnh khác.
  • Gửi đầu ra tới cả luồng đầu ra tiêu chuẩn (stdout) lẫn tới một tập tin.
  • Sử dụng đầu ra lệnh như các đối số cho lệnh khác.

Chuyển hướng vào ra tiêu chuẩn

Nhớ lại rằng các shell sử dụng ba luồng vào ra tiêu chuẩn.

  1. stdoutluồng đầu ra tiêu chuẩn hiển thị đầu ra từ các lệnh. Nó có bộ mô tả tập tin 1 (descriptor 1).
  2. stderrluồng báo báo lỗi tiêu chuẩn hiển thị đầu ra lỗi từ các lệnh. Nó có bộ mô tả tập tin 2 (descriptor 2).
  3. stdinluồng đầu vào tiêu chuẩn cung cấp đầu vào cho các lệnh. Nó có bộ mô tả tập tin 0 (descriptor 0).

Các luồng đầu vào cung cấp đầu vào cho các chương trình, thường là từ việc gõ phím trên bàn phím đầu cuối. Các luồng đầu ra in các ký tự văn bản, thường tới thiết bị đầu cuối. Thiết bị đầu cuối ban đầu là một máy đánh chữ ASCII hoặc thiết bị đầu cuối hiển thị, nhưng hiện nay thường là một cửa sổ trên một màn hình nền đồ họa.

Như chúng ta đã thấy trong phần Các luồng văn bản và các bộ lọc chúng ta có thể chuyển hướng đầu ra tiêu chuẩn đến một tập tin hoặc đến đầu vào tiêu chuẩn của các lệnh khác và chúng ta có thể chuyển hướng đầu vào tiêu chuẩn từ một tập tin hoặc từ đầu ra của lệnh khác.

Chuyển hướng đầu ra

Có hai cách để chuyển hướng đầu ra:

n>
chuyển hướng đầu ra từ bộ mô tả tập tin n tới một tập tin. Bạn phải có quyền viết vào tập tin đó. Nếu tập tin không tồn tại, nó sẽ được tạo ra. Nếu nó đã tồn tại, nội dung hiện tại sẽ luôn bị mất mà không có cảnh báo trước.
n>>
cũng chuyển hướng đầu ra từ bộ mô tả tập tin n tới một tập tin. Một lần nữa, bạn phải có quyền viết vào tập tin. Nếu tập tin không tồn tại, nó sẽ được tạo ra. Nếu nó đã tồn tại, đầu ra được viết thêm vào tập tin hiện có.

Số n trong n> hay n>> dùng để chỉ bộ mô tả tập tin. Nếu nó bị bỏ qua, thì giả định đầu ra tiêu chuẩn. Liệt kê 66 minh họa việc sử dụng chuyển hướng để tách đầu ra tiêu chuẩn và báo báo lỗi tiêu chuẩn từ lệnh ls bằng cách sử dụng các tập tin mà chúng ta đã tạo ra ở trên trong thư mục lpi103 của chúng ta. Chúng ta cũng minh họa việc viết thêm đầu ra vào tập tin hiện có.

Liệt kê 66. Chuyển hướng đầu ra
[ian@echidna lpi103]$ ls x* z* 
ls: z*: No such file or directory 
xaa xab 
[ian@echidna lpi103]$ ls x* z* >stdout.txt 2>stderr.txt 
[ian@echidna lpi103]$ ls w* y* 
ls: w*: No such file or directory 
yaa yab 
[ian@echidna lpi103]$ ls w* y* >>stdout.txt 2>>stderr.txt 
[ian@echidna lpi103]$ cat stdout.txt 
xaa 
xab 
yaa
yab 
[ian@echidna lpi103]$ cat stderr.txt 
ls: z*: No such file or directory 
ls: w*: No such file or directory

Chúng ta đã nói rằng, việc chuyển hướng đầu ra bằng cách sử dụng n> thường viết đè lên tập tin hiện có. Bạn có thể điều khiển việc này bằng tùy chọn noclobber của lệnh dựng sẵn set. Nếu nó đã được thiết lập, bạn có thể viết đè lên nó bằng cách sử dụng n>| như trong Liệt kê 67.

Liệt kê 67. Chuyển hướng đầu ra bằng noclobber
[ian@echidna lpi103]$ set -o noclobber
[ian@echidna lpi103]$ ls x* z* >stdout.txt 2>stderr.txt 
-bash: stdout.txt: cannot overwrite existing file 
[ian@echidna lpi103]$ ls x* z* >|stdout.txt 2>|stderr.txt 
[ian@echidna lpi103]$ cat stdout.txt 
xaa 
xab 
[ian@echidna lpi103]$ cat stderr.txt 
ls: z*: No such file or directory 
[ian@echidna lpi103]$ set +o noclobber #restore original noclobber setting

Đôi khi bạn có thể muốn chuyển hướng cả đầu ra tiêu chuẩn lẫn báo báo lỗi tiêu chuẩn vào một tập tin. Việc chuyển hướng này thường được thực hiện đối với các tiến trình tự động hoặc các công việc nền sau để cho bạn có thể xem lại kết quả sau. Sử dụng &> hay &>> để chuyển hướng cả hai đầu ra tiêu chuẩn và báo báo lỗi tiêu chuẩn đến cùng một vị trí. Một cách khác để làm điều này là chuyển hướng bộ mô tả tập tin n và sau đó chuyển hướng bộ mô tả tập tin m đến cùng một vị trí bằng cách sử dụng cấu trúc m>&n hay m>>&n. Thứ tự trong đó các đầu ra được chuyển hướng là quan trọng. Ví dụ,
command 2>&1 >output.txt
không giống như
command >output.txt 2>&1
Chúng ta minh họa các chuyển hướng này trong Liệt kê 68. Trong lệnh cuối cùng lưu ý rằng đầu ra tiêu chuẩn đã được chuyển hướng sau báo lỗi tiêu chuẩn, do đó đầu ra báo lỗi tiêu chuẩn vẫn xuất ra cửa sổ đầu cuối.

Liệt kê 68. Chuyển hướng hai luồng tới một tập tin
[ian@echidna lpi103]$ ls x* z* &>output.txt 
[ian@echidna lpi103]$ cat output.txt 
ls: z*: No such file or directory 
xaa 
xab 
[ian@echidna lpi103]$ ls x* z* >output.txt 2>&1 
[ian@echidna lpi103]$ cat output.txt 
ls: z*: No such file or directory 
xaa 
xab 
[ian@echidna lpi103]$ ls x* z* 2>&1 >output.txt 
ls: z*: No such file or directory
[ian@echidna lpi103]$ cat output.txt 
xaa 
xab

Đôi lúc bạn có thể muốn bỏ qua hoàn toàn hoặc đầu ra tiêu chuẩn hoặc báo lỗi tiêu chuẩn. Để làm việc này, hãy chuyển hướng luồng thích hợp tới /dev/null. Trong Liệt kê 69 chúng ta thấy làm thế nào để bỏ qua đầu ra lỗi từ lệnh ls.

Liệt kê 69. Bỏ qua đầu ra bằng cách sử dụng /dev/null
[ian@echidna lpi103]$ ls x* z* 2>/dev/null 
xaa xab 
[ian@echidna lpi103]$ cat /dev/null

Chuyển hướng đầu vào

Cũng giống như chúng ta có thể chuyển hướng các luồng đầu ra tiêu chuẩn (stdout) và luồng báo lỗi tiêu chuẩn (stderr), chúng ta cũng có thể chuyển hướng luồng đầu vào tiêu chuẩn (stdin) từ một tập tin bằng cách sử dụng toán tử <. Nếu bạn nhớ lại, trong cuộc thảo luận của chúng ta về lệnh sort và uniq ở đây chúng ta đã sử dụng lệnh tr để thay thế các khoảng trống trong tập tin text1 của chúng ta bằng các tab. Trong ví dụ đó chúng ta đã sử dụng đầu ra của lệnh cat để tạo đầu vào tiêu chuẩn cho lệnh tr Thay vì gọi lệnh cat một cách không cần thiết, bây giờ chúng ta có thể sử dụng chuyển hướng đầu vào để chuyển các khoảng trống thành các tab, như trong Liệt kê 70.

Liệt kê 70. Chuyển hướng đầu vào
[ian@echidna lpi103]$ tr ' ' '\t'<text1 
1 apple
2 pear 
3 banana

Các shell, bao gồm bash, cũng có khái niệm về một tài-liệu-ngay sau đây (here-document), đó là một dạng khác của việc chuyển hướng đầu vào. Chuyển hướng này sử dụng << cùng với một từ, chẳng hạn như END, để làm điểm đánh dấu hoặc điểm canh chừng, báo hiệu sự kết thúc của đầu vào. Chúng ta minh họa điều này trong Liệt kê 71.

Liệt kê 71. Chuyển hướng đầu vào với một tài-liệu-ngay sau đây
[ian@echidna lpi103]$ sort -k2 <<END 
> 1 apple 
> 2 pear 
> 3 banana 
> END 
1 apple 
3 banana 
2 pear

Bạn có nhớ cách bạn đã tạo tập tin text2 trong Liệt kê 23 ở trên không? Bạn có thể thắc mắc tại sao bạn không thể chỉ cần gõ sort -k2, nhập dữ liệu của bạn và sau đó nhấn Ctrl-d để báo hiệu kết thúc đầu vào. Và câu trả lời ngắn gọn là bạn có thể làm như thế, nhưng bạn sẽ không học được về khái niệm tài-liệu-ngay sau đây. Câu trả lời thực sự ở đây là các tài-liệu-ngay sau đây thường xuyên sử dụng nhiều hơn trong các kịch bản lệnh shell (được trình bày trong hướng dẫn cho chủ đề 109 về các shell, việc tạo kịch bản lệnh, lập trình và biên dịch). Một kịch bản lệnh không có cách nào khác để báo hiệu rằng dòng kịch bản lệnh nào phải được coi là đầu vào. Vì các kịch bản lệnh shell sử dụng rộng rãi việc nhấn tab (tabbing) để tạo chỗ thụt đầu dòng cho dễ đọc, có một cách lách khác cho tài-liệu-ngay sau đây. Nếu bạn sử dụng <<- thay vì chỉ là <<, thì các tab đứng đầu bị gỡ bỏ. Trong Liệt kê 72 chúng ta sử dụng kỹ thuật tương tự để tạo ra một ký tự tab bất đắc dĩ như chúng ta đã sử dụng trong Liệt kê 42. Sau đó chúng ta tạo ra một kịch bản lệnh shell rất nhỏ có chứa hai lệnh cat mỗi lệnh đọc từ một tài-liệu-ngay sau đây. Cuối cùng, chúng ta sử dụng lệnh . (dấu chấm) để bắt đầu kịch bản lệnh, có nghĩa là để chạy kịch bản lệnh trong bối cảnh shell hiện tại.

Liệt kê 72. Chuyển hướng đầu vào với một tài-liệu-ngay sau đây
[ian@echidna lpi103]$ ht=$(echo -en "\t") 
[ian@echidna lpi103]$ cat<<END>ex-here.sh
> cat <<-EOF 
> apple 
> EOF 
> ${ht}cat <<-EOF
> ${ht}pear 
> ${ht}EOF 
> END 
[ian@echidna lpi103]$ cat ex-here.sh 
cat <<-EOF 
apple 
EOF 
cat <<-EOF 
pear 
EOF
[ian@echidna lpi103]$ . ex-here.sh 
apple 
pear

Các đường ống

Trong phần về Các luồng văn bản và các bộ lọc chúng ta đã mô tả việc lọc văn bản như là quá trình lấy một luồng đầu vào của văn bản và thực hiện một số chuyển đổi trên văn bản đó trước khi gửi đến một luồng đầu ra. Chúng ta cũng đã nói rằng việc lọc thường được thực hiện bằng cách xây dựng một đường ống của các lệnh, ở đây đầu ra từ một lệnh được đặt đường ống hoặc được chuyển hướng để được sử dụng như đầu vào cho lệnh kế tiếp. Việc sử dụng các đường ống theo cách này không chỉ hạn chế cho luồng văn bản, mặc dù đó là nơi chúng thường được sử dụng.

Đặt đường ống dẫn luồng đầu ra tiêu chuẩn (stdout) tới luồng đầu vào tiêu chuẩn (stdin)

Như chúng ta đã nhận thấy, chúng ta sử dụng toán tử | (ống) giữa hai lệnh để hướng stdout của lệnh đầu tiên đến stdin của lệnh thứ hai. Chúng ta xây dựng các đường ống dài hơn bằng cách thêm lệnh nhiều hơn và nhiều toán tử ống hơn như trong Liệt kê 73.

Liệt kê 73. Đặt đường ống cho đầu ra qua một số lệnh
 command1 | command2 | command3

Một điều cần lưu ý là các đường ống chỉ dẫn bằng ống từ luồng đầu ra tiêu chuẩn tới luồng đầu vào tiêu chuẩn. Bạn không thể sử dụng 2| để đặt ống dẫn cho một mình báo lỗi tiêu chuẩn (strerr), ít nhất cũng là không làm được với các công cụ mà chúng ta đã tìm hiểu được cho đến nay. Nếu báo lỗi tiêu chuẩn đã được chuyển hướng đến luồng đầu ra tiêu chuẩn thì cả hai luồng sẽ được dẫn qua ống. Chúng ta minh họa điều này trong Liệt kê 74, ở đó chúng ta sử dụng một đường ống để sắp xếp cả các thông báo lỗi lẫn các thông báo đầu ra bình thường từ một lệnh ls hiếm xuất hiện với bốn đối số ký tự đại diện không theo thứ tự thứ tự chữ cái abc.

Liệt kê 74. Đặt đường ống cho hai luồng đầu ra
[ian@echidna lpi103]$ ls y* x* z* u* q* 2>&1 |sort 
ls: q*: No such file or directory 
ls: u*: No such file or directory 
ls: z*: No such file or directory 
xaa 
xab 
yaa 
yab

Bất kỳ lệnh nào trong đường ống đều có thể có các tùy chọn hoặc các đối số. Nhiều lệnh sử dụng một dấu nối (-) thay vào chỗ tên tập tin như là một đối số để biểu thị rằng đầu vào lấy từ luồng đầu vào tiêu chuẩn chứ không phải từ một tập tin. Hãy kiểm tra các trang hướng dẫn sử dụng của lệnh này cho chắc chắn. Việc xây dựng các đường ống kéo dài của nhiều lệnh mà mỗi lệnh có khả năng hạn chế là một cách phổ biến để hoàn thành nhiệm vụ của Linux và UNIX.

Một lợi thế của các ống trên các hệ thống Linux và UNIX là ở chỗ, không giống như một số hệ điều hành phổ biến khác, không có tập tin trung gian nào dính líu đến đường ống. Luồng đầu ra tiêu chuẩn của lệnh thứ nhất không được viết tới một tập tin và sau đó được lệnh thứ hai đọc. Nếu phiên bản lệnh tar của bạn không hỗ trợ giải nén các tập tin đã nén bằng bzip2, thì cũng không có vấn đề gì. Như chúng ta đã thấy trong hướng dẫn cho Chủ đề 102, bạn chỉ cần sử dụng một đường ống như là

bunzip2 -c drgeo-1.1.0.tar.bz2 | tar -xvf -

để thực hiện nhiệm vụ này.

Đầu ra làm các đối số

Trong phần Sử dụng dòng lệnh chúng ta đã tìm hiểu về thay thế lệnh và cách sử dụng đầu ra từ một lệnh như là một phần của lệnh khác. Trong phần trước Quản lý tập tin cơ bản chúng ta đã tìm hiểu về cách sử dụng tùy chọn -i của lệnh find để sử dụng đầu ra của lệnh find làm đầu vào cho lệnh khác. Liệt kê 75 cho thấy ba cách hiển thị nội dung của các tập tin text1 và text2 bằng cách sử dụng các kỹ thuật này.

Liệt kê 74. Sử dụng đầu ra làm các đối số với phép thay thế lệnh và lệnh find -exec
[ian@echidna lpi103]$ cat `ls text[12]` 
1 apple 
2 pear 
3 banana 
9 plum
3 banana 
10 apple 
[ian@echidna lpi103]$ cat $(find . -name "text[12]")
1 apple 
2 pear 
3 banana 
9 plum 
3 banana 
10 apple 
[ian@echidna lpi103]$ find . -name "text[12]" -exec cat '{}' \; 
1 apple 
2 pear 
3 banana 
9 plum 
3 banana 
10 apple

Những phương pháp trên là tốt cho đến khi chúng hoạt động, nhưng chúng có một số hạn chế. Chúng ta hãy xem xét trường hợp của một tên tập tin có chứa khoảng trắng (trong trường hợp này là một khoảng trống). Hãy xem xét Liệt kê 76 và xem liệu bạn có thể hiểu những gì đang xảy ra với mỗi một trong các lệnh trước khi đọc lời giải thích dưới đây.

Liệt kê 76. Sử dụng đầu ra làm các đối số với sự thay thế lệnh và lệnh find -exec
[ian@echidna lpi103]$ echo grapes>"text sample2" 
[ian@echidna lpi103]$ cat `ls text*le2` 
cat: text: No such file or directory 
cat: sample2: No such file or directory 
[ian@echidna lpi103]$ cat "`ls text*le2`" 
grapes 
[ian@echidna lpi103]$ cat "`ls text*2`" 
cat: text2
text sample2: No such file or directory

Dưới đây là những gì chúng ta đã làm.

  • Chúng ta đã tạo ra một tập tin gọi là "text sample2" có chứa một dòng có từ "grapes" (các quả nho).
  • Chúng ta đã cố gắng sử dụng phép thay thế lệnh để hiển thị nội dung của "text sample2". Việc hiển thị này không thành công vì shell đã chuyển hai tham số tới lệnh cat, cụ thể là text và sample2.
  • Vì ta thông minh hơn shell, chúng ta quyết định đặt dấu nháy kép quanh các giá trị thay thế lệnh. Lần này lệnh hoạt động được.
  • Cuối cùng, chúng ta đã thay đổi các biểu thức ký tự đại diện và đầu ra có một lỗi trông rất lạ. Điều xảy ra ở đây là shell cung cấp cho lệnh cat một tham số duy nhất tương đương với chuỗi ký tự là kết quả của

    echo -e "text2\ntext sample2"

    Nếu điều này có vẻ kỳ lạ, hãy tự thử nó!

Điều chúng ta cần ở đây là một cách nào đó để phân định các tên tập tin riêng lẻ, cho dù chúng gồm có một từ hoặc nhiều từ. Trước đó chúng ta chưa đề cập đến nó, nhưng khi đầu ra của các lệnh như ls được sử dụng trong một đường ống hoặc phép thay thế lệnh, đầu ra thường được xuất ra mỗi mục trên một dòng. Một phương pháp xử lý việc này là với một lệnh read dựng sẵn trong một vòng lặp while dựng sẵn. Mặc dù vượt quá phạm vi của mục tiêu này, chúng tôi minh họa nó để kích thích sự khao khát của bạn và làm dẫn nhập cho giải pháp mà chúng tôi sẽ trình bày tiếp theo.

Liệt kê 77. Sử dụng while và read trong vòng lặp
[ian@echidna lpi103]$ ls text*2 | while read l; do cat "$l";done 
9 plum 
3 banana 
10 apple 
grapes

Lệnh xargs

Hầu hết thời gian chúng ta muốn xử lý các danh sách các tập tin, do đó, những gì chúng ta thực sự cần là một số cách để tìm chúng và sau đó xử lý chúng. May mắn thay, lệnh find có một tùy chọn, -print0, phân tách các tên tập tin đầu ra bằng một ký tự null thay cho một dòng mới. Các lệnh như tarxargs có một tùy chọn -0 (hay --null cho phép chúng hiểu dạng tham số này. Chúng ta đã thấy lệnh tar. Lệnh xargs hoạt động hơi giống tùy chọn -exec của lệnh find, nhưng có một số sự khác biệt quan trọng như chúng ta sẽ thấy. Đầu tiên hãy xem xét một ví dụ.

Liệt kê 78. Sử dụng xargs với -0
[ian@echidna lpi103]$ find . -name "text*2" -print0 |xargs -0 cat 
9 plum 
3 banana 
10 apple 
1 apple 
2 pear 
3 banana 
grapes

Lưu ý rằng chúng ta bây giờ đặt đường ống cho đầu ra từ find đến xargs. Bạn không cần dấu chấm phẩy phân định ở cuối của lệnh và theo mặc định, xargs viết thêm các đối số vào chuỗi lệnh. Tuy nhiên, chúng ta có lẽ có bảy dòng đầu ra chứ không phải bốn dòng như đã dự kiến. Điều gì đã xảy ra vậy?

Lại lệnh find

Chúng ta có thể sử dụng lệnh wc để kiểm tra rằng chỉ có bốn dòng đầu ra trong hai tập tin mà chúng ta nghĩ rằng đã in ra. Câu trả lời cho vấn đề của chúng ta nằm trong sự kiện là lệnh find đang tìm kiếm thư mục sao lưu của chúng ta, ở đó lệnh này cũng tìm thấy backup/text1.bkp.2 khớp với mẫu ký tự đại diện của chúng ta. Để giải quyết điều này, chúng ta sử dụng tùy chọn -maxdepth của lệnh find để hạn chế độ sâu tìm kiếm trong một thư mục, thư mục hiện tại. Ngoài ra còn có một tùy chọn tương ứng -mindepth cho phép bạn xác định khá cụ thể nơi bạn tìm kiếm. Liệt kê 79 minh họa giải pháp cuối cùng của chúng ta.

Liệt kê 79. Hạn chế tìm đến bốn dòng mong muốn của chúng ta
[ian@echidna lpi103]$ ls text*2
text2 text sample2 
[ian@echidna lpi103]$ wc text*2 
    3 6 25 text2 
    1 1  7 text sample2 
    4 7 32 total 
[ian@echidna lpi103]$ find . -name "text*2" -maxdepth 1 -print0 |xargs -0 cat 
9 plum 
3 banana 
10 apple 
grapes

Nói thêm về lệnh xargs

Có một số khác biệt nữa giữa lệnh xargsfind -exec.

  • Lệnh xargs mặc định sẽ chuyển càng nhiều các đối số càng tốt cho lệnh. Bạn có thể giới hạn số lượng các dòng đầu vào được sử dụng với -l hoặc --max-lines và một con số. Ngoài ra, bạn có thể sử dụng -n hoặc --max-args để giới hạn số lượng các đối số được chuyển qua, hoặc -s hoặc --max-chars để hạn chế số lượng tối đa các ký tự được sử dụng trong chuỗi ký tự biểu thị đối số. Nếu lệnh của bạn có thể xử lý nhiều đối số, thì nói chung thường hiệu quả hơn nếu xử lý một lần càng nhiều càng tốt.
  • Bạn có thể sử dụng '{}' như bạn đã làm với find -exec nếu bạn chỉ rõ tùy chọn -i hoặc --replace. Bạn có thể thay đổi phần mặc định của '{}' bằng một chuỗi ký tự, biểu thị rõ thay thế các tham số đầu vào ở đâu bằng cách chỉ rõ một giá trị với -i. Điều này hàm ý là -l 1.

Ví dụ cuối cùng của chúng ta với xargs được hiển thị trong Liệt kê 80.

Liệt kê 80. Các ví dụ thêm về xargs
[ian@echidna lpi103]$ # pass all arguments at once 
[ian@echidna lpi103]$ find . -name "text*2" |xargs echo 
./text2 ./backup/text1.bkp.2 ./text sample2 
[ian@echidna lpi103]$ # show the files we created earlier with the touch command 
[ian@echidna lpi103]$ ls f[0-n]*|xargs echo 
f1 f1a f2 f3 f4 f5 f6 f7 f8 f9 
[ian@echidna lpi103]$ # remove them in one stroke 
[ian@echidna lpi103]$ ls f[0-n]*|xargs rm 
[ian@echidna lpi103]$ # Use a replace string
[ian@echidna lpi103]$ find . -name "text*2" |xargs -i echo - '{}' - 
- ./text2 - 
- ./backup/text1.bkp.2 - 
- ./text sample2 - 
[ian@echidna lpi103]$ # Limit of one input line per invocation 
[ian@echidna lpi103]$ find . -name "text*2" |xargs -l1 echo 
./text2
./backup/text1.bkp.2 
./text sample2 
[ian@echidna lpi103]$ # Limit of one argument per invocation 
[ian@echidna lpi103]$ find . -name "text*2" |xargs -n1 echo 
./text2 
./backup/text1.bkp.2 
./text sample2

Lưu ý rằng chúng ta đã không sử dụng -print0 ở đây. Việc đó có giải thích ví dụ cuối cùng trong Liệt kê 80 không?

Phân tách đầu ra

Phần này kết thúc bằng một cuộc thảo luận ngắn gọn về một lệnh nữa. Đôi khi bạn có thể muốn nhìn thấy kết quả đầu ra trên màn hình của bạn trong khi vẫn lưu một bản sao về sau. Mặc dù bạn có thể làm điều này bằng cách chuyển hướng đầu ra lệnh tới một tập tin trong một cửa sổ và rồi sử dụng lệnh tail -fn1 để theo dõi đầu ra trong màn hình khác, việc sử dụng lệnh tee sẽ dễ dàng hơn.

Bạn sử dụng lệnh tee với một đường ống. Các đối số là một tập tin (hoặc nhiều tập tin) làm đầu ra tiêu chuẩn. Các tùy chọn -a viết thêm vào chứ không viết đè lên tập tin. Như chúng ta đã thấy ở trên trong thảo luận của chúng ta về các đường ống, bạn cần phải chuyển hướng báo lỗi tiêu chuẩn tới luồng đầu ra tiêu chuẩn trước khi đặt đường ống tới lệnh tee nếu bạn muốn lưu cả hai. Liệt kê 81 cho thấy lệnh tee đang được sử dụng để lưu đầu ra trong hai tập tin, f1 và f2.

Liệt kê 81. Phân tách đầu ra tiêu chuẩn bằng lệnh tee
[ian@echidna lpi103]$ ls text[1-3]|tee f1 f2 
text1 
text2 
text3 
[ian@echidna lpi103]$ cat f1
text1 
text2 
text3 
[ian@echidna lpi103]$ cat f2 
text1 
text2 
text3

Tạo, theo dõi và tắt các tiến trình

Phần này trình bày tư liệu cho chủ đề 1.103.5 cho kỳ thi quản trị trình độ sơ cấp (LPIC-1) 101. Chủ đề này có trọng số 5.

Trong phần này, bạn tìm hiểu về các chủ đề sau đây:

  • Các công việc nền trước và nền sau.
  • Bắt đầu các tiến trình mà không có một thiết bị đầu cuối cho vào ra (I/O).
  • Theo dõi và hiển thị các tiến trình.
  • Gửi các tín hiệu tới các tiến trình.
  • Nhận biết và tắt các tiến trình.

Nếu bạn ngừng suy nghĩ một lát, thật khá rõ ràng là rất nhiều thứ đang chạy trên máy tính của bạn, ngoài các chương trình đầu cuối mà chúng ta vẫn đang chạy. Thật vậy, nếu bạn đang sử dụng một màn hình nền đồ họa, bạn có thể đã mở nhiều hơn một cửa sổ đầu cuối một lúc hoặc có lẽ đã mở một trình duyệt tập tin, trình duyệt internet, trò chơi, bảng tính hoặc ứng dụng khác. Cho đến nay, các ví dụ của chúng ta đã nhập các lệnh tại một cửa sổ đầu cuối. Lệnh chạy và chúng ta chờ đợi cho nó hoàn thành trước khi chúng ta làm bất cứ điều gì khác. Trong phần Sử dụng dòng lệnh, chúng ta đã bắt gặp lệnh ps đã hiển thị trạng thái tiến trình và chúng ta đã thấy rằng các tiến trình có một mã nhận dạng tiến trình (PID) và một mã nhận dạng tiến trình cha mẹ (Parent Process id - PPID). Trong phần này, bạn tìm hiểu làm thế nào để làm nhiều hơn một việc cùng một lúc khi sử dụng cửa sổ đầu cuối của bạn.

Các công việc nền trước và nền sau

Khi bạn chạy một lệnh trong cửa sổ đầu cuối của bạn, chẳng hạn như chúng ta đã làm đến thời điểm này, bạn đang chạy nó trên nền trước. Các lệnh của chúng ta cho đến nay đã chạy rất nhanh, nhưng giả sử chúng ta đang chạy một màn hình nền đồ họa và muốn một chiếc đồng hồ hiện số được hiển thị trên màn hình nền. Tạm thời, chúng ta hãy bỏ qua thực tế là hầu hết các máy tính để bàn đều có một đồng hồ hiện số hiển thị trên màn hình nền rồi, ta chỉ sử dụng điều này như một ví dụ thôi.

Nếu bạn đã cài đặt hệ thống Window X, bạn cũng có thể có một số tiện ích như xclock hay xeyes. Cả hai tiện ích đều tốt cho bài tập tin này, nhưng chúng ta sẽ sử dụng xclock. Trang hướng dẫn sử dụng giải thích rằng bạn có thể khởi chạy một chiếc đồng hồ hiện số trên màn hình nền đồ họa của bạn khi sử dụng lệnh

xclock -d -update 1

Phần -update 1 yêu cầu cập nhật mỗi giây, nếu không đồng hồ này chỉ cập nhật mỗi phút. Vậy ta hãy chạy đồng hồ này trong một cửa sổ đầu cuối. Chúng ta sẽ thấy một đồng hồ giống như Hình 2 và cửa sổ đầu cuối của chúng ta sẽ giống như Liệt kê 82. Nếu bạn không có xclock hoặc hệ thống Window X, chúng tôi sẽ cho bạn thấy cách ngắn gọn để tạo đồng hồ hiện số của người nghèo với thiết bị đầu cuối của bạn, để cho bạn có thể tiếp tục ngay lúc này và sau đó thử lại các bài tập tin này bằng đồng hồ đó.

Hình 2. Một đồng hồ hiện số với xclock
Một đồng hồ hiện số với xclock
Liệt kê 82. Khởi động xclock
[ian@echidna ian]$ xclock -d -update 1

Thật không may, cửa sổ đầu cuối của bạn không có một dấu nhắc nữa, vì thế chúng ta thực sự cần phải lấy lại quyền điều khiển. May mắn thay, bash shell có một phím tạm dừng (suspend) là Ctrl-z. Nhấn tổ hợp phím này sẽ mang lại cho bạn một dấu nhắc đầu cuối như trong Liệt kê 83.

Liệt kê 83. Tạm dừng xclock bằng Ctrl-z
[ian@echidna ian]$ xclock -d -update 1 
[1]+  Stopped       xclock -d -update 1 
[ian@echidna ian]$

Đồng hồ này vẫn còn trên màn hình nền của bạn, nhưng nó đã ngừng chạy. Việc tạm dừng nó đã thực hiện chính xác điều đó. Trong thực tế, nếu bạn kéo một cửa sổ khác đè lên một phần của nó, thì phần đó thậm chí sẽ không được vẽ lại. Bạn cũng thấy một thông báo đầu ra tại đầu cuối biểu thị "[1]+  Stopped". 1 trong thông báo này là số hiệu công việc. Bạn có thể khởi động lại đồng hồ bằng cách gõ fg %1. Bạn cũng có thể sử dụng tên lệnh hay một phần của nó bằng cách sử dụng fg %xclock hay fg %?clo. Cuối cùng, nếu bạn chỉ cần sử dụng lệnh fg không có các tham số, bạn có thể khởi động lại công việc đã bị dừng lại gần đây nhất, công việc 1 trong trường hợp này. Khởi động lại nó bằng lệnh fg cũng làm cho công việc phải quay trở lại ở ngay nền trước và bạn không còn có một dấu nhắc shell nữa. Những gì bạn cần làm là đặt công việc trong nền sau; một lệnh bg có kiểu đặc tả công việc giống như lệnh fg và thực hiện chính xác điều đó. Liệt kê 84 cho thấy cách làm cho công việc xclock quay trở lại nền trước và tạm dừng nó bằng cách sử dụng hai dạng của lệnh fg.. Bạn có thể tạm dừng nó lại một lần nữa và đặt nó trong nền sau; đồng hồ tiếp tục chạy trong khi bạn làm công việc khác tại cửa sổ đầu cuối của bạn.

Liệt kê 84. Đặt xclock trong nền sau
[ian@echidna ian]$ fg %1 
xclock -d -update 1 

[1]+ Stopped         xclock -d -update 1 
[ian@echidna ian]$ fg %?clo 
xclock -d -update 1 

[1]+ Stopped         xclock -d -update 1 
[ian@echidna ian]$ bg 
[1]+ xclock -d -update 1 & 
[ian@echidna ian]$

Sử dụng "&"

Bạn có thể đã nhận thấy rằng khi chúng ta đặt công việc xclock vào nền sau, thông báo không còn nói "Đã dừng" (Stopped) nữa và nó đã được kết thúc bằng một ký hiệu “&”. Thực ra bạn không cần phải tạm dừng quá trình để đặt nó vào nền sau. Bạn chỉ cần viết nối thêm một ký hiệu “&” vào lệnh đó và shell sẽ bắt đầu lệnh (hoặc danh sách lệnh) trong nền sau. Ta hãy khởi động một đồng hồ kim có một nền sau màu vàng nhạt và các kim đỏ, sử dụng phương pháp này. Bạn sẽ thấy một đồng hồ giống như trong Hình 3 và cửa sổ đầu cuối như Liệt kê 85.

Hình 3. Một đồng hồ kim với xclock
Một đồng hồ hiện kim với xclock
Liệt kê 85. Khởi động xclock trong nền sau bằng ký hiệu &
[ian@echidna ian]$ xclock -bg wheat -hd red -update 1& 
[2] 5659

Lưu ý rằng thông báo lần này hơi khác. Nó biểu diễn một số hiệu công việc và một mã nhận dạng tiến trình (PID). Một lát nữa chúng ta sẽ trình bày các PID và nhiều hơn nữa về trạng thái. Bây giờ, chúng ta hãy sử dụng lệnh jobs để tìm ra những công việc nào đang chạy. Thêm tùy chọn -l vào danh sách PID và bạn thấy rằng công việc 2 thực sự có PID 5659 như trong Liệt kê 86. Cũng lưu ý rằng công việc 2 có một dấu cộng (+) bên cạnh số hiệu công việc, báo hiệu rằng đó là công việc hiện tại. Công việc này sẽ trở lại nền trước nếu không có đặc tả công việc nào được đưa ra với lệnh fg.

Liệt kê 86. Hiển thị công việc và thông tin tiến trình
[ian@echidna ian]$ jobs -l 
[1]-   4234 Running    xclock -d -update 1 & 
[2]+   5659 Running    xclock -bg wheat -hd red -update 1 &

Trước khi chúng ta tập trung vào một số vấn đề khác liên quan đến các công việc nền sau, chúng ta hãy tạo một đồng hồ hiện số của người nghèo. Chúng ta sử dụng lệnh sleep để tạo ra độ trễ hai giây và chúng ta sử dụng lệnh date để in ngày tháng và thời giờ hiện tại. Chúng ta bọc các lệnh này trong một vòng lặp while với một khối do/done để tạo ra một vòng lặp vô hạn. Cuối cùng chúng ta đặt toàn bộ lô đó trong các dấu ngoặc đơn để tạo ra một danh sách lệnh và đưa toàn bộ danh sách vào nền sau, sử dụng một ký hiệu &.

Liệt kê 87. Đồng hồ hiện số của người nghèo
[ian@echidna ian]$ (while sleep 2; do date;done) & 
[1] 16291 
[ian@echidna ian]$ Thu Nov 10 22:58:02 EST 2005 
Thu Nov 10 22:58:04 EST 2005 
Thu Nov 10 22:58:06 EST 2005 
Thu Nov 10 22:58:08 EST 2005 
fThu Nov 10 22:58:10 EST 2005
Thu Nov 10 22:58:12 EST 2005 
gThu Nov 10 22:58:14 EST 2005 
( while sleep 2; do 
     date; 
done ) 
Thu Nov 10 22:58:16 EST 2005 
Thu Nov 10 22:58:18 EST 2005

Theo dự kiến, danh sách của chúng ta đang chạy như là công việc 1 với PID 16291. Cứ mỗi hai giây, lệnh date chạy và một ngày tháng và thời giờ được in ra thiết bị đầu cuối. Đầu vào mà bạn gõ được tô đậm. Một người đánh máy chậm sẽ có các ký tự chen lẫn rải rác với một vài dòng đầu ra trước khi gõ vào toàn bộ lệnh. Thực vậy, lưu ý rằng 'f' 'g' mà chúng ta gõ vào để đưa danh sách lệnh tới nền trước đã tách rời vài dòng như thế nào. Cuối cùng khi chúng ta đã có lệnh fg được nhập vào, bash hiển thị lệnh bây giờ đang chạy trong shell của chúng ta, cụ thể là, danh sách lệnh vẫn còn sẵn sàng in ra thời gian cứ mỗi hai giây.

Sau khi chúng ta đã thành công trong việc đưa công việc lên nền trước, chúng ta có thể hoặc kết thúc (hay kill), hoặc có một số hành động khác, trong trường hợp này, chúng ta sử dụng Ctrl-c để kết thúc 'đồng hồ' của chúng ta.

Vào ra tiêu chuẩn và các tiến trình nền sau

Đầu ra từ lệnh date trong ví dụ trước của chúng ta được xen kẽ rải rác với các ký được dội lại dành cho lệnh fg mà chúng ta đang cố gắng gõ vào. Điều này đặt ra một vấn đề thú vị. Điều gì xảy ra với một tiến trình nếu nó cần đầu vào từ luồng đầu vào tiêu chuẩn?

Tiến trình đầu cuối trong đó chúng ta bắt đầu một ứng dụng nền sau được gọi là đầu cuối điều khiển. Trừ khi chuyển hướng tới nơi khác, các luồng đầu ra tiêu chuẩn và báo lỗi tiêu chuẩn từ tiến trình nền sau được hướng tới đầu cuối điều khiển. Tương tự như vậy, nhiệm vụ nền sau đòi hỏi đầu vào từ đầu cuối điều khiển, nhưng đầu cuối điều khiển không có cách nào để gửi các ký tự bạn nhập vào đầu vào tiêu chuẩn của một quá trình nền sau. Trong trường hợp như vậy, Bash shell tạm dừng tiến trình này, để nó không còn chạy nữa. Bạn có thể mang nó lên nền trước và cung cấp đầu vào cần thiết. Liệt kê 88 minh họa một trường hợp đơn giản ở đó bạn có thể đặt một danh sách lệnh trong nền sau. Sau một lúc, nhấn Enter và tiến trình dừng lại. Hãy mang nó lên nền trước và tạo một dòng đầu vào tiếp theo bằng Ctrl-d để báo hiệu kết thúc tập tin đầu vào. Danh sách lệnh hoàn tất và chúng ta hiển thị tập tin mà chúng ta đã tạo ra.

Liệt kê 88. Đang chờ đầu vào tiêu chuẩn
[ian@echidna ian]$ (date; cat - >bginput.txt; date)& 
[1] 18648 
[ian@echidna ian]$ Fri Nov 11 00:03:28 EST 2005

[1]+ Stopped ( date; cat - >bginput.txt; date ) 
[ian@echidna ian]$ fg 
( date; cat - >ginput.txt; date ) 
input data 
Fri Nov 11 00:03:53 EST 2005 
[ian@echidna ian]$ cat bginput.txt 
input data

Các công việc không có các đầu cuối

Trong thực tế, chúng ta có lẽ muốn có các luồng vào ra tiêu chuẩn cho các tiến trình nền sau được chuyển hướng đến hoặc từ một tập tin. Có một câu hỏi liên quan khác; điều gì xảy ra với quá trình đó nếu đầu cuối điều khiển đóng hoặc người sử dụng rời khỏi hệ thống? Câu trả lời phụ thuộc vào shell đang sử dụng. Nếu shell đó gửi một tín hiệu SIGHUP (hoặc gác máy), thì nhiều khả năng ứng dụng sẽ đóng lại. Chúng ta trình bày các tín hiệu một cách ngắn gọn, nhưng bây giờ chúng ta sẽ xem xét một cách khác để tránh vấn đề này.

Lệnh nohup

Lệnh nohup được sử dụng để bắt đầu một lệnh sẽ bỏ qua các tín hiệu gác máy và sẽ viết thêm đầu ra tiêu chuẩn và báo lỗi tiêu chuẩn vào một tập tin. Tập tin mặc định hoặc là nohup.out hoặc là $HOME/nohup.out. Nếu không thể viết vào tập tin được, thì lệnh sẽ không chạy. Nếu bạn muốn đầu ra đi tới một nơi khác, hãy chuyển hướng đầu ra tiêu chuẩn và báo lỗi tiêu chuẩn như chúng ta đã tìm hiểu trong phần trước của hướng dẫn này.

Một khía cạnh khác của lệnh nohup là nó sẽ không thi hành một đường ống hoặc một danh sách lệnh. Trong chủ đề Chuyển hướng vào ra tiêu chuẩn là nó sẽ không thi hành một đường ống hoặc một danh sách lệnh. Trong chủ đề Chuyển hướng vào ra tiêu chuẩn chúng ta đã chỉ ra cách lưu một tập hợp của các lệnh trong một kịch bản lệnh shell và bắt đầu nó. Bạn có thể lưu trữ một đường ống hoặc một danh sách trong một tập tin và sau đó chạy nó bằng cách sử dụng lệnh sh (shell mặc định) hay lệnh bash mặc dù bạn không thể sử dụng . hoặc lệnh source như chúng ta đã làm trong ví dụ trước đó. Hướng dẫn tiếp theo trong loạt bài này (về chủ đề 104, trình bày Các thiết bị, các hệ thống tập tin Linux và tiêu chuẩn phân cấp hệ thống tập tin) cho thấy cách làm cho tập tin kịch bản lệnh có thể thi hành được, nhưng bây giờ chúng ta sẽ bám sát việc chạy các kịch bản lệnh bằng cách bắt đầu chúng hoặc bằng cách sử dụng lệnh sh hay lệnh bash. Liệt kê 89 cho thấy cách chúng ta có thể thực hiện điều này với đồng hồ hiện số cho người nghèo của chúng ta. Không cần phải nói, việc viết thời giờ vào một tập tin không có ích lợi gì đặc biệt và tập tin đó ngày càng lớn, vì vậy chúng ta sẽ đặt đồng hồ để cập nhật cứ mỗi 30 giây thay vì cứ mỗi một giây.

Liệt kê 89. Sử dụng lệnh nohup với một danh sách lệnh trong một kịch bản lệnh
[ian@echidna ian]$ echo "while sleep 30; do date;done">pmc.sh 
[ian@echidna ian]$ nohup . pmc.sh& 
[1] 21700 
[ian@echidna ian]$ nohup: appending output to `nohup.out' 

[1]+    Exit 126       nohup . pmc.sh 
[ian@echidna ian]$ nohup sh pmc.sh& 
[1] 21709 
[ian@echidna ian]$ nohup: appending output to `nohup.out' 

[ian@echidna ian]$ nohup bash pmc.sh& 
[2] 21719 
[ian@echidna ian]$ nohup: appending output to `nohup.out'

Nếu chúng ta hiển thị nội dung của tập tin nohup.out, chúng ta thấy rằng dòng đầu tiên cho thấy lý do tại sao chúng ta đã nhận một mã kết thúc là 126 cho nỗ lực đầu tiên của chúng ta ở trên. Các dòng tiếp theo sẽ là đầu ra từ hai phiên bản của tập tin pmc.sh hiện đang chạy trong nền sau. Điều này được minh họa trong Liệt kê 90.

Liệt kê 90. Đầu ra từ các tiến trình nohup
[ian@echidna ian]$ cat nohup.out 
/bin/nice: .: Permission denied 
Fri Nov 11 15:30:03 EST 2005 
Fri Nov 11 15:30:15 EST 2005 
Fri Nov 11 15:30:33 EST 2005 
Fri Nov 11 15:30:45 EST 2005 
Fri Nov 11 15:31:03 EST 2005

Bây giờ hãy tập trung sự chú ý của chúng ta vào trạng thái của các tiến trình của chúng ta. Nếu bạn đang theo dõi đến đây và đặt kế hoạch tạm nghỉ ngơi vào lúc này, xin vui lòng ở lại thêm vì bây giờ bạn có hai công việc đang tạo ra các tập tin lớn mãi lên trong hệ thống tập tin của bạn. Bạn có thể sử dụng lệnh fg để đưa mỗi công việc trở lại nền trước và sau đó sử dụng Ctrl-c để kết thúc nó, nhưng nếu bạn để cho chúng chạy lâu hơn một chút thì chúng ta sẽ thấy các cách khác để giám sát và tương tác với chúng.

Trạng thái của tiến trình

Trong mục trước của phần này, chúng ta đã có một giới thiệu ngắn gọn về lệnh jobs và đã thấy làm thế nào sử dụng lệnh này để liệt kê các mã nhận dạng tiến trình (hay các PID) của các công việc của chúng ta.

Lệnh ps

Còn có một lệnh khác, lệnh ps mà chúng ta sử dụng để hiển thị các mẩu thông tin khác nhau về trạng thái của tiến trình. Hãy nhớ rằng "ps" là một từ viết tắt của "trạng thái của tiến trình". Lệnh ps chấp nhận không hoặc nhiều PID làm đối số và hiển thị trạng thái tiến trình có liên quan. Nếu chúng ta sử dụng lệnh jobs với tùy chọn -p, đầu ra chỉ đơn giản là PID của đầu nhóm tiến trình cho từng công việc. Chúng ta sẽ sử dụng đầu ra này làm các đối số cho lệnh ps như trong Liệt kê 91.

Liệt kê 91. Trạng thái của các tiến trình nền sau
[ian@echidna ian]$ jobs 
[1]- Running nohup sh pmc.sh & 
[2]+ Running nohup bash pmc.sh &
[ian@echidna ian]$ jobs -p 
21709 
21719 
[ian@echidna ian]$ ps `jobs -p`
  PID TTY   STAT TIME COMMAND 
21709 pts/3 SN   0:00 sh pmc.sh 
21719 pts/3 SN   0:00 bash pmc.sh

Nếu chúng ta sử dụng lệnh ps không có tùy chọn nào, chúng ta thấy một danh sách các tiến trình mà đầu cuối của chúng ta là đầu cuối điều khiển của chúng, như được hiển thị trong Liệt kê 92.

Liệt kê 92. Hiển thị trạng thái bằng lệnh ps
[ian@echidna ian]$ ps 
  PID TTY   TIME     CMD 
20475 pts/3 00:00:00 bash 
21709 pts/3 00:00:00 sh 
21719 pts/3 00:00:00 bash
21922 pts/3 00:00:00 sleep 
21930 pts/3 00:00:00 sleep 
21937 pts/3 00:00:00 ps

Một số tùy chọn, bao gồm -f (full - đầy đủ), -j (jobs - các công việc) và -l (long - dài) giúp kiểm soát có bao nhiêu thông tin được hiển thị. Nếu chúng ta không xác định bất kỳ PID nào, thì một tùy chọn có ích khác là --forest, hiển thị các lệnh trong một hệ phân cấp dạng cây, hiển thị cho chúng ta tiến trình nào là tiến trình con, tiến trình nào là tiến trình cha mẹ. Đặc biệt, chúng ta thấy rằng các lệnh sleep của liệt kê trước đó là tiến trình con của kịch bản lệnh mà chúng ta đang chạy trong nền sau. Nếu chúng ta chạy lệnh đó tại một lúc khác, chúng ta có thể thấy lệnh date được liệt kê thay vào đó trong trạng thái tiến trình, nhưng sự cọc cạch này là rất nhỏ bé so với kịch bản lệnh này. Chúng ta minh họa một số trong số các trạng thái này trong Liệt kê 93.

Liệt kê 93. Thêm nhiều thông tin trạng thái
[ian@echidna ian]$ ps -f 
UID PID    PPID C STIME TTY   TIME     CMD 
ian 20475 20474 0 15:02 pts/3 00:00:00 -bash 
ian 21709 20475 0 15:29 pts/3 00:00:00 sh pmc.sh 
ian 21719 20475 0 15:29 pts/3 00:00:00 bash pmc.sh 
ian 21945 21709 0 15:34 pts/3 00:00:00 sleep 30 
ian 21953 21719 0 15:34 pts/3 00:00:00 sleep 30 
ian 21954 20475 0 15:34 pts/3 00:00:00 ps -f 
[ian@echidna ian]$ ps -j --forest
  PID PGID   SID  TTY   TIME     CMD 
20475 20475 20475 pts/3 00:00:00 bash 
21709 21709 20475 pts/3 00:00:00 sh 
21945 21709 20475 pts/3 00:00:00 \_ sleep 
21719 21719 20475 pts/3 00:00:00 bash 
21953 21719 20475 pts/3 00:00:00 \_ sleep 
21961 21961 20475 pts/3 00:00:00 ps

Liệt kê các tiến trình khác

Lệnh ps mà chúng ta đã sử dụng cho đến nay chỉ liệt kê các tiến trình đã được bắt đầu từ phiên đầu cuối của bạn (lưu ý các cột SID trong ví dụ thứ hai của Liệt kê 93). Để xem tất cả các tiến trình cùng với các đầu cuối điều khiển chúng, hãy sử dụng tùy chọn -a. Tùy chọn -x hiển thị các tiến trình không có một đầu cuối điều khiển và tùy chọn -e hiển thị thông tin cho mỗi tiến trình. Liệt kê 94 cho thấy định dạng đầy đủ cho tất cả các tiến trình có một đầu cuối điều khiển.

Liệt kê 94. Hiển thị các tiến trình khác
[ian@echidna ian]$ ps -af 
UID  PID  PPID  C STIME TTY   TIME     CMD 
ian  4234 32537 0 Nov10 pts/0 00:00:00 xclock -d -update 1
ian  5659 32537 0 Nov10 pts/0 00:00:00 xclock -bg wheat -hd red -update
ian 21709 20475 0 15:29 pts/3 00:00:00 sh pmc.sh 
ian 21719 20475 0 15:29 pts/3 00:00:00 bash pmc.sh 
ian 21969 21709 0 15:35 pts/3 00:00:00 sleep 30 
ian 21977 21719 0 15:35 pts/3 00:00:00 sleep 30 
ian 21978 20475 0 15:35 pts/3 00:00:00 ps -af

Lưu ý rằng liệt kê này bao gồm hai tiến trình xclock mà chúng ta đã bắt đầu ở trên từ trong đầu cuối đồ họa chính của hệ thống này (được biểu thị ở đây bằng pts/0), trong khi các tiến trình còn lại được hiển thị là các tiến trình kết hợp với một kết nối ssh (Secure Shell) (trong trường hợp này là pts/3).

Còn nhiều tùy chọn hơn nữa cho lệnh ps, bao gồm một số cung cấp khả năng kiểm soát đáng kể đối với các trường nào được hiển thị và cách chúng được hiển thị. Các tùy chọn khác cung cấp khả năng kiểm soát đối với sự lựa chọn các quá trình để hiển thị, ví dụ, bằng cách chọn những tiến trình dành cho một người dùng cụ thể. Xem các trang hướng dẫn sử dụng cho lệnh ps để biết chi tiết đầy đủ hoặc sử dụng lệnh ps --help để có được một bản tóm tắt ngắn gọn.

Lệnh top

Nếu bạn chạy lệnh ps nhiều lần trong một hàng, để xem những gì đang thay đổi, có lẽ bạn cần lệnh top thay vào đó. Lệnh này sẽ hiển thị một danh sách các tiến trình được cập nhật liên tục, cùng với thông tin tóm tắt có ích. Xem những trang hướng dẫn sử dụng của lệnh top để biết chi tiết đầy đủ về các tùy chọn, bao gồm cách sắp xếp theo mức sử dụng bộ nhớ hoặc theo những tiêu chí khác. Liệt kê 95 cho thấy vài dòng đầu tiên của một màn hình hiển thị lệnh top.

Liệt kê 95. Hiển thị các quá trình khác
 3:37pm up 46 days, 5:11, 2 users, load average: 0.01, 0.17, 0.19 
96 processes: 94 sleeping, 1 running, 0 zombie, 1 stopped 
CPU states: 0.1% user, 1.0% system, 0.0% nice, 0.9% idle 
Mem: 1030268K av, 933956K used, 96312K free, 0K shrd, 119428K buff 
Swap: 1052216K av, 1176K used, 1051040K free 355156K cached 
  PID USER PRI NI   SIZE RSS   SHARE STAT %CPU %MEM TIME COMMAND 
22069 ian   17  0   1104 1104    848 R     0.9  0.1 0:00 top 
    1 root   8  0    500  480    444 S     0.0  0.0 0:04 init 
    2 root   9  0      0    0      0 SW    0.0  0.0 0:00 keventd 
    3 root   9  0      0    0      0 SW    0.0  0.0 0:00 kapmd 
    4 root  19 19      0    0      0 SWN   0.0  0.0 0:00 ksoftirqd_CPU0 
    5 root   9  0      0    0      0 SW    0.0  0.0 0:00 kswapd

Các tín hiệu

Bây giờ chúng ta hãy xem xét các tín hiệu của Linux. Các tín hiệu này là một cách không đồng bộ để truyền thông với các tiến trình. Chúng ta đã đề cập đến tín hiệu SIGHUP và chúng ta đã sử dụng cả hai tổ hợp phím Ctrl-c và Ctrl-z, đây cũng là những cách khác để gửi một tín hiệu tới các tiến trình. Cách phổ biến để gửi một tín hiệu là bằng lệnh kill (tắt).

Gửi tín hiệu bằng cách sử dụng lệnh kill

Lệnh kill gửi một tín hiệu đến một công việc hoặc tiến trình cụ thể. Liệt kê 96 cho thấy việc sử dụng các tín hiệu SIGTSTP và SIGCONT để tạm dừng và tiếp tục lại một công việc nền sau. Sử dụng tín hiệu SIGTSTP tương đương với việc sử dụng lệnh fg để đưa công việc lên nền trước và sau đó dùng Ctrl-z để tạm dừng nó. Sử dụng tín hiệu SIGCONT cũng giống như việc sử dụng lệnh bg.

Liệt kê 96. Dừng và khởi động lại các công việc nền sau
[ian@echidna ian]$ kill -s SIGTSTP %1 
[ian@echidna ian]$ jobs -l 
[1]+ 21709 Stopped           nohup sh pmc.sh 
[2]- 21719 Running           nohup bash pmc.sh & 
[ian@echidna ian]$ kill -s SIGCONT %1 
[ian@echidna ian]$ jobs -l 
[1]+ 21709 Running           nohup sh pmc.sh & 
[2]- 21719 Running           nohup bash pmc.sh &

Chúng ta sử dụng đặc tả công việc (%1) trong ví dụ này, nhưng bạn cũng có thể gửi tín hiệu cho một mã nhận dạng tiến trình (chẳng hạn như 21709 là PID của công việc %1). Nếu bạn sử dụng lệnh tail trong khi công việc %1 đã dừng lại, chỉ có một tiến trình đang cập nhật tập tin nohup.out thôi.

Có một số tín hiệu khác có thể dùng mà bạn có thể hiển thị trên hệ thống của mình bằng cách sử dụng lệnh kill -l. Một số tín hiệu được sử dụng để thông báo các lỗi, ví dụ như là mã phép toán không hợp lệ, các ngoại lệ dấu phẩy động hoặc lỗi cố gắng truy cập bộ nhớ mà tiến trình không có quyền truy cập vào. Chú ý rằng các tín hiệu vừa có một số hiệu như là 20 vừa có một tên, như SIGTSTP. Bạn có thể sử dụng hoặc số hiệu hoặc tên đó bằng tùy chọn -s. Bạn nên luôn luôn kiểm tra các số tín hiệu trên hệ thống của bạn trước khi giả định số nào thuộc về tín hiệu nào.

Các trình xử lý tín hiệu và kết thúc tiến trình

Chúng ta đã thấy rằng tổ hợp phím Ctrl-c kết thúc một tiến trình. Thực vậy, nó gửi một tín hiệu SIGINT (hoặc ngắt) tới tiến trình đó. Nếu bạn sử dụng lệnh kill mà không có bất cứ tên tín hiệu nào, thì nó sẽ gửi một tín hiệu SIGTERM. Đối với hầu hết các mục đích, hai tín hiệu này là tương đương.

Chúng ta đã nói rằng lệnh nohup làm cho một tiến trình miễn dịch với tín hiệu SIGHUP. Nói chung, một tiến trình có thể triển khai thực hiện một trình xử lý tín hiệu (signal handler) để bắt giữ các tín hiệu. Vì vậy, một tiến trình có thể triển khai thực hiện một trình xử lý tín hiệu để bắt giữ hoặc tín hiệu SIGINT hoặc tín hiệu SIGTERM. Vì trình xử lý tín hiệu biết được tín hiệu nào được gửi đi, nó có thể chọn để bỏ qua SIGINT và chỉ kết thúc khi nó nhận được SIGTERM, ví dụ thế. Liệt kê 97 cho thấy làm thế nào để gửi tín hiệu SIGTERM tới công việc %1. Lưu ý rằng trạng thái tiến trình hiển thị như là "Terminated – đã kết thúc" ngay sau khi chúng ta gửi tín hiệu đó. Trạng thái tiến trình này sẽ hiển thị như là "Interrupt - đã ngắt" nếu chúng ta sử dụng tín hiệu SIGINT thay vào đó. Sau một lát, việc dọn sạch tiến trình diễn ra và công việc này không còn hiển thị trong danh sách công việc nữa.

Liệt kê 97. Kết thúc một tiến trình bằng tín hiệu SIGTERM
[ian@echidna ian]$ kill -s SIGTERM %1 
[ian@echidna ian]$ jobs -l 
[1] 21709 Terminated      nohup sh pmc.sh 
[2]- 21719 Running        nohup bash pmc.sh & 
[ian@echidna ian]$ jobs -l 
[2]+ 21719 Running        nohup bash pmc.sh &

Các trình xử lý tín hiệu mang đến cho tiến trình một sự linh hoạt rất lớn, trong đó một tiến trình có thể thực hiện công việc bình thường của nó và bị ngắt bởi một tín hiệu với một mục đích đặc biệt nào đó. Ngoài việc cho phép một tiến trình bắt giữ các yêu cầu kết thúc và thực hiện các hành động có thể, ví dụ như đóng các tập tin hoặc tạo điểm kiểm tra các giao dịch đang tiếp diễn, các tín hiệu thường được sử dụng để báo cho một quá trình daemon (một trình tiện ích hoạt động kín đáo trong nền sau) đọc lại tập tin cấu hình của nó và có thể khởi động lại hoạt động. Bạn có thể làm điều này cho tiến trình inetd khi bạn thay đổi các tham số mạng hoặc cho daemon của máy in dòng (lpd) khi bạn thêm một máy in mới.

Kết thúc các tiến trình vô điều kiện

Một số tín hiệu không thể bắt giữ được, chẳng hạn như một số ngoại lệ phần cứng. SIGKILL, một trong những tín hiệu có khả năng nhất mà bạn sẽ sử dụng, không thể được bắt giữ bằng một trình xử lý tín hiệu và nó kết thúc vô điều kiện một tiến trình. Nói chung, bạn chỉ phải làm việc này khi tất cả các phương tiện khác để kết thúc tiến trình đều thất bại.

Đăng xuất và lệnh nohup

Hãy nhớ rằng chúng ta đã nói rằng việc sử dụng lệnh nohup sẽ cho phép các tiến trình của chúng ta tiếp tục chạy sau khi chúng ta đăng xuất. Vâng, chúng ta hãy làm điều đó và sau đó đăng nhập trở lại một lần nữa. Sau khi chúng ta đăng nhập lại, hãy kiểm tra tiến trình đồng hồ của người nghèo còn lưu lại của chúng ta bằng cách sử dụng lệnh jobsps như chúng ta đã làm ở trên. Kết quả đầu ra được thể hiện trong Liệt kê 98.

Liệt kê 98. Đăng nhập trở lại
[ian@echidna ian]$ jobs 
[ian@echidna ian]$ ps -a
  PID TTY   TIME     CMD 
 4234 pts/0 00:00:00 xclock 
 5659 pts/0 00:00:00 xclock
27217 pts/4 00:00:00 ps

Chúng ta thấy rằng lúc này chúng ta đang chạy trên pts/4, nhưng không có dấu hiệu nào về các công việc của chúng ta, chỉ có lệnh ps và hai tiến trình xclock chúng ta đã bắt đầu từ đầu cuối đồ họa (pts/0). Có lẽ không phải những gì chúng ta đang mong đợi. Tuy nhiên, tất cả không bị mất. Trong Liệt kê 99 chúng ta cho thấy một cách để tìm ra công việc bị mất bằng cách sử dụng tùy chọn -s cho mã nhận dạng phiên, cùng với mã nhận dạng phiên là 20475 mà chúng ta đã thấy trong Liệt kê 93. Hãy suy nghĩ về những cách khác mà bạn có thể đã tìm thấy nếu bạn không có mã nhận dạng phiên để sẵn dùng.

Liệt kê 99. Đăng nhập trở lại
[ian@echidna ian]$ ps -js 20475 
PID   PGID  SID   TTY TIME     CMD 
21719 21719 20475 ?   00:00:00 bash 
27335 21719 20475 ?   00:00:00 sleep

Dựa vào những gì bây giờ chúng ta đã biết về việc tắt các tiến trình, bạn sẽ có thể tắt các tiến trình bằng cách sử dụng PID của chúng và lệnh kill.


Các mức ưu tiên thực hiện tiến trình

Phần này trình bày tư liệu cho chủ đề 1.103.6 cho kỳ thi quản trị trình độ sơ cấp (LPIC-1) 101. Chủ đề này có trọng số 3.

Trong phần này, bạn tìm hiểu về các chủ đề sau đây:

  • Các mức ưu tiên thực hiện tiến trình.
  • Thiết lập mức ưu tiên.
  • Thay đổi mức ưu tiên

Các mức ưu tiên

Như chúng ta đã thấy trong phần trước, Linux, giống như hầu hết các hệ điều hành hiện đại, có thể chạy nhiều tiến trình. Linux thực hiện điều này bằng cách chia sẻ CPU và các tài nguyên khác giữa các tiến trình. Nếu một tiến trình nào đó có thể sử dụng 100% khả năng của CPU, thì các tiến trình khác có thể trở nên không đáp ứng. Khi chúng ta xem xét phần Trạng thái tiến trình ở trên, chúng ta đã thấy rằng kết quả đầu ra mặc định của lệnh top đã liệt kê các tiến trình theo thứ tự mức sử dụng CPU giảm dần. Nếu chúng ta đã chạy lệnh top với kịch bản lệnh đồng hồ của người nghèo của chúng ta, thì tiến trình này có lẽ sẽ không nằm trong danh sách vì nó hầu như không sử dụng CPU trong phần lớn thời gian hoạt động của mình.

Hệ thống của bạn có thể có nhiều lệnh có khả năng sử dụng rất nhiều CPU. Ví dụ như các công cụ chỉnh sửa phim, các chương trình để chuyển đổi giữa các kiểu hình ảnh khác nhau hoặc giữa các hệ mã hóa âm thanh khác nhau, chẳng hạn như mp3 sang ogg.

Chúng ta sẽ tạo một kịch bản lệnh nhỏ, chỉ sử dụng CPU và làm một chút ít việc khác. Kịch bản lệnh này có hai đầu vào, một số đếm và một nhãn. Nó in nhãn và ngày tháng, thời giờ hiện tại, sau đó làm giảm số đếm cho đến khi nó đạt tới 0, sau đó in lại nhãn và ngày. Kịch bản lệnh này không kiểm tra lỗi và không vững chãi lắm, nhưng nó minh họa vấn đề của chúng ta.

Liệt kê 100. Kịch bản lệnh đòi hỏi nhiều CPU
[ian@echidna ian]$ echo 'x="$1"'>count1.sh 
[ian@echidna ian]$ echo 'echo "$2" $(date)'>>count1.sh 
[ian@echidna ian]$ echo 'while [ $x -gt 0 ]; do let x=$x-1;done'>>count1.sh 
[ian@echidna ian]$ echo 'echo "$2" $(date)'>>count1.sh 
[ian@echidna ian]$ cat count1.sh 
x="$1"
echo "$2" $(date) 
while [ $x -gt 0 ]; do let x=$x-1;done 
echo "$2" $(date)

Nếu bạn chạy kịch bản lệnh này trên hệ thống riêng của bạn, bạn có thể thấy kết quả đầu ra như được hiển thị trong Liệt kê 101. Kịch bản lệnh này sử dụng CPU rất nhiều, như chúng ta sẽ thấy ngay đây. Nếu bạn không sử dụng máy trạm riêng của bạn, hãy chắc chắn rằng nếu sử dụng CPU rất nhiều cũng không gây ra vấn đề gì, trước khi bạn chạy kịch bản lệnh đó.

Liệt kê 101. Chạy count1.sh
[ian@echidna ian]$ sh count1.sh 10000 A 
A Mon Nov 14 07:14:04 EST 2005
A Mon Nov 14 07:14:05 EST 2005 
[ian@echidna ian]$ sh count1.sh 99000 A
A Mon Nov 14 07:14:26 EST 2005 
A Mon Nov 14 07:14:32 EST 2005

Cho đến nay, mọi việc tốt đẹp. Bây giờ chúng ta hãy sử dụng một số thứ khác mà chúng ta đã tìm hiểu trong hướng dẫn này để tạo ra một danh sách các lệnh sao cho chúng ta có thể chạy kịch bản lệnh đó trong nền sau và khởi chạy lệnh top để xem kịch bản lệnh đó đang sử dụng bao nhiêu CPU. Danh sách lệnh được hiển thị trong Liệt kê 102 và kết quả đầu ra của lệnh top trong Liệt kê 103.

Liệt kê 102. Chạy count1.sh và lệnh top
[ian@echidna ian]$ (sh count1.sh 99000 A&);top
Liệt kê 103. Sử dụng nhiều CPU
 7:20am up 48 days, 20:54, 2 users, load average: 0.05, 0.05, 0.00 
91 processes: 88 sleeping, 3 running, 0 zombie, 0 stopped 
CPU states: 0.1% user, 0.0% system, 0.0% nice, 0.9% idle 
Mem: 1030268K av, 1002864K used, 27404K free, 0K shrd, 240336K buff 
Swap:1052216K av, 118500K used, 933716K free 605152K cached 
  PID USER PRI NI  SIZE RSS  SHARE STAT %CPU %MEM TIME COMMAND 
 8684 ian   20 0   1044 1044 932   R    98.4  0.1 0:01 sh

Không tồi lắm. Chúng ta đang sử dụng 98,4% của CPU với một kịch bản đơn giản.

Hiển thị và thiết lập các mức ưu tiên

Nếu chúng ta có một công việc đang chạy kéo dài như công việc này, chúng ta có thể thấy rằng nó đã cản trở khả năng của chúng ta (hoặc khả năng của người sử dụng khác) khi thực hiện công việc khác trên hệ thống của chúng ta. Các hệ thống Linux và UNIX sử dụng một hệ thống ưu tiên với 40 mức ưu tiên, có thứ tự từ -20 (mức ưu tiên cao nhất) đến 19 (mức ưu tiên thấp nhất).

Lệnh nice

Các tiến trình mà người sử dụng thông thường khởi chạy thường có mức ưu tiên 0. Lệnh nice hiển thị mức ưu tiên mặc định của chúng ta. Lệnh ps cũng có thể hiển thị mức ưu tiên đó (mức nice hay NI), chẳng hạn khi sử dụng tùy chọn -l. Chúng ta minh họa điều này trong Liệt kê 104, ở đây chúng ta đã tô đậm giá trị nice bằng 0.

Liệt kê 104. Hiển thị thông tin ưu tiên
[ian@echidna ian]$ nice 
0 
[ian@echidna ian]$ ps -l 
  F S UID PID  PPID C PRI NI ADDR SZ   WCHAN TTY   TIME     CMD 
000 S 500 7283 7282 0 70   0    - 1103 wait4 pts/2 00:00:00 bash
000 R 500 9578 7283 0 72   0    - 784      - pts/2 00:00:00 ps

Lệnh nice cũng có thể được sử dụng để bắt đầu một tiến trình với một mức ưu tiên khác đi. Bạn sử dụng tùy chọn -n hay (--adjustment) với một giá trị dương để tăng giá trị ưu tiên và một giá trị âm để làm giảm nó. Hãy nhớ rằng các tiến trình có giá trị ưu tiên thấp nhất chạy với mức ưu tiên được sắp xếp cao nhất, vì thế hãy nghĩ về việc làm tăng giá trị ưu tiên như là cư xử đẹp (nice) với các tiến trình khác. Lưu ý rằng thông thường bạn cần phải là siêu người dùng (root) để xác định điều chỉnh mức ưu tiên âm. Nói cách khác, những người dùng thông thường nhìn chung chỉ có thể làm cho tiến trình của mình cư xử đẹp hơn (nicer) mà thôi. Trong Liệt kê 105, chúng ta chạy hai bản sao của kịch bản lệnh count1.sh trong nền sau với các mức ưu tiên sắp lịch biểu khác nhau. Chú ý rằng có một khoảng cách 5 giây giữa các lần hoàn thành. Hãy thử nghiệm bằng các giá trị nice khác nhau hoặc bằng cách chạy tiến trình đầu tiên với một điều chỉnh ưu tiên thay cho tiến trình thứ hai để chứng tỏ các khả năng khác nhau cho chính bạn thấy.

Liệt kê 105. Sử dụng lệnh nice để thiết lập các mức ưu tiên
[ian@echidna ian]$ (sh count1.sh 99000 A&);\ 
> (nice -n 19 sh count1.sh 99000 B&);\ 
> sleep 2;ps -l;sleep 20 
B Mon Nov 14 08:17:36 EST 2005 
A Mon Nov 14 08:17:36 EST 2005 
  F S UID PID   PPID C  PRI NI ADDR SZ   WCHAN   TTY   TIME     CMD 
000 S 500 7283  7282 0  70  0     - 1104 wait4   pts/2 00:00:00 bash 
000 R 500 10765 1    84 80  0     - 1033     -   pts/2 00:00:01 sh 
000 R 500 10767 1    14 79 19     - 1033     -   pts/2 00:00:00 sh 
000 R 500 10771 7283  0 72  0     - 784      -   pts/2 00:00:00 ps 
A Mon Nov 14 08:17:43 EST 2005 
B Mon Nov 14 08:17:48 EST 2005

Lưu ý rằng, như với lệnh nohup bạn không thể sử dụng một danh sách lệnh hay một đường ống làm đối số của lệnh nice.

Thay đổi các mức ưu tiên

Lệnh renice

Nếu bạn đã bắt đầu một tiến trình và nhận ra rằng nó phải chạy ở một mức ưu tiên khác, có một cách để thay đổi điều này sau khi quá trình đó đã bắt đầu, bằng cách sử dụng lệnh renice. Bạn xác định một mức ưu tiên tuyệt đối (chứ không phải thực hiện một điều chỉnh) cho tiến trình hoặc các tiến trình cần được thay đổi như trong Liệt kê 106.

Liệt kê 106. Sử dụng lệnh renice để thay đổi các mức ưu tiên
[ian@echidna ian]$ sh count1.sh 299000 A& 
[1] 11322 
[ian@echidna ian]$ A Mon Nov 14 08:30:29 EST 2005 

[ian@echidna ian]$ renice +1 11322;ps -l 
11322: old priority 0, new priority 1 
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 
000 S 500 7283 7282 0 75 0 - 1104 wait4 pts/2 00:00:00 bash
000 R 500 11322 7283 96 77 1 - 1032 - pts/2 00:00:11 sh 
000 R 500 11331 7283 0 76 0 - 786 - pts/2 00:00:00 ps 
[ian@echidna ian]$ renice +3 11322;ps -l 
11322: old priority 1, new priority 3 
  F S UID   PID PPID   C PRI NI ADDR SZ    WCHAN   TTY TIME     CMD 
000 S 500  7283 7282   0 75   0    - 1104  wait4 pts/2 00:00:00 bash 
000 R 500 11322 7283  93 76   3    - 1032      - pts/2 00:00:16 sh 
000 R 500 11339 7283   0 76   0    - 785       - pts/2 00:00:00 ps

Bạn có thể tìm thêm thông tin về nicerenice trong các trang hướng dẫn sử dụng.


Tìm kiếm với các biểu thức chính quy

Phần này trình bày tư liệu cho chủ đề 1.103.7 cho kỳ thi quản trị trình độ sơ cấp (LPIC-1) 101. Chủ đề này có trọng số 3.

Trong phần này, bạn tìm hiểu về các chủ đề sau đây:

  • Các biểu thức chính quy.
  • Tìm kiếm các tập tin và các hệ thống tập tin bằng cách sử dụng các biểu thức chính quy.
  • Sử dụng các biểu thức chính quy với trình soạn thảo sed.

Các biểu thức chính quy

Các biểu thức chính quy có nguồn gốc từ trong lý thuyết ngôn ngữ máy tính. Hầu hết các sinh viên khoa học máy tính biết rằng những ngôn ngữ có thể được biểu hiện bằng các biểu thức chính quy cũng chính là những ngôn ngữ được chấp nhận bởi ô tô mát (automata) hữu hạn. Các biểu thức chính quy được trình bày trong phần này có khả năng biểu diễn phức tạp hơn và như vậy chúng không phải chính là những biểu thức chính quy mà bạn có thể đã học trong các lớp học về khoa học máy tính, mặc dù sự thừa kế là rõ ràng.

Một biểu thức chính quy (regular expression - viết gọn là "regex" hoặc "regexp") là một cách để mô tả một chuỗi hoặc mẫu văn bản sao cho một chương trình có thể so khớp nó với các chuỗi văn bản tùy ý, cung cấp một khả năng tìm kiếm rất mạnh. Tiện ích grep (viết tắt của generalized regular expression processor - bộ xử lý biểu thức chính quy tổng quát) là một phần tiêu chuẩn trong hộp công cụ của bất cứ lập trình viên hay quản trị viên Linux hoặc UNIX nào. Nó cho phép các biểu thức chính quy được sử dụng trong việc tìm kiếm các tập tin hoặc đầu ra lệnh. Trong phần về các luồng văn bản và các bộ lọc, chúng tôi đã giới thiệu sed, stream editor, một trình soạn thảo luồng, là một công cụ tiêu chuẩn khác sử dụng rộng rãi các biểu thức chính quy cho việc tìm kiếm và thay thế văn bản trong các tập tin hoặc các luồng văn bản. Phần này giúp bạn hiểu rõ hơn về các biểu thức chính quy được cả grep lẫn sed sử dụng. Một chương trình khác sử dụng rộng rãi các biểu thức chính quy là awk, là một phần hoặc là tư liệu cho kỳ thi 201 của chứng chỉ LPIC-2.

Như với các phần khác của loạt bài hướng dẫn này, nhiều cuốn sách đã được viết về biểu thức chính quy và lý thuyết ngôn ngữ máy tính. Xem Tài nguyên để thấy một số gợi ý.

Khi bạn tìm hiểu về các biểu thức chính quy, bạn sẽ thấy những sự tương đồng giữa cú pháp biểu thức chính quy và cú pháp của ký tự đại diện (hoặc globbing) đã được thảo luận trong phần Các kí hiệu và globbing. Sự tương đồng này chỉ là bề ngoài.

Các khối xây dựng cơ bản

Hai dạng cú pháp của biểu thức chính quy được sử dụng với chương trình GNU grep có trong hầu hết các hệ thống Linux là: cơ bảnmở rộng. Với GNU grep, không có sự khác biệt nào về chức năng. Cú pháp cơ bản được mô tả ở đây, cùng với các sự khác biệt giữa cú pháp cơ bản và cú pháp mở rộng.

Các biểu thức chính quy được xây dựng từ các ký tựcác toán tử, được tăng cường thêm bởi các siêu ký tự (metacharacter). Hầu hết các ký tự tự khớp với chính nó và hầu hết các siêu ký tự phải được đặt mã thoát bằng cách sử dụng dấu gạch chéo ngược (\). Các phép toán cơ bản là:

Concatenation - Phép nối
Phép nối hai biểu thức chính quy tạo ra một biểu thức dài hơn. Ví dụ, biểu thức chính quy a sẽ khớp với chuỗi abcdcba hai lần (chữ a đầu tiên và cuối cùng) và biểu thức chính quy b cũng thế.Tuy nhiên, ab sẽ chỉ khớp với abcdcba, trong khi ba sẽ chỉ khớp với abcdcba.
Repetition -Lặp lại
Toán tử Kleene * hay toán tử lặp lại sẽ khớp với không hoặc nhiều lần xuất hiện của biểu thức chính quy trước đó. Như vậy một biểu thức như a*b sẽ khớp với bất kỳ chuỗi nào gồm nhiều a và được kết thúc bằng một b, gồm chỉ mỗi b mà thôi. Không đặt mã thoát cho toán tử Kleene *, do đó một biểu thức trong đó bạn muốn khớp đúng với một dấu sao (*) phải có dấu sao được đặt mã thoát.
Alternation - Luân phiên
Toán tử thay đổi luân phiên (|) khớp hoặc với biểu thức trước hoặc biểu thức sau. Nó phải được đặt mã thoát theo cú pháp cơ bản. Ví dụ, biểu thức a*\|b*c sẽ khớp với một chuỗi bao gồm số bất kỳ biểu thức a hoặc số bất kỳ biểu thức b (nhưng không cả hai) và được kết thúc bởi chỉ một c. Một lần nữa, một ký tự đơn c cũng sẽ khớp.

Bạn thường cần đặt dấu nháy kép cho biểu thức chính quy của bạn để tránh khai triển shell.

Chúng ta sẽ sử dụng các tập tin văn bản mà chúng ta đã tạo ra ở trên trong thư mục lpi103 làm ví dụ. Hãy nghiên cứu các ví dụ đơn giản trong Liệt kê 107. Lưu ý rằng grep nhận một biểu thức chính quy làm một tham số bắt buộc và một danh sách gồm không hay nhiều tập tin để tìm kiếm. Nếu không có các tập tin nào được cung cấp, grep sẽ tìm kiếm stdin, làm cho nó trở thành một bộ lọc và có thể được sử dụng trong đường ống. Nếu không có dòng nào khớp, thì cũng không có kết quả đầu ra nào từ grep, mặc dù vẫn có thể kiểm tra mã kết thúc (exit) của nó.

Liệt kê 107. Các biểu thức chính quy đơn giản
[ian@echidna lpi103]$ grep p text1 
1 apple 
2 pear 
[ian@echidna lpi103]$ grep pea text1 
2 pear 
[ian@echidna lpi103]$ grep "p*" text1 
1 apple 
2 pear 
3 banana 
[ian@echidna lpi103]$ grep "pp*" text1 
1 apple 
2 pear 
[ian@echidna lpi103]$ grep "x" text1
[ian@echidna lpi103]$ grep "x*" text1 
1 apple 
2 pear 
3 banana
[ian@echidna lpi103]$ cat text1 | grep "l\|n" 
1 apple 
3 banana
[ian@echidna lpi103]$ echo -e "find an\n* here" | grep "\*" 
* here

Như bạn thấy từ các ví dụ này, bạn đôi khi có thể nhận được kết quả bất ngờ, đặc biệt là với toán tử lặp lại. Bạn có thể đã dự kiến p* hoặc ít nhất là pp* để khớp với một vài biểu thức p liền nhau, nhưng p* và ngay cả x* khớp với mọi dòng trong tập tin vì toán tử * khớp với không hay nhiều biểu thức chính quy trước đó.

Các phím tắt đầu tiên

Bây giờ bạn có khối xây dựng cơ bản của biểu thức chính quy, chúng ta hãy xem xét một vài phím tắt thuận tiện.

+
Toán tử + cũng giống như toán tử *, trừ việc nó khớp với một hoặc nhiều lần xuất hiện của biểu thức chính quy trước đó. Nó phải được đặt mã thoát cho các biểu thức cơ bản.
?
Dấu ? chỉ thị rằng biểu thức trước đó là tùy chọn, do đó nó biểu diễn không hoặc một xuất hiện của một biểu thức đó. Điều này không giống như là dấu ? được sử dụng trong globbing.
.
Dấu . (dấu chấm) là một siêu ký tự viết tắt cho bất cứ ký tự nào. Một trong những mẫu được sử dụng phổ biến nhất là .*, khớp với chuỗi có chiều dài tùy ý có chứa các ký tự bất kỳ (hoặc không có ký tự nào cả). Không cần phải nói, bạn sẽ tìm thấy siêu ký tự này được sử dụng như một phần của một biểu thức dài hơn. Hãy so sánh một dấu chấm duy nhất với dấu ? được sử dụng trong globbing và .* với * sử dụng trong globbing.
Liệt kê 108. Thêm nhiều biểu thức chính quy hơn
[ian@echidna lpi103]$ grep "pp\+" text1 # at least two p's 
1 apple 
[ian@echidna lpi103]$ grep "pl\?e" text1 
1 apple 
2 pear 
[ian@echidna lpi103]$ grep "pl\?e" text1 # pe with optional l between 
1 apple 
2 pear 
[ian@echidna lpi103]$ grep "p.*r" text1 # p, some string then r 
2 pear 
[ian@echidna lpi103]$ grep "a.." text1 # a followed by two other letters 
1 apple 
3 banana

Khớp với đầu hay cuối dòng

Dấu ^ (dấu mũ) khớp với đầu một dòng trong khi dấu $ (ký hiệu đô la) khớp với cuối dòng. Vì vậy ^..b khớp với hai ký tự ở đầu dòng tiếp theo một ký tự b, trong khi ar$ khớp với bất kỳ dòng nào kết thúc bằng ar. Biểu thức chính quy ^$ khớp với một dòng trống.

Các biểu thức phức tạp hơn

Cho đến nay, chúng ta đã thấy toán tử lặp lại được áp dụng cho một ký tự đơn. Nếu bạn muốn tìm kiếm một hoặc nhiều lần xuất hiện của một chuỗi nhiều ký tự chẳng hạn như an xuất hiện hai lần trong từ banana, hãy sử dụng các dấu ngoặc đơn, và phải được đặt mã thoát trong cú pháp cơ bản. Tương tự, bạn có thể muốn tìm kiếm với một vài ký tự, mà không sử dụng một cái gì đó chung như dấu . hoặc là dài dòng như toán tử luân phiên. Bạn cũng có thể làm điều này, bằng cách bao bọc toán tử luân phiên đó trong các dấu ngoặc vuông ([]), mà không cần phải đặt đặt mã thoát cho cú pháp chính quy. Các biểu thức trong dấu ngoặc vuông tạo thành một lớp ký tự. Với một vài ngoại lệ được trình bày sau, việc sử dụng dấu ngoặc vuông cũng giúp loại bỏ sự cần thiết phải đặt mã thoát cho các ký tự đặc biệt như là . và *.

Liệt kê 109. Các dấu ngoặc đơn và các lớp ký tự
[ian@echidna lpi103]$ grep "\(an\)\+" text1 # find at least 1 an 
3 banana 
[ian@echidna lpi103]$ grep "an\(an\)\+" text1 # find at least 2 an's 
3 banana 
[ian@echidna lpi103]$ grep "[3p]" text1 # find p or 3 
1 apple 
2 pear 
3 banana 
[ian@echidna lpi103]$ echo -e "find an\n* here\nsomewhere." | grep "[.*]" 
* here
somewhere.

Có một số khả năng thú vị khác với các lớp ký tự.

Biểu thức dải
Một biểu thức dải là hai ký tự cách nhau bằng dấu gạch ngang - (hyphen), chẳng hạn như 0-9 cho các số, hoặc 0-9a-fA-F cho các số hệ đếm mười sáu. Lưu ý rằng các dải phụ thuộc vào nơi diễn ra.
Các lớp có tên
Một số lớp có tên cung cấp một phương pháp tốc ký thuận tiện cho các lớp được dùng phổ biến. Các lớp có tên mở ra bằng [: và đóng lại bằng :]. Một số ví dụ:
[:alnum:]
Các ký tự là chữ và số.
[:blank:]
Các ký tự khoảng trống và tab.
[:digit:]
Các ký số 0 đến 9 (tương đương với 0-9).
`[:upper:] và [:lower:]
Các chữ cái chữ hoa và chữ thường tương ứng.
^ (Phủ định)
Khi được sử dụng như là ký tự đầu tiên trong một dấu ngoặc vuông, dấu ^ (dấu mũ) phủ định ý nghĩa của các ký tự còn lại để cho sự ăn khớp xảy ra chỉ khi một ký tự (trừ dấu ^ đứng đầu) không có trong lớp đó.

Căn cứ vào ý nghĩa đặc biệt ở trên, nếu bạn muốn làm khớp đúng với một dấu - (gạch nối) trong một lớp ký tự bạn phải đặt dấu - đầu tiên hoặc cuối cùng. Nếu bạn muốn làm khớp đúng với một dấu ^ (dấu mũ) thì dấu này phải không nằm ở vị trí đầu tiên. Và một dấu ] (dấu ngoặc vuông bên phải) đóng các lớp đó, trừ khi nó được đặt lên đầu tiên.

Các lớp ký tự là một lĩnh vực ở đó các biểu thức chính quy và globbing giống nhau, mặc dù toán tử phủ định khác nhau (^ so với !). Liệt kê 108 cho thấy một số ví dụ về các lớp ký tự.

Liệt kê 110. Thêm các lớp ký tự
[ian@echidna lpi103]$ # Match on range 3 through 7
[ian@echidna lpi103]$ echo -e "123\n456\n789\n0" | grep "[3-7]" 
123
456 
789 
[ian@echidna lpi103]$ # Find digit followed by no n or r till end of line 
[ian@echidna lpi103]$ grep "[[:digit:]][^nr]*$" text1 
1 apple

Sử dụng các biểu thức chính quy với sed

Giới thiệu ngắn gọn về Sed đã nói rằng sed sử dụng các biểu thức chính quy. Các biểu thức chính quy có thể được sử dụng trong các biểu thức địa chỉ cũng như trong các biểu thức thay thế. Vì vậy, biểu thức /abc/s/xyz/XYZ/g có nghĩa là áp dụng lệnh thay thế để thay thế XYZ cho mỗi lần xuất hiện của xyz chỉ với các dòng có chứa abc. Liệt kê 111 cho thấy hai ví dụ với tập tin text1 của chúng ta và một ví dụ, ở đây chúng ta thay thế từ cuối cùng trước một dấu chấm (.) thành chuỗi LAST WORD. Lưu ý rằng chuỗi First không thay đổi vì nó không có khoảng trống đứng trước.

Liệt kê 111. Các biểu thức chính quy trong sed
[ian@echidna lpi103]$ sed -e '/\(a.*a\)\|\(p.*p\)/s/a/A/g' text1 
1 Apple 
2 pear 
3 bAnAnA
[ian@echidna lpi103]$ sed -e '/^[^lmnXYZ]*$/s/ear/each/g' text1 
1 apple 
2 peach 
3 banana 
[ian@echidna lpi103]$ echo "First. A phrase. This is a sentence." |\ 
> sed -e 's/ [^ ]*\./ LAST WORD./g' 
First. A LAST WORD. This is a LAST WORD.

Các biểu thức chính quy mở rộng

Cú pháp của các biểu thức chính quy mở rộng loại bỏ sự cần thiết phải đặt mã thoát cho một số ký tự khi sử dụng như chúng ta đã làm trong cú pháp cơ bản, bao gồm các dấu ngoặc đơn, '?', '+', '|', và '{'. Điều này có nghĩa là chúng phải được đặt mã thoát nếu bạn muốn chúng được hiểu là các ký tự thông thường. Bạn có thể sử dụng tùy chọn -E (hoặc --extended-regexp của grep để báo hiệu rằng bạn đang sử dụng cú pháp của biểu thức chính quy mở rộng. Ngoài ra, lệnh egrep cũng thực hiện điều này cho bạn. Một số phiên bản cũ của sed không hỗ trợ các biểu thức chính quy mở rộng. Nếu phiên bản sed của bạn hỗ trợ biểu thức chính quy mở rộng, hãy sử dụng tùy chọn -r để nói cho sed biết rằng bạn đang sử dụng cú pháp mở rộng. Liệt kê 112 cho thấy một ví dụ đã sử dụng ở trên trong phần này cùng với biểu thức mở rộng tương ứng được sử dụng với egrep.

Liệt kê 112. Các biểu thức chính quy mở rộng
[ian@echidna lpi103]$ grep "an\(an\)\+" text1 # find at least 2 an's 
3 banana 
[ian@echidna lpi103]$ egrep "an(an)+" text1 # find at least 2 an's 
3 banana

Tìm thứ gì đó trong các tập tin

Phần này khép lại bằng cách cung cấp cho bạn một số hương vị về sức mạnh của grepfind để săn lùng các thứ trong hệ thống tập tin của bạn. Một lần nữa, các ví dụ này tương đối đơn giản; chúng sử dụng các tập tin được tạo ra trong thư mục lpi103 và thư mục con của nó.

Trước tiên, grep có thể tìm kiếm nhiều tập tin cùng một lúc. Nếu bạn thêm tùy chọn -n, nó sẽ cho bạn biết các số dòng nào đã khớp. Nếu bạn chỉ đơn giản muốn biết có bao nhiêu dòng đã khớp, hãy sử dụng tùy chọn -c và nếu bạn chỉ muốn một danh sách của các tập tin có ăn khớp, hãy sử dụng tùy chọn -l. Liệt kê 113 cho thấy một số ví dụ

Liệt kê 113. Xử lý biểu thức chính quy tổng quát trong nhiều tập tin
[ian@echidna lpi103]$ grep plum * 
text2:9 plum 
text6:9 plum 
text6:9 plum 
yaa:9 plum
[ian@echidna lpi103]$ grep -n banana text[1-4] 
text1:3:3 banana
text2:2:3 banana 
[ian@echidna lpi103]$ grep -c banana text[1-4]
text1:1 
text2:1 
text3:0 
text4:0 
[ian@echidna lpi103]$ grep -l pear *
ex-here.sh 
nohup.out 
text1 
text5 
text6 
xaa

Ví dụ cuối cùng sử dụng lệnh find để định vị tất cả tập tin bình thường trong thư mục hiện tại và thư mục con của nó và sau đó sử dụng lệnh xargs để chuyển danh sách tập tin tới grep để xác định số lần xuất hiện của từ banana trong mỗi tập tin. Cuối cùng, kết quả đầu ra này được lọc bằng cách gọi grep, một lần nữa, lúc này với tùy chọn -v để tìm tất cả các tập tin xuất hiện của chuỗi tìm kiếm.

Liệt kê 114. Săn tìm các tập tin có ít nhất một từ banana
[ian@echidna lpi103]$ find . -type f -print0| xargs -0 grep -c banana| grep -v ":0$" 
./text1:1 
./text2:1
./xab:1 
./yaa:1 
./text5:1 
./text6:4 
./backup/text1.bkp.2:1
./backup/text1.bkp.1:1

Phần này đã chỉ bàn sơ qua bề ngoài của những gì mà bạn có thể làm với các biểu thức chính quy và dòng lệnh của Linux. Hãy sử dụng trang hướng dẫn sử dụng để tìm hiểu thêm về các công cụ vô giá này.


Biên soạn tập tin bằng vi

Phần này trình bày tư liệu cho chủ đề 1.103.8 cho kỳ thi quản trị trình độ sơ cấp (LPIC-1) 101. Chủ đề này có trọng số 1.

Trong phần này, bạn tìm hiểu về các chủ đề sau đây:

  • Biên soạn văn bản bằng vi.

Sử dụng vi

Trình soạn thảo vi hầu như chắc chắn có trên mọi hệ thống Linux và UNIX. Thực vậy, nếu một hệ thống chỉ có một trình soạn thảo, thì nhiều khả năng nó là vi, vì vậy rất đáng tìm hiểu cách làm việc với vi. Phần này giới thiệu cho bạn một số lệnh soạn thảo vi cơ bản, nhưng để tìm một hướng dẫn vi đầy đủ, hãy đọc "giới thiệu vi -- cẩm nang tra cứu" của chúng tôi (xem Tài nguyên), hoặc tham khảo các trang hướng dẫn sử dụng hoặc một trong nhiều cuốn sách xuất sắc có sẵn.

Khởi động vi

Bây giờ hầu hết các bản phân phối Linux được cung cấp với trình soạn thảo Vim (viết tắt của Vi IMproved - Vi đã cải tiến) chứ không phải vi cổ điển. Vim tương thích hướng lên với vi và cũng có sẵn một chế độ đồ họa (gvim) cũng như giao diện chế độ văn bản vi tiêu chuẩn. Lệnh vi thường là một bí danh hoặc liên kết biểu tượng với chương trình vim. Tham khảo lại chủ đề Shell tìm các lệnh ở đâu? để tìm hiểu chính xác lệnh nào được sử dụng.

Nếu bạn nhớ lại phần về thay đổi các mức ưu tiên, chúng ta muốn thay đổi các ưu tiên chạy kịch bản lệnh shell count1.sh của chúng ta. Có lẽ bạn đã tự mình thử điều này và thấy rằng lệnh đó đã chạy nhanh đến mức bạn không có đủ thời gian để hoàn thành việc thay đổi ưu tiên bằng lệnh renice. Vì vậy, hãy bắt đầu bằng cách sử dụng trình soạn thảo vi để thêm một dòng vào đầu tập tin để chờ 20 giây sao cho chúng ta có một chút thời gian để thay đổi các ưu tiên.

Để bắt đầu trình soạn thảo vi, hãy sử dụng lệnh vi với một tên tập tin làm tham số. Bạn có nhiều tùy chọn để lựa chọn, vì vậy hãy xem các trang hướng dẫn sử dụng để biết thêm chi tiết. Hãy sử dụng lệnh

vi count1.sh

Bạn sẽ thấy một màn hình hiển thị tương tự như Liệt kê 115. Nếu bạn đang sử dụng vim, một số trong các từ có thể có các màu khác. Vim có một chế độ tô sáng cú pháp (không phải là một phần của trình soạn thảo vi ban đầu) và nó có thể được bật theo mặc định trên hệ thống của bạn.

Liệt kê 115. Chỉnh sửa count1.sh bằng cách sử dụng vi
x="$1" 
echo "$2" $(date) 
while [ $x -gt 0 ]; do let x=$x-1;done 
echo "$2" $(date) 
~ 
~ 
~ 
~ 
~ 
~ 
"count1.sh" 4L, 82C

Các chế độ vi

Trình soạn thảo vi có hai chế độ hoạt động:

Chế độ lệnh
Trong chế độ lệnh, bạn di chuyển trong tập tin đó và thực hiện các hoạt động chỉnh sửa như tìm kiếm văn bản, xóa các văn bản, thay đổi văn bản, và v.v. Bạn thường bắt đầu trong chế độ lệnh.
Chế độ chèn
Trong chế độ chèn, bạn gõ văn bản mới vào tập tin đó tại điểm chèn vào. Để quay về chế độ lệnh, nhấn phím Esc (Escape) .

Hai chế độ này xác định cách hoạt động của trình soạn thảo. Vi có từ ngày mà không phải tất cả các bàn phím đầu cuối đều có các phím di chuyển con trỏ, do đó mọi thứ bạn có thể làm trong vi là làm với các phím thường thấy trên một máy đánh chữ tiêu chuẩn cộng với một vài phím chẳng hạn như EscInsert. Tuy nhiên, bạn có thể cấu hình vi để sử dụng các phím bổ sung nếu chúng có sẵn; hầu hết các phím trên bàn phím của bạn đều thực hiện được công việc gì đó có ích trong vi. Do di sản này và bản chất chậm của các kết nối thiết bị đầu cuối những buổi đầu, vi rất xứng đáng với danh tiếng là sử dụng các lệnh rất ngắn và khó hiểu.

Thoát ra khỏi vi

Một trong những điều đầu tiên tôi muốn tìm hiểu về một trình soạn thảo mới là làm thế nào để thoát ra khỏi nó trước khi tôi làm bất cứ điều gì mà tôi không nên làm. Những cách sau đây để thoát ra khỏi vi bao gồm việc lưu hoặc từ bỏ các thay đổi của bạn, hoặc khởi động lại từ đầu. Nếu các lệnh này dường như không làm việc cho bạn, có thể bạn đang ở trong chế độ chèn, do đó, hãy nhấn Esc để thoát khỏi chế độ chèn và trở về chế độ lệnh.

:q!
Thoát khỏi việc chỉnh sửa tập tin và bỏ qua tất cả các thay đổi. Đây là một cách rất phổ biến để thoát ra khỏi mọi trục trặc.
:w!
Ghi lên tập tin (cho dù có sửa đổi hay không). Cố gắng để ghi đè lên các tập tin đã có hoặc tập tin chỉ đọc hay không được viết khác. Bạn có thể cung cấp một tên tập tin làm một tham số và tập tin đó sẽ được viết thay cho tập tin bạn đã bắt đầu với nó. Nói chung, bỏ qua! là an toàn hơn trừ khi bạn biết bạn đang làm gì ở đây.
ZZ
Ghi vào tập tin nếu nó đã được sửa đổi. Sau đó thoát ra. Đây là một cách rất phổ biến để thoát khỏi vi bình thường.
:e!
Chỉnh sửa bản sao hiện tại trên đĩa của tập tin. Lệnh này sẽ nạp lại tập tin, bỏ qua những thay đổi bạn đã thực hiện. Bạn cũng có thể sử dụng lệnh này nếu bản sao trên đĩa đã thay đổi vì một số lý do khác và bạn muốn phiên bản mới nhất.
:!
Chạy một lệnh shell. Gõ lệnh này và nhấn Enter. Khi lệnh hoàn thành, bạn sẽ thấy kết quả đầu ra và một dấu nhắc để quay lại việc chỉnh sửa với vi.

Lưu ý:

  1. Khi bạn gõ dấu hai chấm (:), con trỏ của bạn sẽ dịch chuyển tới dòng dưới cùng của màn hình của bạn, ở đây bạn có thể gõ vào các lệnh và tham số bất kỳ.
  2. Nếu bạn bỏ qua dấu chấm than từ các lệnh ở trên, thì bạn có thể nhận được một thông báo lỗi chẳng hạn như thông báo rằng các thay đổi chưa được lưu lại hoặc không thể viết tập tin đầu ra được (ví dụ, bạn đang chỉnh sửa một tập tin chỉ đọc).
  3. Các lệnh : có dạng dài hơn (:quit, :write, :edit), nhưng các dạng dài hơn ít khi được sử dụng.

Di chuyển trong văn bản

Các lệnh sau đây giúp bạn di chuyển đâu đó trong một tập tin:

h
Di chuyển sang trái một ký tự trên dòng hiện tại.
j
Di chuyển xuống dòng kế tiếp.
k
Di chuyển lên dòng trước.
l
Di chuyển sang phải một ký tự trên dòng hiện tại.
w
Chuyển đến từ tiếp theo trên dòng hiện tại.
e
Di chuyển đến điểm cuối của từ tiếp theo trên dòng hiện tại.
b
Di chuyển đến điểm đầu của từ trước đó trên dòng hiện tại.
Ctrl-f
Cuộn tiến lên một trang.
Ctrl-b
Cuộn lùi lại một trang.

Nếu bạn gõ một số vào trước bất kỳ lệnh nào trong các lệnh này, thì lệnh đó sẽ thực hiện nhiều lần. Số này được gọi là số đếm lặp hoặc đơn giản là số đếm. Ví dụ, 5h sẽ di chuyển sang trái năm ký tự. Bạn có thể sử dụng các số đếm lặp với nhiều lệnh vi.

Di chuyển đến các dòng

Các lệnh sau đây giúp bạn di chuyển đến các dòng cụ thể trong tập tin của bạn:

G
Di chuyển đến một dòng cụ thể trong tập tin của bạn. Ví dụ, 3G di chuyển đến dòng 3. Khi không có tham số nào, G di chuyển đến dòng cuối cùng của tập tin.
H
Di chuyển tương đối so với dòng trên cùng trên màn hình. Ví dụ, 3H di chuyển tới dòng hiện tại là thứ 3 từ đầu màn hình của bạn.
L
Cũng giống như H, chỉ khác là di chuyển tương đối so với dòng cuối cùng trên màn hình, Như vậy, 2L di chuyển dòng thứ hai từ dưới lên trên màn hình của bạn.

Tìm kiếm

Bạn có thể tìm kiếm văn bản trong tập tin của bạn bằng cách sử dụng các biểu thức chính quy:

/
Sử dụng dấu / tiếp theo bởi một biểu thức chính quy để tìm kiếm tiếp trong tập tin của bạn theo hướng tiến.
?
Sử dụng dấu ? tiếp theo là một biểu thức chính quy để tìm kiếm trong tập tin của bạn theo hướng lùi.
n
Sử dụng n để lặp lại việc tìm kiếm cuối cùng theo cả hai hướng.

Bạn có thể đặt trước bất kỳ lệnh nào trong các lệnh tìm kiếm trên một số biểu thị số đếm lặp lại. Vì vậy, 3/x sẽ tìm sự xuất hiện thứ ba của x từ điểm hiện tại, giống như là /x sau đó gõ tiếp 2 n.

Sửa đổi văn bản

Sử dụng các lệnh sau đây nếu bạn cần chèn, xóa hoặc sửa đổi văn bản:

i
Chuyển sang chế độ chèn vào trước ký tự ở vị trí hiện tại. Gõ vào văn bản của bạn và nhấn Esc để trở về chế độ lệnh. Sử dụng I để chèn vào đầu dòng hiện tại.
a
Chuyển sang chế độ chèn vào sau ký tự ở vị trí hiện tại. Gõ vào văn bản của bạn và nhấn Esc để trở về chế độ lệnh. Sử dụng A để chèn vào cuối dòng hiện tại.
c
Sử dụng c để thay đổi ký tự hiện tại và chuyển sang chế độ chèn để gõ vào các ký tự thay thế.
o
Mở một dòng mới để chèn thêm văn bản dưới dòng hiện tại. Sử dụng O để mở một dòng trên dòng hiện tại.
cw
Xóa phần còn lại của từ hiện tại và chuyển sang chế độ chèn để thay thế nó. Sử dụng số đếm lặp lại để thay thế nhiều từ. Sử dụng c$ để thay thế đến cuối dòng
dw
Như với cw (và c$) ở trên, chỉ khác là lệnh này không chuyển sang chế độ chèn.
dd
Xóa dòng hiện tại. Sử dụng một số đếm lặp lại để xóa nhiều dòng.
x
Xóa ký tự tại vị trí con trỏ. Sử dụng số đếm lặp lại để xóa nhiều ký tự.
p
Đặt văn bản đã xóa cuối cùng sau ký tự hiện tại. Sử dụng P để đặt nó trước ký tự hiện tại.
xp
Tổ hợp này của x và p là một cách làm có ích. Lệnh này tráo đổi ký tự này ở vị trí con trỏ với một ký tự khác ở bên phải của nó.

Ghép lại cùng nhau

Chúng ta định thêm một dòng vào tập tin count1.sh của chúng ta. Để giữ lại phiên bản gốc và lưu lại phiên bản sửa đổi như là count2.sh, chúng ta có thể sử dụng các lệnh vi này ngay khi chúng ta mở tập tin bằng vi. Lưu ý rằng <Esc> có nghĩa là nhấn phím Esc.

Liệt kê 116. Các lệnh của trình soạn thảo để thêm một dòng tới count1.sh
1G 
O 
sleep 20<Esc> 
:w! count2.sh 
:q

Thật đơn giản khi bạn biết cách làm thế nào.

Hướng dẫn tiếp theo trong loạt bài này trình bày Chủ đề 104 về Các thiết bị, các hệ thống tập tin Linux và tiêu chuẩn phân cấp hệ thống tập tin (FHS).

Tài nguyên

Học tập

Lấy sản phẩm và công nghệ

  • Xây dựng dự án phát triển tiếp theo của bạn trên Linux với phần mềm dùng thử của IBM, có sẵn để tải trực tiếp từ developerWorks.

Thảo luận

Bình luận

developerWorks: Đăng nhập

Các trường được đánh dấu hoa thị là bắt buộc (*).


Bạn cần một ID của IBM?
Bạn quên định danh?


Bạn quên mật khẩu?
Đổi mật khẩu

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Ở lần bạn đăng nhập đầu tiên vào trang developerWorks, một hồ sơ cá nhân của bạn được tạo ra. Thông tin trong bản hồ sơ này (tên bạn, nước/vùng lãnh thổ, và tên cơ quan) sẽ được trưng ra cho mọi người và sẽ đi cùng các nội dung mà bạn đăng, trừ khi bạn chọn việc ẩn tên cơ quan của bạn. Bạn có thể cập nhật tài khoản trên trang IBM bất cứ khi nào.

Thông tin gửi đi được đảm bảo an toàn.

Chọn tên hiển thị của bạn



Lần đầu tiên bạn đăng nhập vào trang developerWorks, một bản trích ngang được tạo ra cho bạn, bạn cần phải chọn một tên để hiển thị. Tên hiển thị của bạn sẽ đi kèm theo các nội dung mà bạn đăng tải trên developerWorks.

Tên hiển thị cần có từ 3 đến 30 ký tự. Tên xuất hiện của bạn phải là duy nhất trên trang Cộng đồng developerWorks và vì lí do an ninh nó không phải là địa chỉ email của bạn.

Các trường được đánh dấu hoa thị là bắt buộc (*).

(Tên hiển thị cần có từ 3 đến 30 ký tự)

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Thông tin gửi đi được đảm bảo an toàn.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=70
Zone=Nguồn mở
ArticleID=507306
ArticleTitle=Chuẩn bị kỳ thi LPI 101: Các lệnh GNU và UNIX
publish-date=08202010