3.2. Operations Deployment: Process, log hệ thống và giám sát tài nguyên
Mục lục
- 1. Process và cách quan sát bằng ps
- 2. Theo dõi liên tục với top và lọc process
- 3. Ưu tiên CPU với nice và renice
- 4. Signal, kill và pkill
- 5. Job trong terminal và lsof
- 6. Log truyền thống trong thư mục var log
- 7. journalctl và systemd-journald
- 8. Giám sát disk, RAM và CPU
- 9. Kiểm tra toàn vẹn file system và service
1. Process và cách quan sát bằng ps
Mỗi lần khởi chạy một chương trình, nó tồn tại trên hệ điều hành dưới dạng một process, cho tới khi nó làm xong việc hoặc bị đóng lại. Chạy một lệnh như ls thì một process ngắn ngủi được tạo ra: process của ls in nội dung thư mục, xong việc là nó kết thúc. Những process khác thì sống rất lâu, SSH daemon là ví dụ điển hình, nó chạy liên tục trên một Linux server.
Lệnh hay dùng để xem process là ps, và ps có một điểm lạ: nó nhận hai kiểu cú pháp cho option của mình. Dạng ps -A dùng cú pháp Unix, còn dạng ps a dùng cú pháp BSD. Hai dạng này không tương đương: ps a cho kết quả khác hẳn ps -A.
Gọi ps không kèm option nào thì mặc định nó chỉ hiện các process được khởi chạy trong cửa sổ terminal hoặc session hiện tại. Nhưng thứ cần là toàn bộ process trên hệ thống, và để có điều đó phải kết hợp ba option a, x và u:
ps aux
# Output (minh họa):
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.4 167892 11420 ? Ss 09:12 0:03 /sbin/init
root 412 0.0 0.1 22016 4180 ? S<s 09:12 0:00 /lib/systemd/systemd-journald
root 920 0.0 0.3 15420 7104 ? Ss 09:12 0:00 sshd: /usr/sbin/sshd -D
root 14 0.0 0.0 0 0 ? I< 09:12 0:00 [kworker/0:1H-kblockd]
jeremy 1312 0.3 0.2 10360 5212 pts/0 Ss 09:30 0:01 -bash
Tổ hợp a và x làm ps hiện mọi process. Option u liệt kê process theo cái gọi là user-oriented format, thêm vào output những cột hữu ích như mức dùng bộ nhớ, mức dùng CPU, và cho biết mỗi process thuộc user nào. Vì vậy ps aux là lệnh hay dùng nhất để xem toàn bộ process trên một hệ thống Linux. Cách nhớ: nghĩ tới từ auxiliary. Lỡ quên thì man ps rồi cuộn xuống một hai trang là tới mục EXAMPLES, nơi liệt kê các lệnh ps thường dùng nhất.
Đọc output trên theo từng cột:
%CPUcho biết process đang dùng bao nhiêu phần trăm CPU.100nghĩa là dùng hết toàn bộ năng lực của một CPU core, nên con số như150nghĩa là một core đầy cộng thêm 50% năng lực của core thứ hai.%MEMcho biết process dùng bao nhiêu phần trăm tổng bộ nhớ.STARTcho biết thời điểm process được khởi chạy, hoặc ngày nếu process không khởi chạy trong hôm nay.TIMEcho biết process đã dùng bao nhiêu CPU time trong suốt đời nó. Một process khởi chạy từ sáu giờ trước vẫn có thể chỉ dùng ba giây CPU time, phần thời gian còn lại nó nằm ở trạng thái sleeping và dùng 0% CPU. Để ghi được một giây ở cột này, process phải dùng 100% của một core trong trọn một giây; dùng 50% của một core trong mười giây thì cột này ghi khoảng năm giây.COMMANDcho biết chính xác lệnh đã được dùng để khởi chạy process, kèm cả option.
Một chi tiết nữa trong output: có những process được bọc trong cặp ngoặc vuông. Đó là các kernel process chạy bên trong vùng đặc quyền của kernel Linux. Chúng do kernel tự quản lý nội bộ nên thường không cần can thiệp. Phần việc hàng ngày chỉ liên quan tới process bình thường chạy bên ngoài vùng đặc quyền đó, tức vùng user space, chính là những process không bọc ngoặc vuông.
2. Theo dõi liên tục với top và lọc process
ps chỉ chụp lại trạng thái các process tại đúng khoảnh khắc lệnh được thực thi. Để theo dõi liên tục xem chuyện gì đang diễn ra thì có lệnh khác:
top
Mặc định top liên tục sắp xếp lại danh sách và đẩy các process ngốn CPU nhiều nhất lên đầu. Di chuyển trong output bằng các phím mũi tên và Page Up, Page Down, rồi nhấn q để thoát.
Phần còn lại của mục này là cách thu hẹp danh sách lại thay vì nhìn hết. Biết PID của một process thì lọc theo PID:
ps 1
ps u 1
Con số 1 trong hai lệnh trên là PID cần tra, còn dòng thứ hai thêm option u chữ thường để có lại kiểu user-oriented format với các cột CPU và bộ nhớ.
Muốn xem các process do user jeremy khởi chạy thì truyền username sau option U chữ hoa, và thêm u chữ thường nếu cần user-oriented format:
ps -U jeremy
ps -U jeremy u
Có lúc lại cần tìm process theo tên. Để tìm mọi process có chữ syslog trong tên, dùng pgrep, tức process grep:
pgrep -a syslog
# Output (minh họa):
1084 /lib/systemd/systemd-journald
Option -a nghĩa là all, bắt pgrep hiện kèm cả lệnh đã dùng để khởi chạy process. Trường đầu tiên trong dòng output là PID, ở đây là 1084, phần theo sau là lệnh đã khởi chạy process đó.
3. Ưu tiên CPU với nice và renice
Linux có khái niệm process niceness, tức mức độ "tử tế" của một process với các process khác. Giá trị niceness là một số từ -20 tới 19. Số càng thấp thì process càng ít tử tế, nghĩa là ưu tiên càng cao.
Hình dung process A có nice value -20 và process B có nice value 19. Khi cả hai cùng chạy, chúng sẽ dùng hết tài nguyên CPU có sẵn, nhưng A gần như không để lại gì cho B: A có thể chiếm CPU 95 tới 99% thời gian, còn B chỉ nhận được rất ít CPU time, chỉ khi còn dư ra chút nào.
Process quan trọng thì cần ưu tiên cao hơn, nghĩa là cần gán nice value thấp hơn. Có hai cách làm việc này.
Gán nice value ngay lúc khởi chạy
Cú pháp là nice -n theo sau là nice value, rồi tới lệnh. Gán nice value 11 cho lệnh bash:
nice -n 11 bash
Lệnh ps aux ở mục trước không hiện nice value. Để thấy nó, dùng option l, bật output dạng BSD long format, trong đó có cột NI chứa nice value. Muốn thấy nice value của toàn bộ process thì thêm luôn tổ hợp a và x:
ps l
ps lax
# Output (minh họa):
F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
0 1000 1312 1309 20 0 10360 5212 - Ss pts/0 0:01 -bash
0 1000 12190 1312 31 11 10360 5188 - SN pts/0 0:00 bash
0 1000 12245 12190 31 11 11284 3980 - RN+ pts/0 0:00 ps lax
Lệnh nice -n 11 bash ở trên đã khởi chạy một bash shell mới. Lệnh ps lax chạy trong shell đó cũng thừa hưởng nice value của shell, vì mọi process đều thừa hưởng niceness từ parent process, tức process đã khởi chạy nó.
Để thấy process nào là parent của process nào, thêm option f, viết tắt của forest display, vì nó vẽ ra các nhánh dạng cây cho quan hệ cha con:
ps fax
ps faux
Output cho thấy rõ bash shell trước đã khởi chạy một bash shell thứ hai, và shell thứ hai lại khởi chạy lệnh ps fax. Muốn có luôn mức dùng CPU, bộ nhớ và các cột đã quen thì thêm u vào. Thứ tự các chữ cái không quan trọng. Gõ exit để thoát khỏi bash shell thứ hai.
Một user thường chỉ được gán nice value trong khoảng 0 tới 19. Muốn gán giá trị thấp hơn để có ưu tiên cao hơn thì cần quyền root, nên lệnh dưới đây thất bại với thông báo permission denied, còn lệnh có sudo thì chạy được:
nice -n -12 bash
# Output:
nice: cannot set niceness: Permission denied
sudo nice -n -12 bash
ps lax
Kiểm tra bằng ps lax sẽ thấy bash shell với nice value -12. Gõ exit để thoát ra.
Đổi nice value của process đang chạy
Vấn đề của sudo nice -n -12 bash là nó cũng khởi chạy bash shell dưới quyền user root. Nhưng nếu muốn process chạy dưới user thường của mình thì làm theo cách khác: khởi chạy chương trình như bình thường trước đã.
bash
ps fax
Trong chế độ forest view, tìm ra PID của bash shell thứ hai này, giả sử là 12238. Nice value hiện tại của một process đang chạy được điều chỉnh sang giá trị khác bằng renice, theo cú pháp renice rồi nice value mới rồi PID:
renice 7 12238
# Output:
12238 (process ID) old priority 0, new priority 7
Thông báo xác nhận cho thấy priority cũ và priority mới. Xem lại bằng ps lax thì giá trị đúng là 7.
Nhưng thử hạ xuống 6 thì thất bại: một user thường không hạ được nice value của process xuống dưới mức nó đang có. Từ mức 7 hiện tại chỉ đổi lên được 8, 9, 10 hay lớn hơn, không xuống được 6, 5 hay thấp hơn:
renice 8 12238
sudo renice 6 12238
Dòng đầu chạy được. Muốn hạ xuống thì lại cần quyền root, vì chỉ root mới hạ được niceness của process. Xong việc thì exit khỏi bash shell thứ hai.
4. Signal, kill và pkill
Linux có khái niệm gửi cho process các thứ gọi là signal. Signal giống những thông báo ưu tiên cao bảo process dừng việc đang làm lại. Ví dụ có signal SIGTRAP. Nhưng một ứng dụng chỉ phản ứng được với một signal cụ thể nếu nó được lập trình để phản ứng với signal đó.
Ngoại lệ là những signal như SIGSTOP và SIGKILL: process không thể bỏ qua hai signal này. Nhận SIGSTOP thì việc thực thi của nó bị tạm dừng cho tới khi nhận được SIGCONT, tức continue. Nhận SIGKILL thì nó bị kết thúc ngay lập tức, không có cả cơ hội lưu lại công việc đang làm. SIGKILL thường chỉ gửi như phương án cuối, khi chương trình không phản hồi và không còn cách nào đóng nó lại.
Danh sách signal gửi được xem bằng option L, tức list:
kill -L
Chọn một signal để gửi thì dùng tên lấy từ danh sách đó. Có thể gõ SIGHUP, cũng có thể bỏ tiền tố SIG và gõ HUP; SIGHUP và HUP tương đương.
Thử một lượt. Tìm PID của SSH daemon bằng top, nhấn q để thoát màn hình đó, giả sử PID là 1457, rồi gửi signal SIGHUP:
kill -SIGHUP 1457
# Output:
kill: (1457): Operation not permitted
Nguyên nhân: process sshd chạy dưới user root. Một user thường chỉ gửi được signal tới các process do chính user đó sở hữu. Root là ngoại lệ, nó gửi signal được tới mọi process, cả của mình và của người khác. Vậy lệnh phải thành:
sudo kill -SIGHUP 1457
systemctl status ssh.service
SSH daemon được lập trình để phản ứng với signal này theo một cách nhất định, và systemctl status cho thấy nó đã làm gì: nhận SIGHUP thì nó nạp lại file cấu hình và restart.
Trong bảng signal, mỗi signal có một số đứng trước nó. Nên để gửi SIGKILL có ba biến thể dùng được:
kill -SIGKILL 1752
kill -KILL 1752
kill -9 1752
Nếu không khai signal nào thì SIGTERM được gửi theo mặc định, nên kill 1752 gửi SIGTERM tới process có PID 1752. SIGTERM bảo chương trình tự tắt một cách nhẹ nhàng: nó có cơ hội lưu công việc và đóng lại bình thường.
kill gửi signal tới process theo PID. Còn pkill gửi signal tới process theo tên. Ví dụ cần gửi SIGKILL tới mọi process có tên chứa chữ bash. Trước khi gửi, nên xem trước những process nào sẽ nhận nó, để không gửi nhầm:
pgrep -a bash
pkill -SIGKILL bash
Nếu danh sách xem trước đúng ý thì chạy dòng thứ hai. Lệnh này ngắt luôn session SSH đang dùng vì bash shell bị đóng cưỡng chế, nên phải đăng nhập lại.
5. Job trong terminal và lsof
Một số lệnh mất rất lâu mới xong việc. Mô phỏng bằng sleep:
sleep 180
Lệnh này chờ 180 giây rồi mới thoát, quá lâu để ngồi đợi. Nhấn Ctrl-C để bảo chương trình bỏ việc đang làm và kết thúc.
Sang một kịch bản khác: đang sửa một file bằng editor, giữa lúc sửa lại cần làm việc khác mà vẫn muốn để editor mở. Nhấn Ctrl-Z để tạm dừng ứng dụng hiện tại và quay về terminal: prompt trở lại, không còn ở trong vim nữa. Làm việc khác xong thì quay về ứng dụng đang tạm dừng:
fg
fg viết tắt của foreground, đưa ứng dụng trở lại tiền cảnh, lấy lại focus trong terminal. Thoát vim bằng Escape rồi :q. Ctrl-C và Ctrl-Z không hoạt động với mọi chương trình, nhưng hoạt động với phần lớn.
Một điểm cần nắm về Ctrl-Z: chương trình bị tạm dừng theo cách đó thì không tiến triển gì với công việc của nó, nó đóng băng toàn bộ. Muốn chương trình vẫn làm việc trong khi mình dùng terminal cho việc khác thì dùng ký hiệu &, gọi là backgrounding một lệnh:
sleep 300 &
💡 Hình dung: backgrounding giống đưa một việc dài cho người khác làm rồi mình đi làm việc khác. Hình dung cần backup 500 GB dữ liệu và việc đó mất 30 phút: không ai muốn ngồi chờ 30 phút để lệnh backup xong. Đẩy nó ra background là nó cứ chạy suốt 30 phút trong khi terminal vẫn dùng được để gõ các lệnh khác.
Để kiểm tra có chương trình nào đang chạy ở background hoặc đang bị tạm dừng:
jobs
# Output (minh họa):
[1]+ Running sleep 300 &
Muốn quay lại lệnh đã đẩy xuống background thì gõ fg 1, vì lệnh đó có job ID là 1. Nhưng làm vậy là lại đưa sleep 300 lên tiền cảnh và bị kẹt ở đó. Nhấn Ctrl-Z để tạm dừng nó và quay về command line, nhưng cách này có vấn đề: ứng dụng giờ đang bị tạm dừng, và nếu đó là job backup thật thì nó không tiến triển gì nữa. Xem lại danh sách job sẽ thấy job backup tưởng tượng đó ở trạng thái stopped. Để nó tiếp tục chạy:
bg
jobs
# Output (minh họa):
[1]+ Running sleep 300 &
bg viết tắt của background, và sau lệnh đó thì jobs cho thấy job đã chạy lại, phần backup đang được hoàn tất.
Xem process đang mở file nào bằng lsof
Có lúc cần biết một process đang dùng những file hoặc thư mục nào. Trước tiên tìm PID của bash shell hiện tại, giả sử là 13536, rồi:
lsof -p 13536
Lệnh này hiện mọi file và thư mục mà process đó đang dùng. Khi khám phá process khác, output có thể báo lỗi quyền, vì process đó thuộc user khác, thường là root. Cách giải quyết là thêm sudo trước lệnh để có quyền khám phá process đó.
Cũng có thể đi theo chiều ngược lại: đưa vào đường dẫn tới một file hoặc thư mục để xem có process nào đang dùng nó:
lsof /var/log/auth.log
sudo lsof /var/log/auth.log
Dòng đầu có thể cho output rỗng, trông như không có gì đang dùng file đó. Nhưng lý do thật là process đang dùng nó thuộc user root, và lsof không có quyền khám phá process đó. Vì không báo lỗi gì nên kết quả rỗng này dễ gây hiểu sai. Thói quen nên giữ là luôn chạy dạng lệnh này với sudo để chắc chắn nhìn được toàn cảnh.
6. Log truyền thống trong thư mục var log
Hệ điều hành Linux phần lớn hướng tới vai trò server, và trên một server thì luôn cần biết chuyện gì đã xảy ra: ai làm gì, cái gì chạy được, cái gì không, gặp lỗi nào, ai truy cập vào hệ thống. Mọi việc quan trọng xảy ra trên một hệ thống Linux đều được lưu lại ở đâu đó dưới dạng thông báo text, gọi là log.
Kernel Linux và phần lớn chương trình chạy trên Linux đều sinh ra thông báo trạng thái, thông báo lỗi, cảnh báo. Có thể có hàng chục chương trình sinh ra những thông báo này liên tục, nên cần một cách thu thập tất cả lại và tổ chức chúng gọn gàng vào file. Đó là việc của các logging daemon: những ứng dụng thu thập, tổ chức và lưu log.
Phổ biến nhất trên Linux là rsyslog, tên đến từ Rocket-fast System for Log Processing. rsyslog lưu toàn bộ log vào thư mục /var/log. Vì chúng thường là file text thường, nên tìm trong đó bằng grep hay bất cứ utility xử lý text nào cũng được, chi tiết ở Part 2.4: grep, regular expression, archive và I/O redirection.
Một lưu ý trước khi mở log: phần lớn file này user thường không đọc được. Nên đăng nhập làm root trước:
su --login
sudo --login
Dòng đầu cần password của root, dòng sau cần password của user hiện tại.
Giả sử không biết log SSH nằm ở đâu và cần xem ai đã đăng nhập qua SSH. Cách làm là tìm trong mọi file xem có gì chứa chữ sshd, để lần ra những thứ thuộc SSH daemon:
grep -r sshd /var/log
# Output (rút gọn):
/var/log/auth.log:Oct 24 09:12:41 server-01 sshd[920]: Server listening on 0.0.0.0 port 22.
Kết quả cho biết một phần log SSH được lưu trong file /var/log/auth.log. Mở file đó ra và tìm log của sshd: trong vim thì gõ dấu /, nhập sshd, nhấn n để tới match kế tiếp, rồi q để thoát. Mở bằng less cũng vậy: nhấn /, nhập sshd, nhấn n để tới match kế tiếp, rồi q để thoát. Phần dùng vim nằm ở Part 2.3: Tìm file, xử lý text stream và vi.
Trong /var/log/auth.log có các log liên quan tới xác thực và phân quyền an toàn: ai đã đăng nhập qua SSH, ai thử đăng nhập và bị từ chối vì sai password hoặc lý do tương tự, ai dùng sudo để lấy quyền root, lệnh gì được chạy qua sudo, ứng dụng nào xin quyền quản trị đặc biệt và đã làm gì với quyền đó, chuyện đó xảy ra lúc nào. Nên nó không chỉ chứa thứ liên quan SSH mà cả các log xác thực khác: đổi password cũng sinh ra một dòng log ở đây.
Một dòng log như vậy cho biết: ngày và giờ việc đó xảy ra, hostname của máy, ứng dụng hoặc nguồn sinh ra thông báo, và bản thân nội dung thông báo. Nhiều log entry theo đúng định dạng này, nhất là các system log theo dõi những gì xảy ra trên hệ điều hành. Phần lớn system log nằm trong file /var/log/syslog.
Trong /var/log thường có cả những file tên kiểu auth.log.1 hoặc auth.log.2.gz. Đó là các log cũ hơn: auth.log là bản mới nhất, auth.log.1 là bản được ghi ngay trước auth.log hiện tại, và auth.log.2.gz là bản được tạo trước auth.log.1, lại được nén bằng utility gzip cho nhỏ file.
Phần lớn thời gian là đọc log để xem chuyện đã xảy ra trong quá khứ. Nhưng có lúc cần xem chuyện đang xảy ra ngay lúc này, ví dụ khi debug một ứng dụng: thử từng thứ rồi xem nó sinh ra lỗi gì. Cách xem live một file log, thấy entry mới ngay khi nó xuất hiện:
tail -f /var/log/auth.log
Option -f bật follow mode cho tail. Thử bằng cách chạy lệnh đó rồi chuyển sang máy ảo và đăng nhập ở console text: ngay khi nhập password sẽ thấy hai dòng mới hiện ra, chứa thông tin về lần đăng nhập đó. Nhấn Ctrl-C để thoát follow mode.
7. journalctl và systemd-journald
Đi lại trong /var/log không khó, nhưng vẫn có thể dễ hơn. Lấy ví dụ cần xem cả team đã làm gì với lệnh sudo: có thể mở /var/log/auth.log rồi lọc kết quả bằng grep hoặc less để chỉ lấy các entry chứa chữ sudo. Nhưng có cách gọn hơn.
rsyslog theo dõi log và lưu vào các file trong /var/log. Các hệ điều hành Linux hiện đại dùng thêm một cách thứ hai để theo dõi log: chương trình systemd-journald thu thập dữ liệu này thông minh hơn một chút, và lệnh journalctl cho phép phân tích log hiệu quả hơn.
Ví dụ, journalctl lọc được log sinh ra bởi một lệnh cụ thể. Trước hết cần đường dẫn đầy đủ tới lệnh sudo:
which sudo
# Output:
/usr/bin/sudo
journalctl /usr/bin/sudo
Output mở ra trong pager less, nên dùng được các phím di chuyển, tìm kiếm và mọi thứ khác đã học về less, rồi nhấn q để thoát.
Phần trước của tài liệu đã nói về việc hệ điều hành quản lý các ứng dụng hệ thống quan trọng bằng service unit, ví dụ SSH daemon chạy thường trực ở nền với một service unit điều khiển và theo dõi hoạt động của nó. Biết tên service thì xem log của nó bằng:
journalctl -u ssh.service
-u bảo journalctl hiện log do unit ssh.service sinh ra. Gõ journalctl một mình thì thấy toàn bộ log mà systemd-journald đã thu thập. Nhấn dấu > để nhảy tới cuối output. Muốn mở journal và nhảy ngay tới cuối thì dùng option -e, tên dài là --pager-end:
journalctl -e
journalctl -f
Giống như mở file log ở follow mode, journalctl cũng có follow mode, bật bằng option -f. Lúc đó có một khung nhìn live mọi log mới xuất hiện trên hệ thống, và Ctrl-C là cách thoát khỏi khung nhìn đó.
Lọc theo mức ưu tiên, regex và thời gian
Phần lớn log chỉ mang tính thông tin, báo về những việc bình thường đang xảy ra trên hệ thống. Nhưng một số là cảnh báo về những thứ đang không ổn, một số là lỗi về những thứ đã thất bại, một số là tín hiệu báo động lớn về những thứ đang sai nghiêm trọng. Chúng được gắn thẻ info, warning, error.
Chỉ cần tìm các lỗi ở mức tương đối nghiêm trọng thì dùng option -p, tên dài là --priority:
journalctl -p err
Danh sách priority dùng được với option này gồm: alert, crit, debug, emerg, err, info, notice, warning. Quên danh sách thì gõ journalctl -p, thêm một dấu cách ở cuối rồi nhấn Tab hai lần là có đủ các tên priority code.
Cũng lọc được output bằng biểu thức grep, qua option -g hay tên dài --grep. Và các option kết hợp được với nhau. Ví dụ chỉ lấy log có priority info và có thông báo bắt đầu bằng chữ B:
journalctl -p info -g '^B'
Với -g và regex ^B, biểu thức grep được truyền vào để chỉ tìm những dòng bắt đầu bằng B.
journalctl cũng hiện được log ghi sau một thời điểm nhất định, qua option --since. Option này dùng định dạng 24 giờ, nên 0200 cho thấy log sinh ra từ hai giờ sáng. Có cả option --until, nên kết hợp cả hai là xem được log trong một khoảng:
journalctl --since 02:00
journalctl --since 01:00 --until 02:00
Cả --since và --until đều nhận ngày, nên lọc được xuống tới từng giây. Phần ngày giờ phải bọc trong cặp nháy đơn:
journalctl --since '2024-03-23 23:32'
Lọc theo lần boot
Mặc định journalctl hiện mọi log thu thập được trên hệ thống, bắt đầu từ entry đầu tiên còn lưu. Nhưng những entry đầu tiên có thể rất cũ, ví dụ từ hai tháng trước, và phần lớn trường hợp không cần dữ liệu cũ tới mức đó. systemd-journald nhóm log theo thời điểm hệ thống boot, nên thường cái cần xem là log sinh ra từ lần boot gần nhất:
journalctl -b 0
journalctl -b -1
journalctl -b -2
Option -b, tức boot, nhận 0 cho lần boot hiện tại, -1 cho lần boot trước, -2 cho hai lần boot trước.
Trên một số hệ điều hành, systemd-journald được cấu hình chỉ giữ log của lần boot hiện tại và chỉ giữ trong bộ nhớ, không ghi xuống disk. Nên reboot là journal log mất, và lệnh journalctl -b -1 sẽ báo không tìm thấy persistent journal. Dù vậy, các log dạng text vẫn được giữ theo lối cũ trong thư mục /var/log.
Thông thường systemd-journald quyết định có lưu persistent journal hay không dựa vào sự tồn tại của thư mục /var/log/journal. Thư mục đó không có thì nó không giữ journal log trên disk; có thì nó bắt đầu lưu journal log vào đó. Nên chỉ cần tạo thư mục này là đã chỉ thị cho systemd-journald lưu log ở đó.
Một điểm nữa: lệnh journalctl yêu cầu người chạy phải đăng nhập làm root, hoặc user hiện tại phải thuộc một số group nhất định, là wheel trên hệ điều hành nhóm Red Hat, hoặc adm hay sudo trên nhóm Ubuntu. Nếu journalctl gọi trơn không ra log thì thêm sudo phía trước để tạm có quyền cần thiết. Phần group và user nằm ở Part 4.1: User, group, environment profile và resource limit.
Lịch sử đăng nhập
Để xem lịch sử ai đã đăng nhập vào hệ thống:
last
Entry mới nhất nằm trên cùng, nên có thể phải cuộn lên để thấy chúng. Các dòng bắt đầu bằng reboot system boot cho biết thời điểm hệ thống được bật nguồn. Một lệnh thay thế:
lastlog
Lệnh này cho biết mỗi user trên hệ thống đăng nhập lần cuối vào lúc nào. Với các lần đăng nhập từ xa, ví dụ qua SSH, nó hiện cả IP address mà họ đăng nhập từ đó.
8. Giám sát disk, RAM và CPU
Thời gian trôi đi thì một server thường dùng càng nhiều tài nguyên hơn. Dung lượng lưu trữ là ví dụ rõ nhất: database lớn dần, người dùng lưu thêm file, và càng nhiều gigabyte dung lượng bị chiếm. Trên cloud thì thêm disk hay SSD cho server khá dễ, nhưng làm sao biết lúc nào sắp hết dung lượng?
Dung lượng disk
df
# Output (minh họa):
Filesystem 1K-blocks Used Available Use% Mounted on
tmpfs 398692 1428 397264 1% /run
/dev/mapper/ubuntu--vg-root 9983232 4089856 5368320 44% /
/dev/vda2 974696 205112 702280 23% /boot
Output này hơi khó đọc, vì dung lượng đã dùng hiện theo block 1 kilobyte. Có thể bảo df in ra dạng người đọc được bằng option -h:
df -h
# Output (minh họa):
Filesystem Size Used Avail Use% Mounted on
tmpfs 390M 1.4M 389M 1% /run
/dev/mapper/ubuntu--vg-root 9.6G 3.9G 5.4G 43% /
/dev/vda2 952M 201M 686M 23% /boot
Giờ dung lượng hiện theo megabyte, gigabyte, terabyte, nhận ra qua chữ M, G hoặc T. Những file system chứa chữ tmpfs thì bỏ qua được: đó là các file system ảo chỉ tồn tại trong bộ nhớ máy, không nằm trên thiết bị lưu trữ.
Ở ví dụ trên có hai file system thật. Cái mount trên / là root file system, nơi hệ điều hành Linux được cài. Cái mount trên /boot là một file system nhỏ chứa các file boot. Ý nghĩa của /dev/mapper và /dev/vda2 thuộc phần quản lý thiết bị lưu trữ, ở Part 6.1: Phân vùng, swap, file system và mount.
Đọc kết quả: root file system đã dùng 3.9 GB và còn trống 5.4 GB. Vì 43% file system đã dùng, còn dư khá nhiều, khoảng 57% dung lượng trống.
Để xem một thư mục cụ thể đang chiếm bao nhiêu dung lượng thì dùng du, tức disk usage:
du -sh /usr
# Output (minh họa):
3.2G /usr
-s là option summarize, bắt du chỉ hiện dung lượng của riêng cả thư mục /usr. Không có -s thì du hiện dung lượng của thư mục đó và của từng subdirectory bên trong nó. -h làm nó in dung lượng ở dạng người đọc được: mebibyte, gibibyte và tương tự.
Bộ nhớ
free -h
# Output (minh họa):
total used free shared buff/cache available
Mem: 3.8Gi 1.0Gi 1.4Gi 12Mi 1.5Gi 2.6Gi
Swap: 2.0Gi 0B 2.0Gi
Option -h lại được dùng để in dung lượng theo megabyte, gigabyte. Về mặt kỹ thuật thì đây là mebibyte, còn một MB mới bằng một triệu byte. Output ví dụ cho thấy khoảng 3.6 GB bộ nhớ dùng được và 1.0 GB đang được dùng.
Nhưng bao nhiêu bộ nhớ đang trống và sẵn sàng cho chương trình dùng? Con số đó nằm ở cột tên Available, không phải cột tên Free, và chỗ này dễ gây nhầm. Giải thích về mặt kỹ thuật: một phần bộ nhớ đang được dùng, tức không trống, nhưng hệ điều hành có thể giải phóng nó bất cứ lúc nào. Đọc một file 1 gigabyte thì hệ điều hành tạm giữ nó trong bộ nhớ để lần sau truy cập nhanh hơn; nhưng nếu một chương trình cần đúng 1 GB bộ nhớ đó, hệ điều hành giải phóng nó ngay. Nên dù 1 gigabyte đó đang được dùng và không trống, nó vẫn là bộ nhớ sẵn sàng mỗi khi cần.
CPU
uptime
# Output (minh họa):
09:42:17 up 2 days, 3:11, 2 users, load average: 0.52, 0.31, 0.14
Thông tin quan trọng ở đây là ba con số sau load average. Số đầu là mức tải trung bình trong một phút gần nhất, số thứ hai là trung bình trong năm phút gần nhất, số thứ ba là trung bình trong mười lăm phút gần nhất.
Thấy load average 1.00 ở số đầu nghĩa là trung bình trong một phút qua, một CPU core đã được dùng hết công suất, tức 100% core đó bị dùng căng trong phút vừa rồi. Vì là trung bình nên con số này có thể nghĩa là 100% suốt trọn một phút, mà cũng có thể nghĩa là 30 giây đầu dùng 0% và 30 giây sau dùng 200%, tức hai core. Cả hai trường hợp đều ra trung bình 100% và hiển thị là 1.00 ở trường này. Thấy 2.00 ở số cuối nghĩa là trung bình có hai CPU core bị dùng hết 100% trong mười lăm phút qua.
Hình dung một hệ thống có tám CPU core và thấy load average 6.00, 0.40, 0.20. Điều đó nghĩa là sáu core bị dùng căng trong một phút gần nhất, nhưng trong năm và mười lăm phút gần nhất thì các core gần như rỗi. Vậy chuyện vừa xảy ra gần đây: vài chương trình làm việc nặng trong một khoảng rất ngắn, còn nhìn tổng thể thì hệ thống không đẩy CPU quá mức, chưa cần lo. Nhưng nếu thấy load average kiểu 7.80, 7.60, 7.40 thì nghĩa là một số chương trình dùng CPU nặng gần như suốt thời gian, và đã đến lúc nâng cấp lên server khỏe hơn hoặc tối ưu lại setup cho nó cần ít tài nguyên CPU hơn.
Chi tiết về CPU và về phần cứng khác trên hệ thống:
lscpu
lspci
9. Kiểm tra toàn vẹn file system và service
Phần cuối chuyển từ dung lượng sang tính toàn vẹn: file system có lỗi hay không, và các process trọng yếu có đang chạy đúng hay không.
File system
Để kiểm tra một file system xem có lỗi hay không, trước tiên phải unmount nó nếu nó đang được mount. Phần file system, partition, mount và unmount nằm ở Part 6.1.
Hệ điều hành nhóm Red Hat thường mặc định dùng file system XFS, còn nhóm Ubuntu dùng ext4, dù điều này có thể thay đổi trong tương lai với cả hai. Với XFS, tool kiểm tra riêng của nó được chạy với option -v, bật verbose output, nghĩa là in thêm chi tiết về việc lệnh đang làm gì; -v không bắt buộc nhưng hữu ích để thấy mọi thứ đang diễn ra. Đối tượng kiểm tra là đường dẫn tới partition chứa file system, ví dụ /dev/vdb1, trỏ tới partition thứ nhất trên thiết bị lưu trữ ảo thứ hai. Trong tình huống thật, đường dẫn đó có thể là thứ khác hẳn, ví dụ /dev/vda2 hoặc /dev/sdc3, tùy file system cần quét nằm ở đâu.
Với ext4 thì lệnh kiểm tra và sửa là:
sudo fsck.ext4 -v -f -p /dev/vdb1
Trong đó -v bật verbose output, còn -f ép kiểm tra kể cả khi file system báo nó đang khỏe. -p bật cái gọi là preen mode, để utility tự sửa một số vấn đề đơn giản mà không hỏi lại gì; nếu gặp lỗi nghiêm trọng thì nó vẫn hỏi các câu yes hoặc no.
Hai option -v và -f đều không bắt buộc. Nếu không nhớ hết các option thì ít nhất nhớ -p: option đó quan trọng hơn khi file system có nhiều lỗi, vì nó giúp khỏi phải gõ yes cho hàng chục câu hỏi, các lỗi đó được sửa tự động luôn. Cách ghi nhớ: nghĩ tới chữ p trong "ext4 filesystem problems".
Service trọng yếu
Làm sao chắc chắn các process then chốt trên hệ thống đang chạy đúng? Lệnh đầu tiên nên dùng:
systemctl list-dependencies
Lệnh này hiện một cấu trúc dạng cây gồm các systemd unit quan trọng, cả active và inactive. Một vòng tròn trong suốt hoặc màu trắng cạnh tên unit nghĩa là unit đó đang inactive. Thường thì không sao: một số unit chạy một lần lúc boot rồi thoát, một số khác không được thiết kế để tự chạy lúc boot mà chỉ chạy khi cần.
Nhưng có ngoại lệ. Một số service unit rất quan trọng và phải chạy liên tục. Ví dụ sshd.service điều khiển vòng đời của SSH daemon: nếu service này hiện inactive thì SSH daemon cũng inactive, nghĩa là người quản trị không kết nối được vào hệ điều hành này từ xa khi cần quản lý nó. Vòng tròn màu xanh cạnh tên unit nghĩa là nó đang active, và nói chung muốn thấy vòng tròn xanh ở mọi service quan trọng cần chạy thường trực. Ngoài ssh.service, cũng muốn cron.service và atd.service ở trạng thái active, nếu không thì các cron job và at job đã lập lịch sẽ không tự chạy, xem Part 3.3: Lập lịch task, kernel parameter và quản lý package.
Thử cố tình kết thúc daemon at để mô phỏng sự cố với một service đáng lẽ phải luôn active. Chạy lại systemctl list-dependencies sẽ thấy một đèn trắng cạnh atd.service, dấu hiệu có vấn đề với một service quan trọng: các at job đã lập lịch sẽ không được thực thi. Bắt đầu điều tra bằng:
systemctl status atd.service
Lệnh này xác nhận service đang inactive, process đáng lẽ phải chạy thì đã chết hoặc không tồn tại, và dòng log cuối cho biết atd.service bị deactivate lúc nào. Ở đây không có lỗi nghiêm trọng nào cần sửa, và service cũng đang được enable để tự khởi chạy mỗi lần hệ thống boot, nên việc cần làm chỉ là start lại service.
Trong tình huống thật thì mọi thứ có thể phức tạp hơn một chút, nhưng các dòng log trong systemctl status thường chỉ ra đúng chuyện gì sai và vì sao service không khởi động được. Nghĩa là phải sửa vấn đề mà log chỉ ra trước, rồi mới thử start service. Nếu log trong systemctl status không cho thấy nguyên nhân thật, thì đào sâu hơn bằng toàn bộ log do service đó sinh ra:
journalctl -u atd.service
Thói quen nên giữ khi vận hành: list-dependencies để soát nhanh toàn cảnh, status để xem nguyên nhân gần, journalctl -u khi status không đủ.
Nguồn tham khảo
Nguồn gốc: Khóa "Prep Course - Linux Foundation Certified System Administrator (LFCS) Certification" — phần "Operations Deployment" (chẩn đoán và quản lý process; định vị và phân tích system log file; kiểm tra tính toàn vẹn và khả dụng của tài nguyên cùng các process quan trọng), nền tảng KodeKloud. Giảng viên: Jeremy Morgan và Alexandru Andrei.
Fact-check:
- Trong
journalctl,-ulà dạng ngắn của--unit(chọn unit cần xem), không phải dạng ngắn của--until. Bài giảng gốc gọi "Until hoặc option -u", trong khi chính bài đó dùng đúngjournalctl -u ssh.serviceở đoạn trước. Tài liệu này chỉ dùng dạng dài--untilcho mốc thời gian. Nguồn:man 1 journalctl, 2026-10-25.