Lệnh terminal trên Linux - 5 nhóm lệnh nên hiểu bản chất thay vì học thuộc

Lệnh terminal trên Linux dễ nắm hơn khi chia thành 5 nhóm: find tìm file, nano sửa cấu hình, less đọc nhật ký, && cùng || nối lệnh theo mã thoát, ps và kill dừng tiến trình bằng SIGTERM 15 hoặc SIGKILL 9.

Màn hình dòng lệnh thường khiến người mới chuyển sang Linux e ngại, vì mỗi dòng chữ trông như mật mã phải học thuộc. Thực chất, một lệnh terminal chỉ là câu yêu cầu gửi cho hệ thống, gồm tên…

Lệnh terminal trên Linux - 5 nhóm lệnh nên hiểu bản chất thay vì học thuộc

Màn hình dòng lệnh thường khiến người mới chuyển sang Linux e ngại, vì mỗi dòng chữ trông như mật mã phải học thuộc. Thực chất, một lệnh terminal chỉ là câu yêu cầu gửi cho hệ thống, gồm tên chương trình, vài tùy chọn và đối tượng cần xử lý. Tôi chia phần cốt lõi thành 5 nhóm: tìm file, sửa cấu hình, đọc nhật ký dài, nối lệnh theo điều kiện và xử lý tiến trình. Mọi tùy chọn trong bài đều được xác nhận theo man page và tài liệu chính thức của GNU, nano và Ubuntu.

Đọc một lệnh terminal theo cấu trúc tên, tùy chọn và đối số

Theo tài liệu Ubuntu, tổ hợp Ctrl+Alt+T mở cửa sổ dòng lệnh trên GNOME, Xfce hay LXDE. Khi cửa sổ terminal Ubuntu hiện ra, dấu nhắc chờ bạn gõ một dòng gồm ba phần: tên chương trình, tùy chọn bắt đầu bằng dấu gạch ngang và đối số là file hoặc thư mục cần xử lý. Với lệnh find dạng find ~/Documents -name "*.pdf", đối số là thư mục Documents, còn -name là điều kiện lọc. Nắm cấu trúc này, mọi lệnh terminal chép từ mạng đều dễ đọc hơn.

Cấu trúc một lệnh terminal gồm tên chương trình, tùy chọn và đối số trên Ubuntu

Hai thao tác nền tảng nên ưu tiên làm quen là pwd và phím Tab. Tài liệu Ubuntu mô tả pwd (print working directory) cho biết bạn đang đứng ở thư mục nào, còn Tab tự hoàn thành tên lệnh hoặc tên file khi chỉ có một khả năng, hoặc liệt kê các phương án. Dấu ngã ~ đại diện thư mục cá nhân. Nếu bạn dùng laptop Windows, terminal Ubuntu vẫn chạy qua WSL2, và bài Cài đặt Codex CLI: Kích hoạt WSL2 rồi cấu hình tài khoản trình bày bước kích hoạt WSL2.

Phần lớn lệnh terminal đi kèm trang hướng dẫn, mở bằng man cộng tên lệnh, ví dụ man find, nhấn q để thoát. Tôi coi đây là thói quen đáng giữ nhất trong terminal Ubuntu: thay vì nhớ hàng trăm tùy chọn, bạn tra đúng mục cần dùng. Người quen Windows sẽ thấy điểm tương đồng đáng kể với CMD, chẳng hạn bài Lệnh cd trong CMD: cách chuyển thư mục và đổi ổ đĩa trên Windows giải thích lệnh cd mà Linux cũng dùng để đổi thư mục, khác ở chỗ Linux không có ký tự ổ đĩa như C: hay D:.

Nhóm một tìm file bằng lệnh find theo tên, dung lượng, thời gian

Lệnh find duyệt một thư mục cùng toàn bộ thư mục con, kiểm từng file theo biểu thức. Biểu thức -name so mẫu với phần tên file sau khi bỏ đường dẫn phía trước, còn -iname làm việc tương tự nhưng không phân biệt chữ hoa, chữ thường. Tài liệu GNU nhấn mạnh mẫu có ký tự đại diện như dấu sao phải đặt trong ngoặc kép, nếu không shell sẽ tự mở rộng mẫu trước khi lệnh find nhận được nó. Thêm -type f để lấy file thường, -type d để lấy thư mục.

Biểu thức Ý nghĩa theo GNU findutils Ví dụ
-name, -iname So mẫu với tên file, -iname không phân biệt hoa thường find ~/Documents -iname "*.pdf"
-type f, -type d Chỉ lấy file thường hoặc chỉ lấy thư mục find . -type d -name "build"
-size +100M Lớn hơn 100 MiB, dung lượng làm tròn lên theo đơn vị find ~/Downloads -size +100M
-mtime -7 Sửa đổi chưa tới 7 chu kỳ 24 giờ find ~/Documents -mtime -7
-mmin -30 Sửa đổi chưa tới 30 phút find ~/Desktop -mmin -30
-exec ... {} + Chạy lệnh khác trên danh sách file tìm thấy find . -name "*.log" -exec ls -l {} +

Hai điều kiện dung lượng và thời gian là chỗ người mới dùng lệnh find hay hiểu sai. Với -size, hậu tố k, M, G lần lượt là KiB, MiB, GiB, và GNU findutils ghi rõ dung lượng được làm tròn lên đơn vị kế tiếp, nên -size -1M chỉ khớp file rỗng chứ không phải mọi file dưới ngưỡng 1 MiB. Với -mtime, số chu kỳ 24 giờ kể từ lần sửa luôn bị làm tròn xuống: dấu cộng nghĩa là lớn hơn, dấu trừ nghĩa là nhỏ hơn, không dấu nghĩa là đúng bằng. Cần độ chính xác theo phút để đáp ứng việc kiểm tra gần đây thì chuyển sang -mmin.

Công dụng thực chất của lệnh find nằm ở chỗ nó vừa tìm vừa xử lý. Dạng -exec lệnh {} \; chạy lệnh một lần cho mỗi file, còn -exec lệnh {} + gom danh sách file vào ít lần chạy hơn, với điều kiện cặp ngoặc nhọn đứng ngay trước dấu cộng. Hành động -delete thì cần thận trọng: GNU cảnh báo nếu đặt nó lên đầu biểu thức, find sẽ xóa mọi thứ dưới điểm bắt đầu. Tôi khuyên chạy lệnh find không có -delete trước để xem danh sách, xác nhận đúng rồi mới thêm hành động xóa vào cuối.

Nhóm hai sửa file cấu hình bằng nano ngay trong terminal Ubuntu

Nano là trình soạn thảo có sẵn trong terminal Ubuntu, hợp với chỉnh sửa ngắn như thêm một dòng cấu hình. Gõ nano ~/.bashrc để mở file cấu hình Bash cá nhân. Theo tài liệu chính thức của nano, hai dòng trợ giúp ở đáy màn hình hiển thị các chức năng thiết yếu nhất, trong đó ký hiệu ^ là phím Ctrl và M- là phím Meta, tức Alt hoặc Cmd. Hiểu quy ước này, bạn không cần thuộc phím tắt trước.

Trình soạn thảo nano mở file .bashrc trong terminal Ubuntu với hai dòng phím tắt ở đáy

Trong nano, mọi thao tác dùng phím tắt chứ không gõ lệnh terminal. Ctrl+O ghi bộ đệm ra đĩa và hỏi tên file, Ctrl+X thoát, và nếu nội dung đã đổi mà chưa lưu, nano sẽ hỏi có lưu trước khi thoát hay không. Tìm chữ bằng Ctrl+W, bản mới nhất nhận thêm Ctrl+F; cắt nguyên dòng bằng Ctrl+K, dán lại bằng Ctrl+U. Bảng phím tắt của phiên bản nano mới nhất còn có Ctrl+S để lưu nhanh, Alt+U để hoàn tác và Alt+E để làm lại, Ctrl+G mở trợ giúp.

Sửa file hệ thống trong thư mục /etc cần quyền quản trị, khi đó gõ sudo nano /etc/hosts. Tài liệu Ubuntu giải thích sudo thực thi một lệnh terminal với đặc quyền quản trị, chỉ tài khoản quản trị mới gọi được. Với ~/.bashrc, bạn có thể thêm alias như alias ll='ls -la' để rút ngắn lệnh hay gõ; thay đổi chỉ được kích hoạt cho cửa sổ mới hoặc sau khi chạy source ~/.bashrc. Tôi khuyên sửa từng dòng nhỏ rồi mở cửa sổ mới kiểm tra.

Nhóm ba đọc nhật ký và kết quả dài bằng less, journalctl

Khi kết quả dài hàng nghìn dòng, phần đầu trôi khỏi màn hình trước khi bạn kịp đọc. Less giải quyết đúng việc đó: theo man page, chương trình này không cần đọc hết dữ liệu đầu vào mới bắt đầu hiển thị, nên mở file nhật ký dung lượng lớn vẫn nhanh. Bạn có thể mở trực tiếp một file bằng less tên_file hoặc đưa đầu ra của lệnh khác vào qua dấu gạch đứng, ví dụ ps aux | less. Mọi lệnh terminal in ra nhiều dòng đều ghép với less theo cách này, và less chỉ là công cụ xem.

Đọc nhật ký hệ thống bằng less và tìm từ khóa error trong terminal Ubuntu

Trong terminal Ubuntu, phím Space hoặc f sang một màn hình, b lùi một màn hình, j và k đi từng dòng, g về đầu, G xuống cuối. Gõ /error rồi Enter để tìm xuôi, ?error để tìm ngược, n lặp lại lần tìm trước, N lặp theo chiều ngược lại, q để thoát. Phím F cuộn tới cuối và tiếp tục chờ dữ liệu mới. Hai tùy chọn hay dùng khi mở là -N hiện số dòng và -i tìm không phân biệt hoa thường khi mẫu tìm toàn chữ thường.

Trong terminal Ubuntu, nhật ký do systemd quản lý được đọc bằng journalctl, và man page ghi rõ đầu ra mặc định đi qua less, nên mọi phím ở trên áp dụng nguyên vẹn. Tùy chọn -u lọc theo một dịch vụ, ví dụ journalctl -u NetworkManager; -b lấy nhật ký của một lần khởi động; -p lọc theo mức ưu tiên; -e nhảy ngay xuống cuối; -f in liên tục dòng mới. Thêm --no-pager khi muốn chuyển kết quả sang lệnh terminal khác mà không phân trang.

Nhóm bốn nối nhiều lệnh theo mã thoát thành công hoặc thất bại

Bản chất của toán tử nối lệnh nằm ở mã thoát. Theo tài liệu Bash của GNU, mỗi lệnh kết thúc với một mã từ 0 đến 255; mã 0 nghĩa là thành công, mọi giá trị khác 0 là thất bại. Trong lệnh1 && lệnh2, lệnh2 chỉ chạy khi lệnh1 trả về 0. Trong lệnh1 || lệnh2, lệnh2 chỉ chạy khi lệnh1 trả về giá trị khác 0. Gõ echo $? ngay sau một lệnh terminal để xem mã thoát của nó, cách nhanh nhất để hiểu vì sao một chuỗi lệnh dừng giữa chừng.

Mã thoát Ý nghĩa theo tài liệu Bash Tình huống thường gặp
0 Lệnh thành công Toán tử && chạy tiếp lệnh sau
2 Lệnh dựng sẵn của shell bị gọi sai cú pháp Thiếu hoặc sai tùy chọn
126 Tìm thấy lệnh nhưng không thực thi được Script chưa có quyền chạy
127 Không tìm thấy lệnh Gõ sai tên hoặc chưa cài chương trình
130 128 cộng 2, dừng do SIGINT Nhấn Ctrl+C khi lệnh đang chạy
137 128 cộng 9, dừng do SIGKILL Tiến trình nhận kill -9
143 128 cộng 15, dừng do SIGTERM Tiến trình nhận kill mặc định

Ví dụ quen thuộc trong terminal Ubuntu là sudo apt update && sudo apt upgrade: bước nâng cấp chỉ chạy khi danh sách gói đã cập nhật thành công. Chuỗi mkdir project && cd project cũng theo nguyên lý ấy, không tạo được thư mục thì không chuyển vào. Ngược lại, || đóng vai trò phương án dự phòng, chẳng hạn cd /opt/app || echo "Không có thư mục" chỉ in thông báo khi lệnh cd thất bại. Dấu chấm phẩy thì khác hẳn: các lệnh ngăn bởi ; chạy lần lượt, bất kể lệnh trước thành hay bại.

Chỗ dễ sai nhất là ghép cả hai toán tử thành a && b || c rồi tưởng đó là cấu trúc nếu, thì, ngược lại. Tài liệu Bash nêu && và || có cùng độ ưu tiên và thực thi từ trái sang phải, nên c sẽ chạy khi a thất bại nhưng cũng chạy khi a thành công mà b thất bại. Mã trả về của cả chuỗi là mã của lệnh cuối cùng được thực thi. Muốn rẽ nhánh chặt chẽ trong một lệnh terminal dài, tôi ưu tiên khối if rõ ràng.

Nhóm năm theo dõi và dừng tiến trình bằng ps, pgrep và kill

Mỗi chương trình đang chạy là một tiến trình có PID riêng, và kill làm việc với PID chứ không với tên. Lệnh ps aux theo cú pháp BSD liệt kê mọi tiến trình, với các cột USER, PID, %CPU, %MEM, STAT và COMMAND. Theo man page, %MEM là tỷ lệ bộ nhớ vật lý tiến trình chiếm; cột STAT cho biết trạng thái: R đang chạy, S ngủ chờ sự kiện, D ngủ không ngắt được, T bị dừng, Z là tiến trình zombie đã kết thúc nhưng chưa được tiến trình cha thu dọn.

Tín hiệu Số hiệu trên x86 và ARM Hành động mặc định Ý nghĩa theo signal(7)
SIGHUP 1 Kết thúc Mất terminal điều khiển hoặc tiến trình điều khiển dừng
SIGINT 2 Kết thúc Ngắt từ bàn phím
SIGQUIT 3 Kết thúc kèm core dump Thoát từ bàn phím
SIGKILL 9 Kết thúc Buộc dừng, không thể bắt, chặn hay bỏ qua
SIGTERM 15 Kết thúc Yêu cầu kết thúc, mặc định của kill
SIGCONT 18 Tiếp tục Chạy tiếp nếu đang bị dừng
SIGSTOP 19 Dừng Tạm dừng, không thể bắt, chặn hay bỏ qua

Tìm PID nhanh hơn với pgrep: pgrep -l firefox in PID kèm tên tiến trình, pgrep -a in cả dòng lệnh đầy đủ, còn -f so mẫu với toàn bộ dòng lệnh thay vì chỉ tên. Theo man page, kill không kèm tín hiệu sẽ gửi TERM, tức SIGTERM số 15, và pkill cũng mặc định gửi SIGTERM tới mọi tiến trình khớp mẫu. Một lệnh terminal như kill 4242 vì thế cho chương trình cơ hội dọn dẹp trước khi thoát.

Chỉ khi tiến trình phớt lờ SIGTERM mới nên dùng lệnh terminal kill -9 PID hoặc kill -KILL PID. Man page signal(7) ghi SIGKILL và SIGSTOP không thể bị bắt, chặn hay bỏ qua, nghĩa là chương trình không có cơ hội ghi nốt dữ liệu đang mở. Với tiến trình trạng thái Z, kill vô tác dụng vì nó đã kết thúc, chỉ chờ tiến trình cha thu dọn. Tôi khuyên xác minh lại PID bằng ps trước khi gửi SIGKILL, vì gõ nhầm một chữ số là dừng sai chương trình.

Câu hỏi thường gặp

Người mới chuyển từ Windows nên học nhóm nào trước? Tôi gợi ý bắt đầu bằng pwd, Tab và man, sau đó tới lệnh find và less vì hai công cụ này chỉ đọc khi chưa thêm -delete hay -exec. Bối cảnh chuyển đổi được bàn trong bài Windows 10 chính thức bị khai tử - Thời điểm lý tưởng để chuyển sang Linux và LibreOffice, còn khi đã quen terminal Ubuntu, bạn mới nên chuyển sang nano, toán tử nối lệnh và kill.

Vì sao kill không dừng được tiến trình? SIGTERM có thể bị chương trình bắt hoặc bỏ qua, khi đó mới cần SIGKILL số 9. Nếu cột STAT hiện Z, tiến trình đã kết thúc và chỉ chờ tiến trình cha thu dọn; nếu hiện D, tiến trình đang ngủ không ngắt được, thường do chờ vào ra dữ liệu. Xác minh trạng thái bằng ps aux trước khi lặp lại lệnh terminal đó.

Có cách nào thử find an toàn trước khi xóa file? Có. Chạy lệnh find không kèm hành động để xem danh sách, sau đó mới thêm -delete vào cuối. Tài liệu GNU findutils lưu ý -delete tự bật tùy chọn -depth và nếu đặt lên đầu biểu thức sẽ xóa mọi thứ dưới điểm bắt đầu.

0 phản hồi cho “Lệnh terminal trên Linux - 5 nhóm lệnh nên hiểu bản chất thay vì học thuộc”

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *