How Linux Works Chương 7 · System Configuration

Chương 7 · Cấu hình hệ thống Chapter 7 · System Configuration

Thư mục /etc trông đáng sợ, nhưng chỉ một nhúm tệp là nền móng Máy có một ngăn tủ chứa toàn giấy tờ — nhưng chỉ vài tờ là quan trọng The /etc directory looks overwhelming, but only a few files are fundamental

Ward mở chương bằng đúng cảm giác của người mới: lần đầu nhìn vào /etc để tìm hiểu cấu hình máy mình, bạn có thể thấy hơi choáng. Tin tốt là tuy hầu hết các tệp ở đó đều ảnh hưởng ít nhiều đến hoạt động của hệ thống, chỉ một vài tệp là thật sự nền móng.1 Chương này nói về phần hệ thống làm cho hạ tầng đã dựng ở Chương 4 trở nên dùng được đối với phần mềm không gian người dùng mà ta vẫn tương tác hằng ngày.1

Trong máy Linux có một ngăn tủ tên là /etc. Mở ra thấy hàng trăm tờ giấy ghi chú, dễ hoa mắt. Nhưng thật ra chỉ vài tờ là quan trọng: ai được vào máy, máy ghi nhật ký ở đâu, mấy giờ rồi, và việc gì cần làm đúng giờ. Nhớ nhé: tủ thì đầy, nhưng tờ giấy quan trọng chỉ có mấy tờ.

Ward opens with exactly the newcomer's feeling: when you first look in /etc to explore your system's configuration, you might feel a bit overwhelmed. The good news is that although most of the files you see affect a system's operations to some extent, only a few are fundamental.1 This chapter covers the parts of the system that make the infrastructure discussed in Chapter 4 available to the user-space software we normally interact with.1

Ông liệt kê rõ sáu mảng sẽ đi qua: ghi nhật ký hệ thống; các tệp cấu hình mà thư viện hệ thống đọc để lấy thông tin máy chủ và người dùng; một vài chương trình máy chủ (đôi khi gọi là daemon) chạy khi hệ thống khởi động; các tiện ích cấu hình để tinh chỉnh chúng; cấu hình thời gian; và lập lịch tác vụ định kỳ.1 Ông cũng ghi chú một xu hướng đáng chú ý: việc systemd được dùng rộng rãi đã giảm số daemon cơ bản độc lập trên một hệ Linux điển hình — ví dụ chức năng của daemon ghi nhật ký syslogd nay phần lớn do journald tích hợp trong systemd đảm nhiệm; nhưng một vài daemon truyền thống vẫn còn, như crond và atd.1 Như các chương trước, chương này gần như không có nội dung mạng, vì mạng là một khối xây dựng riêng sẽ đến ở Chương 9.1

Luận đề của chương: cấu hình hệ thống không phải một mớ tệp rời rạc, mà là bốn cơ chế hạ tầng đặt cạnh nhau — nhật ký (nó kể cho bạn chuyện gì đã xảy ra), danh tính người dùng (nó nói bạn là ai), thời gian (nó nói chuyện đó xảy ra lúc nào), và lập lịch (nó làm việc thay bạn khi bạn không ngồi đó). Tất cả đều là quy ước của không gian người dùng; nhân chỉ biết những con số.1

Ý chính: máy cần bốn thứ để tự chăm sóc mình — sổ nhật ký, danh sách người dùng, một cái đồng hồ đúng giờ, và một cái báo thức để làm việc định kỳ. Nhớ nhé: sổ, danh sách, đồng hồ, báo thức.

The chapter's thesis: system configuration is not a pile of unrelated files but four pieces of infrastructure standing side by side — logging (what happened), user identity (who you are), time (when it happened), and scheduling (what runs while you are away). All of them are user-space conventions; the kernel only knows numbers.1

Cụm khái niệm 01 Concept cluster 01

Nhật ký hệ thống: nơi đầu tiên nên nhìn khi hỏng Cuốn sổ ghi lại mọi chuyện trong máy System logging: the first place to look when things break

Phần lớn chương trình hệ thống ghi đầu ra chẩn đoán của chúng dưới dạng thông điệp gửi tới dịch vụ syslog.1 Ward nói thẳng: bộ ghi nhật ký hệ thống là một trong những phần quan trọng nhất của hệ thống — khi có sự cố mà bạn không biết bắt đầu từ đâu, xem nhật ký luôn là lựa chọn khôn ngoan.1

Máy tính có một cuốn sổ. Mỗi khi có chuyện gì xảy ra — một chương trình khởi động, một cái gì đó hỏng — máy viết một dòng vào sổ. Khi máy trở chứng, việc đầu tiên là mở sổ ra đọc. Nhớ nhé: hỏng thì mở sổ trước, đoán mò sau.

Most system programs write their diagnostic output as messages to the syslog service.1 Ward puts it plainly: the system logger is one of the most important parts of the system — when something goes wrong and you don't know where to start, it's always wise to check the log.1

Vì sao chủ đề này rối. Ward thừa nhận hiểu chuyện ghi nhật ký trên Linux có thể khá khó, do sự pha trộn giữa các thành phần cũ và mới: một số bản phân phối như Fedora đã chuyển sang mặc định chỉ-journald, số khác chạy một phiên bản syslogd cũ hơn (ví dụ rsyslogd) song song với journald; các hệ cũ hoặc chuyên dụng có thể không dùng systemd chút nào và chỉ có một phiên bản syslogd; và một số hệ phần mềm bỏ qua hẳn chuẩn ghi nhật ký để tự viết lấy.1 Nghĩa là: đừng kỳ vọng máy của bạn giống hệt ví dụ trong sách — hãy kiểm tra máy mình trước.

Một dòng nhật ký trông thế nào. Ward đưa một mẫu duy nhất làm mỏ neo cho cả mục:
Aug 19 17:59:48 duplex sshd[484]: Server listening on 0.0.0.0 port 22.1 Một thông điệp nhật ký thường chứa thông tin quan trọng như tên tiến trình, ID tiến trình và dấu thời gian; ngoài ra còn có thể có hai trường nữa: facility (một hạng mục chung) và severity (mức khẩn cấp).1

Một dòng sổ có gì? Ngày giờ, tên máy, tên chương trình, số hiệu của nó, rồi mới đến câu chuyện. Đọc từ trái sang phải là ra ai nói và nói lúc nào. Nhớ nhé: lúc nào — ai nói — nói gì.

What a log line looks like. Ward anchors the whole section with one sample:
Aug 19 17:59:48 duplex sshd[484]: Server listening on 0.0.0.0 port 22.1 A log message typically contains important information such as the process name, process ID and timestamp; there can also be two other fields: the facility (a general category) and severity (how urgent the message is).1

journalctl -S -4h  → 4 giờ gần đây
journalctl -u cron → theo unit
journalctl -b -1  → lần khởi động trước
journalctl -p 3   → mức 0..3
journalctl -f    → theo dõi trực tiếp

-S -4h → 4 tiếng vừa rồi
-u     → theo chương trình
-b -1  → lần bật máy trước
-f     → xem sổ đang viết

journalctl -S -4h  → last 4 hours
journalctl -u cron → by unit
journalctl -b -1  → previous boot
journalctl -p 3   → levels 0..3
journalctl -f    → follow live

  1. checking your log setup

    Kiểm tra bộ ghi nhật ký của chính máy bạn Xem máy mình ghi sổ kiểu nào Check the logging setup on your own machine

    Ward đưa một quy trình ba bước rất cụ thể. Một: kiểm tra journald — gần như chắc chắn bạn có nếu đang chạy systemd; cách dễ nhất là chỉ cần chạy journalctl, nếu journald đang hoạt động bạn sẽ thấy một danh sách thông điệp được phân trang.1 Hai: kiểm tra rsyslogd trong danh sách tiến trình và tìm tệp /etc/rsyslog.conf.1 Ba: nếu không có rsyslogd, tìm syslog-ng qua thư mục /etc/syslog-ng.1

    Trước khi đọc sổ, phải biết máy mình dùng loại sổ nào. Gõ journalctl: nếu chữ chạy ra đầy màn hình thì máy bạn dùng loại sổ mới. Nếu không, đi tìm mấy tờ giấy cũ trong ngăn tủ. Nhớ nhé: biết sổ nằm ở đâu rồi mới đọc được sổ.

    Ward gives a very concrete three-step tour. One: check for journald — you almost certainly have it if you're running systemd, and the easiest way is simply to run journalctl; if journald is active you'll get a paged list of log messages.1 Two: look for rsyslogd in a process listing and for /etc/rsyslog.conf.1 Three: if you don't have rsyslogd, check for syslog-ng by looking for a directory called /etc/syslog-ng.1

    Bạn gặp nó ở đâuWhere you meet it Mỗi lần bạn nhận một máy chủ lạ và phải chẩn đoán nó, ba bước này là ba câu hỏi đầu tiên bạn nên tự trả lời. Khi ngồi vào một máy lạ, hỏi trước: sổ của máy này ở đâu? Every time you inherit an unfamiliar server and have to diagnose it, these three steps are the first three questions to answer.

    /var/log còn gì khác

    Ward chỉ tiếp: tiếp tục chuyến tham quan bằng cách nhìn vào /var/log. Nếu bạn có một phiên bản syslogd, thư mục này sẽ chứa nhiều tệp, phần lớn do daemon syslog tạo. Nhưng có vài tệp ở đây do dịch vụ khác duy trì; hai ví dụ là wtmp và lastlog — các tệp nhật ký mà tiện ích như last và lastlog truy cập để lấy bản ghi đăng nhập.1

    /var/log/journal

    Có thể còn các thư mục con trong /var/log chứa nhật ký; chúng gần như luôn đến từ các dịch vụ khác. Một trong số đó, /var/log/journal, là nơi journald lưu các tệp nhật ký nhị phân của nó.1 Đây chính là lý do grep và tail không dùng được với journal.

  2. journalctl filters

    Lọc journal: thời gian, unit, trường, văn bản, lần khởi động, mức độ Sáu cách tìm đúng dòng mình cần Filtering the journal: time, unit, field, text, boot, severity

    Không đối số, journalctl giống một vòi cứu hoả: nó phun ra toàn bộ thông điệp trong journal, bắt đầu từ cũ nhất.1 May thay nó mặc định dùng một bộ phân trang như less nên terminal của bạn không bị ngập.1 Bạn có thể tìm bằng bộ phân trang và đảo thứ tự thời gian bằng journalctl -r, nhưng Ward nói có những cách tốt hơn nhiều — và đó là các bộ lọc.1

    Nếu bạn mở cả cuốn sổ ra thì chữ nhiều đến hoa mắt. Nên phải biết cách lật đúng trang: theo giờ, theo tên chương trình, theo lần bật máy. Nhớ nhé: đừng đọc cả sổ — hãy hỏi sổ một câu hỏi.

    With no arguments, journalctl is like a fire hose, giving you all the messages in the journal, starting with the oldest.1 Mercifully it defaults to a pager such as less, so your terminal won't be flooded.1 You can search with the pager and reverse the time order with journalctl -r, but Ward says there are much better ways — the filters.1

    Bạn gặp nó ở đâuWhere you meet it “Máy chết lúc chiều” → journalctl -S -4h. “Dịch vụ X không lên” → journalctl -u X. “Lần trước tắt máy có sạch không” → journalctl -r -b -1.1 Ba câu hỏi hay dùng nhất: lúc nãy có gì, chương trình này có gì, lần trước tắt máy có êm không. "It died this afternoon" → journalctl -S -4h. "Service X won't start" → journalctl -u X. "Did it shut down cleanly?" → journalctl -r -b -1.1

    Theo thời gian (-S / -U)

    Tuỳ chọn -S (since) nằm trong số hữu ích nhất. journalctl -S -4h — phần -4h trông như một tuỳ chọn nhưng thật ra là một đặc tả thời gian, bảo journalctl tìm thông điệp của bốn giờ qua theo múi giờ hiện tại của bạn.1 Bạn cũng có thể dùng ngày và/hoặc giờ cụ thể: -S 06:00:00, -S 2020-01-14, -S '2020-01-14 14:30:00'.1 Tuỳ chọn -U (until) hoạt động tương tự nhưng thường không hữu ích bằng, vì bạn hay lật tới khi tìm thấy thứ mình cần rồi thoát.1

    Theo unit (-u) và theo trường (-F, -N)

    journalctl -u cron.service lọc theo unit của systemd; bạn thường có thể bỏ phần kiểu unit (.service).1 Không nhớ tên unit? journalctl -F _SYSTEMD_UNIT — tuỳ chọn -F hiển thị mọi giá trị trong journal cho một trường nhất định.1 Còn journalctl -N liệt kê tất cả các trường có sẵn.1 Bạn cũng có thể tìm theo từng trường ngay trên dòng lệnh, ví dụ journalctl _PID=8792.1

    Trường “được tin cậy”

    Một chi tiết an ninh quan trọng: bất kỳ trường nào bắt đầu bằng dấu gạch dưới (như _SYSTEMD_UNIT) là một trusted field — máy khách gửi thông điệp không thể thay đổi các trường này.12 Đó là khác biệt nền tảng so với syslog cổ điển, vốn không có xác thực đáng kể.1

    Theo văn bản (-g) và cảnh báo kèm theo

    Bạn có thể tìm thông điệp bằng biểu thức chính quy với -g, ví dụ journalctl -g 'kernel.*memory'.1 Nhưng Ward cảnh báo hai điều. Thứ nhất, bạn chỉ nhận các dòng khớp, trong khi thông tin quan trọng thường nằm lân cận về thời gian — mẹo của ông là nhặt dấu thời gian từ một dòng khớp rồi chạy journalctl -S với mốc ngay trước đó.1 Thứ hai, -g đòi hỏi bản dựng journalctl có một thư viện nhất định; một số bản phân phối không kèm phiên bản hỗ trợ nó.1

    Theo lần khởi động (-b) và theo nhân (-k)

    journalctl -b lấy thông điệp của lần khởi động hiện tại; thêm một độ lệch như -b -1 để về lần khởi động trước.1 Thay cho độ lệch, bạn có thể xem theo ID: journalctl --list-boots in ra danh sách các lần khởi động kèm ID và khoảng thời gian.1 Cuối cùng, journalctl -k hiển thị các thông điệp của nhân, có hoặc không kèm chọn một lần khởi động cụ thể.1

    Theo mức độ (-p) — và vì sao nó ít hữu dụng

    Bạn lọc theo mức nghiêm trọng bằng một giá trị từ 0 (quan trọng nhất) đến 7 (ít quan trọng nhất) cùng tuỳ chọn -p: journalctl -p 3 lấy mức 0 đến 3, còn cú pháp khoảng -p 2..3 lấy đúng một dải.1 Ward thành thật: lọc theo mức nghe như tiết kiệm nhiều thời gian, nhưng bạn có thể thấy nó không mấy hữu dụng — đa số ứng dụng không sinh nhiều dữ liệu thông tin theo mặc định.1

  3. log monitoring

    Theo dõi trực tiếp: tail -f cho tệp, journalctl -f cho journal Xem sổ trong lúc đang được viết Live monitoring: tail -f for files, journalctl -f for the journal

    Cách truyền thống để theo dõi nhật ký là dùng tail -f hoặc chế độ follow của less (less +F) trên một tệp nhật ký để thấy thông điệp khi chúng đến.1 Ward đánh giá thẳng: đây không phải cách giám sát hệ thống thường xuyên hiệu quả — quá dễ bỏ sót thứ gì đó — nhưng rất hữu ích khi bạn đang soi một dịch vụ để tìm lỗi, hoặc muốn nhìn kỹ quá trình khởi động và vận hành theo thời gian thực.1

    Bạn có thể đứng cạnh người thư ký và đọc từng dòng họ vừa viết. Cách này vui và hữu ích khi đang săn một lỗi, nhưng đừng coi nó là cách trông máy hằng ngày — mắt người sẽ bỏ sót. Nhớ nhé: đứng xem thì để bắt lỗi, không phải để canh máy.

    The traditional way to monitor logs is tail -f or the less follow mode (less +F) on a logfile, to see messages as they arrive.1 Ward's verdict is blunt: this isn't a very effective regular monitoring practice — it's too easy to miss something — but it's useful when you're examining a service to find a problem, or want a closer look at startup and operation in real time.1

    Bạn gặp nó ở đâuWhere you meet it Khi khởi động lại một dịch vụ ở cửa sổ này và xem nó kêu gì ở cửa sổ kia. Bật lại một chương trình rồi ngồi xem nó nói gì. When you restart a service in one window and watch what it says in another.

    Vì sao tail -f không chạy với journald

    Dùng tail -f không hiệu lực với journald vì journald không dùng tệp văn bản thuần; thay vào đó bạn dùng tuỳ chọn -f của journalctl để có cùng hiệu ứng in nhật ký khi chúng đến: journalctl -f.1 Ward nói lời gọi đơn giản này là đủ cho hầu hết nhu cầu, nhưng bạn có thể thêm các bộ lọc ở trên nếu hệ thống của bạn có dòng thông điệp chảy đều không liên quan tới thứ bạn đang tìm.1

    Quyền đọc journal

    Một ghi chú dễ bị bỏ qua: để có quyền truy cập đầy đủ các thông điệp journal, bạn cần chạy journalctl với tư cách root, hoặc là người dùng thuộc nhóm adm hay systemd-journal. Người dùng mặc định trên hầu hết bản phân phối đều đã có quyền đó.12

  4. log rotation

    Xoay vòng nhật ký — và vì sao journal không cần xoay Sổ đầy thì làm gì? Logfile rotation — and why the journal doesn't need it

    Với một daemon syslog, mọi thông điệp hệ thống ghi lại đều vào một tệp nhật ký nào đó, nghĩa là thỉnh thoảng bạn phải xoá thông điệp cũ để chúng không ngốn hết dung lượng lưu trữ.1 Các bản phân phối làm việc này theo những cách khác nhau, nhưng hầu hết dùng tiện ích logrotate.13 Cơ chế này gọi là log rotation (xoay vòng nhật ký): vì một tệp nhật ký văn bản truyền thống chứa thông điệp cũ nhất ở đầu và mới nhất ở cuối, việc xoá riêng phần cũ để lấy lại chỗ khá khó; thay vào đó, nhật ký do logrotate quản lý được chia thành nhiều khúc.1

    Cuốn sổ viết mãi cũng đầy. Nếu cứ để vậy, một ngày máy hết chỗ. Cách giải quyết rất giống ở nhà: sổ năm nay để trên bàn, sổ năm ngoái cất vào hộp, sổ ba năm trước thì bỏ đi. Nhớ nhé: giữ sổ mới, cất sổ cũ, bỏ sổ quá cũ.

    With a syslog daemon, every log message your system records goes into a logfile somewhere, which means you need to delete old messages occasionally so they don't eventually consume all your storage.1 Distributions do this differently, but most use the logrotate utility.13 The mechanism is called log rotation: because a traditional text logfile holds the oldest messages at the beginning and the newest at the end, removing just the older ones is quite difficult — so a logrotate-managed log is divided into many chunks.1

    Bạn gặp nó ở đâuWhere you meet it Lần tới thấy auth.log, auth.log.1, auth.log.2.gz nằm cạnh nhau trong /var/log — đó chính là bốn bước xoay vòng đang hiện hình. Khi thấy nhiều tệp cùng tên nhưng có thêm số ở đuôi. Next time you see auth.log, auth.log.1 and auth.log.2.gz side by side in /var/log — that is rotation made visible.

    Bốn bước xoay vòng

    Giả sử bạn có auth.log trong /var/log chứa thông điệp mới nhất, rồi auth.log.1, auth.log.2, auth.log.3 với dữ liệu ngày càng cũ. Khi logrotate quyết định đã đến lúc xoá bớt, nó “xoay” các tệp: (1) xoá tệp cũ nhất auth.log.3; (2) đổi tên auth.log.2 thành auth.log.3; (3) đổi auth.log.1 thành auth.log.2; (4) đổi auth.log thành auth.log.1.1 Tên và chi tiết khác nhau theo bản phân phối: cấu hình Ubuntu quy định nén tệp khi chuyển từ vị trí “1” sang “2”, nên bạn sẽ thấy auth.log.2.gz và auth.log.3.gz; bản khác đặt hậu tố ngày tháng như -20200529, tiện cho việc tìm nhật ký của một thời điểm cụ thể.1

    Cuộc đua giữa logrotate và trình ghi

    Ward trả lời một câu hỏi rất hay: nếu logrotate xoay vòng đúng lúc rsyslogd muốn ghi thêm thì sao? Nếu chương trình ghi đã mở tệp nhưng chưa đóng trước khi logrotate đổi tên, thông điệp vẫn được ghi thành công — vì trong Linux, một khi tệp đã mở, hệ thống vào/ra không có cách nào biết nó đã bị đổi tên. Nhưng thông điệp sẽ nằm trong tệp mang tên mới, chẳng hạn auth.log.1.1 Ngược lại, nếu logrotate đã đổi tên trước khi chương trình ghi mở tệp, lời gọi hệ thống open() sẽ tạo một tệp nhật ký mới, y như khi không có logrotate.1

    Journal tự dọn dẹp

    Các journal lưu trong /var/log/journal không cần xoay vòng, vì journald tự nhận biết và gỡ bỏ thông điệp cũ. Khác với quản lý nhật ký truyền thống, journald thường quyết định xoá dựa trên: còn bao nhiêu chỗ trống trên hệ thống tệp của journal, journal nên chiếm bao nhiêu phần trăm hệ thống tệp đó, và kích thước journal tối đa được đặt là bao nhiêu.1 Còn các tuỳ chọn khác nữa, như tuổi tối đa cho phép của một thông điệp; Ward chỉ bạn tới trang hướng dẫn journald.conf(5) để xem mặc định và các thiết lập.14

  5. facility & severity

    Facility, severity, priority — và tám mức từ emerg tới debug Mỗi dòng sổ có “ai nói” và “khẩn cỡ nào” Facility, severity, priority — and the eight levels from emerg to debug

    Vì syslog gửi thông điệp đủ loại từ các dịch vụ khác nhau tới các đích khác nhau, nó cần cách phân loại từng thông điệp. Cách truyền thống là dùng giá trị mã hoá của facility và severity.1 Facility là một hạng mục chung của dịch vụ, xác định cái gì đã gửi thông điệp — gồm các dịch vụ và thành phần hệ thống như kernel, hệ thống thư, máy in.1 Severity là mức khẩn cấp: có tám mức, đánh số 0 đến 7, thường được gọi bằng tên, dù các tên không nhất quán lắm và đã biến thiên giữa các hiện thực: 0 emerg, 1 alert, 2 crit, 3 err, 4 warning, 5 notice, 6 info, 7 debug.15

    Mỗi dòng sổ có hai nhãn: ai nói (máy in? nhân? thư điện tử?) và chuyện khẩn cỡ nào (cháy nhà hay chỉ là ghi chú?). Có tám mức khẩn, từ 0 là “cháy” đến 7 là “chuyện vặt”. Nhớ nhé: số càng nhỏ, chuyện càng gấp.

    Because syslog sends messages of various types from different services to different destinations, it needs a way to classify each message. The traditional method uses encoded values of facility and severity.1 The facility is a general category of service identifying what sent the message — services and system components such as kernel, mail system and printer.1 The severity is the urgency: there are eight levels, numbered 0 through 7, usually referred to by name although the names aren't very consistent across implementations: 0 emerg, 1 alert, 2 crit, 3 err, 4 warning, 5 notice, 6 info, 7 debug.15

    Bạn gặp nó ở đâuWhere you meet it Mỗi lần gõ journalctl -p 3: con số đó chính là severity của syslog, chỉ đổi tên thành “priority” trong thế giới journald.1 Con số sau -p chính là mức khẩn. Every time you type journalctl -p 3: that number is the syslog severity, merely renamed "priority" in the journald world.1

    Priority = facility + severity

    Facility và severity cùng nhau tạo thành priority, được đóng gói thành một con số duy nhất trong giao thức syslog.15 Bạn có thể đọc đầy đủ về các trường này trong RFC 5424, học cách chỉ định chúng trong ứng dụng ở trang syslog(3), và học cách khớp chúng ở rsyslog.conf(5).156 Điểm dễ gây nhầm: khi dịch sang thế giới journald, severity lại được gọi là priority — ví dụ khi bạn chạy journalctl -o json để lấy đầu ra máy đọc được.1

    Chỗ giao thức không theo kịp

    Ward chỉ ra một điểm yếu thật: khi soi kỹ phần priority của giao thức, bạn sẽ thấy nó chưa theo kịp các thay đổi và yêu cầu ở phần còn lại của hệ điều hành. Định nghĩa severity vẫn còn tốt, nhưng danh sách facility thì được đóng cứng và bao gồm cả những dịch vụ hiếm dùng như UUCP, mà không có cách nào định nghĩa facility mới — chỉ có một số khe chung local0 đến local7.15

    Structured data

    RFC 5424 cũng có điều khoản cho structured data — các tập cặp khoá–giá trị tuỳ ý mà lập trình viên ứng dụng có thể dùng để tự định nghĩa trường riêng.15 Chúng có thể dùng với journald nếu chịu thêm chút công, nhưng phổ biến hơn nhiều là gửi chúng tới các loại cơ sở dữ liệu khác.1

  6. syslog vs journald

    Vì sao syslog vẫn sống sót bên cạnh journald Hai kiểu sổ, mỗi kiểu giỏi một việc Why syslog survives alongside journald

    Ward kể gốc gác: vào thập niên 1980, một khoảng trống bắt đầu lộ ra — các máy chủ Unix cần cách ghi lại thông tin chẩn đoán, nhưng chưa có chuẩn nào. Khi syslog xuất hiện cùng máy chủ thư điện tử sendmail, nó hợp lý đến mức các nhà phát triển dịch vụ khác sẵn sàng áp dụng theo; RFC 3164 mô tả quá trình tiến hoá của syslog, còn giao thức hiện được định nghĩa trong RFC 5424.175

    Ngày xưa mỗi chương trình tự ghi sổ theo kiểu riêng, rất lộn xộn. Rồi có người nghĩ ra một kiểu sổ chung, ai cũng thích nên dùng theo. Sau này có kiểu sổ mới gọn hơn, nhưng kiểu cũ vẫn còn vì nó gom được sổ của nhiều máy về một chỗ. Nhớ nhé: cái mới gọn hơn, cái cũ gom giỏi hơn.

    Ward gives the origin story: in the 1980s a gap was emerging — Unix servers needed a way to record diagnostic information, but there was no standard. When syslog appeared with the sendmail email server, it made enough sense that developers of other services readily adopted it; RFC 3164 describes syslog's evolution, and the protocol is currently defined in RFC 5424.175

    Bạn gặp nó ở đâuWhere you meet it Trong bất kỳ hạ tầng nào có “máy chủ nhật ký trung tâm”: đó là di sản của thiết kế client–server của syslog. Ở những nơi gom sổ của cả trăm máy về một chỗ. In any infrastructure with a "central log server": that is the legacy of syslog's client–server design.

    Cơ chế syslogd truyền thống

    Cơ chế khá đơn giản: một syslogd truyền thống lắng nghe và chờ thông điệp trên socket miền Unix /dev/log. Một tính năng mạnh nữa là khả năng lắng nghe trên socket mạng ngoài /dev/log, cho phép máy khách gửi thông điệp qua mạng.1 Điều này khiến việc gom toàn bộ thông điệp syslog của cả một mạng về một máy chủ ghi nhật ký trở nên khả thi — và vì thế syslog rất được quản trị viên mạng ưa chuộng; nhiều thiết bị mạng như bộ định tuyến và thiết bị nhúng có thể đóng vai máy khách syslog.1

    Hai lý do syslog còn lại

    Ward nêu đúng hai lý do chính. Một: syslog có phương tiện gom nhật ký qua nhiều máy được định nghĩa rõ ràng — theo dõi nhật ký dễ hơn nhiều khi chúng nằm trên một máy.1 Hai: các phiên bản như rsyslogd có tính mô-đun và có thể xuất ra nhiều định dạng và cơ sở dữ liệu khác nhau (kể cả định dạng journal), giúp nối chúng vào công cụ phân tích và giám sát.16 Ngược lại, journald nhấn mạnh việc thu thập và tổ chức đầu ra nhật ký của một máy vào một định dạng.1

    Ba mặt trận còn dang dở

    Trong “Final Notes on Logging”, Ward nêu ba chỗ chưa chuẩn hoá. Thứ nhất, có một rừng lựa chọn khi muốn gom và lưu nhật ký qua mạng nhiều máy: nhật ký nay có thể vào cơ sở dữ liệu, và máy chủ trung tâm thường bị thay bằng một dịch vụ internet.1 Thứ hai, bản chất tiêu thụ nhật ký đã đổi: có thời nhật ký không được coi là dữ liệu “thật”, chỉ là thứ để con người đọc khi có sự cố; nay nhu cầu gồm tìm kiếm, trích xuất, hiển thị và phân tích — nhưng công cụ dùng nhật ký trong ứng dụng vẫn còn sơ khai.1 Thứ ba là độ tin cậy: syslog nguyên thuỷ gần như không có xác thực, và nhật ký không được mã hoá nên dễ bị nghe lén trên mạng; máy chủ syslog hiện đại đã có cách chuẩn để mã hoá thông điệp và xác thực máy gửi, nhưng xuống tới từng ứng dụng thì bức tranh kém rõ ràng hơn — làm sao bạn chắc rằng thứ tự xưng là máy chủ web thật sự là máy chủ web?1

Cụm khái niệm 02 Concept cluster 02

Cấu trúc /etc và bảy trường của một người dùng Ngăn tủ giấy tờ và tấm thẻ của mỗi người The structure of /etc and a user's seven fields

Hầu hết tệp cấu hình hệ thống trên Linux nằm trong /etc. Trong lịch sử, mỗi chương trình hoặc dịch vụ hệ thống có một hoặc vài tệp cấu hình ở đó, và do số lượng thành phần trên một hệ Unix rất lớn, /etc tích tụ tệp rất nhanh.1 Ward nêu hai vấn đề của lối làm này: khó tìm một tệp cấu hình cụ thể trên hệ thống đang chạy, và khó bảo trì một hệ thống cấu hình như vậy.1

Tủ giấy tờ của máy tên là /etc. Ngày xưa mọi tờ giấy đều ném chung vào tủ, nên vừa khó tìm vừa dễ bị người khác ghi đè lên. Sau này người ta chia tủ thành nhiều ngăn nhỏ. Nhớ nhé: chia ngăn thì dễ tìm và khó mất.

Most system configuration files on a Linux system live in /etc. Historically each program or system service had one or more configuration files there, and because of the sheer number of components on a Unix system, /etc accumulated files quickly.1 Ward names two problems with that approach: it was hard to find particular configuration files on a running system, and hard to maintain a system configured that way.1

Ví dụ cụ thể của ông về cái giá phải trả. Nếu muốn đổi cấu hình sudo, bạn phải sửa /etc/sudoers. Nhưng sau khi sửa, một lần nâng cấp bản phân phối có thể xoá sạch tuỳ biến của bạn, vì nó ghi đè mọi thứ trong /etc.1 Lời giải là đặt tuỳ biến vào các tệp riêng trong thư mục con cấu hình, như những tệp trong /etc/grub.d.1 Đó cũng là xu hướng nhiều năm nay: đưa tệp cấu hình hệ thống vào các thư mục con dưới /etc, như systemd đã làm với /etc/systemd; vẫn còn vài tệp lẻ trong /etc, nhưng nếu chạy ls -F /etc bạn sẽ thấy phần lớn mục ở đó nay là thư mục con.1

Cái gì thuộc về /etc? Nguyên tắc cơ bản của Ward: cấu hình có thể tuỳ biến cho một máy đơn lẻ — như thông tin người dùng (/etc/passwd) và chi tiết mạng (/etc/network) — thì vào /etc. Nhưng chi tiết ứng dụng chung, chẳng hạn mặc định giao diện người dùng của một bản phân phối, không thuộc về /etc; các tệp cấu hình mặc định hệ thống không nhằm để tuỳ biến cũng thường nằm chỗ khác, như các tệp unit systemd đóng gói sẵn trong /usr/lib/systemd.1

Tờ giấy nào để trong tủ? Những tờ mà riêng máy này cần sửa: ai được dùng máy, máy tên gì, nối mạng thế nào. Những tờ in sẵn cho mọi máy thì để chỗ khác. Nhớ nhé: tủ /etc chỉ chứa thứ riêng của máy này.

What belongs in /etc? Ward's basic guideline: customizable configurations for a single machine — user information (/etc/passwd) and network details (/etc/network) — go into /etc. General application details, such as a distribution's defaults for a user interface, don't belong there; system default configuration files not meant to be customized usually live elsewhere, as with the prepackaged systemd unit files in /usr/lib/systemd.1

juser:x:3119:1000:J. Random User:/home/juser:/bin/bash
  1 tên  2 mật khẩu  3 UID
  4 GID  5 GECOS  6 home  7 shell

tên : x : số của bạn :
số nhóm : tên thật :
thư mục nhà : chương trình dòng lệnh

juser:x:3119:1000:J. Random User:/home/juser:/bin/bash
  1 name  2 password  3 UID
  4 GID  5 GECOS  6 home  7 shell

  1. /etc/passwd

    /etc/passwd — bảy trường, phân tách bằng dấu hai chấm Tấm thẻ của mỗi người dùng /etc/passwd — seven colon-separated fields

    Hệ Unix cho phép nhiều người dùng độc lập. Ở mức nhân, người dùng chỉ là những con số (user ID); nhưng vì nhớ tên dễ hơn nhớ số, khi quản trị Linux bạn thường làm việc với tên người dùng (hay tên đăng nhập). Điểm mấu chốt Ward nhấn mạnh: tên người dùng chỉ tồn tại trong không gian người dùng, nên mọi chương trình làm việc với tên đều phải tra ra ID tương ứng khi nói chuyện với nhân.1 Tệp văn bản thuần /etc/passwd chính là ánh xạ tên ↔ UID đó; mỗi dòng đại diện một người dùng và có bảy trường ngăn cách bởi dấu hai chấm.18

    Máy không nhớ tên bạn — nó nhớ một con số. Tệp /etc/passwd là quyển danh bạ để đổi tên ra số. Mỗi người một dòng, mỗi dòng bảy ô, các ô ngăn nhau bằng dấu hai chấm. Nhớ nhé: với máy, bạn là một con số; cái tên là để cho bạn dễ nhớ.

    Unix systems allow multiple independent users. At the kernel level users are simply numbers (user IDs); because a name is easier to remember than a number, you normally work with usernames (or login names) when managing Linux. The point Ward stresses: usernames exist only in user space, so any program that works with a username must find its corresponding user ID when talking to the kernel.1 The plaintext file /etc/passwd is that name ↔ UID map; each line represents one user and has seven fields separated by colons.18

    Bạn gặp nó ở đâuWhere you meet it Mỗi lần ls -l hiện tên chủ sở hữu thay vì một con số — đó là ánh xạ này đang làm việc. Khi máy hiện tên bạn thay vì hiện con số. Every time ls -l shows an owner's name instead of a number — that is this map at work.

    Năm trường còn lại

    Sau tên và mật khẩu, Ward liệt kê: UID — biểu diễn của người dùng trong nhân; bạn có thể có hai mục cùng UID, nhưng điều đó sẽ làm bạn (và có thể cả phần mềm của bạn) bối rối, nên hãy giữ UID duy nhất. GID — nên là một trong các mục có đánh số trong /etc/group; nhóm quyết định quyền tệp và ít thứ khác, và nhóm này còn gọi là nhóm chính của người dùng. Tên thật — thường gọi là trường GECOS; đôi khi bạn thấy dấu phẩy trong trường này, biểu thị số phòng và số điện thoại. Thư mục nhà. Và shell — chương trình chạy khi người dùng mở một phiên terminal.18 Cú pháp của tệp khá nghiêm ngặt: không cho phép chú thích hay dòng trống.1

    Trường mật khẩu: x, dấu sao, và khoảng trống

    Trường thứ hai từng là mật khẩu; trên hầu hết hệ Linux mật khẩu không còn lưu trong passwd mà trong tệp shadow.1 Mật khẩu Unix không bao giờ được lưu dạng văn bản rõ — trường này không phải mật khẩu mà là một dẫn xuất của nó, trông như một mớ ký tự vô nghĩa kiểu d1CVEWiB/oppc; trong hầu hết trường hợp, lấy lại mật khẩu gốc từ trường này là cực kỳ khó (giả sử mật khẩu không dễ đoán).1 Một chữ x nghĩa là mật khẩu mã hoá nằm trong tệp shadow; một dấu * nghĩa là người dùng không thể đăng nhập; còn nếu trường này để trống (hai dấu hai chấm liền nhau, ::) thì đăng nhập không cần mật khẩu — Ward cảnh báo rõ: hãy coi chừng mật khẩu trống như vậy, bạn không bao giờ nên để một người dùng đăng nhập được mà không cần mật khẩu.18

    “Tài khoản” là một quy ước, không phải luật

    Một người dùng trong /etc/passwd cùng thư mục nhà tương ứng được gọi chung là một account. Nhưng Ward nhắc: đây là quy ước của không gian người dùng. Một mục trong passwd thường đã đủ để tính là tài khoản; thư mục nhà không nhất thiết phải tồn tại để hầu hết chương trình nhận ra tài khoản đó. Hơn nữa, có những cách thêm người dùng mà không ghi họ vào passwd — ví dụ thêm người dùng từ một máy chủ mạng bằng NIS (Network Information Service) hay LDAP (Lightweight Directory Access Protocol) từng khá phổ biến.1

  2. special users

    Người dùng đặc biệt: root, daemon, nobody, và các pseudo-user Mấy “người dùng” không phải là người Special users: root, daemon, nobody, and pseudo-users

    Trong /etc/passwd bạn sẽ thấy vài người dùng đặc biệt. Siêu người dùng (root) luôn có UID 0 và GID 0.1 Một số người dùng như daemon không có đặc quyền đăng nhập. Người dùng nobody là một người dùng thiếu đặc quyền; một số tiến trình chạy dưới danh nghĩa nobody vì (bình thường) nó không thể ghi vào bất cứ thứ gì trên hệ thống.1 Những người dùng không thể đăng nhập được gọi là pseudo-user; tuy không đăng nhập được, hệ thống vẫn có thể khởi động tiến trình với UID của họ, và pseudo-user như nobody thường được tạo ra vì lý do an ninh.1

    Trong danh sách người dùng có mấy cái tên không phải người thật: chúng là “vai” để chương trình mặc vào khi chạy. Có vai gần như không được làm gì cả — để nếu chương trình đó bị lỗi thì cũng không phá được gì. Nhớ nhé: cho chương trình mặc vai nhỏ nhất có thể.

    You'll find a few special users in /etc/passwd. The superuser (root) always has UID 0 and GID 0.1 Some users, such as daemon, have no login privileges. The nobody user is an underprivileged user; some processes run as nobody because it cannot (normally) write to anything on the system.1 Users that cannot log in are called pseudo-users; although they can't log in, the system can start processes with their user IDs, and pseudo-users such as nobody are usually created for security reasons.1

    Bạn gặp nó ở đâuWhere you meet it Mỗi lần ps -ef hiện một hàng dài tiến trình chạy dưới những cái tên bạn chưa từng đăng nhập. Khi thấy nhiều chương trình chạy dưới tên lạ. Every time ps -ef shows a column of processes running as names you never logged in as.

    Chỉ UID 0 có ý nghĩa với nhân

    Ward lặp lại điểm then chốt: những thứ trên đều là quy ước của không gian người dùng. Các người dùng này không có ý nghĩa đặc biệt nào với nhân; UID duy nhất có ý nghĩa đặc biệt với nhân là UID của siêu người dùng, 0.19 Hệ quả hơi phản trực giác mà ông nói thẳng: hoàn toàn có thể cho người dùng nobody quyền truy cập mọi thứ trên hệ thống, y như với bất kỳ người dùng nào khác.1

    Đọc lại Listing 7-1 với con mắt đó

    Trong danh sách mẫu của sách, root mang x ở trường mật khẩu (mật khẩu nằm ở shadow), còn daemon, bin, sys, nobody mang dấu * — nghĩa là không đăng nhập được. nobody mang UID/GID 65534.1 Nhìn một tệp passwd thật theo cách này, bạn đọc được ngay chính sách an ninh của máy mà không cần công cụ nào.

  3. /etc/shadow

    /etc/shadow — mật khẩu dọn ra khỏi tệp ai cũng đọc được Mật khẩu cất vào ngăn khoá riêng /etc/shadow — passwords moved out of the world-readable file

    Tệp mật khẩu bóng (/etc/shadow) trên hệ Linux thường chứa thông tin xác thực người dùng, gồm mật khẩu mã hoá và thông tin hết hạn mật khẩu tương ứng với các người dùng trong /etc/passwd.110 Định dạng shadow tương tự passwd, nhưng người dùng thường không có quyền đọc shadow.1

    Ngày xưa mật khẩu (dạng đã xáo trộn) nằm chung trong quyển danh bạ ai cũng mở được. Sau người ta tách nó sang một quyển khác, cất trong ngăn khoá. Nhớ nhé: danh bạ thì công khai, mật khẩu thì khoá lại.

    The shadow password file (/etc/shadow) on a Linux system normally contains user authentication information, including the encrypted passwords and password expiration information corresponding to the users in /etc/passwd.110 Its format is similar to passwd, but normal users don't have read permission for shadow.1

    Bạn gặp nó ở đâuWhere you meet it Mỗi khi cat /etc/shadow trả về “Permission denied” — đó đúng là hành vi được thiết kế. Khi máy từ chối cho bạn xem tệp mật khẩu. Every time cat /etc/shadow answers "Permission denied" — that is the design working.

    Lịch sử: shadow suite rồi PAM

    Tệp shadow ra đời để cung cấp cách lưu mật khẩu linh hoạt hơn (và có lẽ an toàn hơn). Nó đi kèm một bộ thư viện và tiện ích, mà nhiều trong số đó sớm bị thay thế bởi các mảnh của PAM. Thay vì đưa vào một bộ tệp hoàn toàn mới cho Linux, PAM vẫn dùng /etc/shadow, nhưng không dùng một số tệp cấu hình tương ứng như /etc/login.defs.111

    Số trường của shadow

    Sách mô tả nội dung shadow theo chức năng (mật khẩu mã hoá + thông tin hết hạn) chứ không liệt kê từng trường như với passwd.1 Trang hướng dẫn shadow(5) ghi rõ hơn: mỗi dòng có chín trường ngăn bằng dấu hai chấm, bắt đầu bằng tên đăng nhập, mật khẩu mã hoá, ngày đổi mật khẩu gần nhất (tính bằng số ngày kể từ 1970-01-01), tuổi mật khẩu tối thiểu, tuổi tối đa, v.v.10 Trang này cũng ghi: nếu trường mật khẩu bắt đầu bằng dấu chấm than ! thì mật khẩu đang bị khoá.10 Con số chín trường là của man page, không phải của sách — ghi ở đây để bạn biết chúng bổ sung nhau chứ không mâu thuẫn.

  4. manipulating users

    Sửa người dùng: dùng lệnh, đừng mở tệp ra gõ Muốn sửa danh bạ thì dùng đúng công cụ Changing users: use the commands, don't hand-edit

    Người dùng thường tương tác với /etc/passwd qua lệnh passwd và vài công cụ khác: passwd để đổi mật khẩu, chfn và chsh để đổi tên thật và shell (shell phải có trong /etc/shells).1 Ward giải thích cơ chế đằng sau: tất cả đều là tệp thực thi suid-root, vì chỉ siêu người dùng mới được đổi tệp /etc/passwd.1

    Muốn đổi mật khẩu, gõ passwd. Đừng mở quyển danh bạ ra tự sửa bằng tay — rất dễ viết sai một dấu hai chấm rồi khoá chính mình ra ngoài. Nhớ nhé: dùng lệnh có sẵn, đừng sửa tay.

    Regular users interact with /etc/passwd through the passwd command and a few other tools: passwd to change your password, chfn and chsh to change the real name and shell respectively (the shell must be listed in /etc/shells).1 Ward explains the mechanism behind them: these are all suid-root executables, because only the superuser can change /etc/passwd.1

    Bạn gặp nó ở đâuWhere you meet it Mỗi lần một người dùng thường đổi được mật khẩu của chính mình trong một tệp mà họ không có quyền ghi — đó là suid đang làm việc. Khi bạn đổi được mật khẩu dù không phải quản trị viên. Every time an ordinary user changes their own password in a file they cannot write — that is suid at work.

    Vì sao không nên sửa passwd bằng trình soạn thảo

    Vì /etc/passwd chỉ là tệp văn bản thuần, siêu người dùng về mặt kỹ thuật được phép dùng bất kỳ trình soạn thảo nào để sửa; thêm người là thêm một dòng thích hợp và tạo thư mục nhà, xoá người là làm ngược lại.1 Nhưng Ward nói thẳng đó là ý tưởng tồi: không chỉ quá dễ mắc lỗi, mà bạn còn có thể vướng vấn đề tương tranh nếu thứ gì khác đang sửa passwd cùng lúc.1 Dễ hơn và an toàn hơn nhiều là dùng các lệnh riêng: đặt mật khẩu cho người dùng bằng passwd user với tư cách siêu người dùng, thêm và xoá người dùng bằng adduser và userdel.1

    Khi buộc phải sửa tay: vipw

    Nếu bạn thật sự phải sửa trực tiếp (ví dụ tệp bị hỏng cách nào đó), hãy dùng chương trình vipw: nó sao lưu và khoá /etc/passwd trong lúc bạn sửa, như một biện pháp phòng ngừa thêm. Để sửa /etc/shadow thay vì /etc/passwd, dùng vipw -s.112 Ward đóng ngoặc bằng một câu rất đúng tinh thần quản trị: “hy vọng bạn sẽ không bao giờ phải làm một trong hai việc đó”.1

  5. /etc/group

    Nhóm: bốn trường, và một tính năng đang phai nhạt Nhóm để vài người dùng chung tệp Groups: four fields, and a fading feature

    Nhóm trong Unix là cách chia sẻ tệp giữa một số người dùng nhất định: bạn đặt bit quyền đọc hoặc ghi cho một nhóm cụ thể, loại trừ những người còn lại.1 Ward kèm một nhận xét lịch sử trung thực: tính năng này từng quan trọng vì nhiều người dùng chung một máy hay một mạng, nhưng đã bớt quan trọng trong những năm gần đây khi máy trạm ít được dùng chung hơn.1 Tệp /etc/group định nghĩa các group ID; như /etc/passwd, mỗi dòng là một tập trường ngăn bởi dấu hai chấm — bốn trường: tên nhóm, mật khẩu nhóm, GID, và một danh sách tuỳ chọn các người dùng thuộc nhóm.113

    Nhóm giống như một chiếc chìa khoá chung: ai trong nhóm cũng mở được cùng một ngăn tủ. Ngày xưa nhiều người dùng chung một máy nên nhóm rất quan trọng; giờ mỗi người một máy nên ít dùng hơn. Gõ groups để xem mình thuộc nhóm nào. Nhớ nhé: nhóm là chìa khoá dùng chung.

    Groups in Unix are a way to share files among certain users: you set read or write permission bits for a particular group, excluding everyone else.1 Ward adds an honest historical note: this feature was once important because many users shared one machine or network, but it has become less significant in recent years as workstations are shared less often.1 The /etc/group file defines the group IDs; as in /etc/passwd, each line is a set of colon-separated fields — four of them: group name, group password, GID, and an optional list of users belonging to the group.113

    Bạn gặp nó ở đâuWhere you meet it Để xem bạn thuộc những nhóm nào, chạy groups.1 Tên nhóm cũng xuất hiện khi bạn chạy một lệnh như ls -l.1 Gõ groups là biết mình ở trong nhóm nào. To see the groups you belong to, run groups.1 Group names also appear when you run a command like ls -l.1

    Mật khẩu nhóm — đừng dùng

    Ward khuyến nghị rất dứt khoát: mật khẩu nhóm Unix hầu như không bao giờ được dùng, và bạn cũng không nên dùng (một thay thế tốt trong hầu hết trường hợp là sudo). Hãy dùng * hoặc giá trị mặc định nào khác. Một chữ x ở đây nghĩa là có mục tương ứng trong /etc/gshadow, và đó cũng gần như luôn là một mật khẩu đã bị vô hiệu, ký hiệu bằng * hoặc !.113

    Hai đường vào một nhóm

    GID phải duy nhất trong tệp group, và con số này đi vào trường nhóm của người dùng trong mục /etc/passwd của họ.1 Một chi tiết dễ bỏ sót: ngoài những người được liệt kê ở trường thứ tư, những người dùng có GID tương ứng trong mục passwd của họ cũng thuộc nhóm đó.113 Nghĩa là nhìn mỗi /etc/group chưa đủ để biết ai ở trong nhóm nào. Ward cũng ghi chú: các bản phân phối Linux thường tạo một nhóm mới cho mỗi người dùng mới, trùng tên với người dùng.1

  6. getty and login

    getty và login: cánh cửa cũ mà bạn gần như không còn đi qua Cánh cửa đăng nhập kiểu cũ getty and login: the old door you rarely use

    Chương trình getty gắn vào các terminal và hiển thị dấu nhắc đăng nhập. Trên hầu hết hệ Linux, getty khá đơn giản vì hệ thống chỉ dùng nó cho việc đăng nhập trên terminal ảo.1 Sau khi bạn nhập tên đăng nhập, getty tự thay thế chính nó bằng chương trình login, chương trình này hỏi mật khẩu; nếu bạn nhập đúng, login lại tự thay thế chính nó (bằng exec()) bằng shell của bạn — nếu không, bạn nhận thông báo “Login incorrect”.1 Phần lớn công việc xác thực thật sự của login do PAM đảm nhiệm.1

    Ngày xưa muốn vào máy, bạn gõ tên rồi gõ mật khẩu ở một màn hình đen. Chương trình gác cửa đó vẫn còn, nhưng giờ đa số người vào máy qua màn hình đồ hoạ hoặc qua mạng. Nhớ nhé: cửa cũ vẫn còn, chỉ là ít ai đi nữa.

    The getty program attaches to terminals and displays a login prompt. On most Linux systems getty is uncomplicated because the system uses it only for logins on virtual terminals.1 After you enter your login name, getty replaces itself with the login program, which asks for your password; if you enter it correctly, login replaces itself (using exec()) with your shell — otherwise you get a "Login incorrect" message.1 Much of login's real authentication work is handled by PAM.1

    Bạn gặp nó ở đâuWhere you meet it Trên nhiều hệ, bạn thậm chí không thấy tiến trình getty nào cho tới khi truy cập một terminal ảo bằng tổ hợp như CTRL-ALT-F1.1 Bấm CTRL-ALT-F1 là thấy cánh cửa cũ hiện ra. On many systems you won't even see a getty process until you reach a virtual terminal with something like CTRL-ALT-F1.1

    agetty và tốc độ baud đã lỗi thời

    Trong một danh sách tiến trình, getty thường trông như /sbin/agetty -o -p -- \u --noclear tty1 linux; agetty là phiên bản mà nhiều bản phân phối Linux kèm theo mặc định.1 Khi tìm hiểu getty, bạn có thể gặp tham chiếu tới một tốc độ baud như “38400”. Ward nói rõ: thiết lập này gần như đã lỗi thời hoàn toàn — terminal ảo bỏ qua tốc độ baud; nó chỉ còn ở đó để kết nối với các đường nối tiếp thật.1

    Vì sao bạn gần như không cần cấu hình chúng

    Ward kết mục bằng một lời trấn an thực tế: giờ bạn đã biết getty và login làm gì, nhưng bạn có lẽ sẽ không bao giờ cần cấu hình hay thay đổi chúng — thực tế bạn hiếm khi dùng tới, vì hầu hết người dùng nay đăng nhập qua giao diện đồ hoạ như gdm hoặc từ xa bằng SSH, và không cái nào trong hai dùng getty hay login.1

Cụm khái niệm 03 Concept cluster 03

Nhận dạng, xác thực, uỷ quyền — và ba (thật ra bốn) user ID Bạn là ai, làm sao chứng minh, và được làm gì Identification, authentication, authorization — and three (really four) user IDs

Ward tách bạch ba việc mà một hệ đa người dùng phải hỗ trợ: identification (nhận dạng) trả lời câu hỏi người dùng là ai; authentication (xác thực) yêu cầu người dùng chứng minh họ đúng là người họ nói; và authorization (uỷ quyền) dùng để định nghĩa và giới hạn những gì người dùng được phép làm.1

Ba câu hỏi khác nhau: Bạn tên gì? Chứng minh đi! Bạn được làm gì? Máy trả lời ba câu này bằng ba cơ chế khác nhau. Nhớ nhé: tên — bằng chứng — quyền hạn.

Ward separates three things a multiuser system must support: identification answers who users are; authentication asks users to prove that they are who they say they are; and authorization defines and limits what users are allowed to do.1

Đường phân chia giữa nhân và không gian người dùng. Đây là câu then chốt của cả mục: khi nói tới nhận dạng người dùng, nhân Linux chỉ biết các user ID dạng số cho quyền sở hữu tiến trình và tệp. Nhân biết các quy tắc uỷ quyền về cách chạy tệp thực thi setuid và cách các UID có thể gọi họ hàm setuid() để chuyển từ người dùng này sang người dùng khác. Nhưng nhân không biết gì về xác thực: tên người dùng, mật khẩu, v.v. — thực tế gần như mọi thứ liên quan đến xác thực đều xảy ra trong không gian người dùng.19 Ward còn nói rõ hơn ở chỗ khác: về cốt lõi, việc chuyển người dùng không liên quan gì tới mật khẩu hay tên đăng nhập — đó hoàn toàn là khái niệm của không gian người dùng.1

Ba quy tắc cốt lõi của nhân. Nhân có các quy tắc cơ bản về việc một tiến trình có thể hoặc không thể làm gì, và Ward rút gọn còn ba điều thiết yếu bao trùm tệp thực thi setuid và setuid(): (1) một tiến trình có thể chạy một tệp thực thi setuid miễn là nó có đủ quyền tệp; (2) một tiến trình chạy dưới root (UID 0) có thể dùng setuid() để trở thành bất kỳ người dùng nào khác; (3) một tiến trình không chạy dưới root chịu hạn chế nghiêm ngặt về cách dùng setuid() — trong hầu hết trường hợp, nó không thể.114

Ba luật. Một: chương trình có “dấu đặc biệt” thì được đổi vai. Hai: ai đang là quản trị viên thì đổi thành ai cũng được. Ba: người thường thì gần như không được đổi. Nhớ nhé: đổi vai là đặc quyền, không phải mặc định.

The kernel's three core rules. The kernel has basic rules about what a process can and can't do, and Ward reduces them to three essentials covering setuid executables and setuid(): (1) a process can run a setuid executable as long as it has adequate file permissions; (2) a process running as root (user ID 0) can use setuid() to become any other user; (3) a process not running as root has severe restrictions on how it may use setuid() — in most cases, it cannot.114

euid → “diễn viên” · quyền truy cập
ruid → “chủ sở hữu” · ai kill được
saved uid → chỗ cất để quay lại
fsuid → hiếm dùng

ps -eo pid,euser,ruser,comm

euid = vai đang đóng
ruid = người thật đứng sau
saved = vai cất trong túi

euid → the "actor" · access rights
ruid → the "owner" · who may kill it
saved uid → parking spot to return to
fsuid → rarely used

ps -eo pid,euser,ruser,comm

  1. effective vs real UID

    euid là diễn viên, ruid là chủ sở hữu Vai đang đóng và người thật đứng sau The euid is the actor, the ruid is the owner

    Ward thừa nhận cách trình bày trước đó là đơn giản hoá: thực tế mỗi tiến trình có nhiều hơn một user ID.1 Effective UID (euid) định nghĩa quyền truy cập của tiến trình (quan trọng nhất là quyền tệp). Real UID (ruid) cho biết ai đã khởi tạo tiến trình. Bình thường hai ID này giống nhau, nhưng khi bạn chạy một chương trình setuid, Linux đặt euid thành chủ sở hữu của chương trình trong lúc thực thi, đồng thời giữ UID gốc của bạn trong ruid.19

    Hãy tưởng tượng một vở kịch: người thật là bạn, nhưng bạn đang đóng vai ông vua. Quyền của ông vua là vai; còn ai được gọi bạn xuống sân khấu thì tính theo người thật. Máy tính cũng vậy: một con số cho vai, một con số cho người thật. Nhớ nhé: vai quyết định được làm gì, người thật quyết định ai điều khiển được.

    Ward admits the earlier account was simplified: in reality every process has more than one user ID.1 The effective UID (euid) defines the access rights for a process (most significantly, file permissions). The real UID (ruid) indicates who initiated a process. Normally these are identical, but when you run a setuid program Linux sets the euid to the program's owner during execution, while keeping your original user ID in the ruid.19

    Bạn gặp nó ở đâuWhere you meet it Chạy ps -eo pid,euser,ruser,comm để xem cả hai cột — và đừng ngạc nhiên nếu chúng giống hệt nhau cho mọi tiến trình trên máy bạn.1 Gõ lệnh đó để xem vai và người thật của từng chương trình. Run ps -eo pid,euser,ruser,comm to see both columns — and don't be surprised if they're identical for every process on your system.1

    Vì sao ruid mới là người “sở hữu”

    Ward đưa cách nhớ rất gọn: nghĩ euid là diễn viên và ruid là chủ sở hữu. Ruid định nghĩa người dùng nào có thể tương tác với tiến trình đang chạy — quan trọng nhất là ai có thể kill và gửi tín hiệu cho nó. Ví dụ, nếu người dùng A khởi động một tiến trình chạy dưới người dùng B (nhờ quyền setuid), thì A vẫn sở hữu tiến trình đó và có thể kill nó.19 Ông nói thẳng rằng khác biệt giữa euid và ruid gây nhầm lẫn tới mức rất nhiều tài liệu về quyền sở hữu tiến trình là sai.1

    Saved UID và fsuid

    Ngoài real và effective, còn có saved user ID (thường không viết tắt): một tiến trình có thể chuyển euid của nó sang ruid hoặc sang saved user ID trong lúc thực thi.19 Và để rắc rối thêm, Linux còn có một UID nữa: filesystem user ID (fsuid), định nghĩa người dùng truy cập hệ thống tệp — nhưng nó hiếm khi được dùng.19

    Thí nghiệm nhỏ Ward gợi ý

    Vì hầu hết tiến trình có euid và ruid giống nhau, đầu ra mặc định của ps và các chương trình chẩn đoán khác chỉ hiện euid.1 Để tạo một ngoại lệ mà nhìn thấy hai cột khác nhau, ông đề xuất: tạo một bản sao setuid của lệnh sleep, chạy bản sao đó vài giây, rồi chạy lệnh ps ở trên trong cửa sổ khác trước khi nó kết thúc.1

  2. setuid behavior

    Vì sao phải dùng sudo để kill thứ mình đã sudo chạy Vì sao đôi khi bạn không tắt được chương trình của chính mình Why you need sudo to kill what you started with sudo

    Ward đặt đúng câu hỏi mà kinh nghiệm hằng ngày gợi lên: nếu ruid là của bạn, tại sao sau khi khởi động một tiến trình bằng sudo, bạn vẫn phải dùng sudo để kill nó, chứ không kill được bằng người dùng thường của mình?1 Câu trả lời: sudo và nhiều chương trình setuid khác chủ động đổi cả euid lẫn ruid bằng một trong các lời gọi hệ thống setuid(). Chúng làm vậy vì thường có tác dụng phụ ngoài ý muốn và vấn đề truy cập khi các user ID không khớp nhau.114

    Bạn nhờ quản trị viên chạy giúp một chương trình. Sau đó bạn muốn tắt nó, nhưng máy nói “không được” — vì lúc chạy, chương trình đã đổi cả vai lẫn người thật thành quản trị viên. Muốn tắt, lại phải nhờ quản trị viên. Nhớ nhé: mượn quyền để bật thì cũng phải mượn quyền để tắt.

    Ward asks exactly the question daily experience raises: if the ruid is yours, why must you still use sudo to kill a process you started with sudo, instead of killing it as your regular user?1 The answer: sudo and many other setuid programs explicitly change both the euid and the ruid with one of the setuid() system calls. They do so because there are often unintended side effects and access problems when the user IDs do not all match.114

    Bạn gặp nó ở đâuWhere you meet it Lần tới khi kill trả về “Operation not permitted” cho tiến trình bạn vừa tự khởi động — bạn đã biết vì sao. Khi máy không cho bạn tắt chương trình bạn vừa mở bằng quyền quản trị. Next time kill answers "Operation not permitted" for a process you started yourself — now you know why.

    stay_setuid

    Một số chương trình không thích có ruid là root. Để ngăn sudo đổi ruid, Ward chỉ cách thêm dòng Defaults    stay_setuid vào tệp /etc/sudoers — kèm một cảnh báo rõ ràng: hãy coi chừng tác dụng phụ với các chương trình khác mà bạn muốn chạy dưới root.1 Ông cũng chỉ bạn tới setuid(2) và các trang trong mục SEE ALSO nếu muốn đọc chi tiết và quy tắc chuyển UID — có rất nhiều lời gọi hệ thống khác nhau cho các tình huống khác nhau.114

    Hệ quả an ninh: hai thứ phải cực kỳ cẩn thận

    Vì nhân Linux xử lý mọi chuyển đổi người dùng (và qua đó là quyền truy cập tệp) thông qua chương trình setuid và các lời gọi hệ thống tiếp theo, nhà phát triển và quản trị viên phải cực kỳ cẩn thận với hai thứ: số lượng và chất lượng các chương trình có quyền setuid, và những gì các chương trình đó làm.1 Ward minh hoạ bằng một ví dụ lạnh gáy và cố ý đơn giản: nếu bạn tạo một bản sao của shell bash mang setuid root, bất kỳ người dùng cục bộ nào cũng có thể thực thi nó và toàn quyền định đoạt hệ thống — “thật sự đơn giản như thế”.1 Hơn nữa, ngay cả một chương trình chuyên dụng mang setuid root cũng nguy hiểm nếu nó có lỗi: khai thác điểm yếu trong chương trình chạy dưới root là phương pháp xâm nhập hệ thống hàng đầu, và có quá nhiều khai thác kiểu này để đếm hết.1

  3. getpwuid()

    Sáu bước ngây thơ, và lời giải bằng thư viện Từ con số ra cái tên: đường dài và đường tắt Six naive steps, and the library solution

    Ward dựng một ví dụ “đơn giản hoá quá mức” rất hữu ích: một tiến trình muốn biết tên người dùng của chính nó. Trên hệ Unix truyền thống nó sẽ: (1) hỏi nhân euid của mình bằng geteuid(); (2) mở /etc/passwd và đọc từ đầu; (3) đọc một dòng — nếu hết thì thất bại; (4) tách dòng thành các trường, trường thứ ba là UID; (5) so sánh UID đó với UID ở bước 1, nếu trùng thì trường đầu tiên chính là tên cần tìm; (6) nếu không, sang dòng tiếp theo và quay lại bước 3.1 Ông kết luận: đây là một thủ tục dài, và hiện thực thực tế thường còn phức tạp hơn.1

    Máy biết số của bạn, nhưng muốn in ra tên thì phải đi tra danh bạ từng dòng một. Nếu chương trình nào cũng tự viết đoạn tra cứu này thì rối lắm. Nên người ta viết sẵn một hàm chung cho mọi người dùng. Nhớ nhé: việc lặp đi lặp lại thì để thư viện làm.

    Ward builds a deliberately oversimplified example: a process wants to know its own username. On a traditional Unix system it would: (1) ask the kernel for its euid with geteuid(); (2) open /etc/passwd and start reading at the beginning; (3) read a line — if nothing is left, it has failed; (4) parse the line into fields, the third being the user ID; (5) compare that ID with the one from step 1, and if identical, the first field is the username; (6) otherwise move to the next line and go back to step 3.1 His conclusion: this is a long procedure, and a real-world implementation is usually even more complicated.1

    Bạn gặp nó ở đâuWhere you meet it Mọi chương trình in ra tên chủ sở hữu tệp đều đang gọi vào cùng một hàm thư viện này, chứ không tự đọc /etc/passwd. Mọi chương trình đều dùng chung một cách tra danh bạ. Every program that prints a file owner's name is calling the same library function, not reading /etc/passwd itself.

    Vì sao thư viện dùng chung là chìa khoá

    Nếu mọi lập trình viên cần biết tên người dùng hiện tại đều phải tự viết toàn bộ đoạn mã đó, hệ thống sẽ thành “một mớ rời rạc, đầy lỗi, phình to và không bảo trì nổi” — chữ của Ward.1 May thay có các thư viện chuẩn: thường bạn chỉ cần gọi một hàm như getpwuid() sau khi đã có câu trả lời từ geteuid().115 Vì thư viện chuẩn được chia sẻ giữa các tệp thực thi trên máy, bạn có thể thay đổi đáng kể hiện thực xác thực mà không đổi chương trình nào: ví dụ chuyển từ /etc/passwd sang một dịch vụ mạng như LDAP chỉ bằng cách đổi cấu hình hệ thống.1

    Bốn giới hạn của cách làm truyền thống

    Cách tra tên theo UID thì ổn, nhưng mật khẩu thì rắc rối hơn nhiều. Ward liệt kê các giới hạn của hiện thực truyền thống (mã hoá thứ người dùng gõ rồi so với nội dung /etc/passwd): nó không cho phép đặt một chuẩn mã hoá chung toàn hệ thống; nó giả định bạn có quyền truy cập mật khẩu đã mã hoá; nó giả định bạn muốn hỏi mật khẩu mỗi lần người dùng cần xác thực (điều này gây khó chịu); và nó giả định bạn muốn dùng mật khẩu — nếu muốn dùng mã dùng một lần, thẻ thông minh, sinh trắc học hay hình thức khác, bạn phải tự thêm hỗ trợ đó.1 Chính một số giới hạn này đã góp phần dẫn tới bộ shadow password, và lời giải cho phần lớn vấn đề còn lại đến cùng thiết kế và hiện thực của PAM.1

  4. PAM

    PAM — mô-đun xác thực cắm được, đề xuất năm 1995 Ổ cắm để lắp nhiều kiểu “chứng minh mình là ai” PAM — pluggable authentication modules, proposed in 1995

    Để có sự linh hoạt trong xác thực người dùng, năm 1995 Sun Microsystems đề xuất một chuẩn mới gọi là Pluggable Authentication Modules (PAM) — một hệ thống thư viện chia sẻ dùng cho xác thực (Open Software Foundation RFC 86.0, tháng 10 năm 1995).111 Để xác thực một người dùng, ứng dụng giao người dùng đó cho PAM quyết định xem họ có tự nhận dạng thành công hay không. Nhờ vậy, việc thêm hỗ trợ cho các kỹ thuật xác thực mới — như hai yếu tố và khoá vật lý — trở nên tương đối dễ.1 Ngoài hỗ trợ cơ chế xác thực, PAM còn cung cấp một lượng kiểm soát uỷ quyền hạn chế cho dịch vụ — chẳng hạn nếu bạn muốn từ chối một dịch vụ như cron đối với một số người dùng.1

    Trước kia, mỗi chương trình tự hỏi mật khẩu theo cách riêng. PAM giống một ổ cắm chung: chương trình chỉ việc cắm vào và nói “kiểm tra giúp người này”. Muốn đổi sang vân tay hay khoá USB thì chỉ đổi cái cắm vào ổ, không phải viết lại chương trình. Nhớ nhé: một ổ cắm chung, nhiều kiểu chìa khoá.

    To accommodate flexibility in user authentication, in 1995 Sun Microsystems proposed a new standard called Pluggable Authentication Modules (PAM), a system of shared libraries for authentication (Open Software Foundation RFC 86.0, October 1995).111 To authenticate a user, an application hands the user to PAM to determine whether the user can successfully identify itself. This way it's relatively easy to add support for additional authentication techniques, such as two-factor and physical keys.1 Besides authentication mechanisms, PAM also provides a limited amount of authorization control for services — for example if you'd like to deny a service like cron to certain users.1

    Bạn gặp nó ở đâuWhere you meet it Trong /etc/pam.d: các tên tệp như cron, passwd, sshd chính là danh sách các ứng dụng đã giao việc xác thực cho PAM.1 Mở thư mục /etc/pam.d là thấy danh sách các chương trình dùng chung cái ổ cắm đó. In /etc/pam.d: filenames such as cron, passwd and sshd are the roster of applications that handed authentication to PAM.1

    Mô-đun là gì, về mặt kỹ thuật

    Vì có rất nhiều kịch bản xác thực, PAM dùng một số mô-đun xác thực nạp động. Mỗi mô-đun thực hiện một nhiệm vụ cụ thể và là một đối tượng chia sẻ mà tiến trình có thể nạp động và chạy trong không gian thực thi của nó. Ví dụ, pam_unix.so là mô-đun có thể kiểm tra mật khẩu của người dùng.116

    Ward không tô hồng PAM

    Ông viết rất thẳng: “đây là việc khó, nói nhẹ đi là vậy” — giao diện lập trình không dễ, và không rõ PAM có thật sự giải quyết hết các vấn đề tồn tại hay không.1 Tuy vậy, PAM được hỗ trợ trong gần như mọi chương trình cần xác thực trên hệ Linux, và hầu hết bản phân phối đều dùng PAM; vì nó hoạt động trên nền API xác thực Unix sẵn có, tích hợp hỗ trợ vào một máy khách đòi hỏi rất ít — nếu có — công sức thêm.1

    Nơi tìm cấu hình

    Bạn thường tìm thấy tệp cấu hình ứng dụng của PAM trong thư mục /etc/pam.d; các hệ cũ hơn có thể dùng một tệp duy nhất /etc/pam.conf.117 Hầu hết cài đặt gồm rất nhiều tệp, nên bạn có thể không biết bắt đầu từ đâu; một số tên tệp như cron và passwd tương ứng với các phần hệ thống bạn đã biết.1

  5. pam.conf syntax

    Ba trường một dòng: function type, control argument, module Mỗi dòng luật có ba ô Three fields per line: function type, control argument, module

    Ward lấy một dòng cấu hình mẫu cho chsh (chương trình đổi shell): auth    requisite    pam_shells.so. Dòng này nói rằng shell của người dùng phải được liệt kê trong /etc/shells thì người dùng mới xác thực thành công với chương trình chsh.1 Mỗi dòng cấu hình có ba trường, theo thứ tự: function type (chức năng mà ứng dụng yêu cầu PAM thực hiện — ở đây là auth, nhiệm vụ xác thực người dùng); control argument (điều khiển PAM làm gì sau khi hành động của dòng hiện tại thành công hay thất bại — ở đây là requisite); và module (mô-đun xác thực chạy cho dòng này, quyết định dòng đó thật sự làm gì — ở đây pam_shells.so kiểm tra xem shell hiện tại của người dùng có trong /etc/shells không).11718

    Mỗi dòng luật có ba ô: làm việc gì, nếu đúng/sai thì sao, và ai làm. Đọc từ trái sang phải là hiểu được dòng luật. Nhớ nhé: việc gì — rồi sao — ai làm.

    Ward takes a sample configuration line for chsh (the change-shell program): auth    requisite    pam_shells.so. It says the user's shell must be listed in /etc/shells for the user to authenticate successfully with chsh.1 Each configuration line has three fields, in order: the function type (the function the user application asks PAM to perform — here auth, the task of authenticating the user); the control argument (what PAM does after success or failure of the action for the current line — here requisite); and the module (the authentication module that runs for this line, determining what it actually does — here pam_shells.so checks whether the user's current shell is listed in /etc/shells).11718

    Bạn gặp nó ở đâuWhere you meet it Mở bất kỳ tệp nào trong /etc/pam.d và đọc theo ba cột — cấu hình vốn khó hiểu bỗng trở nên đọc được. Mở một tệp trong /etc/pam.d rồi đọc theo ba cột. Open any file in /etc/pam.d and read it in three columns — the configuration suddenly becomes legible.

    Bốn function type

    Một ứng dụng có thể yêu cầu PAM thực hiện một trong bốn chức năng: auth — xác thực người dùng (xem họ có đúng là người họ nói không); account — kiểm tra trạng thái tài khoản (ví dụ người dùng có được uỷ quyền làm việc gì đó không); session — thực hiện điều gì đó chỉ cho phiên hiện tại của người dùng (như hiển thị thông điệp trong ngày); password — đổi mật khẩu hoặc thông tin xác thực khác của người dùng.117 Ward nhấn mạnh một điều dễ sai: mô-đun và chức năng cùng nhau quyết định hành động của PAM, vì một mô-đun có thể có nhiều loại chức năng — ví dụ pam_unix.so kiểm tra mật khẩu khi thực hiện chức năng auth, nhưng đặt mật khẩu khi thực hiện chức năng password.116

    Ba control argument cú pháp đơn giản

    sufficient: nếu luật này thành công thì xác thực thành công và PAM không cần xem luật nào nữa; nếu thất bại, PAM đi tiếp các luật sau. requisite: nếu thành công thì đi tiếp; nếu thất bại thì xác thực thất bại ngay và PAM không cần xem thêm. required: nếu thành công thì đi tiếp; nếu thất bại, PAM vẫn đi tiếp các luật sau nhưng sẽ luôn trả về xác thực thất bại bất kể kết quả các luật đó.117 Ngoài ra có cú pháp nâng cao đặt trong dấu ngoặc vuông [], cho phép điều khiển phản ứng thủ công dựa trên giá trị trả về cụ thể của mô-đun chứ không chỉ thành công/thất bại; Ward trấn an rằng khi đã hiểu cú pháp đơn giản, bạn sẽ không gặp khó với cú pháp nâng cao.117

    Function ≠ action

    Ward đặt riêng một ghi chú để tránh nhầm hai thuật ngữ: function là mục tiêu ở mức cao — điều ứng dụng muốn PAM làm (ví dụ xác thực một người dùng); còn action là một bước cụ thể PAM thực hiện để đạt mục tiêu đó. Chỉ cần nhớ: ứng dụng gọi function trước, PAM lo phần chi tiết bằng các action.1

  6. stacked rules

    Ngăn xếp luật: bốn dòng của chsh, đọc như một lưu đồ Bốn dòng luật, đi từ trên xuống Stacked rules: chsh's four lines, read as a flowchart

    Một tính năng quan trọng của PAM là các luật xếp chồng (stack): bạn có thể áp dụng nhiều luật khi thực hiện một chức năng — và đó chính là lý do control argument quan trọng, vì thành công hay thất bại của một dòng có thể tác động lên các dòng sau hoặc khiến cả chức năng thành công/thất bại.1 Ngăn xếp mẫu của ông cho chức năng auth của chsh gồm bốn dòng: sufficient pam_rootok.so, requisite pam_shells.so, sufficient pam_unix.so, required pam_deny.so.117

    Máy hỏi lần lượt bốn câu. Nếu bạn là quản trị viên thì qua luôn. Nếu không, xem shell của bạn có hợp lệ không — không hợp lệ thì chặn ngay. Rồi mới hỏi mật khẩu. Nếu tới dòng cuối thì chắc chắn bị từ chối. Nhớ nhé: luật đọc từ trên xuống, dừng ở chỗ đủ kết luận.

    An important PAM feature is that its rules stack: you can apply many rules when performing a function — which is why the control argument matters, since success or failure on one line can affect later lines or decide the whole function.1 His sample stack for chsh's auth function has four lines: sufficient pam_rootok.so, requisite pam_shells.so, sufficient pam_unix.so, required pam_deny.so.117

    Bạn gặp nó ở đâuWhere you meet it Khi root đổi shell cho người khác mà không bị hỏi mật khẩu — đó là dòng pam_rootok.so đang cắt ngắn ngăn xếp. Khi quản trị viên không bị hỏi mật khẩu. When root changes someone's shell without a password prompt — that is pam_rootok.so short-circuiting the stack.

    Bốn bước, theo đúng thứ tự

    (1) pam_rootok.so kiểm tra xem root có phải người đang cố xác thực không; nếu phải, nó thành công ngay và không thử xác thực thêm — vì control argument là sufficient, thành công ở đây là đủ để PAM báo thành công về cho chsh.1 (2) pam_shells.so kiểm tra shell của người dùng có trong /etc/shells; nếu không, mô-đun trả về thất bại và requisite buộc PAM báo thất bại về chsh ngay lập tức.118 (3) pam_unix.so hỏi mật khẩu và kiểm tra; control argument là sufficient nên mật khẩu đúng là đủ để PAM báo thành công.116 (4) pam_deny.so luôn thất bại, và vì control argument là required, PAM báo thất bại về chsh — đây là mặc định cho trường hợp không còn gì để thử.1

    Sắc thái của required

    Ward đóng ngoặc một điểm tinh tế dễ hiểu sai: control argument required không khiến PAM thất bại chức năng ngay lập tức — nó vẫn chạy nốt các dòng còn lại trong ngăn xếp — nhưng PAM sẽ luôn báo thất bại về cho ứng dụng.117

    Đối số của mô-đun

    Mô-đun PAM có thể nhận đối số sau tên mô-đun. Ví dụ bạn hay gặp với pam_unix.so: auth  sufficient  pam_unix.so  nullok — đối số nullok ở đây nói rằng người dùng có thể không có mật khẩu (mặc định sẽ là thất bại nếu người dùng không có mật khẩu).116

  7. PAM and passwords

    PAM và mật khẩu: obscure sha512, và bí ẩn khi kiểm tra Máy xáo mật khẩu bằng cách nào? PAM and passwords: obscure sha512, and the verification mystery

    Do quá trình tiến hoá của việc kiểm tra mật khẩu trên Linux qua nhiều năm, còn lại một số “di tích cấu hình” đôi khi gây bối rối.1 Đầu tiên là tệp /etc/login.defs — tệp cấu hình của bộ shadow password nguyên thuỷ; nó chứa thông tin về thuật toán mã hoá dùng cho /etc/shadow, nhưng hiếm khi được dùng trên hệ có PAM, vì cấu hình PAM đã chứa thông tin đó. Dù vậy, thuật toán trong /etc/login.defs nên khớp với cấu hình PAM, phòng trường hợp hiếm hoi bạn gặp ứng dụng không hỗ trợ PAM.119

    Mật khẩu của bạn không được lưu nguyên; nó bị xáo trộn theo một công thức. Công thức nào thì ghi trong cấu hình. Nhưng khi kiểm tra, máy còn không cần biết công thức — nó cứ thử cho tới khi khớp. Nhớ nhé: máy lưu dấu vết của mật khẩu, không lưu mật khẩu.

    Because Linux password verification evolved over many years, a number of configuration artifacts remain that can cause confusion.1 The first is /etc/login.defs — the configuration file for the original shadow password suite; it holds information about the encryption algorithm used for /etc/shadow, but is rarely used on a system with PAM installed, because the PAM configuration contains that information. Still, the algorithm in /etc/login.defs should match the PAM configuration for the rare case of an application that doesn't support PAM.119

    Bạn gặp nó ở đâuWhere you meet it Chạy grep password.*unix /etc/pam.d/* — cách Ward đề xuất để truy ra tham số đặt mật khẩu trên máy bạn.1 Một lệnh grep là tìm ra công thức xáo mật khẩu của máy mình. Run grep password.*unix /etc/pam.d/* — Ward's suggested way to track down your machine's password-setting parameters.1

    Hai đường PAM chạm vào mật khẩu

    Có hai cách PAM tương tác với mật khẩu: chức năng auth (để kiểm tra một mật khẩu) và chức năng password (để đặt một mật khẩu).1 Tham số đặt mật khẩu dễ truy nhất — grep ra, các dòng khớp sẽ chứa pam_unix.so và trông như: password  sufficient  pam_unix.so obscure sha512. Đối số obscure và sha512 bảo PAM làm gì khi đặt mật khẩu: trước hết PAM kiểm tra xem mật khẩu có đủ “obscure” không (tức là không quá giống mật khẩu cũ, cùng vài điều kiện khác), rồi dùng thuật toán SHA512 để mã hoá mật khẩu mới.116

    Còn khi kiểm tra thì sao?

    Đây là chỗ Ward kể một sự thật ít ai nói ra. Cấu hình không cho bạn biết gì cả — không có đối số mã hoá nào cho pam_unix.so ở chức năng auth, và các trang hướng dẫn cũng không nói gì. Hoá ra (tại thời điểm sách viết) pam_unix.so chỉ đơn giản là đoán thuật toán, thường bằng cách nhờ thư viện libcrypt làm việc bẩn: thử một loạt thứ cho tới khi có cái khớp hoặc hết cái để thử. Vì vậy bạn thường không phải lo về thuật toán mã hoá khi xác minh.116

    Sáu mẹo cấu hình PAM

    Ward kết mục bằng vài lời khuyên thực dụng: để biết có những mô-đun PAM nào trên máy, thử man -k pam_ (chú ý dấu gạch dưới); khó lần ra vị trí mô-đun thì thử locate pam_unix.so. Trang hướng dẫn chứa các chức năng và đối số của từng mô-đun. Nhiều bản phân phối tự sinh một số tệp cấu hình PAM, nên sửa trực tiếp trong /etc/pam.d có thể không khôn ngoan — hãy đọc phần chú thích trong tệp trước khi sửa, nếu là tệp tự sinh thì chú thích sẽ cho biết nó đến từ đâu. Tệp /etc/pam.d/other định nghĩa cấu hình mặc định cho mọi ứng dụng thiếu tệp cấu hình riêng, và mặc định đó thường là từ chối tất cả. Có nhiều cách nhúng tệp cấu hình khác: cú pháp @include nạp cả một tệp, nhưng bạn cũng có thể dùng control argument để chỉ nạp cấu hình cho một chức năng — cách dùng khác nhau giữa các bản phân phối. Và cuối cùng: cấu hình PAM không dừng ở đối số mô-đun — một số mô-đun có thể truy cập tệp bổ sung trong /etc/security, thường để cấu hình hạn chế theo từng người dùng.117

Cụm khái niệm 04 Concept cluster 04

Thời gian, và việc giao cho máy làm lúc bạn không ngồi đó Đồng hồ của máy và cái báo thức giao việc Time, and handing work to the machine while you're away

Máy Unix phụ thuộc vào việc giữ giờ chính xác. Nhân duy trì system clock — chiếc đồng hồ được tra cứu khi bạn chạy lệnh như date.1 Bạn cũng có thể đặt đồng hồ hệ thống bằng date, nhưng Ward nói thường đó là ý tưởng tồi vì bạn sẽ không bao giờ đặt đúng chính xác — đồng hồ hệ thống nên gần giờ đúng nhất có thể.1 Phần cứng PC có một đồng hồ thời gian thực (RTC) chạy bằng pin; RTC không phải chiếc đồng hồ tốt nhất thế giới nhưng vẫn hơn không có gì, và nhân thường đặt giờ của nó dựa trên RTC lúc khởi động.1

Máy có hai cái đồng hồ. Một cái chạy bằng pin, vẫn tích tắc cả khi tắt máy. Một cái nằm trong nhân, chạy khi máy bật. Lúc bật máy, cái trong nhân nhìn cái chạy pin để biết mấy giờ. Nhớ nhé: đồng hồ pin để nhớ, đồng hồ nhân để chạy.

Unix machines depend on accurate timekeeping. The kernel maintains the system clock — the clock consulted when you run commands like date.1 You can set the system clock with date, but Ward says it's usually a bad idea because you'll never get the time exactly right — your system clock should be as close to correct as possible.1 PC hardware has a battery-backed real-time clock (RTC); the RTC isn't the best clock in the world but it's better than nothing, and the kernel usually sets its time from the RTC at boot.1

Giữ RTC ở UTC. Ward khuyên giữ đồng hồ phần cứng theo Universal Coordinated Time (UTC) để tránh rắc rối với múi giờ hoặc hiệu chỉnh giờ mùa hè, và bạn đặt RTC theo đồng hồ UTC của nhân bằng hwclock --systohc --utc.120 Nhưng ông cũng nói một sự thật hơi trái trực giác: nhân còn giữ giờ tệ hơn cả RTC, và vì máy Unix thường chạy liên tục hàng tháng hay hàng năm sau một lần khởi động, chúng có xu hướng phát sinh time drift — độ lệch hiện thời giữa giờ của nhân và giờ thật (theo một đồng hồ nguyên tử hoặc đồng hồ rất chính xác khác).1 Và bạn không nên sửa drift bằng hwclock, vì các sự kiện hệ thống dựa trên thời gian có thể bị mất hoặc méo; bạn có thể chạy tiện ích như adjtimex để cập nhật đồng hồ một cách mượt mà dựa trên RTC, nhưng thường tốt nhất là giữ giờ đúng bằng một daemon thời gian mạng.1

Giờ của nhân là một con số. Đồng hồ hệ thống của nhân biểu diễn thời gian hiện tại bằng số giây kể từ 12:00 nửa đêm ngày 1 tháng 1 năm 1970, UTC. Để thấy con số đó ngay lúc này, chạy date +%s.1 Để đổi nó thành thứ con người đọc được, các chương trình không gian người dùng chuyển sang giờ địa phương và bù cho giờ mùa hè cùng mọi tình huống kỳ quặc khác.1

Máy đếm giây. Với máy, “bây giờ” chỉ là một con số rất lớn: số giây đã trôi qua kể từ đầu năm 1970. Việc đổi số đó ra “8 giờ sáng thứ Ba” là của phần mềm, không phải của nhân. Nhớ nhé: nhân đếm giây, phần mềm mới nói giờ.

Kernel time is one number. The kernel's system clock represents the current time as the number of seconds since 12:00 midnight on January 1, 1970, UTC. To see that number right now, run date +%s.1 To convert it into something humans can read, user-space programs change it to local time and compensate for daylight saving time and other strange circumstances.1

15 09 * * * /home/juser/bin/spmake
 │  │  │ │ │
 │  │  │ │ └ thứ trong tuần 0–7
 │  │  │ └── tháng 1–12
 │  │  └──── ngày 1–31
 │  └────── giờ 0–23
 └───────── phút 0–59

phút giờ ngày tháng thứ lệnh
15   09   *    *    *
= 9 giờ 15 mỗi ngày

15 09 * * * /home/juser/bin/spmake
 │  │  │ │ │
 │  │  │ │ └ day of week 0–7
 │  │  │ └── month 1–12
 │  │  └──── day of month 1–31
 │  └────── hour 0–23
 └───────── minute 0–59

  1. time zones

    Múi giờ: /etc/localtime là một tệp nhị phân Máy biết bạn ở đâu nhờ một tệp Time zones: /etc/localtime is a binary file

    Múi giờ địa phương được điều khiển bởi tệp /etc/localtime — và Ward đóng ngoặc một lời khuyên rất thực tế: “đừng bận tâm cố mở nó ra xem; đó là tệp nhị phân”.1 Các tệp múi giờ trên hệ thống của bạn nằm trong /usr/share/zoneinfo, thư mục này chứa rất nhiều múi giờ và các bí danh của chúng.1 Để đặt múi giờ thủ công, hoặc sao chép một tệp từ /usr/share/zoneinfo sang /etc/localtime (hoặc tạo liên kết tượng trưng), hoặc đổi bằng công cụ múi giờ của bản phân phối; chương trình dòng lệnh tzselect có thể giúp bạn xác định tệp múi giờ.1

    Máy cần biết bạn ở múi giờ nào thì mới hiện đúng giờ địa phương. Thông tin đó nằm trong một tệp nhỏ; tệp này máy đọc được chứ người đọc thì thành ký tự loằng ngoằng. Nhớ nhé: giờ trong máy là giờ thế giới, giờ trên màn hình là giờ của bạn.

    The local time zone is controlled by the file /etc/localtime — and Ward adds a practical parenthesis: "don't bother trying to look at it; it's a binary file."1 The time zone files on your system are in /usr/share/zoneinfo, a directory containing a lot of time zones and aliases for them.1 To set your time zone manually, either copy one of those files to /etc/localtime (or make a symbolic link) or use your distribution's time zone tool; the command-line program tzselect may help you identify a time zone file.1

    Bạn gặp nó ở đâuWhere you meet it Dùng một múi giờ khác cho một phiên shell: export TZ=US/Central rồi date. Hoặc cho đúng một lệnh: TZ=US/Central date.1 Muốn xem giờ nơi khác: đặt biến TZ rồi gõ date. To use another time zone for one shell session: export TZ=US/Central then date. Or for exactly one command: TZ=US/Central date.1

    TZ là một biến môi trường bình thường

    Ward xử lý múi giờ theo phiên bằng đúng cơ chế biến môi trường đã dựng ở Chương 2: đặt TZ thành tên một tệp trong /usr/share/zoneinfo, và như với các biến môi trường khác, bạn cũng có thể đặt nó chỉ cho thời lượng của một lệnh duy nhất.1 Đây là một ví dụ đẹp về nguyên tắc xuyên suốt sách: một cơ chế chung, dùng lại ở nhiều chỗ, thay vì một cơ chế riêng cho mỗi chỗ.

    Một câu đùa có thật trong sách

    Khi giải thích vì sao chương trình không gian người dùng phải bù trừ đủ thứ, Ward viết rằng chúng phải bù cho giờ mùa hè “và mọi tình huống kỳ quặc khác (chẳng hạn sống ở Indiana)”.1 Đằng sau câu đùa là một điểm kỹ thuật thật: quy tắc múi giờ là dữ liệu thay đổi theo chính trị và địa phương, nên chúng được đóng gói thành tệp dữ liệu chứ không viết cứng vào mã.

  2. network time

    Thời gian mạng: timesyncd, ntpd, chronyd Máy hỏi giờ từ internet Network time: timesyncd, ntpd, chronyd

    Nếu máy bạn kết nối internet thường trực, bạn có thể chạy một daemon Network Time Protocol (NTP) để duy trì giờ bằng một máy chủ từ xa. Việc này từng do daemon ntpd đảm nhiệm, nhưng như nhiều dịch vụ khác, systemd đã thay nó bằng gói riêng tên timesyncd.121 Hầu hết bản phân phối Linux đều kèm timesyncd và nó được bật theo mặc định; Ward nói bạn không cần cấu hình gì, nhưng nếu quan tâm thì trang timesyncd.conf(5) sẽ giúp — thứ hay bị ghi đè nhất là (các) máy chủ thời gian từ xa.121

    Đồng hồ nào rồi cũng chạy sai dần. Cách chữa: thỉnh thoảng hỏi giờ từ những chiếc đồng hồ rất chuẩn trên internet. Máy của bạn gần như chắc chắn đã tự làm việc này rồi. Nhớ nhé: đồng hồ hay sai, nên phải hỏi lại người giữ giờ chuẩn.

    If your machine is permanently connected to the internet, you can run a Network Time Protocol (NTP) daemon to maintain the time using a remote server. This was once handled by ntpd, but as with many other services, systemd has replaced it with its own package named timesyncd.121 Most Linux distributions include timesyncd and it's enabled by default; Ward says you shouldn't need to configure it, but if you're interested the timesyncd.conf(5) manual page helps — the most common override is to change the remote time server(s).121

    Bạn gặp nó ở đâuWhere you meet it Mỗi lần máy bạn ngủ vài ngày rồi thức dậy vẫn đúng giờ — đó là một daemon thời gian mạng đã làm việc lặng lẽ. Khi máy tắt lâu ngày bật lên vẫn đúng giờ. Every time your machine sleeps for days and wakes up with the right time — a network time daemon did that quietly.

    Khi muốn dùng ntpd, và khi không có mạng thường trực

    Nếu bạn muốn chạy ntpd thay thế, bạn sẽ cần tắt timesyncd nếu đã cài nó; Ward chỉ bạn tới ntppool.org để xem hướng dẫn — trang này cũng hữu ích nếu bạn vẫn muốn dùng timesyncd với máy chủ khác.122 Còn nếu máy không có kết nối internet thường trực, bạn có thể dùng một daemon như chronyd để duy trì giờ trong những lúc mất kết nối.123

    Đặt đồng hồ phần cứng theo giờ mạng

    Bạn cũng có thể đặt đồng hồ phần cứng dựa trên giờ mạng, để giúp hệ thống giữ được sự nhất quán thời gian khi khởi động lại. Nhiều bản phân phối làm tự động; muốn làm thủ công, hãy chắc rằng giờ hệ thống đã được đặt từ mạng rồi chạy hwclock --systohc --utc.120 Đây đúng là lệnh đã xuất hiện ở đầu mục — lần này dùng với ý nghĩa ngược lại: không phải “tin RTC”, mà là “dạy lại RTC”.

  3. cron

    cron: năm trường thời gian, một lệnh Báo thức năm ô cron: five time fields and a command

    Có hai cách chạy chương trình theo lịch lặp lại: cron và timer unit của systemd; khả năng này là thiết yếu để tự động hoá các tác vụ bảo trì hệ thống — một ví dụ chính là các tiện ích xoay vòng nhật ký để ổ cứng bạn không đầy ứ tệp cũ.1 Chương trình chạy qua cron gọi là một cron job; để cài đặt, bạn tạo một dòng trong tệp crontab của mình, thường bằng lệnh crontab.1 Ví dụ của Ward: 15 09 * * * /home/juser/bin/spmake — chạy lệnh đó hằng ngày lúc 9:15 sáng theo múi giờ địa phương.124

    Bạn muốn máy làm một việc mỗi ngày vào đúng giờ? Viết một dòng gồm năm con số (phút, giờ, ngày, tháng, thứ) rồi đến tên việc cần làm. Dấu sao nghĩa là “mọi giá trị”. Nhớ nhé: năm ô thời gian, rồi mới tới việc.

    There are two ways to run programs on a repeating schedule: cron and systemd timer units; this ability is vital to automating system maintenance tasks — one example being logfile rotation utilities that keep your hard drive from filling with old logs.1 A program run through cron is called a cron job; to install one you create an entry line in your crontab file, usually with the crontab command.1 Ward's example: 15 09 * * * /home/juser/bin/spmake — runs that command daily at 9:15 AM in the local time zone.124

    Bạn gặp nó ở đâuWhere you meet it crontab -l liệt kê cron job của bạn, crontab -e sửa và cài trong một bước, crontab -r xoá crontab.1 Ba lệnh: -l để xem, -e để sửa, -r để xoá. crontab -l lists your cron jobs, crontab -e edits and installs in one step, crontab -r removes the crontab.1

    Năm trường, theo thứ tự

    Năm trường đầu dòng, ngăn bởi khoảng trắng, chỉ định thời điểm: phút (0–59), giờ (0–23), ngày trong tháng (1–31), tháng (1–12), và thứ trong tuần (0–7, trong đó 0 và 7 đều là Chủ nhật).124 Một dấu * ở bất kỳ trường nào nghĩa là khớp mọi giá trị — ví dụ ở trên chạy hằng ngày vì ba trường ngày/tháng/thứ đều là sao, mà cron đọc là “chạy việc này mỗi ngày, mỗi tháng, mỗi thứ trong tuần”.1 Bạn có thể chọn nhiều giá trị cho một trường: để chạy vào ngày 5 và 14 hằng tháng, đặt 5,14 vào trường thứ ba.1

    Đầu ra của cron job đi đâu

    Nếu một cron job sinh đầu ra chuẩn, hoặc lỗi, hoặc thoát bất thường, cron nên gửi thông tin này qua email tới chủ sở hữu của job (giả sử email hoạt động trên hệ thống của bạn). Ward gợi ý: chuyển hướng đầu ra sang /dev/null hoặc một tệp nhật ký khác nếu bạn thấy email phiền.124 Muốn biết đầy đủ về định dạng, ông chỉ tới trang crontab(5).124

    Crontab của người dùng và crontab hệ thống

    Mỗi người dùng có thể có crontab riêng, nên mỗi hệ thống có thể có nhiều crontab, thường nằm trong /var/spool/cron/crontabs; người dùng thường không ghi được vào thư mục này — chính lệnh crontab mới cài, liệt kê, sửa và xoá crontab của một người dùng.1 Cách cài dễ nhất là đặt các mục vào một tệp rồi dùng crontab file; lệnh crontab sẽ kiểm tra định dạng tệp để chắc rằng bạn không mắc lỗi.1 Với tác vụ hệ thống chạy dưới siêu người dùng, các bản phân phối Linux thường có tệp /etc/crontab cho toàn hệ thống; bạn không dùng lệnh crontab để sửa tệp này, và định dạng của nó hơi khác: trước lệnh cần chạy có thêm một trường chỉ định người dùng sẽ chạy job đó.1 Ví dụ của ông: 42 6 * * * root /usr/local/bin/cleansystem > /dev/null 2>&1 chạy lúc 6:42 sáng dưới quyền siêu người dùng.1 Một số bản phân phối còn để thêm crontab hệ thống trong /etc/cron.d (tên tệp tuỳ ý nhưng cùng định dạng với /etc/crontab), và có thể có các thư mục như /etc/cron.daily — nhưng tệp ở đó thường là kịch bản được một cron job cụ thể trong /etc/crontab hay /etc/cron.d chạy; Ward thừa nhận đôi khi khá rối để lần ra job nằm ở đâu và chạy lúc nào.1

  4. timer units

    Timer unit: hai tệp, vì timer không biết gì về công việc Cái báo thức và việc cần làm là hai thứ tách rời Timer units: two files, because a timer knows nothing about the task

    Với một tác vụ hoàn toàn mới, bạn phải tạo hai unit: một timer unit và một service unit. Ward giải thích lý do rất rõ: timer unit không chứa bất kỳ chi tiết nào về công việc cần làm — nó chỉ là một cơ chế kích hoạt để chạy một service unit (hoặc về mặt khái niệm, một loại unit khác, nhưng dùng phổ biến nhất là service unit).125 Cặp ví dụ của ông là loggertest.timer với OnCalendar=*-*-* *:00,20,40 và Unit=loggertest.service, đặt trong /etc/systemd/system như các tệp unit tuỳ chỉnh khác; timer này chạy mỗi 20 phút: đầu mỗi giờ, cùng phút 20 và phút 40.125

    Cái báo thức chỉ biết reo, nó không biết phải làm gì. Nên ta viết hai tờ giấy: một tờ ghi “reo lúc mấy giờ”, một tờ ghi “reo xong thì làm việc này”. Nhớ nhé: một tờ cho lúc nào, một tờ cho làm gì.

    For an entirely new task you must create two units: a timer unit and a service unit. Ward's reason is clear: a timer unit contains no specifics about the task to perform — it's just an activation mechanism to run a service unit (or conceptually another kind of unit, though service units are the most common usage).125 His example pair is loggertest.timer with OnCalendar=*-*-* *:00,20,40 and Unit=loggertest.service, placed in /etc/systemd/system like other custom unit files; the timer runs every 20 minutes: at the top of each hour plus 20 and 40 minutes past.125

    Bạn gặp nó ở đâuWhere you meet it Trên bất kỳ bản phân phối hiện đại nào: nhiều tác vụ bảo trì định kỳ mức hệ thống nay đã chuyển sang timer unit.1 Máy mới bây giờ hay dùng cách này thay cho cron. On any modern distribution: many system-level periodic maintenance tasks have now moved to timer units.1

    Cú pháp OnCalendar

    Định dạng thời gian của OnCalendar là năm-tháng-ngày giờ:phút:giây, trong đó trường giây là tuỳ chọn. Như với cron, * đóng vai ký tự đại diện và dấu phẩy cho phép nhiều giá trị; cú pháp chu kỳ / cũng hợp lệ — trong ví dụ trên bạn có thể đổi *:00,20,40 thành *:00/20 (mỗi 20 phút) để có cùng hiệu ứng.126 Ward ghi chú rằng cú pháp thời gian trong trường OnCalendar có rất nhiều lối tắt và biến thể, và chỉ bạn tới mục Calendar Events trong systemd.time(7) để xem danh sách đầy đủ.126

    Vì sao service unit dùng Type=oneshot

    Service unit đi kèm (loggertest.service) có Type=oneshot và ExecStart=/usr/bin/logger -p local3.debug I\'m a logger; phần cốt lõi là dòng ExecStart — lệnh mà dịch vụ chạy khi được kích hoạt, ở đây là gửi một thông điệp tới nhật ký hệ thống.1 Kiểu oneshot nghĩa là dịch vụ được kỳ vọng chạy rồi thoát, và systemd sẽ không coi dịch vụ đã khởi động cho tới khi lệnh trong ExecStart hoàn tất. Ward nêu ba lợi thế của điều này với timer: bạn có thể chỉ định nhiều lệnh ExecStart trong một tệp unit (các kiểu service unit khác ở Chương 6 không cho phép); dễ kiểm soát thứ tự phụ thuộc chặt chẽ khi kích hoạt unit khác bằng Wants và Before; và bạn có bản ghi tốt hơn về thời điểm bắt đầu và kết thúc của unit trong journal.125 Bạn cũng không bắt buộc phải nêu tên service trong timer bằng tuỳ chọn Unit, vì systemd tự tìm tệp .service cùng tên cơ sở với tệp timer.125

    Một cuộc đua nho nhỏ đáng biết

    Ward kèm một ghi chú rất thực tế về chính ví dụ của ông: unit dùng logger để gửi một mục tới syslog và journal, nhưng unit có thể kết thúc trước khi journald kịp nhận thông điệp. Đó là một race condition: nếu unit hoàn tất quá nhanh, journald không tra được unit gắn với thông điệp syslog (việc tra này làm theo process ID), nên thông điệp ghi vào journal có thể thiếu trường unit — khiến lệnh lọc như journalctl -f -u loggertest.service không hiện được thông điệp đó. Với các dịch vụ chạy lâu hơn, đây thường không phải vấn đề.1

  5. cron vs timer units

    cron hay timer unit? Ba lợi thế đối bốn lợi thế Cái cũ và cái mới, mỗi cái hay một kiểu cron or timer units? Three advantages against four

    cron là một trong những thành phần lâu đời nhất của hệ Linux — nó đã tồn tại hàng thập kỷ (có trước cả Linux), và định dạng cấu hình của nó gần như không đổi trong nhiều năm; khi một thứ cũ đến mức đó, nó trở thành mồi ngon cho việc thay thế.1 Timer unit trông như một sự thay thế hợp lý, và quả thật nhiều bản phân phối đã chuyển các tác vụ bảo trì định kỳ mức hệ thống sang timer unit. Nhưng hoá ra cron có vài lợi thế: cấu hình đơn giản hơn, tương thích với nhiều dịch vụ bên thứ ba, và dễ hơn cho người dùng tự cài tác vụ của mình.1

    Cái cũ dễ dùng và ai cũng biết. Cái mới ghi chép kỹ hơn và hẹn giờ linh hoạt hơn. Không cái nào “thắng” — chọn cái hợp việc của bạn. Nhớ nhé: cũ chưa chắc dở, mới chưa chắc hơn.

    cron is one of the oldest components of a Linux system — it's been around for decades (predating Linux itself), and its configuration format hasn't changed much in many years; when something gets that old it becomes fodder for replacement.1 Timer units look like a logical replacement, and indeed many distributions have moved system-level periodic maintenance to them. But it turns out cron has advantages: simpler configuration, compatibility with many third-party services, and being easier for users to install their own tasks.1

    Bạn gặp nó ở đâuWhere you meet it Trên một máy hiện đại, hai cơ chế thường cùng chạy: tác vụ hệ thống ở timer unit, tác vụ cá nhân ở crontab. Máy mới thường dùng cả hai cùng lúc. On a modern machine both mechanisms usually run side by side: system tasks in timer units, personal tasks in a crontab.

    Bốn lợi thế của timer unit

    Ward liệt kê: theo dõi tốt hơn các tiến trình gắn với tác vụ/unit nhờ cgroup; theo dõi xuất sắc thông tin chẩn đoán trong journal; thêm tuỳ chọn về thời điểm và tần suất kích hoạt; và khả năng dùng các phụ thuộc và cơ chế kích hoạt của systemd.125 Ba lợi thế đầu đều là hệ quả trực tiếp của việc systemd quản lý tiến trình theo cgroup — cùng cơ chế đã xuất hiện ở Chương 6.

    Dự đoán của Ward

    Ông không kết luận rằng cron sẽ chết. “Có lẽ một ngày nào đó sẽ có một lớp tương thích cho cron job, giống như với mount unit và /etc/fstab. Tuy nhiên, riêng chuyện cấu hình đã là lý do khiến khó có khả năng định dạng cron sẽ biến mất sớm.”1 Ông cũng ghi chú rằng tiện ích systemd-run có cho phép tạo timer unit và service đi kèm mà không cần viết tệp unit, nhưng cách quản lý và hiện thực khác biệt đủ nhiều để nhiều người dùng có lẽ vẫn thích cron hơn.127

  6. at & transient timers

    Việc chạy một lần: at, và systemd-run thay thế Hẹn máy làm một việc, đúng một lần One-time tasks: at, and its systemd-run equivalent

    Để chạy một việc một lần trong tương lai mà không dùng cron, hãy dùng dịch vụ at: ví dụ để chạy myjob lúc 10:30 tối, gõ at 22:30 rồi nhập lệnh ở dấu nhắc at>, kết thúc đầu vào bằng CTRL-D (tiện ích at đọc lệnh từ đầu vào chuẩn).128 Kiểm tra việc đã được lên lịch chưa bằng atq, gỡ bằng atrm; bạn cũng có thể hẹn nhiều ngày trong tương lai bằng cách thêm ngày theo định dạng DD.MM.YY — ví dụ at 22:30 30.09.15.1 Ward kết gọn: “không còn gì nhiều ở lệnh at; tuy không hay được dùng, nó có thể vô giá khi bạn thật sự cần”.1

    Đôi khi bạn chỉ cần máy làm một việc một lần, chứ không phải mỗi ngày. Khi đó dùng lệnh at: nói giờ, nói việc, xong. Nhớ nhé: cron là việc lặp lại, at là việc một lần.

    To run a job once in the future without cron, use the at service: to run myjob at 10:30 PM, type at 22:30, enter the command at the at> prompt, and end the input with CTRL-D (at reads commands from standard input).128 Check that the job is scheduled with atq, remove it with atrm; you can also schedule days into the future by adding the date in DD.MM.YY format — for example at 22:30 30.09.15.1 Ward wraps up: there isn't much else to at; though it isn't used that often, it can be invaluable when the need does arise.1

    Bạn gặp nó ở đâuWhere you meet it “Khởi động lại dịch vụ này lúc 2 giờ sáng, đúng một lần” — đó chính xác là công việc của at. Khi cần máy làm giúp một việc lúc bạn đang ngủ. "Restart this service at 2 AM, just once" — that is precisely at's job.

    Timer unit tạm thời bằng systemd-run

    Bạn có thể dùng timer unit của systemd thay cho at; những timer này dễ tạo hơn nhiều so với timer unit định kỳ ở trên và chạy ngay trên dòng lệnh: # systemd-run --on-calendar='2022-08-14 18:00' /bin/echo this is a test. Lệnh này tạo một timer unit tạm thời (transient) mà bạn có thể xem bằng lệnh systemctl list-timers quen thuộc.127 Nếu không quan tâm tới một thời điểm cụ thể, bạn có thể chỉ định độ lệch thời gian bằng --on-active — ví dụ --on-active=30m cho 30 phút nữa.127

    Cái bẫy của --on-calendar

    Ward cảnh báo rõ: khi dùng --on-calendar, điều quan trọng là bạn phải bao gồm cả một ngày lịch (trong tương lai) lẫn giờ. Nếu không, timer và service unit sẽ ở lại, và timer sẽ chạy service mỗi ngày vào giờ đã chỉ định — y như khi bạn tạo một timer unit bình thường. Cú pháp của tuỳ chọn này giống hệt tuỳ chọn OnCalendar trong tệp timer unit.127

    Timer unit chạy dưới người dùng thường

    Mọi timer unit ở trên đều chạy dưới root, nhưng bạn cũng có thể tạo timer unit với tư cách người dùng thường bằng cách thêm tuỳ chọn --user vào systemd-run.127 Có một cái bẫy: nếu bạn đăng xuất trước khi unit chạy, unit sẽ không khởi động; và nếu bạn đăng xuất trước khi unit hoàn tất, unit bị chấm dứt. Lý do là systemd có một trình quản lý người dùng gắn với mỗi người dùng đang đăng nhập, và nó cần thiết để chạy timer unit.1 Cách bảo systemd giữ trình quản lý người dùng lại sau khi bạn đăng xuất là loginctl enable-linger; với tư cách root, bạn cũng có thể bật trình quản lý cho một người dùng khác bằng loginctl enable-linger user.129

Đính chính Corrections

Bốn ngộ nhận mà người đọc lần đầu hay mắc Bốn chỗ hay hiểu nhầm Four misconceptions first readers hit

Phần này thuộc mức đọc Đầy đủ: nó đối chiếu điều người đọc thường nghĩ với điều bản văn thật sự nói.

Phần này hơi khó, bạn có thể bỏ qua và quay lại sau. Nhớ nhé: hiểu chậm mà chắc vẫn hơn.

This block belongs to the Đầy đủ (full) reading level: it sets what readers usually assume against what the text actually says.

“/etc/passwd chứa mật khẩu” "/etc/passwd contains passwords"

Ngộ nhận: cái tên nói lên tất cả — tệp này giữ mật khẩu của người dùng.

Bản văn nói: trường thứ hai là mật khẩu mã hoá, “hay ít nhất là trường từng dành cho mật khẩu”; trên hầu hết hệ Linux mật khẩu không còn lưu ở đó mà ở tệp shadow, và một chữ x chính là dấu hiệu của điều đó.18 Hơn nữa, ngay cả trong shadow thì trường ấy không phải mật khẩu mà là một dẫn xuất của nó — mật khẩu Unix không bao giờ được lưu dạng văn bản rõ.1

Misconception: the name says it all — this file holds users' passwords.

The text says: the second field is the encrypted password, "or at least what was once the field for the password"; on most Linux systems the password is no longer stored there but in the shadow file, and an x is exactly that signal.18 And even in shadow, that field is not the password but a derivation of it — Unix passwords are never stored as clear text.1

“Tiến trình chạy dưới một người dùng duy nhất” "A process runs as one single user"

Ngộ nhận: mỗi tiến trình có đúng một chủ, và ps hiện ra người đó.

Bản văn nói: thật ra mỗi tiến trình có nhiều hơn một user ID — effective, real, saved, và cả filesystem UID hiếm dùng.19 ps mặc định chỉ hiện euid vì với hầu hết tiến trình euid và ruid trùng nhau; muốn thấy cả hai, phải yêu cầu rõ bằng ps -eo pid,euser,ruser,comm.1 Ward nói thẳng rằng nhầm lẫn này lớn tới mức “rất nhiều tài liệu về quyền sở hữu tiến trình là sai”.1

Misconception: each process has exactly one owner, and ps shows it.

The text says: in reality every process has more than one user ID — effective, real, saved, plus the rarely used filesystem UID.19 ps shows only the euid by default because for most processes euid and ruid are the same; to see both you must ask explicitly with ps -eo pid,euser,ruser,comm.1 Ward says the confusion runs so deep that "a lot of documentation regarding process ownership is incorrect."1

“required nghĩa là thất bại thì dừng ngay” "required means it stops on failure"

Ngộ nhận: trong PAM, required là luật bắt buộc, nên hỏng ở đó là cả chuỗi dừng lại.

Bản văn nói: required không khiến PAM thất bại chức năng ngay lập tức — PAM vẫn chạy nốt các dòng còn lại trên ngăn xếp — nhưng nó sẽ luôn báo thất bại về cho ứng dụng.117 Luật dừng ngay khi thất bại là requisite.1

Misconception: in PAM, required is the mandatory rule, so a failure there stops the chain.

The text says: a required control argument does not cause PAM to fail its function immediately — it will run any lines left on its stack — but PAM will always report failure back to the application.117 The rule that stops immediately on failure is requisite.1

“systemd đã thay thế cron” "systemd has replaced cron"

Ngộ nhận: timer unit là bản nâng cấp, nên cron đã lỗi thời và sắp biến mất.

Bản văn nói: Ward liệt kê lợi thế của cả hai bên — cron được ba điểm (cấu hình đơn giản hơn, tương thích nhiều dịch vụ bên thứ ba, dễ cho người dùng tự cài tác vụ), timer unit được bốn (theo dõi tiến trình bằng cgroup, chẩn đoán trong journal, nhiều tuỳ chọn thời gian hơn, dùng được phụ thuộc systemd) — rồi kết luận rằng “riêng chuyện cấu hình đã là lý do khiến khó có khả năng định dạng cron sẽ biến mất sớm”.1

Misconception: timer units are the upgrade, so cron is obsolete and on its way out.

The text says: Ward lists advantages on both sides — three for cron (simpler configuration, compatibility with many third-party services, easier for users to install their own tasks) and four for timer units (cgroup process tracking, journal diagnostics, more activation-time options, systemd dependencies) — then concludes that "configuration alone is a reason why it's unlikely that the cron format will go away any time soon."1

Tự kiểm tra Self-check

Bạn đã nắm được cấu hình hệ thống chưa? Thử trả lời xem nào Do you have system configuration yet?

Trả lời bằng lời của bạn, không tra sách. Nếu một câu khiến bạn ngập ngừng, đó chính là mục bạn nên đọc lại.

Thử trả lời miệng thôi, không cần giở lại. Câu nào bí thì quay lại đọc phần đó nhé. Nhớ nhé: chỗ bí chính là chỗ cần học.

Answer in your own words, without looking back. Whichever question makes you hesitate points at the section you should reread.

  1. Ba bước Ward đề xuất để kiểm tra bộ ghi nhật ký của một máy lạ là gì?

    Gợi ý sâu hơn: nêu thêm hai tệp trong /var/log không do daemon syslog tạo ra.

  2. Vì sao tail -f không dùng được với journald, và cái gì thay thế nó?

    Gợi ý sâu hơn: journald lưu nhật ký ở đâu, và dưới định dạng gì?

  3. Facility, severity và priority quan hệ với nhau thế nào? Mức 0 và mức 7 tên là gì?

    Gợi ý sâu hơn: khi chuyển sang thế giới journald, thuật ngữ nào đổi tên?

  4. Kể bảy trường của một dòng /etc/passwd, và cho biết chữ x ở trường thứ hai nghĩa là gì.

    Gợi ý sâu hơn: một dấu * ở đó khác gì, và hai dấu hai chấm liền nhau nguy hiểm ra sao?

  5. Vì sao passwd phải là tệp thực thi suid-root, còn sửa /etc/passwd bằng trình soạn thảo lại là ý tưởng tồi?

    Gợi ý sâu hơn: chương trình nào khoá và sao lưu tệp giúp bạn khi buộc phải sửa tay?

  6. euid và ruid khác nhau ở điểm nào — và cái nào quyết định ai được kill tiến trình?

    Gợi ý sâu hơn: vì sao bạn vẫn phải dùng sudo để kill thứ mình đã chạy bằng sudo?

  7. Nhận dạng, xác thực và uỷ quyền khác nhau thế nào? Nhân biết cái nào trong ba cái đó?

    Gợi ý sâu hơn: UID nào là UID duy nhất có ý nghĩa đặc biệt với nhân?

  8. Một dòng cấu hình PAM có ba trường nào, và ba control argument đơn giản khác nhau ra sao?

    Gợi ý sâu hơn: đi lại bốn bước trong ngăn xếp auth của chsh, từ pam_rootok.so tới pam_deny.so.

  9. Đồng hồ hệ thống của nhân biểu diễn thời gian như thế nào, và ai đổi nó thành giờ địa phương?

    Gợi ý sâu hơn: vì sao không nên sửa time drift bằng hwclock?

  10. Năm trường thời gian của một dòng crontab là gì, theo đúng thứ tự?

    Gợi ý sâu hơn: /etc/crontab khác crontab của người dùng ở trường nào?

  11. Vì sao một tác vụ định kỳ bằng timer unit cần hai tệp unit chứ không phải một?

    Gợi ý sâu hơn: Type=oneshot mang lại ba lợi thế nào cho timer?

  12. Nếu bạn tạo một timer unit bằng systemd-run --user rồi đăng xuất, chuyện gì xảy ra — và cách khắc phục?

    Gợi ý sâu hơn: vì sao quên ngày trong --on-calendar lại biến việc một lần thành việc hằng ngày?

  1. Máy ghi “nhật ký” để làm gì? Khi máy hỏng thì nên mở cái gì ra trước?

  2. Tệp nào chứa danh sách người dùng của máy? Mỗi dòng có mấy ô?

  3. Vì sao mật khẩu được cất sang một tệp khác mà người thường không đọc được?

  4. “Vai đang đóng” và “người thật đứng sau” của một chương trình khác nhau chỗ nào?

  5. PAM giống cái gì? Vì sao có nó thì thêm kiểu đăng nhập mới dễ hơn?

  6. Máy có mấy cái đồng hồ? Cái nào chạy khi máy đang tắt?

  7. Một dòng cron có năm con số. Chúng lần lượt là gì?

  8. Việc lặp lại mỗi ngày thì dùng gì, việc chỉ làm một lần thì dùng gì?

  1. What are Ward's three steps for checking the logging setup on an unfamiliar machine?

  2. Why doesn't tail -f work with journald, and what replaces it?

  3. How are facility, severity and priority related? What are levels 0 and 7 called?

  4. Name the seven fields of an /etc/passwd line, and say what an x in the second field means.

  5. Why must passwd be a suid-root executable, and why is hand-editing /etc/passwd a bad idea?

  6. How do the euid and ruid differ — and which one decides who may kill the process?

  7. How do identification, authentication and authorization differ? Which of them does the kernel know about?

  8. What are the three fields of a PAM configuration line, and how do the three simple control arguments differ?

  9. How does the kernel's system clock represent time, and who converts it to local time?

  10. What are the five time fields of a crontab line, in order?

  11. Why does a periodic timer-unit task need two unit files rather than one?

  12. If you create a timer unit with systemd-run --user and then log out, what happens — and what fixes it?

Khép lại chương Closing the chapter

Ward tự đặt cột mốc: đến đây ta đã ở khoảng giữa hành trình qua quyển sách, đã đi qua nhiều khối xây dựng thiết yếu của một hệ Linux. Và bài học mà chương về nhật ký cùng người dùng để lại là: có thể chia dịch vụ và tác vụ thành những mẩu nhỏ, độc lập, mà vẫn tương tác được với nhau. Chương này gần như chỉ nói về không gian người dùng — nên giờ ta cần tinh chỉnh lại cái nhìn về tiến trình người dùng và tài nguyên chúng tiêu thụ, và quay trở lại vào trong nhân ở Chương 8.1

Ta đã đi được nửa đường. Bài học lớn nhất của chương này: việc to thì chia thành nhiều mẩu nhỏ, mỗi mẩu làm tốt một việc, rồi cho chúng nói chuyện với nhau. Chương sau ta sẽ quay lại bên trong nhân. Nhớ nhé: chia nhỏ để hiểu, ghép lại để chạy.

Ward marks the milestone himself: we are now at about the midpoint of our progression through the book, having covered many of the vital building blocks of a Linux system. The lesson the chapter on logging and users leaves behind: it's possible to divide services and tasks into small, independent chunks that can still interact. This chapter dealt almost exclusively with user space — so now we need to refine our view of user-space processes and the resources they consume, and go back into the kernel in Chapter 8.1