1 điểm bởi GN⁺ 5 giờ trước | 1 bình luận | Chia sẻ qua WhatsApp
  • Bắt đầu từ màn hình htop trên Ubuntu Server 16.04 x64 để lần theo bằng /proc và đầu ra lệnh xem uptime, load average, Tasks, PID, cây tiến trình, trạng thái, thời gian CPU, độ ưu tiên và các chỉ số bộ nhớ thực sự có ý nghĩa gì
  • Nhiều giá trị trên màn hình đến từ procfs và các tệp hệ thống như /etc/passwd, /etc/group, /etc/shadow, /etc/nsswitch.conf; có thể dùng strace để kiểm tra chương trình đang đọc những tệp nào
  • Load average không phải là giá trị giống với mức sử dụng CPU; đây là trung bình trượt hàm mũ suy giảm bao gồm các tiến trình đang chạy, đang chờ chạy và các tiến trình ở trạng thái uninterruptible
  • Các mã trạng thái như R, S, D, Z, T, t liên quan tới signal, kill, hành vi fork/exec/wait, nên là manh mối để xác định vì sao tiến trình bị dừng hoặc vẫn còn tồn tại
  • VIRT, RES, SHR, MEM% cho thấy bộ nhớ ảo, bộ nhớ vật lý và bộ nhớ có thể chia sẻ từ các góc nhìn khác nhau, nên khó kết luận mức dùng bộ nhớ thực tế chỉ từ một con số

Các giá trị trong htop đến từ đâu

  • uptime cho biết hệ thống đã chạy bao lâu; cùng thông tin này cũng có thể kiểm tra bằng lệnh uptime
  • Chương trình uptime đọc /proc/uptime
    • Số thứ nhất là tổng thời gian tính bằng giây mà hệ thống đã bật
    • Số thứ hai là thời gian tính bằng giây mà hệ thống ở trạng thái idle
    • Trên hệ thống đa lõi, thời gian idle được cộng dồn theo từng lõi nên có thể lớn hơn tổng uptime
  • Có thể xem các tệp mà uptime mở bằng strace uptime 2>&1 | grep open hoặc strace -e open uptime
    • Đầu ra ví dụ bao gồm /proc/uptime, /var/run/utmp, /proc/loadavg
  • Các con số trong /proc/uptime thuận tiện để dùng trong chương trình hoặc script, còn đầu ra uptime được định dạng để con người dễ đọc

Load average và mức sử dụng CPU

  • Ba giá trị đầu trong /proc/loadavg biểu thị load average của hệ thống trong 1 phút, 5 phút, 15 phút gần nhất
  • Giá trị thứ tư hiển thị số tiến trình đang chạy và tổng số tiến trình theo dạng như 1/120, còn giá trị cuối là PID được sử dụng gần nhất
  • Khi chạy một tiến trình mới, PID sẽ được cấp phát; PID thường tăng dần rồi được tái sử dụng khi cạn
    • PID 1 thuộc về /sbin/init, tiến trình được khởi chạy khi boot
  • Nếu trong htop chỉ thấy một tiến trình đang chạy thì đó có thể chính là htop
  • sleep 30 không ở trạng thái running mà ở trạng thái sleep, nên không làm tăng số running process
  • Tác vụ liên tục dùng CPU như cat /dev/urandom > /dev/null sẽ làm tăng số running process và load average
  • Load number là giá trị đếm các tiến trình đang chạy, đang chờ chạy hoặc ở trạng thái uninterruptible
  • load average không phải trung bình đơn giản mà là trung bình trượt hàm mũ suy giảm
    • Ngay cả load average 1 phút cũng không chỉ phản ánh 60 giây cuối mà đặt trọng số lớn hơn cho 1 phút gần nhất, đồng thời vẫn bao gồm một phần hoạt động trước đó
  • Trên hệ thống một CPU, nếu có một tiến trình CPU-bound thì có thể đơn giản hóa rằng load average 1.00 tương ứng CPU dùng 100%
    • Trên hệ thống 2 lõi, cùng tình huống đó có thể xem là mức sử dụng CPU 50%
    • Có thể đơn giản hóa rằng load average tương ứng với CPU 100% trên hệ thống 2 lõi là 2.00
  • Cách đơn giản hóa này không phải lúc nào cũng đúng vì các tiến trình ở trạng thái uninterruptible cũng được tính vào load
    • Cũng có thể xảy ra tình huống load average cao nhưng mức sử dụng CPU không cao
  • Có thể kiểm tra mức sử dụng CPU tức thời bằng mpstat
    • sudo apt install sysstat -y
    • mpstat 1

Tasks, PID, cây tiến trình

  • Tasks ở góc trên bên phải của htop hiển thị tổng số tiến trình và số tiến trình đang chạy
  • Linux kernel nội bộ gọi tiến trình là task, và htop dùng Tasks thay cho Processes để tiết kiệm không gian màn hình
  • Có thể bật/tắt hiển thị thread bằng Shift+H
    • Nếu thấy như Tasks: 23, 10 thr thì đang hiển thị thread
  • Có thể bật/tắt hiển thị kernel thread bằng Shift+K
    • Nếu thấy như Tasks: 23, 40 kthr thì đang hiển thị kernel thread
  • Mỗi khi một tiến trình mới khởi động, một PID sẽ được cấp phát
    • Nếu chạy nền như sleep 1000 & thì số job và PID sẽ được hiển thị
    • $! trong bash sẽ được mở rộng thành ID của tiến trình nền gần nhất
  • Thông tin liên quan tới tiến trình nằm dưới /proc/<pid>/
    • /proc/<pid>/cmdline chứa lệnh được chạy và các đối số được phân tách bằng byte \0
    • Có thể xem dễ đọc hơn bằng tr '\0' '\n' < /proc/<pid>/cmdline hoặc strings /proc/<pid>/cmdline
    • /proc/<pid>/cwd là liên kết tới thư mục làm việc hiện tại, còn /proc/<pid>/exe là liên kết tới tệp nhị phân đã chạy
  • Các công cụ chẩn đoán như htop, top, ps đọc chi tiết tiến trình từ /proc/<pid>/<file>
  • Bên tạo tiến trình mới gọi là parent process, bên được tạo mới gọi là child process; quan hệ này tạo thành cây tiến trình
  • Trong htop, nhấn F5 để xem phân cấp tiến trình
    • ps fpstree -a cũng hiển thị cùng quan hệ đó
  • Khi chạy date trong bash, bash tạo một bản sao của chính nó bằng fork, nạp /bin/date vào bộ nhớ bằng exec, rồi bash parent chờ child kết thúc
  • /sbin/init được khởi chạy khi boot và khởi tạo sshd; khi kết nối SSH, sshd tạo tiến trình phiên làm việc, và tiến trình phiên đó chạy shell bash

Người dùng tiến trình và quyền hạn

  • Mỗi tiến trình thuộc sở hữu của một người dùng, và người dùng được biểu diễn bằng ID dạng số
  • Có thể kiểm tra ID người dùng của tiến trình qua mục Uid trong /proc/<pid>/status
  • Lệnh như id 1000 sẽ hiển thị tên người dùng và nhóm tương ứng với ID dạng số đó
  • id chọn nguồn phân giải tên theo cấu hình trong /etc/nsswitch.conf
    • Trên hệ thống ví dụ, nó đọc /etc/passwd/etc/group
    • compat là chế độ tương thích, giống files nhưng cho phép các mục đặc biệt
    • Thông tin người dùng cũng có thể được lưu trong các cơ sở dữ liệu hoặc dịch vụ khác như LDAP
  • /etc/passwd/etc/group là các tệp văn bản thuần ánh xạ ID số sang tên mà con người có thể đọc được
  • Thông tin mật khẩu thực tế nằm trong /etc/shadow
    • $6$ nghĩa là thuật toán băm sha512
    • Sau đó là salt ngẫu nhiên để ngăn tấn công rainbow table và giá trị băm của password+salt
  • Theo mặc định, chương trình chạy với quyền của người dùng đã thực thi nó
    • Điều này vẫn đúng ngay cả khi chủ sở hữu của tệp thực thi là người dùng khác
  • Muốn chạy bằng người dùng khác hoặc root thì dùng sudo
    • sudo id sẽ chạy với UID 0 của root
    • Có thể chạy bằng người dùng cụ thể như sudo -u daemon id
  • Nếu cố ghi trực tiếp vào /etc/sudoers bằng redirect thì chỉ echo chạy với quyền root còn thao tác append vẫn do người dùng hiện tại thực hiện nên có thể thất bại
    • echo "$USER ALL=(ALL) NOPASSWD: ALL" | sudo tee -a /etc/sudoers
    • sudo bash -c "echo '$USER ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers"
  • Nên chỉnh sửa /etc/sudoers bằng sudo visudo
    • Nó kiểm tra nội dung trước khi lưu để tránh lỗi khiến sudo không dùng được nữa
  • /usr/bin/passwd vẫn có thể ghi vào /etc/shadow dù được người dùng thường chạy
    • Quyền tệp có s nên nó hoạt động như một tệp thực thi setuid
    • Nó chạy với quyền của chủ sở hữu tệp thực thi là root
    • Có thể tìm các tệp thực thi setuid thuộc sở hữu root bằng find /bin -user root -perm -u+s

Mã trạng thái tiến trình

  • Cột trạng thái của htop được hiển thị với tên S, các giá trị chính như sau
    • R: running hoặc runnable, đang chạy hoặc đang chờ trong run queue
    • S: interruptible sleep, đang chờ một sự kiện hoàn tất
    • D: uninterruptible sleep, thường là đang chờ I/O
    • Z: defunct zombie, đã kết thúc nhưng parent chưa reap
    • T: bị dừng bởi job control signal
    • t: bị debugger dừng trong lúc tracing
    • X: dead, trạng thái lẽ ra không nên xuất hiện
  • ps cũng hiển thị các substate như Ss, R+, Ss+
  • R: Đang chạy hoặc có thể chạy

    • Trạng thái R là khi tiến trình đang thực sự chạy hoặc đang chờ trong hàng đợi thực thi
    • Mã nguồn chương trình sau khi biên dịch trở thành lệnh CPU, và khi chạy sẽ được nạp vào bộ nhớ để CPU thực thi các lệnh đó
    • Đang chạy nghĩa là CPU đang thực sự thực thi các lệnh đó
  • S: Sleep có thể bị ngắt

    • Ở trạng thái S, các lệnh của tiến trình không chạy trên CPU mà đang chờ một sự kiện hoặc điều kiện
    • Khi sự kiện xảy ra, kernel sẽ đổi trạng thái sang running
    • sleep 1000 là ví dụ về việc chờ trong một khoảng thời gian chỉ định
    • Trạng thái này có thể bị ngắt bằng signal
    • Trong htop, có thể nhấn F9 để gửi signal
    • kill là system call dùng để gửi signal, còn /bin/kill là chương trình ở userland gọi system call đó
    • Signal mặc định là TERM và dùng để yêu cầu tiến trình kết thúc
    • Signal là các giá trị số; tên thường được viết hoa và có thể có tiền tố SIG
    • Ví dụ: INT, KILL, STOP, CONT, HUP
    • kill -INT 10089, kill -2 10089, /bin/kill -2 10089 đều cho cùng một hành vi
    • Khi nhấn CTRL+C, bash sẽ gửi SIGINT tới foreground process
    • Gửi SIGINT hoặc SIGTERM không có nghĩa là tiến trình chắc chắn sẽ kết thúc
    • Chương trình có thể thiết lập signal handler để xử lý, chẳng hạn dọn dẹp rồi mới thoát
    • SIGKILL hoặc 9 sẽ khiến kernel buộc tiến trình kết thúc mà không cho nó cơ hội phản hồi
  • D: Sleep không thể bị ngắt

    • Trạng thái D không thể được đánh thức bằng signal, và vì SIGKILL cũng là một signal nên cũng không thể kill các tiến trình này
    • Trạng thái này được dùng khi tiến trình phải chờ mà không được gián đoạn hoặc khi dự kiến sự kiện sẽ xảy ra nhanh
    • Ví dụ: đọc/ghi đĩa
    • Một uninterruptible process thường có thể đang chờ I/O sau page fault
    • Trạng thái này có thể xuất hiện khi đọc hoặc ghi NFS bị chậm
    • Nó cũng có thể xuất hiện khi bộ nhớ khả dụng quá ít khiến tiến trình phải swap nhiều
    • Ví dụ, chạy sudo mount 8.8.8.8:/tmp /tmp & thì /sbin/mount.nfs sẽ vào trạng thái D
    • Nếu xem bằng strace, sẽ thấy system call mount đang block tiến trình
    • Có thể dùng tùy chọn intr cho mount để chạy theo cách có thể bị ngắt
    • sudo mount 8.8.8.8:/tmp /tmp -o intr
  • Z: Tiến trình zombie

    • Trạng thái Z là khi tiến trình đã kết thúc nhưng parent vẫn chưa reap nó
    • Tiến trình zombie tồn tại trong thời gian ngắn có thể là bình thường
    • Zombie tồn tại lâu có thể cho thấy lỗi trong chương trình
    • Tiến trình zombie không tiêu thụ bộ nhớ mà chỉ chiếm PID
    • Bản thân tiến trình zombie không thể bị kill
    • Có thể gửi SIGCHLD tới parent process để yêu cầu nó reap zombie
    • Nếu kill parent process thì có thể loại bỏ cả parent lẫn zombie của nó
    • Có thể tái hiện trạng thái zombie bằng một chương trình C trong đó child exit(0) sau fork, còn parent thì sleep(20)
    • Khi parent kết thúc, zombie sẽ biến mất
    • Zombie được giữ lại vì parent cần có thể kiểm tra exit code của child bằng system call wait
  • T và t: Tiến trình bị dừng

    • Trạng thái T là trạng thái bị dừng bởi job control signal
    • Khi đang chạy cat /dev/urandom > /dev/null, nếu nhấn CTRL+Z thì nó sẽ vào trạng thái T
    • Có thể dùng fg để chạy lại
    • Cũng có thể dừng bằng signal STOP và tiếp tục bằng signal CONT
    • Trạng thái t là trạng thái bị debugger dừng trong lúc tracing
    • Nếu attach sudo gdb -p <pid> vào tiến trình chạy bằng nc -l 1234 & thì nó sẽ vào trạng thái t

Thời gian CPU, niceness, priority

  • Linux là hệ điều hành đa nhiệm nên ngay cả trên một CPU đơn, nhiều tiến trình vẫn có vẻ như đang chạy đồng thời
  • Trên thực tế, một CPU đơn chỉ có thể thực thi một lệnh tại một thời điểm, vì vậy hệ thống dùng time sharing
    • Một tiến trình chạy trong chốc lát rồi bị tạm dừng
    • Các tiến trình khác đang chờ chạy sẽ lần lượt được thực thi
    • Khoảng thời gian ngắn mà một tiến trình được chạy được gọi là time slice
  • Time slice thường chỉ vài mili giây nên nếu load của hệ thống không cao thì khó cảm nhận được
  • Trên hệ thống đơn lõi, nếu load average là 1.0 thì có thể xem như CPU đã được sử dụng 100%
    • Nếu cao hơn 1.0 thì số tiến trình muốn chạy nhiều hơn khả năng xử lý của CPU, có thể gây slowdown hoặc delay
    • Nếu thấp hơn 1.0 thì CPU đôi lúc ở trạng thái idle
  • Việc running time của tiến trình có thể không khớp chính xác với thời gian thực tế đã trôi qua cũng được giải thích bằng cơ chế time sharing
  • Khi số task cần chạy nhiều hơn số lõi CPU có sẵn, hệ thống phải quyết định task nào sẽ được chạy trước
  • Scheduler của nhân Linux chọn tiến trình tiếp theo từ run queue, và việc này phụ thuộc vào thuật toán scheduler của kernel
  • Thông thường không thể điều khiển trực tiếp scheduler, nhưng có thể cho hệ thống biết tiến trình nào quan trọng hơn
  • Niceness hiển thị bằng NI là mức ưu tiên ở user-space
    • Phạm vi từ -20 đến 19
    • -20 là ưu tiên cao nhất và 19 là ưu tiên thấp nhất
    • Có thể hiểu rằng tiến trình càng nice thì càng nhường nhiều hơn cho tiến trình kém nice hơn
  • PRI là mức ưu tiên ở kernel-space mà nhân Linux sử dụng
    • Phạm vi từ 0 đến 139
    • 0~99 là real time, 100~139 là dải dành cho user
  • Mối quan hệ giữa giá trị nice và priority được mô tả bằng PR = 20 + NI
    • NI từ -20~+19 trở thành PR từ 0~39, rồi được ánh xạ vào 100~139
  • Trước khi chạy, có thể đặt niceness bằng nice -n niceness program
  • Có thể đổi niceness của tiến trình đang chạy bằng renice -n niceness -p PID
  • Màu của mức sử dụng CPU như sau
    • Blue: thread ưu tiên thấp, nice > 0
    • Green: thread ưu tiên thông thường
    • Red: kernel thread

Chỉ số bộ nhớ: VIRT, RES, SHR, MEM%

  • Tiến trình trông như thể nó tồn tại riêng trong bộ nhớ, và điều này được hiện thực bằng bộ nhớ ảo
  • Tiến trình không truy cập trực tiếp bộ nhớ vật lý mà có virtual address space riêng
  • Kernel có thể chuyển đổi địa chỉ virtual memory sang bộ nhớ vật lý hoặc ánh xạ một phần ra disk
  • Vì vậy, tiến trình có thể trông như đang dùng nhiều bộ nhớ hơn cả dung lượng bộ nhớ cài trên máy
  • Mức sử dụng bộ nhớ của tiến trình sẽ khác nhau tùy theo việc có tính các mục sau hay không
    • shared library
    • bộ nhớ được ánh xạ với disk
    • bộ nhớ đã bị swap out
  • Màu của mức sử dụng bộ nhớ như sau
    • Green: bộ nhớ đang dùng
    • Blue: buffers
    • Orange: cache
  • VIRT/VSZ

    • VIRT là tổng lượng virtual memory mà task đang dùng
    • Bao gồm code, data, shared library, page đã swap out, và page đã được ánh xạ nhưng chưa dùng
    • Ngay cả khi ứng dụng yêu cầu 1GB nhưng chỉ dùng 1MB thì VIRT vẫn có thể hiện là 1GB
    • Ngay cả khi mmap một file 1GB nhưng không thực sự dùng, VIRT vẫn có thể hiển thị là 1GB
    • Trong đa số trường hợp, VIRT không phải là con số hữu ích
  • RES/RSS

    • RES là lượng bộ nhớ vật lý chưa bị swap out, tức lượng resident memory hiện đang nằm trong bộ nhớ vật lý
    • RES có thể phản ánh mức dùng bộ nhớ thực tế tốt hơn VIRT, nhưng vẫn có giới hạn
    • Không bao gồm bộ nhớ đã bị swap out
    • Một phần bộ nhớ có thể được chia sẻ với các tiến trình khác
    • Nếu một tiến trình dùng 1GB bộ nhớ rồi fork(), RES của mỗi tiến trình có thể đều hiện là 1GB, nhưng do cơ chế copy-on-write của Linux nên trên thực tế có thể chỉ dùng 1GB
  • SHR

    • SHR là lượng shared memory mà task đang dùng
    • Phản ánh phần bộ nhớ có thể được chia sẻ với các tiến trình khác
    • Chương trình C minh họa cho thấy VIRT, RES, SHR thay đổi ra sao khi đi qua các bước malloc, sử dụng một phần bộ nhớ, fork, rồi ghi thêm vào bộ nhớ
    • Phần ví dụ bộ nhớ đó hiện vẫn được để TODO
  • MEM%

    • MEM% là tỷ lệ bộ nhớ vật lý khả dụng mà task hiện đang sử dụng
    • Đây là giá trị RES chia cho tổng RAM
    • Ví dụ: nếu RES400M và RAM là 8GB thì 400/8192*100 = 4.88%

Các tiến trình mặc định của Ubuntu Server 16.04

  • Khảo sát các tiến trình được khởi động trên Ubuntu Server 16.04.1 LTS x64 của một droplet Digital Ocean mới tạo

  • /sbin/init

    • /sbin/init điều phối phần còn lại của boot process và thiết lập môi trường người dùng
    • Trở thành parent hoặc grandparent của các tiến trình tự khởi động
    • Kết quả dpkg -S /sbin/initsystemd-sysv: /sbin/init, nên trên hệ thống này đó là systemd
    • Kể cả kill thì cũng không có gì xảy ra
  • /lib/systemd/systemd-journald

    • systemd-journald là một system service thu thập và lưu trữ logging data
    • Tạo và duy trì journal có cấu trúc, được lập chỉ mục dựa trên thông tin log nhận từ nhiều source
    • Dùng định dạng tệp đặc biệt tối ưu cho log message thay vì các file log văn bản thuần túy đơn giản
    • Tra cứu bằng journalctl
    • journalctl _COMM=sshd
    • journalctl _COMM=sshd -o json-pretty
    • journalctl --since yesterday
    • journalctl -b
    • journalctl -f
    • journalctl --disk-usage
    • journalctl --vacuum-size=1G
    • Có vẻ không thể gỡ bỏ hoặc vô hiệu hóa, chỉ có thể tắt logging
  • /sbin/lvmetad -f

    • lvmetad cache LVM metadata để các lệnh LVM có thể đọc metadata mà không cần disk scan
    • Disk scan tốn thời gian và có thể cản trở hoạt động bình thường của hệ thống và disk
    • LVM có thể xem như các “dynamic partitions” cho phép Linux tạo, resize và xóa logical volume khi đang chạy
    • Nếu đang dùng LVM thì nên giữ lại
  • /lib/systemd/udevd

    • systemd-udevd lắng nghe kernel uevent và với mỗi event sẽ thực thi chỉ thị khớp trong udev rules
    • udev là device manager của Linux kernel và chủ yếu quản lý các device node trong thư mục /dev
    • Chưa chắc nó có cần thiết trên virtual server hay không
  • /lib/systemd/timesyncd

    • systemd-timesyncd là một system service đồng bộ local system clock với remote NTP server
    • Thay thế ntpd
    • Trên hệ thống ví dụ, timedatectl status hiển thị network time và NTP synchronized là yes
    • Trong đầu ra netstat chỉ thấy SSH port ở trạng thái listening, không mở nhiều UDP 123 port như ntpd trên Ubuntu 14.04
  • /usr/sbin/atd -f

    • atd thực thi các job đã được đưa vào queue để chạy sau này
    • atbatch đọc lệnh từ stdin hoặc từ file để chạy sau
    • Khác với cron dùng để lên lịch chạy lặp lại, at chạy một lần vào thời điểm cụ thể
    • Trong ví dụ, echo "touch /tmp/yolo.txt" | at now + 1 minute tạo file sau 1 phút
    • Nếu không dùng thì gỡ bằng sudo apt remove at -y --purge
  • /usr/lib/snapd/snapd

    • Snappy Ubuntu Core được giới thiệu là một rendition của Ubuntu dùng transactional update
    • snap được mô tả là universal Linux package format cho phép một binary package chạy trên Linux desktop, server, cloud và device
    • Có thể hiểu như một deb package được đơn giản hóa, gói dependency vào một single snap để phân phối
    • Vì chưa từng deploy hay distribute ứng dụng bằng snappy trên server nên đã gỡ bằng sudo apt remove snapd -y --purge
  • /usr/bin/dbus-daemon

    • D-Bus là cơ chế IPC và RPC giữa nhiều process cùng chạy đồng thời trên một machine
    • Nó cần cho desktop environment, nhưng có nghi vấn liệu có cần trên server chạy web app hay không
    • Khi gỡ dbus, timedatectl status thất bại với Failed to create bus connection: No such file or directory
    • Vì vậy tốt hơn là nên giữ lại
  • /lib/systemd/systemd-logind

    • systemd-logind là system service quản lý user login
  • /usr/sbin/cron -f

    • cron là daemon thực thi các lệnh theo lịch
    • -f nghĩa là foreground mode, không daemonize
    • Các tác vụ cần chạy định kỳ có thể lên lịch bằng cron
    • crontab -e
    • Trên Ubuntu thường dùng /etc/cron.hourly, /etc/cron.daily v.v.
    • Có thể xem log theo cách sau
    • grep cron /var/log/syslog
    • journalctl _COMM=cron
    • journalctl _COMM=cron --since="date" --until="date"
    • Khả năng cao là sẽ giữ cron
    • Nếu không gỡ thì có thể dừng và vô hiệu hóa bằng sudo systemctl stop cron, sudo systemctl disable cron
    • apt remove cron có thể sẽ cố cài postfix v.v.
    • Vì cron suggest mail transport agent
  • /usr/sbin/rsyslogd -n

    • rsyslogd là system utility hỗ trợ message logging
    • Nó có vai trò điền dữ liệu vào các file log trong /var/log/ như /var/log/auth.log
    • File cấu hình nằm trong /etc/rsyslog.d
    • Có thể gửi log tới remote server để xây dựng centralized logging
    • Có thể dùng lệnh logger để ghi message vào /var/log/syslog từ background script
    • Dù đã có systemd-journald, rsyslog và journal có những đặc tính khác nhau nên có những trường hợp dùng cùng nhau sẽ hữu ích
    • Vì vậy tạm thời giữ lại
  • /usr/sbin/acpid

    • acpid là ACPI event daemon
    • Được thiết kế để thông báo ACPI event cho user-space program
    • ACPI được dùng cho hardware component discovery/configuration, power management, status monitoring v.v.
    • Vì không định suspend/resume trên virtual server nên đã thử gỡ
    • reboot thành công nhưng sau halt, Digital Ocean vẫn nhận là máy còn bật nên phải Power Off từ web interface
    • Do đó kết luận là nên giữ lại
  • /usr/bin/lxcfs /var/lib/lxcfs/

    • lxcfs là FUSE filesystem được thiết kế cho LXC container
    • Cung cấp virtualized view cho một số file trong /proc và filtered access tới host cgroup filesystem
    • Giúp uptime, top v.v. trong container cho kết quả “đúng” hơn
    • Nếu không dùng LXC container thì có thể gỡ bằng sudo apt remove lxcfs -y --purge
  • /usr/lib/accountservice/accounts-daemon

    • AccountsService cung cấp D-Bus interface và phần triển khai để query và thao tác thông tin user account
    • Phần triển khai dựa trên các lệnh usermod(8), useradd(8), userdel(8)
  • Sau khi gỡ bỏ thì những gì sẽ bị hỏng vẫn được để ngỏ là “Time will tell”

  • /sbin/mdadm

    • mdadm là tiện ích Linux dùng để quản lý và giám sát software RAID device
    • RAID là cách sử dụng nhiều hard drive như thể chúng là một
    • RAID 0 mở rộng dung lượng drive
    • RAID 1, RAID 5, RAID 6, RAID 10 nhằm ngăn mất dữ liệu khi drive bị lỗi
    • Có thể gỡ bằng sudo apt remove mdadm -y --purge
  • /usr/lib/policykit-1/polkitd --no-debug

    • polkitd là daemon của PolicyKit, còn polkit là Authorization Framework
    • Có thể hiểu như một sudo chi tiết theo quyền
    • Có thể cấp cho user không đặc quyền quyền thực hiện một số action nhất định với quyền root
    • Ví dụ: cho phép reboot trên desktop Linux
    • Tác giả tổng kết rằng trên server có thể gỡ bằng sudo apt remove policykit-1 -y --purge
    • Những gì sẽ bị hỏng vẫn còn là một câu hỏi bỏ ngỏ
  • /usr/sbin/sshd -D

    • sshd là OpenSSH Daemon
    • Tùy chọn -D khiến nó không detach và không chạy thành daemon, giúp việc monitoring dễ hơn
  • /sbin/iscsid

    • iscsid là background daemon hoạt động theo cấu hình iSCSI và quản lý các connection
    • iSCSI là tiêu chuẩn storage networking dựa trên IP, truyền SCSI command qua IP network để có thể dùng remote storage như local disk
    • Có thể gỡ bằng sudo apt remove open-iscsi -y --purge
  • /sbin/agetty --noclear tty1 linux

    • agetty là một getty thay thế trên Linux
    • getty quản lý terminal vật lý hoặc ảo, và khi phát hiện kết nối thì hiển thị username prompt rồi chạy chương trình login
    • Trên Digital Ocean, có thể tương tác với terminal này trong trình duyệt thông qua Console ở phần chi tiết droplet
    • Sau khi gỡ các file liên quan đến getty@tty1.service và reboot, vẫn có thể SSH vào nhưng không thể đăng nhập bằng web console của Digital Ocean
  • Phiên SSH, bash, htop

    • sshd: root@pts/0 nghĩa là phiên SSH của user root được thiết lập trên pseudoterminal pts/0
    • pseudoterminal mô phỏng một text terminal thực
    • bash là shell đang được sử dụng
    • Nếu có dấu gạch ở đầu như -bash thì nó được khởi động như một login shell
    • Shell có ký tự đầu tiên của argument zero là - hoặc được khởi động với tùy chọn --login là login shell
    • Trong trường hợp này, nó sẽ đọc một bộ configuration file khác
    • htop là trình xem process tương tác đang chạy trong ảnh chụp màn hình

Thử nghiệm gỡ bỏ dịch vụ

  • Danh sách gỡ bỏ thông thường như sau
    • sudo apt remove lvm2 -y --purge
    • sudo apt remove at -y --purge
    • sudo apt remove snapd -y --purge
    • sudo apt remove lxcfs -y --purge
    • sudo apt remove mdadm -y --purge
    • sudo apt remove open-iscsi -y --purge
    • sudo apt remove accountsservice -y --purge
    • sudo apt remove policykit-1 -y --purge
  • Bản Extreme bao gồm các thao tác sau
    • sudo apt remove dbus -y --purge
    • sudo apt remove rsyslog -y --purge
    • sudo apt remove acpid -y --purge
    • sudo systemctl stop cron && sudo systemctl disable cron
    • sudo rm /etc/systemd/system/getty.target.wants/getty@tty1.service
    • sudo rm /lib/systemd/system/getty@.service
  • Cấu hình nginx, PHP7, MySQL theo hướng dẫn unattended installation of WordPress on Ubuntu Server vẫn hoạt động

Phụ lục: Công cụ khảo sát và hoạt động của shell

  • Tìm mã nguồn

    • Khi chỉ strace là chưa đủ thì có thể xem mã nguồn
    • Dùng which uptime để tìm vị trí binary, rồi dùng dpkg -S /usr/bin/uptime để tìm package Ubuntu
    • Trong ví dụ, uptime thuộc package procps
    • Có thể tìm package trên packages.ubuntu.com và tìm link tới source repository
  • File descriptor và redirection

    • Khi redirect stderr sang stdout thì dùng 2>&1
    • echo something > file là ghi stdout vào file, tương đương echo something 1> file
    • echo something 2> file là ghi stderr vào file
    • echo something 2>1 có nghĩa là redirect stderr vào filename 1
    • Trong 2>&1 có dấu &, số 1 không phải filename mà là stream ID
  • Vấn đề màu sắc của PuTTY

    • Nếu các thành phần của htop hiển thị như bị thiếu trong PuTTY thì có thể xử lý trong phần thiết lập Window → Colours
    • Nhấp chuột phải vào thanh tiêu đề
    • Change settings...
    • Window → Colours
    • Chọn nút radio Both
    • Apply
  • Shell đơn giản viết bằng C

    • Một shell đơn giản viết bằng C cho thấy cách dùng các system call fork, exec, wait
    • Nếu input là exit thì thoát bằng shell built-in
    • Các lệnh khác sẽ fork, sau đó child thực thi bằng execlp, còn parent chờ trạng thái kết thúc bằng waitpid
    • Ví dụ chạy date, true, false sẽ lần lượt in ra exit code của child
    • Lý do thông báo kết thúc của background process như sleep 1 & chỉ hiện ra sau khi nhấn Enter là vì shell đang chờ input, rồi chỉ kiểm tra trạng thái background process khi có lệnh được nhập

Các mục cần khảo sát thêm và lịch sử chỉnh sửa

  • Các mục muốn tìm hiểu thêm gồm process state substatus, kernel thread, /dev/pts, bộ nhớ CODE·DATA·SWAP, độ dài time slice, thuật toán scheduler của Linux, core pinning, manual page, màu của thanh CPU/memory, process ID limit và fork bomb, lsof, ionice, schedtool v.v.
  • Các chỉnh sửa/cập nhật chính gồm những mục sau
    • idle time của /proc/uptime là tổng cộng của tất cả các core
    • Đã sửa printf của parent/child trong ví dụ zombie C
    • Đã bổ sung việc apt remove cron sẽ cố cài postfix do dependency của MTA
    • id có thể tải thông tin không chỉ từ /etc/passwd mà còn từ nguồn khác thông qua /etc/nsswitch.conf
    • Đã bổ sung giải thích về password hash format của /etc/shadow
    • /etc/sudoers cần được chỉnh sửa an toàn bằng visudo
    • Đã bổ sung giải thích về MEM%
    • Phần load average đã được viết lại
    • Đã sửa signal mặc định của kill 1234 từ INT thành TERM
    • Đã bổ sung giải thích về thanh màu CPU và memory

1 bình luận

 
Ý kiến trên Hacker News
  • Gần đây tôi đã chuyển sang btop, vì nó có giao diện hiện đại và hữu ích vừa đủ, đồng thời lượng thông tin cũng khá đầy đủ
    Có vẻ như nó cũng hiển thị mức tiêu thụ điện năng (Watts) như những người khác đã nói, và còn kèm cả thông tin mạng, GPU, ổ đĩa
    https://github.com/aristocratos/btop

    • btop tốt đấy, nhưng cũng có nhược điểm: không có thống kê zram/zswap (htop cũng chỉ hỗ trợ zram), không có phân tách chi tiết thống kê ZFS, và hiện vẫn chưa hỗ trợ Arc GPU
      Không thể tắt thanh mức sử dụng đĩa, nên nếu cửa sổ console không đủ lớn thì biểu đồ tốc độ I/O trông sẽ bị ép rất nhiều
    • Tôi đã dùng btop khá lâu, và thứ còn thiếu chỉ cỡ một cột cổng bên cạnh các cột khác
      Biểu đồ CPU/GPU đang chiếm quá nhiều diện tích, và nhìn chung tôi muốn bảng file đang mở chiếm nhiều không gian hơn
    • Tôi vẫn thỉnh thoảng dùng Alpine làm image nền cho container, nhưng btop có vẻ không hỗ trợ musl nên bị loại
    • Tôi là tín đồ của btop đến mức trên chiếc MacBook mới, nó còn thay thế cả iStatMenu
  • Có 2 thiết lập mà tôi luôn đổi mỗi khi dùng htop, và khác biệt là rất lớn
    Thứ nhất, tôi tắt luồng người dùng. Phần lớn chúng chỉ làm màn hình htop rối thêm mà hầu như không cho thông tin hữu ích
    Thứ hai, tôi bật chế độ xem cây tiến trình. Nhiều khi biết tiến trình bắt đầu từ đâu còn quan trọng hơn các thông tin khác, và cũng dễ lần theo những tiến trình như compiler xử lý nhiều file rồi ngốn CPU
    Cá nhân tôi thấy cả hai nên là hành vi mặc định của htop

    • Chế độ xem cây tiến trình rất hay, nhưng tiếc là khi bật lên thì cập nhật động và sắp xếp lại danh sách tiến trình sẽ dừng
  • Tôi rất vui khi thấy phần giải thích rằng bộ nhớ ảo khó mà tin cậy được. Cách Windows Task Manager hiển thị mặc định theo hướng đó thì thật sự tệ
    Kích thước tập thường trú (RSS) là chỉ số đáng tin nhất, còn các giá trị khác có thể bị phình sai vì những thứ như file ánh xạ bộ nhớ mà thực ra không gây vấn đề gì
    Ví dụ, dù bạn ánh xạ một file log 2GB vào bộ nhớ, phần đó chỉ được nạp thành trang khi đọc tới, nên thực tế không phải là đang dùng lượng RAM ấy, nhưng người dùng nhìn tiến trình rồi sẽ hỏi “sao ứng dụng này dùng nhiều bộ nhớ thế”
    Chrome cũng từng gặp vấn đề này một thời gian và đã giảm việc dùng file ánh xạ bộ nhớ, không phải vì file ánh xạ bộ nhớ là xấu mà vì người dùng phản ứng quá mức khi nhìn vào những con số không phản ánh mức dùng bộ nhớ vật lý thực tế
    Trên web cũng có cả hướng dẫn bảo nên đánh giá mức dùng theo lượng cấp phát bộ nhớ ảo, nhưng ít nhất bài này đã chỉ ra đúng điểm đó

    • Trên thực tế, kích thước tập tỷ lệ (PSS) còn chính xác hơn RSS
      Tham khảo: https://en.wikipedia.org/wiki/Proportional_set_size
    • Nếu dùng file ánh xạ bộ nhớ, các trang đã được cache sẽ được tính vào kích thước tập thường trú của tiến trình
      Nếu dùng I/O file thông thường thì sẽ không bị tính. Trên các cụm HPC nơi người ta giám sát mức dùng bộ nhớ của từng job rồi kill nếu vượt yêu cầu, điều này tạo ra những kết quả khá thú vị
    • Kích thước tập thường trú không phải là lượng bộ nhớ mà tiến trình muốn, mà là lượng mà hệ điều hành quyết định cấp cho tiến trình đó
      Khi bắt đầu có áp lực bộ nhớ, nó không còn mang tính đại diện nữa. Tôi đã thấy vài quyết định sai vì hiểu nhầm này, và từng phải loại hẳn giá trị đó khỏi biểu đồ để ngăn đồng đội kết luận ngược
    • Nói chính xác thì Windows Task Manager dùng Private Working Set làm mặc định cho mức dùng bộ nhớ của tiến trình, và không tính các trang được chia sẻ với tiến trình khác như thư viện hay file ánh xạ bộ nhớ
      Đúng như tên gọi, nó chỉ hiển thị phần được ánh xạ vào bộ nhớ vật lý được cấp riêng cho từng tiến trình, nên gần với Resident Set trên Unix hơn
      Có lẽ ý ở đây là mức dùng bộ nhớ trong tab hiệu năng, nhưng tôi phân biệt ra để tránh bị hiểu nhầm là nói về mọi mục mức dùng bộ nhớ
  • Trong top, dùng ký tự > sẽ sắp xếp theo mức dùng bộ nhớ
    Tôi thỉnh thoảng dùng khi tìm nguyên nhân máy chủ bị chậm, và cũng có thể thấy swapd đang ngốn CPU

    • Tôi thích dùng chữ hoa M cho bộ nhớ và chữ hoa P cho CPU hơn
  • Mỗi lần đọc những bài như thế này, tôi lại nhận ra rằng dù đã dùng Linux hằng ngày hơn 20 năm, mình vẫn chỉ mới khai thác một phần tiềm năng của nó. Bài viết rất hay

  • Có cảm giác HN đang hồi phục trở lại
    Mong là đây không phải thời kỳ bóng ma lững thững của HN

    • Có 3 bài liên quan đến AI trên trang đầu, nhưng một bài là để chê thứ nội dung tạo sinh chất lượng thấp, nên tôi vẫn còn hy vọng
    • Chắc là đang phục hồi bằng cách quay lại những bài viết từ trước thời slop của 7 năm trước
  • Nếu ai chưa biết nmon thì cũng đáng thử xem
    Nhấn h sẽ hiện danh sách các màn hình giám sát có thể dùng, nhấn lại sẽ ẩn đi, và q để thoát
    https://nmon.sourceforge.io/pmwiki.php
    Đặc biệt, thông lượng đĩa và I/O xem bằng phím dD khá hữu ích

    • Tôi biết đến nó trên các máy AIX dùng ở công ty, và cũng nhớ tới topas
    • Đây là công cụ rất hữu ích nên tôi cài nó trên mọi máy mà mình có thể kiểm soát
      Biểu đồ mức dùng CPU dạng rộng rất tốt cho việc hiển thị số lượng lõi lớn một cách dễ hiểu
  • Với cách dùng khác với dòng *top, tôi ngày càng thích kiểu báo cáo chênh lệch điềm tĩnh theo phong cách ps và kiểu báo cáo toàn hệ thống như vmstat hơn
    Làm vậy thì mọi thứ đều được giữ lại trong buffer cuộn của terminal: https://github.com/c-blake/procs
    Nó được viết bằng Nim, một ngôn ngữ hiếm khi không vừa hiệu quả vừa giàu khả năng biểu đạt

  • Tôi đã bookmark bài này từ năm 2016 và trong nhiều năm qua đã quay lại tham khảo nó nhiều lần