How Linux Works Chương 6 · How User Space Starts

Chương 6 · Không gian người dùng khởi động thế nào Chapter 6 · How User Space Starts

Từ khoảnh khắc nhân gọi init, hệ thống thôi là một đường thẳng và trở thành một đồ thị Sau khi nhân xong việc, máy bắt đầu tự dựng chính mình The moment the kernel calls init, the system stops being a line and becomes a graph

Ward gọi điểm nhân khởi chạy init — tiến trình không gian người dùng đầu tiên của nó — là một mốc quan trọng: không chỉ vì bộ nhớ và CPU cuối cùng đã sẵn sàng cho vận hành bình thường, mà vì đó là chỗ bạn nhìn thấy phần còn lại của hệ thống tự dựng lên thành một tổng thể.1 Trước mốc đó, nhân đi theo một lộ trình thực thi được kiểm soát chặt, do một số tương đối nhỏ lập trình viên định nghĩa. Sau mốc đó, không gian người dùng mô-đun hơn nhiều, tuỳ biến được nhiều hơn — và cũng dễ quan sát hơn hẳn.1

Nhân giống người mở cửa hàng buổi sáng: bật điện, mở khoá, kiểm tra máy móc. Xong việc đó, nhân gọi một chương trình tên là init — và init mới là người gọi tất cả nhân viên khác vào chỗ của họ. Từ lúc này trở đi, mọi thứ diễn ra ở “tầng trên”, nơi bạn được phép xem và sửa. Nhớ nhé: nhân mở cửa, còn init mới sắp xếp người làm.

Ward calls the point where the kernel starts init, its first user-space process, significant — not just because memory and CPU are finally ready for normal system operation, but because that's where you can see how the rest of the system builds up as a whole.1 Prior to that point the kernel follows a well-controlled path of execution defined by a relatively small number of software developers. After it, user space is far more modular and customizable — and much easier to observe.1

Ông còn thêm một lời mời rất đặc trưng của quyển sách: nếu bạn thấy hơi phiêu lưu, bạn có thể tận dụng điều này, bởi hiểu và thay đổi quá trình khởi động không gian người dùng không đòi hỏi lập trình mức thấp.1 Đây là khác biệt thực tế giữa Chương 5 và Chương 6: Chương 5 bạn đọc để hiểu; Chương 6 bạn đọc để sửa được.

Luận đề của chương: không gian người dùng khởi động theo đại thể thứ tự init → các dịch vụ mức thấp thiết yếu (udevd, syslogd) → cấu hình mạng → dịch vụ mức trung và cao (cron, in ấn…) → dấu nhắc đăng nhập, giao diện đồ hoạ và ứng dụng mức cao.1 Nhưng trên một hệ thống systemd hiện đại, thứ tự ấy không còn là một chuỗi cứng: systemd hướng mục tiêu, kích hoạt các unit ngay khi chúng sẵn sàng thay vì tuần tự theo kịch bản.1

Ý chính: máy bật lên theo thứ tự: init trước, rồi các dịch vụ nhỏ quan trọng, rồi mạng, rồi các dịch vụ lớn, cuối cùng là màn hình đăng nhập. Nhưng ngày nay máy không làm từng việc một — nó làm nhiều việc song song. Nhớ nhé: không xếp hàng nữa, mà ai xong trước thì chạy trước.

The chapter's thesis: user space starts roughly in this order — init, then essential low-level services such as udevd and syslogd, then network configuration, then mid- and high-level services (cron, printing and so on), and finally login prompts, GUIs and high-level applications.1 But on a modern systemd system that order is no longer a rigid sequence: systemd is goal-oriented and activates units whenever they are ready.1

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

init: một chương trình bình thường, ở một vị trí không bình thường init chỉ là một chương trình — nhưng là chương trình đầu tiên init: an ordinary program in a very unusual position

Ward mở mục 6.1 bằng một câu làm xẹp hết vẻ huyền bí: init là một chương trình không gian người dùng như mọi chương trình khác trên hệ thống Linux, và bạn sẽ tìm thấy nó trong /sbin cùng nhiều tệp nhị phân hệ thống khác. Mục đích chính của nó là khởi động và dừng các tiến trình dịch vụ thiết yếu.1 Không có phép màu nào ở đây — chỉ có một chương trình tình cờ được nhân gọi trước tất cả.

init nghe rất oai, nhưng nó chỉ là một chương trình nằm trong thư mục /sbin, giống mọi chương trình khác. Việc của nó là bật và tắt những dịch vụ quan trọng. Nó đặc biệt chỉ vì nó được gọi đầu tiên. Nhớ nhé: init không phải phép thuật, chỉ là người tới sớm nhất.

Ward opens §6.1 with a line that deflates all the mystique: init is a user-space program like any other on a Linux system, and you'll find it in /sbin along with many other system binaries. Its main purpose is to start and stop the essential service processes on the system.1 There is no magic — only a program that the kernel happens to call before all others.

Về “bản chuẩn”. Ward viết rằng trên mọi bản phát hành hiện thời của các distro Linux lớn, hiện thực chuẩn của init là systemd, và chương này tập trung vào cách systemd vận hành cùng cách tương tác với nó.1 Hai biến thể khác bạn có thể gặp trên hệ thống cũ: System V init — một init tuần tự truyền thống, gốc từ Unix System V, thường đọc là “sys-five”, có trên Red Hat Enterprise Linux trước 7.0 và Debian 8; và Upstart — init trên các bản Ubuntu trước 15.04.1 Quyển sách nói thẳng là không bàn về Upstart, vì nó đã bị systemd thay thế trên diện rộng.1

Định nghĩa. init là tiến trình không gian người dùng đầu tiên mà nhân khởi chạy, và do đó mang số hiệu tiến trình 1. Trang man init(1) mô tả nó là tiến trình khởi tạo hệ thống, cha của mọi tiến trình khác, và ghi rằng nếu init kết thúc thì nhân sẽ hoảng loạn (panic).2 Ward nói rằng xem trang man init(1) thường cho bạn biết ngay bạn đang chạy hiện thực nào.1

Nói đơn giản. init là chương trình số 1 — đúng nghĩa đen, máy đánh số nó là 1. Mọi chương trình khác đều là con cháu của nó. Nhớ nhé: init mang số 1, và ai cũng là con cháu nó.

Definition. init is the first user-space process the kernel starts, and therefore carries process ID 1. The init(1) manual page describes it as the system initialization process, parent of all other processes, and notes that the kernel panics if init terminates.2 Ward notes that viewing the init(1) manual page normally tells you right away which implementation you're running.1

/usr/lib/systemd + /etc/systemd → systemd
/etc/init/*.conf           → Upstart
chỉ có /etc/inittab      → System V init

có thư mục systemd → systemd
có /etc/inittab    → cách cũ

/usr/lib/systemd + /etc/systemd → systemd
/etc/init/*.conf           → Upstart
only /etc/inittab        → System V init

  1. identifying your init

    Nhận diện init — ba câu hỏi theo thứ tự Máy bạn dùng loại init nào? Identifying your init — three questions in order

    Ward đưa một quy trình kiểm tra ba bước, rất cụ thể: nếu hệ thống có các thư mục /usr/lib/systemd và /etc/systemd, bạn đang dùng systemd. Nếu có thư mục /etc/init chứa vài tệp .conf, nhiều khả năng bạn đang chạy Upstart — trừ khi đó là Debian 7 trở về trước, khi ấy nhiều phần là System V init. Nếu không thuộc hai trường hợp trên nhưng có tệp /etc/inittab, nhiều khả năng bạn đang chạy System V init.1

    Muốn biết máy mình dùng loại nào: mở xem có thư mục /etc/systemd không — có thì là systemd, loại phổ biến nhất bây giờ. Nếu chỉ có một tệp tên /etc/inittab thì đó là loại cũ. Nhớ nhé: nhìn tên thư mục là đoán được đời máy.

    Ward gives a concrete three-step check: if your system has /usr/lib/systemd and /etc/systemd directories, you have systemd. If you have an /etc/init directory containing several .conf files, you're probably running Upstart — unless you're on Debian 7 or older, in which case you probably have System V init. If neither is true but you have an /etc/inittab file, you're probably running System V init.1

    Bạn gặp nó ở đâuWhere you meet it Mỗi lần một hướng dẫn trên mạng bảo bạn “sửa tệp /etc/inittab” mà máy bạn không có tệp đó — bạn vừa gặp ranh giới giữa hai thế hệ init. Khi bạn làm theo hướng dẫn cũ trên mạng mà không tìm thấy tệp nào như nó nói. Every time an online guide tells you to "edit /etc/inittab" and your machine has no such file, you have just met the boundary between two generations of init.

    Những init khác

    Ward ghi nhận rằng còn các phiên bản init khác, đặc biệt trên nền tảng nhúng: Android có init riêng của nó, và một bản tên runit phổ biến trên các hệ thống nhẹ. Các hệ BSD cũng có bản init riêng, nhưng bạn khó gặp chúng trên một máy Linux đương thời.1

    Một lưu ý về kiểu BSD

    Ông cũng ghi chú rằng một số distro đã sửa cấu hình System V init để trông giống kiểu BSD.1 Nói cách khác, ngay cả “System V init” cũng không phải một khối đồng nhất — đây là lý do quy trình nhận diện ba bước ở trên hữu ích hơn việc đoán theo tên distro.

  2. System V init's limitations

    Bốn giới hạn đã khai tử init tuần tự Vì sao người ta bỏ cách cũ The four limitations that killed sequential init

    Để hiểu vì sao có systemd, Ward yêu cầu bạn nhìn vào ruột của một init truyền thống: về cơ bản đó là một loạt kịch bản mà init chạy tuần tự, mỗi lần một cái. Mỗi kịch bản thường khởi động một dịch vụ hoặc cấu hình một mảnh của hệ thống.1 Ông chia các giới hạn thành hai nhóm — “vấn đề hiệu năng” và “phiền toái quản trị hệ thống” — rồi liệt kê bốn điểm quan trọng nhất.1

    Cách cũ giống như xếp hàng mua vé: mỗi người phải đợi người trước xong. Chậm, và nếu ai đó kẹt thì cả hàng kẹt theo. Nhớ nhé: xếp hàng thì an toàn nhưng chậm.

    To see why systemd exists, Ward asks you to look inside a traditional init: it is basically a series of scripts that init runs in sequence, one at a time. Each script usually starts one service or configures an individual piece of the system.1 He groups the limitations into "performance problems" and "system management hassles", then lists the four most important.1

    Bốn điểm Ward liệt kêThe four points Ward lists (1) Hiệu năng kém vì hai phần của chuỗi khởi động thường không thể chạy cùng lúc. (2) Quản lý hệ thống đang chạy rất khó: để tìm PID của một tiến trình nền dịch vụ bạn phải dùng ps, một cơ chế riêng của dịch vụ, hoặc một hệ thống bán chuẩn ghi PID như /var/run/myservice.pid. (3) Kịch bản khởi động có xu hướng chứa nhiều mã “khuôn mẫu” lặp lại, khiến khó đọc. (4) Hầu như không có khái niệm dịch vụ theo yêu cầu: phần lớn dịch vụ khởi động lúc boot.1 Chậm; khó biết chương trình nào đang chạy; kịch bản dài dòng; và mọi thứ đều bật lên dù bạn không cần. (1) Performance suffers because two parts of the boot sequence cannot normally run at once. (2) Managing a running system is hard: to find a service daemon's PID you need ps, some service-specific mechanism, or a semistandardized PID file such as /var/run/myservice.pid. (3) Startup scripts tend to include a lot of "boilerplate" code, making them hard to read. (4) There is little notion of on-demand services: most services start at boot time.1

    inetd, cái đã mất

    Ward ghi rằng đã có thời tiến trình nền inetd truyền thống xử lý được các dịch vụ mạng theo yêu cầu, nhưng nó phần lớn đã rơi vào quên lãng.1 Chi tiết này quan trọng: khởi động theo yêu cầu không phải phát minh của systemd, mà là một ý tưởng cũ được hồi sinh ở quy mô toàn hệ thống.

    Điều còn lại của cách cũ

    Ông cũng công bằng với init truyền thống: trong phần lớn trường hợp, việc giải quyết phụ thuộc là tương đối dễ, và có rất nhiều mềm dẻo để chiều những yêu cầu khởi động bất thường bằng cách sửa kịch bản.1 Cái giá của systemd là đánh đổi sự mềm dẻo thô sơ ấy lấy một mô hình khai báo chặt chẽ hơn.

  3. goal-oriented

    systemd hướng mục tiêu — và theo dõi được cái nó khởi động systemd nhắm tới đích, không đi theo lối systemd is goal-oriented — and can track what it starts

    Ward mô tả systemd là một trong những hiện thực init mới nhất trên Linux; ngoài việc lo tiến trình khởi động thường lệ, nó còn nhắm tới việc thâu nạp chức năng của một loạt dịch vụ Unix chuẩn như cron và inetd, và nó lấy ít nhiều cảm hứng từ launchd của Apple.1 Nhưng chỗ systemd thực sự nổi bật so với các bậc tiền bối là năng lực quản lý dịch vụ: khác init truyền thống, systemd có thể theo dõi từng tiến trình nền dịch vụ sau khi chúng khởi động, và gom nhiều tiến trình thuộc cùng một dịch vụ lại với nhau.1

    systemd không đi theo một lối mòn cố định. Bạn nói cho nó biết đích cần tới, nó tự tìm đường và làm nhiều việc cùng lúc. Nó cũng nhớ được mỗi dịch vụ đang chạy những tiến trình nào. Nhớ nhé: nói đích đến, đừng chỉ đường.

    Ward describes systemd as one of the newest init implementations on Linux; besides handling the regular boot process it aims to incorporate the functionality of a number of standard Unix services such as cron and inetd, and it takes some inspiration from Apple's launchd.1 Where it really stands out from its predecessors is service management: unlike a traditional init, systemd can track individual service daemons after they start and group together the multiple processes belonging to one service.1

    Hệ quả thực tếThe practical consequence Ở mức cao nhất, bạn định nghĩa một mục tiêu — gọi là một unit — cho một tác vụ hệ thống nào đó. Unit chứa chỉ dẫn cho các tác vụ khởi động thông thường và có các phụ thuộc là những unit khác. Khi khởi động (hay kích hoạt) một unit, systemd cố kích hoạt các phụ thuộc của nó trước, rồi mới lo chi tiết của chính unit đó.1 Bạn ghi ra “tôi muốn có cái này”, còn việc cần bật gì trước thì máy tự lo. At the top level you define a goal — called a unit — for some system task. A unit can contain instructions for common startup tasks and has dependencies, which are other units. When starting (or activating) a unit, systemd attempts to activate its dependencies and then moves on to the details of the unit.1

    Không theo chuỗi cứng

    Khi khởi động các dịch vụ, systemd không đi theo một chuỗi cứng; thay vào đó nó kích hoạt các unit bất cứ khi nào chúng sẵn sàng. Sau khi boot xong, systemd có thể phản ứng với các sự kiện hệ thống — chẳng hạn các uevent nói ở Chương 3 — bằng cách kích hoạt thêm unit.1

    Vì sao “theo dõi được” lại là bước ngoặt

    Ward đặt vấn đề rất thẳng: trong lịch sử, việc này khó. Một dịch vụ có thể khởi động theo nhiều cách — nó có thể fork ra các thể hiện mới của chính nó, hoặc thậm chí tự biến thành tiến trình nền và tách khỏi tiến trình gốc; và không cách nào biết máy chủ sẽ sinh ra bao nhiêu tiến trình con.1 Trang man daemon(7) của systemd mô tả đúng nghi thức “daemon hoá” kiểu SysV ấy, cùng kiểu daemon mới đơn giản hơn dành cho systemd.3

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

Unit, loại unit, và cái đồ thị không phải là cây Unit là gì, và chúng nối với nhau ra sao Units, unit types, and the graph that isn't a tree

Điểm khiến systemd tham vọng hơn các đời init trước là nó không chỉ vận hành tiến trình và dịch vụ: nó còn quản lý được việc gắn hệ thống tệp, theo dõi các yêu cầu kết nối mạng, chạy bộ hẹn giờ, và hơn thế. Mỗi năng lực như vậy gọi là một loại unit (unit type), và mỗi chức năng cụ thể — chẳng hạn một dịch vụ — gọi là một unit. Khi bạn bật một unit lên, ta nói bạn kích hoạt nó.1

Unit là “một việc cần làm”, ghi trong một tệp nhỏ. Có nhiều loại việc: chạy một chương trình nền, gắn một ổ đĩa, canh một cổng mạng, hẹn giờ. Bật một việc lên thì gọi là kích hoạt. Nhớ nhé: một unit = một việc, ghi trong một tệp.

What makes systemd more ambitious than previous versions of init is that it doesn't just operate processes and services: it can also manage filesystem mounts, monitor network connection requests, run timers and more. Each capability is called a unit type, and each specific function — such as a service — is called a unit. When you turn a unit on, you activate it.1

Bao nhiêu loại unit? Ward cố tình không liệt kê hết: ông nêu bốn loại quan trọng nhất thực hiện các tác vụ lúc khởi động trên một hệ thống Linux điển hình — service, target, socket, mount — rồi ghi chú rằng bạn có thể tìm danh sách đầy đủ các loại unit trong trang man systemd(1).1 Trang man đó ngày nay liệt kê nhiều hơn hẳn, trong đó có device, path, slice và scope unit.4 Trang này theo cách chọn bốn loại của Ward trong phần thân, và ghi chú sự khác biệt ở đây thay vì lặng lẽ chọn một con số.

Bốn loại unit Ward nêu. Service unit điều khiển các tiến trình nền dịch vụ tìm thấy trên một hệ thống Unix. Target unit điều khiển các unit khác, thường bằng cách gom nhóm chúng. Socket unit biểu diễn các vị trí nhận yêu cầu kết nối mạng đi vào. Mount unit biểu diễn việc gắn hệ thống tệp vào hệ thống.1 Trong bốn loại ấy, service và target là phổ biến nhất và dễ hiểu nhất.1

Bốn loại hay gặp. Loại “dịch vụ” chạy chương trình nền. Loại “target” gom nhiều việc thành một nhóm. Loại “socket” canh một cổng mạng. Loại “mount” gắn ổ đĩa. Nhớ nhé: chạy, gom, canh, gắn.

The four unit types Ward names. Service units control the service daemons found on a Unix system. Target units control other units, usually by grouping them. Socket units represent incoming network connection request locations. Mount units represent the attachment of filesystems to the system.1 Of these, service and target units are the most common and the easiest to understand.1

default.target
  └─ multi-user.target
      ├─ basic.target
      │   └─ sysinit.target
      ├─ cron.service
      └─ dbus.service

đích cuối
 └─ nhóm việc lớn
    ├─ nhóm việc nền
    └─ từng dịch vụ

default.target
  └─ multi-user.target
      ├─ basic.target
      │   └─ sysinit.target
      ├─ cron.service
      └─ dbus.service

  1. dependency graph

    Đồ thị phụ thuộc — không phải cây, mà là đồ thị Các nhánh không chỉ toả ra, chúng còn nhập lại The dependency graph — not a tree, a graph

    Khi bạn khởi động một hệ thống, bạn đang kích hoạt một unit mặc định — bình thường là một target unit tên default.target, gom nhiều service unit và mount unit lại làm phụ thuộc của nó.1 Bạn có thể ngỡ các phụ thuộc tạo thành một cây, nhưng thực tế chúng tạo thành một đồ thị: một unit đến muộn trong tiến trình khởi động có thể phụ thuộc vào nhiều unit trước đó, khiến các nhánh của cây phụ thuộc nhập lại với nhau.1

    Nhìn từ trên xuống, các việc trông như một cái cây: đích lớn chia thành việc nhỏ. Nhưng đôi khi hai nhánh khác nhau lại cùng cần một việc, nên các nhánh chụm lại. Thế thì nó không còn là cây nữa. Nhớ nhé: cành có thể chụm lại chứ không chỉ toả ra.

    When you boot a system you are activating a default unit — normally a target unit called default.target that groups a number of service and mount units together as dependencies.1 You might expect the dependencies to form a tree, but they actually form a graph: a unit that comes late in the boot process can depend on several previous units, making earlier branches of a dependency tree join back together.1

    Công cụ để nhìnThe tool for looking Bạn thậm chí có thể tạo ra đồ thị phụ thuộc bằng lệnh systemd-analyze dot.1 Ward cảnh báo ngay: toàn bộ đồ thị khá lớn trên một hệ thống điển hình, đòi hỏi năng lực tính toán đáng kể để dựng hình, và khó đọc — nhưng có cách lọc unit để khoanh vùng từng phần.1 Trang man systemd-analyze(1) mô tả lệnh con dot này.5 Có một lệnh vẽ được sơ đồ đó, nhưng sơ đồ thật thì rất to và rối. You can even create a dependency graph with the systemd-analyze dot command.1 Ward warns immediately: the entire graph is quite large on a typical system (requiring significant computing power to render) and is hard to read, but there are ways to filter units and zero in on individual portions.1 The systemd-analyze(1) manual page documents this dot verb.5

    Hình 6-1 và cái nó giấu đi

    Ward mô tả Hình 6-1 là một phần rất nhỏ của đồ thị phụ thuộc cho unit default.target trên một hệ thống điển hình: dưới default.target là multi-user.target, dưới nữa là basic.target, cron.service và dbus.service, và dưới basic.target là sysinit.target.1 Ông nói thẳng đây là một cái nhìn giản lược rất nhiều: trên hệ thống của chính bạn, phác ra các phụ thuộc chỉ bằng cách đọc tệp cấu hình unit ở trên cùng rồi lần xuống là không khả thi.1

    default.target là một liên kết

    Trên hầu hết hệ thống, default.target là một liên kết tới một target unit mức cao khác, chẳng hạn một target biểu diễn việc khởi động giao diện người dùng. Trên hệ thống dùng làm ví dụ cho Hình 6-1, default.target gom các unit cần thiết để khởi động một GUI.1 Đây cũng là chỗ dễ gây nhầm: đổi “máy khởi động vào đâu” không phải là sửa một unit, mà là đổi cái liên kết ấy.

  2. unit file format

    Tệp unit — cú pháp mượn từ đặc tả Desktop Entry Tệp unit trông như thế nào Unit files — syntax borrowed from the Desktop Entry spec

    Định dạng tệp unit bắt nguồn từ đặc tả XDG Desktop Entry — dùng cho các tệp .desktop, vốn rất giống tệp .ini trên hệ thống Microsoft — với tên mục đặt trong ngoặc vuông [] và các phép gán biến–giá trị (gọi là tuỳ chọn) bên trong mỗi mục.1 Đặc tả gốc do freedesktop.org duy trì.6

    Tệp unit chỉ là một tệp chữ, chia thành vài đoạn. Mỗi đoạn có một cái tên trong ngoặc vuông, rồi từng dòng ghi “tên = giá trị”. Bạn mở bằng trình soạn thảo nào cũng đọc được. Nhớ nhé: chỉ là tệp chữ, không phải mã lập trình.

    The unit file format is derived from the XDG Desktop Entry specification — used for .desktop files, which are very similar to .ini files on Microsoft systems — with section names in square brackets [] and variable/value assignments (options) in each section.1 The original specification is maintained by freedesktop.org.6

    Ví dụ của tác giảThe author's example Ward lấy tệp unit dbus-daemon.service của tiến trình nền desktop bus làm ví dụ: mục [Unit] có Description=D-Bus System Message Bus, Documentation=man:dbus-daemon(1), Requires=dbus.socket và RefuseManualStart=yes; mục [Service] có các dòng ExecStart= và ExecReload=.1 Mục [Unit] cho vài chi tiết về unit cùng thông tin mô tả và phụ thuộc; ở đây unit này yêu cầu unit dbus.socket làm phụ thuộc.1 Ví dụ trong sách là tệp của dịch vụ “bus tin nhắn”. Đoạn đầu ghi tên và thứ nó cần; đoạn sau ghi lệnh để chạy nó. Ward's example is the dbus-daemon.service unit file for the desktop bus daemon: the [Unit] section carries Description=D-Bus System Message Bus, Documentation=man:dbus-daemon(1), Requires=dbus.socket and RefuseManualStart=yes; the [Service] section carries ExecStart= and ExecReload= lines.1 The [Unit] section gives details about the unit and contains description and dependency information; here the unit requires the dbus.socket unit as a dependency.1

    Tệp trên máy bạn có thể khác

    Ward ghi chú rằng các tệp unit bạn thấy trên hệ thống của mình có thể khác đôi chút: trong ví dụ đó, Fedora dùng tên dbus-daemon.service còn Ubuntu dùng dbus.service. Cũng có thể có thay đổi trong chính nội dung tệp, nhưng thường chỉ là bề mặt.1

    Nơi tra cứu chính thức

    Với một service unit, chi tiết về cách chuẩn bị, khởi động và nạp lại dịch vụ nằm trong mục [Service]; Ward chỉ bạn tới hai trang man systemd.service(5) và systemd.exec(5) để có danh sách đầy đủ.1 Các tuỳ chọn chung cho mọi loại unit — kể cả Description= và Documentation= — thì thuộc về systemd.unit(5).7

  3. variables & specifiers

    Biến $ và bộ chỉ định % — hai cơ chế giống nhau, gốc khác nhau Dấu $ và dấu % trong tệp unit Variables $ and specifiers % — same look, different origins

    Mọi thứ bắt đầu bằng dấu đô la là một biến. Ward nhấn mạnh rằng dù các biến này có cùng cú pháp, nguồn gốc của chúng khác nhau: trong ví dụ sshd.service của ông, $OPTIONS và $CRYPTO_POLICY được định nghĩa trong tệp mà thiết lập EnvironmentFile= trỏ tới, còn $MAINPID thì chứa ID của tiến trình được theo dõi của dịch vụ — systemd tự ghi lại và lưu PID này khi kích hoạt unit.1

    Trong tệp unit có hai loại “chỗ trống” sẽ được điền sau. Loại có dấu $ lấy giá trị từ một tệp khác hoặc từ máy. Loại có dấu % thì máy tự điền, ví dụ tên máy hoặc tên của chính việc đó. Nhớ nhé: $ lấy từ nơi khác, % là máy tự biết.

    Everything starting with a dollar sign is a variable. Ward stresses that although these variables share a syntax, their origins differ: in his sshd.service example, $OPTIONS and $CRYPTO_POLICY are defined in the file named by the EnvironmentFile= setting, while $MAINPID contains the ID of the service's tracked process — systemd records and stores this PID upon unit activation.1

    Thể hiện và ký hiệu @Instances and the @ sign Bộ chỉ định (specifier) bắt đầu bằng dấu phần trăm: %n là tên unit hiện tại, %H là tên máy hiện tại.1 Bạn cũng có thể dùng specifier để tạo nhiều bản sao của một unit từ một tệp duy nhất bằng cách thêm ký hiệu @ vào cuối tên unit, trước dấu chấm. Ví dụ Ward đưa ra là getty@.service — cho phép tạo động các unit như getty@tty1 và getty@tty2; phần sau dấu @ gọi là thể hiện (instance), và systemd thay %I hoặc %i bằng thể hiện đó để tạo tên dịch vụ mới.1 Một tệp mẫu có thể sinh ra nhiều bản: ví dụ một mẫu “màn hình đăng nhập” sinh ra bản cho màn hình 1, bản cho màn hình 2. Dấu @ chính là chỗ điền số. A specifier starts with a percent sign: %n is the current unit name, %H the current hostname.1 You can also use specifiers to create multiple copies of a unit from a single unit file by adding an @ to the end of the unit name, before the dot. Ward's example is getty@.service — allowing dynamic creation of units such as getty@tty1 and getty@tty2; anything after the @ is called the instance, and systemd replaces %I or %i with it to create the new service name.1

    $MAINPID dùng để làm gì

    Tệp unit sshd.service dùng $MAINPID để gửi tín hiệu treo máy (HUP) tới sshd khi bạn muốn nạp lại cấu hình — Ward gọi đây là một kỹ thuật rất phổ biến để xử lý việc nạp lại và khởi động lại các tiến trình nền Unix.1 Dòng ông trích là ExecReload=/bin/kill -HUP $MAINPID.1

    Danh sách specifier đầy đủ

    Ward chỉ nêu %n, %H, %I và %i vì đó là những thứ bạn gặp hằng ngày.1 Bảng specifier đầy đủ — gồm cả phân biệt giữa %i (tên thể hiện thô) và %I (tên thể hiện đã giải thoát khỏi mã hoá đường dẫn) — nằm trong mục “Specifiers” của trang man systemd.unit(5).7

  4. configuration directories

    Hai thư mục, một quy tắc: sửa ở /etc, đừng sửa ở /usr Sửa ở đâu cho khỏi mất Two directories, one rule: edit /etc, not /usr

    Tệp cấu hình systemd nằm rải rác trong nhiều thư mục khắp hệ thống, nên đôi khi bạn phải đi săn một chút. Có hai thư mục chính: thư mục unit hệ thống — cấu hình toàn cục, thường là /lib/systemd/system hoặc /usr/lib/systemd/system — và thư mục cấu hình hệ thống — các định nghĩa cục bộ, thường là /etc/systemd/system.1

    Có hai chỗ để tệp cấu hình. Một chỗ là của nhà sản xuất, một chỗ là của bạn. Đừng sửa chỗ của họ, vì lần cập nhật sau sẽ ghi đè mất. Nhớ nhé: đồ của mình thì để chỗ của mình.

    The systemd configuration files are spread among many directories across the system, so you might need to hunt a little. There are two main ones: the system unit directory — global configuration, usually /lib/systemd/system or /usr/lib/systemd/system — and the system configuration directory — local definitions, usually /etc/systemd/system.1

    Quy tắc Ward đặt raWard's rule “Để tránh nhầm lẫn, hãy giữ quy tắc này: đừng thay đổi thư mục unit hệ thống, vì distro của bạn sẽ duy trì nó giúp bạn. Hãy đặt các thay đổi cục bộ vào thư mục cấu hình hệ thống.” Ông nói quy tắc chung này áp dụng cho toàn hệ thống: khi phải chọn giữa sửa cái gì đó trong /usr và trong /etc, luôn luôn sửa /etc.1 Quy tắc vàng: khi phân vân sửa chỗ nào, hãy sửa trong /etc. "To prevent confusion, stick to this rule: avoid making changes to the system unit directory, because your distribution will maintain it for you. Make your local changes to the system configuration directory." Ward says this general rule applies systemwide: when given the choice between modifying something in /usr and in /etc, always change /etc.1

    Xem đường tìm kiếm thật

    Ward đưa một lệnh để kiểm tra đường tìm kiếm cấu hình systemd hiện tại, bao gồm cả thứ tự ưu tiên: systemctl -p UnitPath show.1 Kết quả ông in ra bắt đầu bằng /etc/systemd/system.control và /run/systemd/system.control, đi qua /etc/systemd/system, và kết thúc ở /lib/systemd/system cùng /run/systemd/generator.late — nghĩa là thư mục cục bộ đứng trước thư mục của distro.1 Trang man systemctl(1) mô tả cờ -p/--property= và lệnh con show.8

    Hỏi thẳng hệ thống đóng gói

    Để xem chính xác hai thư mục ấy trên máy mình, Ward dùng pkg-config systemd --variable=systemdsystemunitdir (cho ra /lib/systemd/system) và pkg-config systemd --variable=systemdsystemconfdir (cho ra /etc/systemd/system).1 Cách này bền hơn việc nhớ thuộc lòng đường dẫn, vì nó hỏi chính bản systemd đang cài.

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

systemctl, job, và cgroup: cách systemd giữ được dấu vết Điều khiển máy và theo dõi dịch vụ systemctl, jobs, and cgroups: how systemd keeps track

Bạn tương tác với systemd chủ yếu qua lệnh systemctl, cho phép kích hoạt và vô hiệu hoá dịch vụ, liệt kê trạng thái, nạp lại cấu hình và nhiều hơn nữa.1 Những lệnh thiết yếu nhất là các lệnh giúp bạn lấy thông tin về unit — chẳng hạn systemctl list-units để xem danh sách các unit đang hoạt động; Ward ghi chú rằng đây là lệnh con mặc định của systemctl, nên về mặt kỹ thuật bạn không cần gõ list-units.1

Muốn nói chuyện với systemd, bạn dùng một lệnh duy nhất tên là systemctl: bật, tắt, hỏi xem cái gì đang chạy. Gõ systemctl không thôi cũng ra danh sách. Nhớ nhé: một lệnh cho tất cả — systemctl.

You'll interact with systemd primarily through the systemctl command, which lets you activate and deactivate services, list status, reload configuration and much more.1 The most essential commands help you obtain unit information — for example systemctl list-units for a list of active units; Ward notes this is systemctl's default command, so technically you don't need the list-units argument.1

Vì sao đầu ra bị cắt. Ward giải thích rằng mặc định systemctl list-units in ra rất nhiều dòng, vì một hệ thống điển hình có rất nhiều unit đang hoạt động — nhưng nó vẫn là một dạng rút gọn, bởi systemctl cắt bớt những tên unit thật sự dài. Để thấy tên đầy đủ, dùng tuỳ chọn --full; để thấy mọi unit chứ không chỉ những unit đang hoạt động, dùng --all.1 Hai cờ này được mô tả trong trang man systemctl(1).8

Đọc một dòng đầu ra. Định dạng đầu ra là kiểu điển hình của một lệnh liệt kê thông tin Unix. Ward lấy phần tiêu đề và dòng cho -.mount — chính là hệ thống tệp gốc — làm ví dụ: các cột UNIT, LOAD, ACTIVE, SUB, DESCRIPTION, với giá trị loaded active mounted Root Mount.1

Đọc bảng. Mỗi dòng là một việc: tên việc, đã nạp chưa, đang chạy không, và mô tả ngắn. Nhớ nhé: mỗi dòng một việc, đọc từ trái sang phải.

Reading one output line. The output format is typical of a Unix information-listing command. Ward takes the header and the line for -.mount — the root filesystem — as his example: the columns UNIT, LOAD, ACTIVE, SUB, DESCRIPTION, with the values loaded active mounted Root Mount.1

systemctl start   unit → kích hoạt
systemctl stop    unit → dừng
systemctl restart unit → khởi động lại
systemctl reload  unit → nạp lại cấu hình
systemctl daemon-reload → nạp lại tất cả

start   → bật
stop    → tắt
restart → tắt rồi bật
status  → hỏi thăm

systemctl start   unit → activate
systemctl stop    unit → deactivate
systemctl restart unit → restart
systemctl reload  unit → reload its config
systemctl daemon-reload → reload all configs

  1. systemctl status

    status — một lệnh trả về nhiều hơn bạn tưởng Hỏi thăm một dịch vụ status — one command that returns more than you expect

    Ward gọi việc lấy trạng thái của một unit cụ thể là một thao tác systemctl đặc biệt hữu ích, và đưa ví dụ systemctl status sshd.service. Đầu ra của ông cho thấy dòng Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled), dòng Active: active (running) since…, một Main PID: 1110 (sshd), số Tasks, và tên nhóm điều khiển CGroup: /system.slice/sshd.service với các tiến trình liệt kê bên dưới.1

    Gõ systemctl status rồi tên dịch vụ, máy sẽ kể cho bạn: nó có đang chạy không, chạy từ bao giờ, số hiệu tiến trình chính là bao nhiêu, và vài dòng nhật ký gần nhất. Nhớ nhé: một câu hỏi, rất nhiều câu trả lời.

    Ward calls getting the status of a specific unit a particularly useful systemctl operation, and gives the example systemctl status sshd.service. His output shows a Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled) line, an Active: active (running) since… line, a Main PID: 1110 (sshd), a Tasks count, and the control group name CGroup: /system.slice/sshd.service with its processes listed beneath.1

    Điều gây bất ngờThe surprise Ward viết rằng nếu bạn quen một hệ thống init truyền thống, bạn có thể ngạc nhiên trước lượng thông tin hữu ích lấy được từ một lệnh duy nhất: bạn có không chỉ trạng thái unit mà cả các tiến trình gắn với dịch vụ, thời điểm unit khởi động, và một số thông điệp nhật ký nếu có.1 Với các loại unit khác cũng vậy: đầu ra của mount unit gồm thời điểm gắn, dòng lệnh chính xác đã dùng, và trạng thái thoát của nó.1 Ngày xưa phải hỏi ba bốn lệnh mới biết được từng ấy thứ. Ward writes that if you're used to a traditional init system you might be surprised by how much useful information one command yields: not only the unit's state but the processes associated with the service, when the unit started, and a number of log messages if available.1 The same holds for other unit types: a mount unit's output includes when the mount happened, the exact command line used, and its exit status.1

    Chỉ thấy vài dòng nhật ký gần nhất

    Lệnh status chỉ hiển thị những thông điệp chẩn đoán gần nhất của unit. Để xem toàn bộ thông điệp của một unit, Ward đưa lệnh journalctl --unit=unit_name, và hẹn bàn kỹ về journalctl ở Chương 7.1 Trang man journalctl(1) mô tả cờ --unit= này.9 Ông cũng ghi chú: tuỳ hệ thống và cấu hình người dùng, bạn có thể cần đặc quyền siêu người dùng để chạy journalctl.1

    Tên cgroup nói gì

    Ward gọi tên nhóm điều khiển là “một mảnh thú vị” của đầu ra. Trong ví dụ, nhóm điều khiển là /system.slice/sshd.service. Ông cảnh báo rằng bạn cũng có thể thấy các nhóm điều khiển có tên bắt đầu bằng systemd:/system nếu các tiến trình của một unit — ví dụ một mount unit — đã kết thúc rồi. Bạn có thể xem các cgroup liên quan tới systemd mà không cần phần còn lại của trạng thái unit bằng lệnh systemd-cgls.110

  2. jobs

    Job — một từ bị quá tải, và một cửa sổ nhìn vào lúc boot “Job” ở đây nghĩa là gì Jobs — an overloaded word, and a window into boot

    Các yêu cầu kích hoạt, kích hoạt lại và khởi động lại unit được systemd gọi là job, và về bản chất chúng là những thay đổi trạng thái của unit. Bạn kiểm tra các job hiện tại bằng systemctl list-jobs.1 Nếu hệ thống đã chạy một thời gian, bạn có thể kỳ vọng hợp lý rằng không còn job nào đang hoạt động, vì mọi kích hoạt cần thiết để dựng hệ thống đáng ra đã xong.1

    Khi bạn bảo máy bật hay tắt một dịch vụ, yêu cầu đó gọi là một “job”. Máy đang chạy ổn định thì thường chẳng còn job nào. Nếu còn, nghĩa là có việc đang bị kẹt. Nhớ nhé: còn job tức là còn việc dở dang.

    Requests to activate, reactivate and restart units are called jobs in systemd, and they are essentially unit state changes. You check current jobs with systemctl list-jobs.1 If a system has been up for some time you can reasonably expect no active jobs, because all activations required to start the system should be complete.1

    Ví dụ chẩn đoán của tác giảThe author's diagnostic example Ward dựng một ví dụ rất thực tế: lúc khởi động, đôi khi bạn đăng nhập đủ nhanh để thấy các job của những unit khởi động rất chậm. Trong danh sách ông in ra, job 76 — sendmail.service — đang ở trạng thái running, còn các job khác như graphical.target và multi-user.target đều waiting, nhiều khả năng vì tất cả đang chờ job 76. Khi sendmail.service khởi động xong và hoàn toàn hoạt động, job 76 hoàn tất, phần còn lại cũng hoàn tất, và danh sách job trở nên rỗng.1 Nếu máy bạn khởi động chậm bất thường, danh sách job cho bạn thấy đúng cái đang làm mọi thứ chờ. Ward builds a very practical example: at boot time you can sometimes log in fast enough to see jobs for units that start very slowly. In his listing, job 76 — sendmail.service — is running while the others, such as graphical.target and multi-user.target, are waiting, most likely because they are all waiting for job 76. When sendmail.service finishes starting and is fully active, job 76 completes, the rest complete too, and the job list is empty.1

    Cảnh báo về thuật ngữ

    Ward ghi chú thẳng rằng thuật ngữ job có thể gây nhầm lẫn, đặc biệt vì một số hệ thống init khác dùng nó để chỉ những tính năng giống unit của systemd hơn. Ông nhấn mạnh thêm: các job này không liên quan gì tới việc điều khiển job của shell.1

    Hai cách nạp lại cấu hình

    Nếu bạn đã sửa một tệp cấu hình unit, bạn có thể bảo systemd nạp lại theo một trong hai cách: systemctl reload unit chỉ nạp lại cấu hình cho unit đó, còn systemctl daemon-reload nạp lại toàn bộ cấu hình unit.1 Nhầm lẫn giữa hai lệnh này là nguyên nhân kinh điển của cảnh “tôi sửa tệp rồi mà không thấy gì thay đổi”.

  3. cgroups & Type=

    cgroup và tuỳ chọn Type — hỏi một câu thay vì đoán mọi thứ Làm sao máy biết một dịch vụ đã sẵn sàng cgroups and Type= — asking one question instead of guessing everything

    systemd muốn có một lượng thông tin và quyền kiểm soát hợp lý đối với mọi tiến trình nó khởi động — và điều này trong lịch sử là khó.1 Để quản lý các unit đã kích hoạt một cách dễ dàng, systemd dùng cgroup, một tính năng của nhân Linux cho phép theo dõi một cây tiến trình mịn hơn.111 Việc dùng cgroup cũng giúp giảm thiểu công sức mà người đóng gói hay quản trị viên phải bỏ ra để tạo một tệp unit hoạt động được.1

    Một dịch vụ có thể tự nhân bản ra nhiều tiến trình con. Ngày xưa rất khó biết cái nào thuộc về ai. Nhân Linux có một cơ chế gọi là cgroup, giống như cái rổ: mọi tiến trình con đều nằm trong rổ của dịch vụ đó. Nhớ nhé: mỗi dịch vụ một cái rổ, không lẫn được.

    systemd wants a reasonable amount of information about and control over every process it starts — historically a difficult thing.1 To manage activated units easily, systemd uses cgroups, a Linux kernel feature allowing finer tracking of a process hierarchy.111 Using cgroups also minimizes the work a package developer or administrator must do to create a working unit file.1

    Một câu hỏi duy nhấtThe single question Ward tóm gọn lợi ích: trong systemd, bạn không phải lo tính hết mọi hành vi khởi động có thể có; tất cả những gì bạn cần biết là tiến trình khởi động dịch vụ có fork hay không. Bạn dùng tuỳ chọn Type trong tệp service unit để chỉ ra hành vi ấy.1 Hai kiểu cơ bản: Type=simple — tiến trình dịch vụ không fork rồi kết thúc, nó vẫn là tiến trình dịch vụ chính; và Type=forking — dịch vụ fork, và systemd chờ tiến trình dịch vụ gốc kết thúc, coi việc kết thúc đó là dấu hiệu dịch vụ đã sẵn sàng.1 Bạn chỉ phải trả lời một câu: dịch vụ này có tự tách ra không? Còn lại máy lo. Ward sums up the benefit: in systemd you don't have to account for every possible startup behavior; all you need to know is whether the service startup process forks. You use the Type option in the service unit file to indicate it.1 The two basic styles: Type=simple — the service process doesn't fork and terminate, it remains the main service process; and Type=forking — the service forks and systemd expects the original service process to terminate, taking that termination as the sign the service is ready.1

    Khi “simple” chưa đủ

    Ward chỉ ra một lỗ hổng: Type=simple không tính tới việc một dịch vụ có thể cần chút thời gian để khởi tạo, nên systemd không biết khi nào thì khởi động các unit phụ thuộc nhất thiết cần dịch vụ ấy sẵn sàng.1 Hai kiểu Type giải quyết bằng cách để chính dịch vụ báo tin: Type=notify — dịch vụ gửi một thông báo riêng cho systemd bằng một lời gọi hàm đặc biệt khi sẵn sàng; và Type=dbus — dịch vụ tự đăng ký trên D-Bus khi sẵn sàng.1 Trang man systemd.service(5) liệt kê đầy đủ các giá trị Type=.12

    oneshot và idle

    Một kiểu khởi động nữa là Type=oneshot: tiến trình dịch vụ kết thúc hoàn toàn, không còn tiến trình con nào sau khi khởi động. Nó giống simple, khác ở chỗ systemd không coi dịch vụ là đã khởi động cho tới khi tiến trình dịch vụ kết thúc — mọi phụ thuộc chặt sẽ không khởi động trước thời điểm đó. Một dịch vụ dùng Type=oneshot cũng nhận mặc định chỉ thị RemainAfterExit=yes, để systemd vẫn xem dịch vụ là đang hoạt động ngay cả sau khi các tiến trình của nó kết thúc.1 Tuỳ chọn cuối là Type=idle: hoạt động như simple, nhưng chỉ thị systemd không khởi động dịch vụ cho tới khi mọi job đang hoạt động hoàn tất — ý tưởng là trì hoãn để các dịch vụ không giẫm lên đầu ra của nhau.1

  4. adding & removing units

    Thêm và bỏ unit — bài tập hai target vô hại Tự tạo thử một unit Adding and removing units — the harmless two-target exercise

    Thêm unit vào systemd chủ yếu là việc tạo tệp unit, rồi kích hoạt và có thể là bật (enable) chúng. Ward khuyên: bạn nên đặt các tệp unit của riêng mình vào thư mục cấu hình hệ thống /etc/systemd/system, để không nhầm lẫn chúng với thứ đi kèm distro, và để distro không ghi đè lên khi bạn nâng cấp.1

    Bạn hoàn toàn có thể tự viết một tệp unit. Cứ để nó trong thư mục /etc/systemd/system là an toàn. Nhớ nhé: đồ tự làm thì để riêng một chỗ.

    Adding units to systemd is primarily a matter of creating, then activating and possibly enabling, unit files. Ward advises putting your own unit files in the system configuration directory /etc/systemd/system so you won't confuse them with anything that came with your distribution, and so the distribution won't overwrite them when you upgrade.1

    Bài tập tác giả đề nghịThe exercise the author proposes Vì rất dễ tạo ra những target unit không thực sự làm gì, Ward mời bạn thử: tạo test1.target chỉ với [Unit] và Description=test 1; rồi tạo test2.target với Description=test 2 và Wants=test1.target. Từ khoá Wants ở đây định nghĩa một phụ thuộc khiến test1.target được kích hoạt khi bạn kích hoạt test2.target. Chạy systemctl start test2.target, rồi kiểm tra bằng systemctl status test1.target test2.target.1 Tạo hai “việc rỗng” không làm gì cả, để tập bật tắt mà không sợ hỏng máy. Because it's easy to create target units that don't actually do anything, Ward invites you to try: create test1.target with just [Unit] and Description=test 1; then create test2.target with Description=test 2 and Wants=test1.target. The Wants keyword defines a dependency that causes test1.target to activate when you activate test2.target. Run systemctl start test2.target, then check with systemctl status test1.target test2.target.1

    Gỡ một unit theo đúng thứ tự

    Để bỏ một unit, Ward đưa hai bước: vô hiệu hoá unit nếu cần bằng systemctl stop unit; rồi nếu unit có mục [Install], chạy systemctl disable unit để xoá các liên kết tượng trưng mà hệ thống phụ thuộc đã tạo. Sau đó bạn có thể xoá tệp unit nếu muốn.1

    Một cái bẫy nhỏ

    Ông ghi chú rằng vô hiệu hoá một unit vốn được bật ngầm — tức là không có mục [Install] — thì không có tác dụng gì.1 Đây là lý do systemctl disable đôi khi chạy êm ru mà dịch vụ vẫn tiếp tục khởi động: nó được kéo lên bởi phụ thuộc của một unit khác, chứ không bởi một liên kết trong thư mục .wants.

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

Phụ thuộc: bốn kiểu, hai bộ điều chỉnh thứ tự, và nghệ thuật chịu lỗi Việc nào cần việc nào, và việc nào trước việc nào Dependencies: four types, two ordering modifiers, and the art of fault tolerance

Ward mở mục phụ thuộc bằng một lập luận về thiết kế: một hệ thống mềm dẻo cho các phụ thuộc lúc khởi động và lúc vận hành đòi hỏi một mức phức tạp nhất định, bởi các quy tắc quá chặt có thể gây hiệu năng kém và mất ổn định.1 Ví dụ ông đưa rất sắc: giả sử bạn muốn hiện dấu nhắc đăng nhập sau khi khởi động máy chủ cơ sở dữ liệu, nên bạn định nghĩa một phụ thuộc chặt từ dấu nhắc đăng nhập tới máy chủ ấy. Nghĩa là nếu máy chủ cơ sở dữ liệu hỏng, dấu nhắc đăng nhập cũng hỏng — và bạn thậm chí không đăng nhập được vào máy để sửa lỗi.1

Nếu bạn bảo máy “không có A thì đừng làm B”, và A hỏng, thì B cũng hỏng theo. Đôi khi như thế là đúng. Nhưng nếu B là cái cửa để bạn vào sửa A, thì bạn tự nhốt mình ở ngoài. Nhớ nhé: đừng buộc chặt cái cửa vào cái bạn định sửa.

Ward opens the dependency section with a design argument: a flexible system for boot-time and operational dependencies requires some degree of complexity, because overly strict rules can cause poor performance and instability.1 His example is sharp: say you want a login prompt after a database server starts, so you define a strict dependency from the prompt to the server. If the database server fails, the login prompt fails too — and you can't even log in to fix it.1

Vì sao chịu lỗi lại là mặc định đúng. Ward nhận xét rằng các tác vụ khởi động Unix khá chịu lỗi và thường có thể thất bại mà không gây vấn đề nghiêm trọng cho các dịch vụ chuẩn. Ví dụ của ông: nếu bạn gỡ đĩa dữ liệu của hệ thống nhưng vẫn để lại mục /etc/fstab của nó (hoặc mount unit trong systemd), việc gắn hệ thống tệp lúc khởi động sẽ thất bại — điều này có thể ảnh hưởng tới các máy chủ ứng dụng như máy chủ web, nhưng thường không ảnh hưởng tới vận hành hệ thống chuẩn.1

Bốn kiểu, theo từ khoá. Requires — phụ thuộc chặt: khi kích hoạt một unit có phụ thuộc Requires, systemd cố kích hoạt unit phụ thuộc; nếu unit phụ thuộc hỏng, systemd cũng vô hiệu hoá unit phụ thuộc vào nó. Wants — phụ thuộc chỉ để kích hoạt: systemd kích hoạt các phụ thuộc Wants nhưng không quan tâm nếu chúng thất bại. Requisite — các unit phải đã hoạt động sẵn: systemd kiểm tra trạng thái trước, và nếu phụ thuộc chưa được kích hoạt thì việc kích hoạt unit kia thất bại. Conflicts — phụ thuộc âm: systemd tự động vô hiệu hoá unit đối lập nếu nó đang hoạt động; kích hoạt đồng thời hai unit xung đột sẽ thất bại.1

Bốn mức. “Bắt buộc phải có” — thiếu là hỏng cả hai. “Muốn có” — thiếu cũng không sao. “Phải có sẵn từ trước” — chưa có thì không làm. “Kỵ nhau” — có cái này thì tắt cái kia. Nhớ nhé: bắt buộc, muốn có, phải sẵn, kỵ nhau.

Four types, by keyword. Requires — strict dependencies: when activating a unit with a Requires dependency, systemd attempts to activate the dependency; if it fails, systemd deactivates the dependent unit too. Wants — activation-only dependencies: systemd activates them but doesn't care if they fail. Requisite — units that must already be active: systemd checks status first and fails the activation if the dependency isn't active. Conflicts — negative dependencies: systemd automatically deactivates the opposing unit if it's active, and simultaneous activation of conflicting units fails.1

Requires  → hỏng theo
Wants     → mặc kệ
Requisite → phải có sẵn
Conflicts → loại trừ nhau

Before / After → thứ tự

Requires → cùng sống cùng chết
Wants    → có thì tốt
Before/After → ai trước ai sau

Requires  → failure propagates
Wants     → failure ignored
Requisite → must be active already
Conflicts → mutually exclusive

Before / After → ordering

  1. Wants

    Wants — kiểu phụ thuộc mà chính tài liệu khuyên dùng “Muốn có” là lựa chọn an toàn nhất Wants — the dependency type the documentation itself recommends

    Ward gọi Wants là kiểu phụ thuộc đặc biệt quan trọng, bởi nó không lan truyền thất bại sang các unit khác. Ông dẫn thẳng tài liệu: trang man systemd.service(5) nói rằng đây là cách bạn nên chỉ định phụ thuộc nếu có thể — và lý do rất dễ thấy.1 Hành vi ấy tạo ra một hệ thống bền vững hơn nhiều, cho bạn cái lợi của một init truyền thống, nơi thất bại của một thành phần khởi động sớm không nhất thiết ngăn các thành phần sau khởi động.1

    Nếu phân vân chọn kiểu nào, hãy chọn “muốn có”. Nó khiến một chỗ hỏng không kéo sập cả dây chuyền. Nhớ nhé: buộc lỏng thì đứt một chỗ, buộc chặt thì đứt cả dây.

    Ward calls Wants especially significant because it doesn't propagate failures to other units. He cites the documentation directly: the systemd.service(5) manual page states this is how you should specify dependencies if possible — and it's easy to see why.1 The behaviour produces a much more robust system, giving you the benefit of a traditional init, where the failure of an earlier startup component doesn't necessarily prohibit later components from starting.1

    Xác nhận từ nguồn gốcConfirmed at the source Trang man systemd.unit(5) hiện hành mô tả Wants= bằng đúng tinh thần ấy: nếu các unit được liệt kê không khởi động được, điều đó không ảnh hưởng tới tính hợp lệ của giao dịch tổng thể, và unit này vẫn sẽ được khởi động; đây là cách được khuyến nghị để móc việc khởi động một unit vào việc khởi động một unit khác.7 Tài liệu chính thức cũng nói đúng như vậy. The current systemd.unit(5) manual page describes Wants= in exactly that spirit: if the listed units fail to start, this has no impact on the validity of the transaction as a whole and this unit will still be started; it is the recommended way to hook the start-up of one unit to the start-up of another.7

    Xem phụ thuộc của một unit

    Ward chỉ ra rằng bạn có thể xem các phụ thuộc của một unit bằng systemctl, miễn là bạn nêu rõ một kiểu phụ thuộc như Wants hay Requires: systemctl show -p type unit.1 Lệnh con show và cờ -p được mô tả trong systemctl(1).8

    Một biến thể đã bị gỡ bỏ

    Ward viết rằng các phụ thuộc khác chủ yếu là biến thể của những kiểu trên, và nêu ví dụ RequiresOverridable — giống Requires khi chạy bình thường nhưng hành xử như Wants nếu unit được kích hoạt thủ công.1 Cần ghi chú thẳng: RequiresOverridable= và RequisiteOverridable= đã bị gỡ khỏi systemd từ phiên bản 228, theo tệp NEWS của dự án, vì chúng ít được dùng và chỉ được hiện thực nửa vời.13 Trang này giữ nguyên cách trình bày của sách trong phần thân và ghi chú sự khác biệt ở đây.

  2. Before / After

    Thứ tự là một trục riêng, không đi kèm phụ thuộc “Cần nhau” khác với “trước sau” Ordering is a separate axis from dependency

    Đây là chỗ Ward đặt một cái bẫy tinh tế: cú pháp phụ thuộc cho tới đây chưa hề chỉ định thứ tự. Kích hoạt phần lớn service unit có phụ thuộc Requires hay Wants khiến các unit ấy khởi động cùng lúc. Và điều đó là tối ưu, bởi bạn muốn khởi động càng nhiều dịch vụ càng nhanh càng tốt để giảm thời gian boot.1

    Nói “B cần A” không có nghĩa là “A phải xong trước B”. Đó là hai câu khác nhau, và bạn phải nói riêng từng câu. Nhớ nhé: cần nhau là một chuyện, ai trước ai là chuyện khác.

    Here Ward lays a subtle trap: the dependency syntax so far has not explicitly specified order. Activating most service units with Requires or Wants dependencies causes those units to start at the same time. That is optimal, because you want to start as many services as possible as quickly as possible to reduce boot time.1

    Hai bộ điều chỉnhThe two modifiers Before — unit hiện tại sẽ kích hoạt trước (các) unit được liệt kê; ví dụ của Ward: nếu Before=bar.target xuất hiện trong foo.target, systemd kích hoạt foo.target trước bar.target. After — unit hiện tại kích hoạt sau (các) unit được liệt kê. Khi bạn dùng thứ tự, systemd đợi cho tới khi một unit có trạng thái đang hoạt động rồi mới kích hoạt các unit phụ thuộc vào nó.1 Muốn xếp trước sau thì dùng hai chữ: Before và After. Before — the current unit activates before the listed unit(s); Ward's example: if Before=bar.target appears in foo.target, systemd activates foo.target before bar.target. After — the current unit activates after the listed unit(s). When you use ordering, systemd waits until a unit has an active status before activating its dependent units.1

    Thứ tự ẩn trong Hình 6-1

    Ward thừa nhận thẳng rằng hình vẽ giấu một điều: trong hệ thống mà Hình 6-1 dựa vào, unit default.target được đặt khởi động sau multi-user.target — và sự phân biệt thứ tự này không được thể hiện trong hình.1 Đây chính là lý do một sơ đồ phụ thuộc đẹp mắt vẫn không đủ để suy ra trình tự khởi động thật.

    Hai trục trực giao

    Tài liệu systemd nói điều này còn thẳng hơn: các phụ thuộc thứ tự và phụ thuộc yêu cầu là trực giao với nhau. Nếu chỉ có một phụ thuộc yêu cầu giữa hai unit — ví dụ foo.service yêu cầu bar.service — mà không có phụ thuộc thứ tự, thì cả hai sẽ được khởi động song song.4

  3. default & conditional dependencies

    Phụ thuộc mặc định và phụ thuộc có điều kiện Những phụ thuộc bạn không hề viết ra Default and conditional dependencies

    Khi khám phá các phụ thuộc — đặc biệt với systemd-analyze — bạn có thể bắt đầu nhận ra rằng một số unit có những phụ thuộc không được nêu tường minh trong tệp unit hay cơ chế nào nhìn thấy được. Bạn dễ gặp điều này nhất ở các target unit có phụ thuộc Wants: systemd thêm một bộ điều chỉnh After bên cạnh bất kỳ unit nào được liệt kê là phụ thuộc Wants. Các phụ thuộc bổ sung này nằm bên trong systemd, được tính toán lúc khởi động, và không lưu trong tệp cấu hình.1

    Máy tự thêm vào vài quy tắc mà bạn không viết, để tránh những lỗi phổ biến và để tệp của bạn ngắn gọn. Nên đừng ngạc nhiên nếu thấy sơ đồ có nhiều mũi tên hơn bạn nghĩ. Nhớ nhé: máy tự thêm luật giúp bạn, nhưng không ghi vào tệp.

    As you explore dependencies — especially with systemd-analyze — you may notice that some units acquire dependencies not explicitly stated in unit files or other visible mechanisms. You're most likely to meet this in target units with Wants dependencies: systemd adds an After modifier alongside any unit listed as a Wants dependency. These additional dependencies are internal to systemd, calculated at boot time, and not stored in configuration files.1

    Tên gọi và cách tắtThe name and the off switch Bộ điều chỉnh After được thêm vào ấy gọi là một phụ thuộc mặc định (default dependency) — một bổ sung tự động vào cấu hình unit, nhằm tránh những lỗi phổ biến và giữ cho tệp unit nhỏ gọn. Chúng khác nhau tuỳ loại unit; những khác biệt ấy được liệt kê trong các mục DEFAULT DEPENDENCIES của các trang man cấu hình unit, như systemd.service(5) và systemd.target(5). Bạn có thể tắt một phụ thuộc mặc định trong một unit bằng cách thêm DefaultDependencies=no vào tệp cấu hình của nó.17 Nếu không muốn máy tự thêm luật, viết một dòng DefaultDependencies=no. That added After modifier is called a default dependency — an automatic addition to the unit configuration meant to avoid common mistakes and keep unit files small. These vary by unit type and are listed in the DEFAULT DEPENDENCIES sections of the unit configuration manual pages, such as systemd.service(5) and systemd.target(5). You can disable a default dependency in a unit by adding DefaultDependencies=no to its configuration file.17

    Kiểm tra trạng thái hệ điều hành, không phải unit

    Ward nêu ba ví dụ về tham số phụ thuộc có điều kiện, vốn kiểm tra các trạng thái của hệ điều hành thay vì kiểm tra unit: ConditionPathExists=p đúng nếu đường dẫn tệp p tồn tại trong hệ thống; ConditionPathIsDirectory=p đúng nếu p là một thư mục; ConditionFileNotEmpty=p đúng nếu p là một tệp và không rỗng.1 Cả ba đều có trong mục Conditions and Asserts của systemd.unit(5).7

    Phạm vi của một điều kiện sai

    Nếu một phụ thuộc có điều kiện trong một unit là sai khi systemd cố kích hoạt unit ấy, unit đó không được kích hoạt — nhưng điều này chỉ áp dụng cho chính unit chứa điều kiện. Nghĩa là nếu bạn kích hoạt một unit vừa có phụ thuộc có điều kiện vừa có phụ thuộc unit, systemd vẫn cố kích hoạt các phụ thuộc unit đó bất kể điều kiện đúng hay sai.1

  4. [Install] & enabling

    Mục [Install] — khai báo phụ thuộc “ngược” Bật một unit thật ra là tạo một lối tắt The [Install] section — declaring a dependency "in reverse"

    Cho tới đây ta chỉ định nghĩa phụ thuộc trong tệp cấu hình của unit phụ thuộc. Ward chỉ ra rằng cũng có thể làm ngược lại — nêu tên unit phụ thuộc trong tệp của chính unit được phụ thuộc — bằng cách thêm tham số WantedBy hoặc RequiredBy vào mục [Install]. Cơ chế này cho phép bạn thay đổi thời điểm một unit nên khởi động mà không phải sửa các tệp cấu hình khác, chẳng hạn khi bạn không muốn động tới một tệp unit hệ thống.1

    Thay vì viết trong tệp A rằng “A cần B”, bạn có thể viết trong tệp B rằng “B thuộc về A”. Cách thứ hai tiện hơn khi tệp A không phải của bạn. Nhớ nhé: nói từ phía nào cũng được, miễn là nói một lần.

    So far we've defined dependencies in the dependent unit's configuration file. Ward points out you can also do it "in reverse" — naming the dependent unit in the dependency's own file — by adding a WantedBy or RequiredBy parameter in the [Install] section. This lets you alter when a unit should start without modifying additional configuration files, for example when you'd rather not edit a system unit file.1

    Bật một unit làm gìWhat enabling actually does Ward viết lại hai target ví dụ: test1.target giờ có mục [Install] với WantedBy=test2.target, còn test2.target không còn dòng Wants nào. Vì đã có mục [Install], bạn phải bật unit trước khi khởi động nó — và đầu ra của systemctl enable test1.target cho thấy chính xác chuyện gì xảy ra: Created symlink /etc/systemd/system/test2.target.wants/test1.target → /etc/systemd/system/test1.target. Tác dụng của việc bật một unit là tạo một liên kết tượng trưng trong thư mục con .wants tương ứng với unit phụ thuộc.1 “Bật” một dịch vụ chỉ là tạo một lối tắt trong một thư mục. Không có gì bí ẩn. Ward rewrites the two example targets: test1.target now has an [Install] section with WantedBy=test2.target, and test2.target has no Wants line. Because there is now an [Install] section, you must enable the unit before starting it — and the output of systemctl enable test1.target shows exactly what happens: Created symlink /etc/systemd/system/test2.target.wants/test1.target → /etc/systemd/system/test1.target. The effect of enabling a unit is to create a symbolic link in a .wants subdirectory corresponding to the dependent unit.1

    Bật không phải là kích hoạt

    Ward đặt hẳn một ghi chú cho câu này: bật một unit không kích hoạt nó.1 Trong vận hành bình thường, systemd bỏ qua mục [Install] của một unit nhưng ghi nhận sự hiện diện của nó, và mặc định coi unit đó là đã bị vô hiệu hoá. Việc bật một unit tồn tại qua các lần khởi động lại.1 Để tắt và xoá liên kết, dùng systemctl disable — đầu ra ông in ra là Removed /etc/systemd/system/test2.target.wants/test1.target.1

    Những liên kết thủ công khó lần

    Mục [Install] thường chịu trách nhiệm cho các thư mục .wants và .requires trong thư mục cấu hình hệ thống. Tuy nhiên, thư mục cấu hình unit [/usr]/lib/systemd/system cũng chứa các thư mục .wants, và bạn cũng có thể thêm các liên kết không tương ứng với mục [Install] nào trong tệp unit. Ward gọi đây là một cách đơn giản để thêm phụ thuộc mà không sửa một tệp unit có thể bị ghi đè trong tương lai — nhưng ông nói thẳng là không đặc biệt được khuyến khích, vì một bổ sung thủ công rất khó lần dấu.1

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

Khởi động theo yêu cầu: tách tài nguyên ra khỏi dịch vụ Chỉ bật khi có người gõ cửa On-demand startup: separating the resource from the service

Một trong những tính năng của systemd là khả năng trì hoãn việc khởi động một unit cho tới khi nó thực sự cần thiết.1 Ward mô tả bố cục thường thấy theo bốn bước: bạn tạo một unit (gọi là Unit A) cho dịch vụ bạn muốn cung cấp; bạn xác định một tài nguyên hệ thống mà Unit A dùng để cung cấp dịch vụ của nó — như một cổng/socket mạng, một tệp, hay một thiết bị; bạn tạo một unit khác (Unit R) biểu diễn tài nguyên ấy; và bạn định nghĩa quan hệ giữa hai unit — thường là ngầm định dựa trên tên, nhưng cũng có thể tường minh.1

Tưởng tượng một quầy hàng: thay vì để nhân viên đứng chờ cả ngày, ta chỉ đặt sẵn cái chuông. Ai bấm chuông thì nhân viên mới ra. Systemd làm đúng thế: nó canh cái “chuông” — là một cổng mạng hay một tệp — rồi mới bật dịch vụ. Nhớ nhé: đặt chuông trước, gọi người sau.

One of systemd's features is the ability to delay a unit's startup until it is absolutely needed.1 Ward describes the usual setup in four steps: you create a unit (call it Unit A) for the service you'd like to provide; you identify a system resource Unit A uses to offer its services — a network port/socket, a file, or a device; you create another unit (Unit R) to represent that resource; and you define the relationship between them — normally implicit based on the units' names, but it can also be explicit.1

Vận hành, cũng bốn bước. Khi đã dựng xong: (1) khi Unit R được kích hoạt, systemd theo dõi tài nguyên; (2) khi có thứ gì đó cố truy cập tài nguyên, systemd chặn tài nguyên lại và đệm dữ liệu đi vào; (3) systemd kích hoạt Unit A; (4) khi sẵn sàng, dịch vụ từ Unit A nắm quyền kiểm soát tài nguyên, đọc dữ liệu đã đệm, và chạy bình thường.1 Bước (2) — đệm dữ liệu — là chi tiết khiến cả cơ chế trở nên trong suốt với máy khách: nó không hề biết rằng dịch vụ vừa mới được khởi động cho nó.

Ba điều cần lưu tâm. Ward nêu ba mối lo: bạn phải bảo đảm unit tài nguyên của mình bao phủ mọi tài nguyên mà dịch vụ cung cấp — thường không thành vấn đề vì hầu hết dịch vụ chỉ có một điểm truy cập; bạn phải bảo đảm unit tài nguyên được gắn với service unit mà nó biểu diễn, ngầm định hoặc tường minh; và không phải mọi máy chủ đều biết cách giao tiếp với các unit tài nguyên mà systemd có thể cung cấp.1

Ba chỗ dễ hụt. Phải canh đủ mọi cửa, phải nối đúng chuông với đúng người, và phải chắc là dịch vụ đó biết nhận chuông. Nhớ nhé: đủ cửa, đúng người, biết nhận.

Three concerns. Ward names three: you must make sure your resource unit covers every resource the service provides — normally not a problem, since most services have just one point of access; you must make sure the resource unit is tied to the service unit it represents, implicitly or explicitly; and not all servers know how to interface with the resource units systemd can provide.1

echo.socket  [Socket]
  ListenStream=22222
  Accept=true

echo@.service [Service]
  ExecStart=/bin/cat
  StandardInput=socket

chuông: cổng 22222
người: chương trình cat
nối nhau bằng cùng tên “echo”

echo.socket  [Socket]
  ListenStream=22222
  Accept=true

echo@.service [Service]
  ExecStart=/bin/cat
  StandardInput=socket

  1. socket unit

    Dịch vụ echo — liên kết được thiết lập bằng quy ước đặt tên Ví dụ nhỏ: dịch vụ nói theo The echo service — the link is made by naming convention

    Ward dựng một ví dụ ông tự nhận là “hơi nâng cao”: một dịch vụ echo mạng đơn giản, lặp lại bất cứ thứ gì máy khách gửi sau khi kết nối, lắng nghe trên cổng TCP 22222.1 Tệp echo.socket chỉ có [Unit] Description=echo socket và [Socket] với ListenStream=22222, Accept=true. Điểm mấu chốt ông nhấn mạnh: trong tệp unit đó không hề nhắc tới service unit mà socket này hỗ trợ.1

    Ví dụ trong sách là một dịch vụ “nói theo”: bạn gõ gì nó lặp lại y hệt. Có hai tệp: một tệp canh cổng, một tệp chạy chương trình. Chúng nhận ra nhau nhờ cùng một cái tên. Nhớ nhé: cùng tên thì tự tìm thấy nhau.

    Ward builds an example he calls "somewhat advanced": a simple network echo service that repeats whatever a client sends after connecting, listening on TCP port 22222.1 The echo.socket file carries only [Unit] Description=echo socket and a [Socket] section with ListenStream=22222 and Accept=true. His key point: there is no mention of the service unit this socket supports inside the unit file.1

    Liên kết ngầmThe implicit link Tệp service unit tương ứng tên là echo@.service, và liên kết được thiết lập bằng quy ước đặt tên: nếu một tệp service unit có cùng tiền tố với một tệp .socket — ở đây là echo — systemd biết phải kích hoạt service unit ấy khi có hoạt động trên socket unit.1 Tệp echo@.service chỉ có ExecStart=/bin/cat và StandardInput=socket.1 Hai tệp nhận nhau chỉ nhờ trùng tên ở phần đầu. The corresponding service unit file is echo@.service, and the link is established by naming convention: if a service unit file has the same prefix as a .socket file — here echo — systemd knows to activate that service unit when there's activity on the socket unit.1 The echo@.service file carries only ExecStart=/bin/cat and StandardInput=socket.1

    Khi bạn không thích liên kết ngầm

    Ward ghi chú: nếu bạn không thích việc kích hoạt ngầm dựa trên tiền tố, hoặc cần nối các unit có tiền tố khác nhau, bạn dùng một tuỳ chọn tường minh trong unit định nghĩa tài nguyên — ví dụ đặt Socket=bar.socket bên trong foo.service để bar.socket trao socket của nó cho foo.service.1 Trang man systemd.socket(5) mô tả các tuỳ chọn ListenStream=, Accept= và cơ chế ghép cặp socket–service này.14

    Chạy thử và dọn dẹp

    Để ví dụ chạy được, bạn khởi động socket unit: systemctl start echo.socket. Sau đó thử dịch vụ bằng cách kết nối tới cổng TCP 22222 cục bộ với một tiện ích như telnet; dịch vụ sẽ lặp lại thứ bạn gõ. Khi chán, nhấn CTRL-] trên một dòng riêng rồi CTRL-D; để dừng dịch vụ, bạn dừng socket unit: systemctl stop echo.socket.1 Ward cũng nhắc rằng telnet có thể không được cài sẵn trên distro của bạn.1

  2. Accept=true

    Thể hiện và bàn giao — ai là người nhận kết nối Vì sao có nhiều bản cùng lúc Instances and handoff — who accepts the connection

    Vì unit echo@.service hỗ trợ nhiều thể hiện đồng thời, nên tên nó có dấu @. Ward đặt câu hỏi vì sao bạn lại muốn nhiều thể hiện, và tự trả lời: giả sử có hơn một máy khách mạng kết nối tới dịch vụ cùng lúc, và bạn muốn mỗi kết nối có thể hiện riêng. Trong trường hợp này, service unit phải hỗ trợ nhiều thể hiện vì ta đã đưa tuỳ chọn Accept=true vào echo.socket.1

    Nếu nhiều người cùng gõ cửa một lúc, mỗi người cần một nhân viên riêng. Dấu @ trong tên tệp chính là cách nói “cho phép nhiều bản”. Nhớ nhé: dấu @ nghĩa là được nhân bản.

    Because the echo@.service unit supports multiple simultaneous instances, there's an @ in the name. Ward asks why you'd want multiple instances and answers: say more than one network client connects to the service at the same time and you want each connection to have its own instance. In this case the service unit must support multiple instances because we included Accept=true in echo.socket.1

    Tuỳ chọn này làm gìWhat that option does Accept=true chỉ thị systemd không chỉ lắng nghe trên cổng, mà còn chấp nhận các kết nối đi vào thay mặt service unit rồi chuyển chúng cho unit ấy, tạo một thể hiện riêng cho mỗi kết nối. Mỗi thể hiện đọc dữ liệu từ kết nối như đầu vào chuẩn, nhưng không nhất thiết cần biết dữ liệu đó đến từ một kết nối mạng.1 Máy tự nhận cuộc gọi rồi chuyển máy cho một nhân viên mới toanh. Accept=true instructs systemd not only to listen on the port but also to accept incoming connections on the service unit's behalf and pass them to it, creating a separate instance for each connection. Each instance reads data from the connection as standard input, but doesn't necessarily need to know the data comes from a network connection.1

    Trường hợp ngược lại

    Ward nêu rõ cấu hình đối xứng: nếu một service unit có thể tự làm việc chấp nhận kết nối, thì đừng đặt dấu @ trong tên tệp unit của nó, và đừng đặt Accept=true trong socket unit. Khi ấy service unit nắm toàn quyền kiểm soát socket từ tay systemd, và systemd sẽ không cố lắng nghe trên cổng mạng lần nữa cho tới khi service unit kết thúc.1

    Đừng kỳ vọng quá nhiều ở ví dụ này

    Ông cảnh báo rằng hầu hết kết nối mạng đòi hỏi nhiều mềm dẻo hơn một cổng nối đơn giản tới đầu vào và đầu ra chuẩn, nên đừng kỳ vọng tạo được các dịch vụ mạng phức tạp bằng một tệp service unit như echo@.service.1 Ông cũng thừa nhận tài liệu cho các tuỳ chọn bàn giao trải rộng trên nhiều trang man, và chỉ ra ba trang cho các unit hướng tài nguyên — systemd.socket(5), systemd.path(5), systemd.device(5) — cùng một trang thường bị bỏ sót cho service unit là systemd.exec(5), vốn chứa thông tin về việc service unit có thể kỳ vọng nhận tài nguyên thế nào khi được kích hoạt.115

  3. boot optimization

    Unit phụ trợ — dùng cơ chế theo yêu cầu để không chờ Cùng một mẹo, dùng cho mục đích khác Auxiliary units — using the on-demand machinery not to wait

    Đây là chỗ khéo nhất của chương. Ward chỉ ra rằng một mục tiêu tổng thể của systemd là đơn giản hoá thứ tự phụ thuộc và tăng tốc thời gian khởi động — và các unit tài nguyên cho phép làm điều đó theo cách giống khởi động theo yêu cầu. Vẫn có một service unit và một unit phụ trợ biểu diễn tài nguyên mà service unit cung cấp, chỉ khác ở chỗ lần này systemd khởi động service unit ngay khi nó kích hoạt unit phụ trợ, thay vì ngồi chờ một yêu cầu.1

    Mẹo cái chuông còn dùng được cho việc khác: đặt chuông xong là gọi người ngay, không đợi ai bấm. Vì sao? Vì trong lúc người đó đang tới, ai cần đã có thể xếp hàng trước cái chuông rồi. Nhớ nhé: mở cửa trước, dọn hàng sau.

    This is the cleverest turn in the chapter. Ward notes that an overall goal of systemd is to simplify dependency order and speed up boot time — and resource units offer a way to do this similar to on-demand startup. There's still a service unit and an auxiliary unit representing the resource it offers, except that here systemd starts the service unit as soon as it activates the auxiliary unit rather than waiting for a request.1

    Lý do của cách làm nàyThe reason for the scheme Ward giải thích: các service unit thiết yếu lúc khởi động — ví dụ systemd-journald.service — mất chút thời gian để khởi động, và nhiều unit khác phụ thuộc vào chúng. Nhưng systemd có thể cung cấp tài nguyên thiết yếu của một unit (như một socket unit) rất nhanh, rồi lập tức kích hoạt không chỉ unit thiết yếu ấy mà cả những unit phụ thuộc vào nó. Khi unit thiết yếu sẵn sàng, nó tiếp quản tài nguyên.1 Dịch vụ ghi nhật ký cần vài giây để bật. Nhưng cái “hộp thư” của nó thì mở ngay được — nên mọi thứ khác không phải chờ. Ward explains: essential boot-time service units such as systemd-journald.service take some time to start, and many other units depend on them. But systemd can offer a unit's essential resource (such as a socket unit) very quickly, and then immediately activate not only the essential unit but any units that depend on it. Once the essential unit is ready, it takes control of the resource.1

    Hai dòng thời gian

    Hình 6-2 của Ward vẽ một dòng thời gian khởi động tuần tự: Dịch vụ E cung cấp Tài nguyên R thiết yếu; các Dịch vụ A, B, C phụ thuộc vào tài nguyên này (nhưng không phụ thuộc lẫn nhau) và phải đợi tới khi Dịch vụ E khởi động xong — vì hệ thống không khởi động dịch vụ mới cho tới khi xong dịch vụ trước, nên rất lâu mới tới lượt Dịch vụ C.1 Hình 6-3 vẽ cấu hình systemd tương đương: vì systemd có thể cung cấp giao diện cho Unit R trong lúc Unit E đang khởi động, các Unit A, B, C và E đều có thể khởi động cùng lúc; khi sẵn sàng, Unit E tiếp quản Unit R.1

    Cái giá của song song hoá

    Ward không giấu mặt trái: khi bạn song song hoá quá trình khởi động như vậy, có khả năng hệ thống của bạn chậm đi tạm thời vì một lượng lớn unit cùng khởi động một lúc.1 Ông cũng đưa một quan sát tinh: Unit A, B hay C có thể không cần truy cập tài nguyên mà Unit R cung cấp trước khi hoàn tất khởi động — điều ta làm ở đây chỉ là cho chúng tuỳ chọn bắt đầu truy cập tài nguyên sớm nhất có thể.1 Để xem ví dụ thực tế, ông bảo hãy nhìn các unit cấu hình journald và D-Bus trên một máy chạy systemd; chúng rất có thể được song song hoá theo cách này.1 Lennart Poettering, tác giả systemd, mô tả cùng ý tưởng kích hoạt qua socket trong bài giới thiệu gốc về systemd.16

  4. auxiliary components

    Những thành phần phụ trợ mang tiền tố systemd- systemd đã lớn ra ngoài việc khởi động The auxiliary components prefixed systemd-

    Ward ghi nhận một hiện tượng: khi systemd trở nên phổ biến, nó lớn dần để bao gồm hỗ trợ cho một vài tác vụ không liên quan tới khởi động và quản lý dịch vụ, cả trực tiếp lẫn qua các lớp tương thích phụ trợ. Bạn có thể để ý số lượng chương trình lớn trong /lib/systemd; đó là các tệp thực thi liên quan tới những chức năng ấy.1

    Ban đầu systemd chỉ lo việc bật máy. Giờ nó làm thêm nhiều việc khác: ghi nhật ký, quản lý thiết bị, tra cứu tên miền. Tên của chúng đều bắt đầu bằng systemd-. Nhớ nhé: thấy tên bắt đầu bằng systemd- là biết họ hàng nhà nó.

    Ward records a phenomenon: as systemd has grown in popularity, it has grown to include support for a few tasks not related to startup and service management, both directly and through auxiliary compatibility layers. You may notice the numerous programs in /lib/systemd; those are the executables related to those functions.1

    Ba dịch vụ ông kể tênThe three services he names udevd — bạn đã học ở Chương 3; nó là một phần của systemd. journald — một dịch vụ ghi nhật ký xử lý vài cơ chế ghi nhật ký khác nhau, kể cả dịch vụ syslog Unix truyền thống, bàn kỹ ở Chương 7. resolved — một tiến trình nền đệm dịch vụ tên cho DNS, bàn ở Chương 9. Mọi tệp thực thi cho các dịch vụ này đều mang tiền tố systemd-; ví dụ udevd tích hợp trong systemd được gọi là systemd-udevd.1 Ba cái tên hay gặp: quản lý thiết bị, ghi nhật ký, và tra tên miền. udevd — met in Chapter 3; it's part of systemd. journald — a logging service handling several logging mechanisms including the traditional Unix syslog service, covered in Chapter 7. resolved — a name service caching daemon for DNS, covered in Chapter 9. All executables for these services are prefixed with systemd-; for example the systemd-integrated udevd is called systemd-udevd.1

    Nhiều thứ chỉ là lớp bọc

    Ward khuyên đào sâu hơn một chút: bạn sẽ thấy một số chương trình trong đó là những lớp bọc tương đối đơn giản, mà chức năng chỉ là chạy các tiện ích hệ thống chuẩn rồi báo kết quả cho systemd. Ví dụ ông đưa là systemd-fsck.1

    Cách tra một chương trình lạ

    Nếu bạn thấy một chương trình trong /lib/systemd mà không nhận ra, Ward bảo hãy tìm trang man của nó: khả năng cao trang đó không chỉ mô tả tiện ích ấy, mà còn cho biết loại unit mà nó được thiết kế để bổ trợ.1 Đây là một thói quen tra cứu đáng giữ — nó biến một thư mục đầy tên lạ thành một bản đồ đọc được.

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

Runlevel và System V init: thế giới của liên kết tượng trưng Cách cũ: đánh số trạng thái và xếp lối tắt Runlevels and System V init: a world of symbolic links

Tại bất kỳ thời điểm nào trên một hệ thống Linux, một tập tiến trình nền tảng nhất định — chẳng hạn crond và udevd — đang chạy. Trong System V init, trạng thái này của máy gọi là runlevel (mức chạy), được ký hiệu bằng một số từ 0 tới 6. Một hệ thống dành phần lớn thời gian ở một runlevel duy nhất, nhưng khi bạn tắt máy, init chuyển sang một runlevel khác để kết thúc các dịch vụ hệ thống một cách có trật tự và bảo nhân dừng lại.1

Ngày xưa người ta đánh số các trạng thái của máy: 0 là tắt, 6 là khởi động lại, 5 thường là có màn hình đồ hoạ. Máy ở một số, và khi tắt thì chuyển sang số khác. Nhớ nhé: mỗi số là một trạng thái của máy.

At any given time on a Linux system a certain base set of processes — such as crond and udevd — is running. In System V init this state of the machine is called its runlevel, denoted by a number from 0 through 6. A system spends most of its time in a single runlevel, but when you shut down, init switches to a different runlevel to terminate system services in an orderly fashion and tell the kernel to stop.1

Lập trường của Ward. Ông không giả vờ trung lập: runlevel đang trở thành chuyện của quá khứ. Ngay cả khi systemd có hỗ trợ chúng, systemd vẫn coi runlevel là lỗi thời với vai trò trạng thái kết thúc của hệ thống, và ưa dùng target unit hơn. Với systemd, runlevel tồn tại chủ yếu để khởi động các dịch vụ vốn chỉ hỗ trợ kịch bản System V init.1 Ward cũng nói trước rằng bạn có thể sẽ không thực sự gặp bất cứ thứ gì trong mục này.1

Cấu trúc của một cài đặt System V init. Ward mô tả nó có hai thành phần: một tệp cấu hình trung tâm, và một tập lớn các kịch bản khởi động được bổ sung bởi một trang trại liên kết tượng trưng. Tệp cấu hình /etc/inittab là nơi mọi thứ bắt đầu; nếu bạn có System V init, hãy tìm một dòng như id:5:initdefault: trong tệp inittab — dòng đó cho biết runlevel mặc định là 5.1

Hai phần. Một tệp chính ghi “máy này mặc định vào trạng thái nào”, và một đống kịch bản nhỏ để bật từng thứ. Nhớ nhé: một tệp chỉ huy, nhiều kịch bản thi hành.

The structure of a System V init installation. Ward describes two components: a central configuration file and a large set of boot scripts augmented by a symbolic link farm. The configuration file /etc/inittab is where it all starts; if you have System V init, look for a line like id:5:initdefault: in your inittab — that line indicates the default runlevel is 5.1

inittab: id : runlevel : action : command

id:5:initdefault:
l5:5:wait:/etc/rc.d/rc 5
1:2345:respawn:/sbin/mingetty tty1

mỗi dòng có 4 phần:
tên : số : việc gì : lệnh nào

inittab: id : runlevel : action : command

id:5:initdefault:
l5:5:wait:/etc/rc.d/rc 5
1:2345:respawn:/sbin/mingetty tty1

  1. inittab

    Bốn trường, và bốn hành động đáng nhớ Đọc được một dòng inittab Four fields, and four actions worth knowing

    Mọi dòng trong inittab có dạng bốn trường phân tách bằng dấu hai chấm, theo thứ tự: một định danh duy nhất (một chuỗi ngắn như id); số runlevel áp dụng; hành động mà init nên thực hiện; và một lệnh để chạy (tuỳ chọn).1 Bạn có thể kiểm tra runlevel hiện tại bằng lệnh who -r; đầu ra ví dụ của Ward là run-level 5 2019-01-27 16:43 — cho biết runlevel hiện tại là 5 cùng ngày giờ nó được thiết lập.1

    Mỗi dòng chia làm bốn ô, cách nhau bằng dấu hai chấm: tên riêng, số trạng thái, kiểu việc, và câu lệnh. Đọc trái sang phải là hiểu. Nhớ nhé: bốn ô, cách nhau dấu hai chấm.

    Every line in inittab takes the form of four colon-separated fields in this order: a unique identifier (a short string such as id); the applicable runlevel number(s); the action init should take; and a command to execute (optional).1 You can check your current runlevel with who -r; Ward's sample output is run-level 5 2019-01-27 16:43 — the current runlevel is 5, plus the date and time it was established.1

    Bốn hành độngThe four actions initdefault đặt runlevel mặc định. wait — trong dòng l5:5:wait:/etc/rc.d/rc 5 — quyết định khi nào và cách nào init chạy lệnh: chạy /etc/rc.d/rc 5 một lần khi vào runlevel 5, rồi đợi lệnh này xong mới làm việc khác. respawn bảo init chạy lệnh theo sau và, nếu lệnh kết thúc, chạy lại nó — dòng 1:2345:respawn:/sbin/mingetty tty1 dùng cho bảng điều khiển ảo đầu tiên, và chính hành động này mang dấu nhắc đăng nhập trở lại sau khi bạn đăng xuất. ctrlaltdel điều khiển việc hệ thống làm khi bạn nhấn CTRL-ALT-DEL. sysinit là thứ đầu tiên init nên chạy khi khởi động, trước khi vào bất kỳ runlevel nào.1 Bốn kiểu việc hay gặp: đặt mặc định; chạy rồi đợi; chạy lại mãi; và việc chạy đầu tiên. initdefault sets the default runlevel. wait — in the line l5:5:wait:/etc/rc.d/rc 5 — determines when and how init runs the command: run /etc/rc.d/rc 5 once on entering runlevel 5, then wait for it to finish before doing anything else. respawn tells init to run the following command and, if it finishes, run it again — the line 1:2345:respawn:/sbin/mingetty tty1 serves the first virtual console, and this action is what brings the login prompt back after you log out. ctrlaltdel controls what the system does when you press CTRL-ALT-DEL. sysinit is the first thing init should run when starting, before entering any runlevels.1

    Dòng quan trọng nhất

    Ward gọi dòng l5:5:wait:/etc/rc.d/rc 5 là đặc biệt quan trọng, vì nó kích hoạt phần lớn cấu hình và dịch vụ hệ thống: lệnh rc 5 thực thi mọi thứ trong /etc/rc5.d bắt đầu bằng một con số, theo thứ tự số.1 Ông cũng giải nghĩa cái tên: rc là viết tắt của run commands, thứ mà nhiều người gọi là kịch bản, chương trình, hoặc dịch vụ.1

    Tra cứu đầy đủ

    Ward chỉ nêu những hành động thường gặp nhất và hẹn bạn xem trang man inittab(5) để biết thêm các hành động khả dụng khác.1 Trang man ấy ngày nay đi kèm gói sysvinit-core trên các distro dựa trên Debian.17

  2. link farm

    Trang trại liên kết — chữ S, chữ K, và hai chữ số Vì sao tên tệp có số ở đầu The link farm — an S, a K, and two digits

    Lệnh rc 5 khởi động các chương trình trong thư mục rc5.d bằng cách chạy lần lượt S10sysklogd start, S12kerneld start, S15netstd_init start… Ward giải mã quy ước đặt tên: chữ S hoa trong tên lệnh nghĩa là lệnh đó nên chạy ở chế độ start, còn con số — từ 00 tới 99 — quyết định vị trí của lệnh trong trình tự mà rc khởi động. Các lệnh rc*.d thường là kịch bản shell khởi động các chương trình trong /sbin hoặc /usr/sbin.1

    Tên tệp kiểu S10sysklogd nghĩa là: chữ S = hãy bật, số 10 = bật ở lượt thứ 10. Máy cứ theo số nhỏ tới số lớn mà chạy. Nhớ nhé: chữ cái bảo làm gì, con số bảo làm lúc nào.

    The rc 5 command starts programs in the rc5.d directory by running S10sysklogd start, S12kerneld start, S15netstd_init start and so on. Ward decodes the convention: a capital S in a command name means the command should run in start mode, and the number — 00 through 99 — determines where in the sequence rc starts it. The rc*.d commands are usually shell scripts that start programs in /sbin or /usr/sbin.1

    Liên kết trỏ về đâuWhere the links point Nội dung các thư mục rc*.d thực ra là liên kết tượng trưng tới các tệp trong một thư mục khác: init.d. Một danh sách dài của thư mục như rc5.d cho thấy cấu trúc kiểu S10sysklogd -> ../init.d/sysklogd.1 Một số lượng lớn liên kết tượng trưng trải khắp nhiều thư mục con như vậy gọi là trang trại liên kết (link farm). Các distro chứa những liên kết này để dùng chung một bộ kịch bản khởi động cho mọi runlevel — Ward nhấn mạnh đây là một quy ước, không phải yêu cầu, nhưng nó đơn giản hoá tổ chức.1 Những tệp trong rc5.d chỉ là lối tắt trỏ về một thư mục duy nhất tên init.d. The contents of the rc*.d directories are actually symbolic links to files in another directory, init.d. A long listing of a directory such as rc5.d reveals a structure like S10sysklogd -> ../init.d/sysklogd.1 A large number of symbolic links across several subdirectories like this is called a link farm. Distributions contain these links so they can use the same startup scripts for all runlevels — Ward stresses this is a convention, not a requirement, but it simplifies organization.1

    Chữ K và chế độ dừng

    Ward ghi chú rằng một số thư mục rc*.d chứa các lệnh bắt đầu bằng chữ K — nghĩa là “kill”, tức chế độ dừng. Trong trường hợp này, rc chạy lệnh với đối số stop thay vì start. Bạn dễ gặp các lệnh K nhất ở những runlevel dùng để tắt hệ thống.1

    Mẹo gạch dưới

    Cách phổ biến nhất để đổi trình tự khởi động là sửa trang trại liên kết — và Ward cảnh báo phải cẩn thận. Bạn có thể nghĩ tới việc xoá liên kết tượng trưng trong thư mục rc*.d, nhưng nếu sau này cần đặt lại, bạn có thể không nhớ đúng tên. Một trong những cách tốt nhất là thêm dấu gạch dưới vào đầu tên liên kết: mv S99httpd _S99httpd. Thay đổi này khiến rc bỏ qua _S99httpd vì tên tệp không còn bắt đầu bằng S hay K, nhưng tên gốc vẫn cho biết mục đích của nó.1 Khi thêm một dịch vụ, ông khuyên chọn chỗ thích hợp trong trình tự: với các dịch vụ không thiết yếu, phần lớn quản trị viên ưa các số trong khoảng 90, đặt chúng sau hầu hết dịch vụ đi kèm hệ thống.1

  3. run-parts & telinit

    run-parts và telinit — hai công cụ sống lâu hơn cha chúng Hai công cụ nhỏ còn sót lại run-parts and telinit — two tools that outlived their parent

    Cơ chế mà System V init dùng để chạy các kịch bản init.d đã len vào nhiều hệ thống Linux, bất kể chúng có dùng System V init hay không. Đó là tiện ích run-parts, và điều duy nhất nó làm là chạy một loạt chương trình thực thi trong một thư mục cho trước, theo một thứ tự nào đó có thể đoán được. Ward mô tả nó gần như một người gõ lệnh ls trong một thư mục rồi chạy lần lượt mọi chương trình trong đầu ra.1

    Có một công cụ nhỏ tên run-parts: đưa cho nó một thư mục, nó chạy hết mọi chương trình trong đó. Đơn giản vậy thôi, nhưng vẫn còn được dùng nhiều nơi. Nhớ nhé: một thư mục vào, một loạt chương trình chạy.

    The mechanism System V init uses to run the init.d scripts has found its way into many Linux systems, whether or not they use System V init. It's a utility called run-parts, and the only thing it does is run a bunch of executable programs in a given directory in some predictable order. Ward describes it as almost like a person entering ls in a directory and then running whatever programs are listed.1

    Hai phiên bảnTwo versions Hành vi mặc định là chạy mọi chương trình trong một thư mục, nhưng bạn thường có tuỳ chọn chọn một số chương trình và bỏ qua số khác. Ward ghi nhận sự phân hoá giữa các distro: Fedora xuất xưởng một run-parts rất đơn giản, trong khi Debian và Ubuntu có một chương trình run-parts phức tạp hơn — với khả năng chạy chương trình dựa trên biểu thức chính quy (ví dụ dùng biểu thức S[0-9]{2} để chạy mọi kịch bản “start” trong một thư mục runlevel /etc/init.d) và truyền đối số cho chương trình.118 Bản Debian/Ubuntu thông minh hơn bản Fedora, chọn lọc được chương trình nào cần chạy. The default behavior is to run all programs in a directory, but you often have the option to select certain programs and ignore others. Ward records the split between distributions: Fedora ships a very simple run-parts, while Debian and Ubuntu have a more complicated one — able to run programs based on a regular expression (for example using S[0-9]{2} to run all "start" scripts in an /etc/init.d runlevel directory) and to pass arguments to the programs.118

    Điều khiển init bằng telinit

    Thỉnh thoảng bạn cần “thúc” init một chút — bảo nó chuyển runlevel, đọc lại cấu hình, hoặc tắt hệ thống. Với System V init, bạn dùng telinit: telinit 3 để chuyển sang runlevel 3. Ward cảnh báo rằng khi chuyển runlevel, init cố diệt mọi tiến trình không có trong tệp inittab cho runlevel mới, nên hãy cẩn thận. Khi bạn cần thêm hoặc bỏ việc, hay bất kỳ thay đổi nào với inittab, bạn phải báo cho init và bắt nó nạp lại tệp bằng telinit q. Bạn cũng có thể dùng telinit s để chuyển sang chế độ một người dùng.1

    Khởi động và dừng bằng tay

    Để khởi động và dừng dịch vụ bằng tay, Ward bảo hãy dùng kịch bản trong thư mục init.d chứ không phải các thư mục rc*.d: chẳng hạn init.d/httpd start để khởi động máy chủ web httpd thủ công, và httpd stop để diệt một dịch vụ đang chạy.1 Ông cũng nói không cần thực sự hiểu chi tiết cách dùng run-parts; thực tế phần lớn người ta còn không biết nó tồn tại — điều đáng nhớ chỉ là nó thỉnh thoảng xuất hiện trong kịch bản và nó tồn tại thuần tuý để chạy các chương trình trong một thư mục cho trước.1

  4. SysV compatibility

    Lớp tương thích năm bước — và giới hạn của nó systemd chạy giúp kịch bản cũ The five-step compatibility layer — and its limit

    Một tính năng khiến systemd khác các hệ init thế hệ mới khác là nó cố làm một công việc đầy đủ hơn trong việc theo dõi các dịch vụ được khởi động bởi kịch bản init tương thích System V.1 Ward mô tả cơ chế ấy thành năm bước rõ ràng, và kết lại bằng một hệ quả thực tế: vì systemd tạo liên hệ với một tên service unit, bạn có thể dùng systemctl để khởi động lại dịch vụ hoặc xem trạng thái của nó.1

    Những kịch bản cũ vẫn chạy được: systemd nhận chúng, đặt cho mỗi cái một cái tên kiểu mới, rồi quản lý như dịch vụ bình thường. Nhớ nhé: đồ cũ vẫn dùng được, chỉ là được gọi bằng tên mới.

    One feature that sets systemd apart from other newer-generation init systems is that it tries to do a more complete job of tracking services started by System V–compatible init scripts.1 Ward describes the mechanism in five clear steps, and closes with the practical consequence: because systemd makes the association with a service unit name, you can use systemctl to restart the service or view its status.1

    Năm bướcThe five steps (1) systemd kích hoạt runlevel<N>.target, với N là runlevel. (2) Với mỗi liên kết tượng trưng trong /etc/rc<N>.d, systemd xác định kịch bản trong /etc/init.d. (3) systemd liên hệ tên kịch bản với một service unit — ví dụ /etc/init.d/foo sẽ thành foo.service. (4) systemd kích hoạt service unit và chạy kịch bản với đối số start hoặc stop, tuỳ theo tên của nó trong rc<N>.d. (5) systemd cố liên hệ mọi tiến trình sinh từ kịch bản với service unit ấy.1 Máy đọc từng lối tắt cũ, đặt tên mới cho nó, rồi chạy nó như một dịch vụ. (1) systemd activates runlevel<N>.target, where N is the runlevel. (2) For each symbolic link in /etc/rc<N>.d, systemd identifies the script in /etc/init.d. (3) systemd associates the script name with a service unit — for example /etc/init.d/foo becomes foo.service. (4) systemd activates the service unit and runs the script with either a start or stop argument, based on its name in rc<N>.d. (5) systemd attempts to associate any processes from the script with the service unit.1

    Đừng trông chờ phép màu

    Ward kết mục này bằng một câu tỉnh táo: đừng trông chờ phép màu nào từ chế độ tương thích System V — nó vẫn phải chạy các kịch bản init tuần tự.1 Nghĩa là chính cái lợi lớn nhất của systemd — song song hoá — biến mất đúng ở phần hệ thống còn dùng kịch bản cũ. Đây là lý do thực tiễn để di chuyển sang tệp unit gốc, chứ không chỉ là lý do thẩm mỹ.

    Vì sao mục này vẫn đáng đọc

    Ward nói System V init hiện không phổ biến trên phần lớn cài đặt máy chủ và máy để bàn, nhưng bạn có thể gặp nó ở các phiên bản RHEL trước 7.0, cũng như trong các môi trường Linux nhúng như bộ định tuyến và điện thoại. Ngoài ra, một số gói cũ có thể chỉ cung cấp kịch bản khởi động thiết kế cho System V init — và systemd xử lý được chúng bằng chế độ tương thích này.1

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

Tắt máy, initramfs, và đường thoát khi mọi thứ hỏng Tắt máy đúng cách, và cứu máy khi hỏng Shutdown, initramfs, and the way out when things break

init điều khiển cách hệ thống tắt và khởi động lại, và Ward nhấn mạnh rằng các lệnh để tắt máy là như nhau bất kể bạn chạy phiên bản init nào. Cách đúng để tắt một máy Linux là dùng lệnh shutdown.1 Có hai cách dùng cơ bản: nếu bạn halt hệ thống, nó tắt máy và giữ máy ở trạng thái tắt — shutdown -h now để tắt ngay lập tức; trên phần lớn máy và phiên bản Linux, một lệnh halt sẽ cắt nguồn điện. Để khởi động lại, dùng -r thay cho -h.1

Muốn tắt máy đúng cách, dùng lệnh shutdown. Thêm -h là tắt hẳn, thêm -r là khởi động lại. Đừng rút điện giữa chừng. Nhớ nhé: -h là tắt, -r là bật lại.

init controls how the system shuts down and reboots, and Ward stresses that the commands to shut down are the same regardless of which version of init you run. The proper way to shut down a Linux machine is the shutdown command.1 There are two basic ways to use it: if you halt the system, it shuts the machine down and keeps it down — shutdown -h now makes it halt immediately, and on most machines and versions of Linux a halt cuts the power. For a reboot, use -r instead of -h.1

Đối số thời gian là bắt buộc. Trong ví dụ shutdown -h now, now chính là thời điểm tắt máy — và Ward nói rõ rằng việc đưa một đối số thời gian là bắt buộc, dù có nhiều cách chỉ định nó. Nếu bạn muốn máy tắt vào một lúc nào đó trong tương lai, bạn dùng +n, với n là số phút shutdown nên đợi trước khi tiến hành; ví dụ shutdown -r +10 khởi động lại sau 10 phút.1 Ông chỉ bạn tới trang man shutdown(8) cho các tuỳ chọn khác.119

Tám bước của một lần tắt máy. Khi thời điểm tắt máy tới, shutdown bảo init bắt đầu quy trình: với systemd nghĩa là kích hoạt các shutdown unit, còn với System V init nghĩa là đổi runlevel sang 0 (halt) hoặc 6 (reboot). Ward nói rõ rằng bất kể hiện thực hay cấu hình init nào, quy trình nói chung diễn ra như nhau — tám bước, từ việc init yêu cầu mọi tiến trình tắt một cách sạch sẽ, tới lời gọi hệ thống reboot(2) ở bước cuối.120

Tám bước. Máy lần lượt: bảo mọi chương trình dừng, đợi, ép dừng nếu bướng, khoá tệp, tháo ổ đĩa, ghi nốt dữ liệu, rồi mới bảo nhân tắt. Nhớ nhé: tắt máy là dọn dẹp, không phải cắt điện.

The eight steps of a shutdown. When the shutdown time arrives, shutdown tells init to begin the process: on systemd that means activating the shutdown units, on System V init it means changing the runlevel to 0 (halt) or 6 (reboot). Ward is explicit that regardless of the init implementation or configuration, the procedure generally goes the same way — eight steps, from init asking every process to shut down cleanly to the reboot(2) system call at the end.120

1 yêu cầu tắt sạch
2 TERM nếu không đáp
3 KILL với kẻ bướng
4 khoá tệp hệ thống
5 tháo mọi fs trừ root
6 gắn lại root chỉ-đọc
7 sync dữ liệu đệm
8 reboot(2)

xin dừng → ép dừng
→ khoá → tháo đĩa
→ ghi nốt → tắt

1 ask processes to stop
2 TERM the unresponsive
3 KILL the stragglers
4 lock system files
5 unmount all but root
6 remount root read-only
7 sync buffered data
8 reboot(2)

  1. shutdown sequence

    Từ TERM tới KILL — và /etc/nologin Máy tắt như thế nào, từng bước From TERM to KILL — and /etc/nologin

    Ward liệt kê tám bước: (1) init yêu cầu mọi tiến trình tắt một cách sạch sẽ; (2) nếu một tiến trình không đáp ứng sau một lúc, init diệt nó, trước hết là thử một tín hiệu TERM; (3) nếu tín hiệu TERM không ăn thua, init dùng tín hiệu KILL với những kẻ còn sót; (4) hệ thống khoá các tệp hệ thống vào chỗ và chuẩn bị các việc khác cho lần tắt; (5) hệ thống tháo mọi hệ thống tệp trừ hệ thống tệp gốc; (6) hệ thống gắn lại hệ thống tệp gốc ở chế độ chỉ đọc; (7) hệ thống ghi mọi dữ liệu đã đệm ra hệ thống tệp bằng chương trình sync; (8) bước cuối là bảo nhân khởi động lại hay dừng bằng lời gọi hệ thống reboot(2).1

    Máy không tắt phụt một cái. Nó lần lượt nhắc từng chương trình dừng lại, đợi, rồi mới ép; sau đó nó cất dữ liệu vào ổ đĩa cẩn thận, rồi mới thật sự tắt. Nhớ nhé: tắt máy mất vài giây là vì nó đang dọn nhà.

    Ward lists eight steps: (1) init asks every process to shut down cleanly; (2) if a process doesn't respond after a while, init kills it, first trying a TERM signal; (3) if TERM doesn't work, init uses KILL on any stragglers; (4) the system locks system files into place and makes other preparations; (5) the system unmounts all filesystems other than the root; (6) the system remounts the root filesystem read-only; (7) the system writes all buffered data out to the filesystem with the sync program; (8) the final step is telling the kernel to reboot or stop with the reboot(2) system call.1

    Chi tiết ít người biếtThe little-known detail Trên Linux, shutdown thông báo cho mọi người đang đăng nhập rằng máy sắp tắt, nhưng nó làm rất ít việc thật. Nếu bạn chỉ định một thời điểm khác now, lệnh shutdown tạo một tệp tên /etc/nologin; khi tệp này có mặt, hệ thống cấm mọi người đăng nhập trừ siêu người dùng.1 Nếu hẹn giờ tắt máy, hệ thống tạo một tệp nhỏ để chặn không cho ai đăng nhập thêm. On Linux, shutdown notifies anyone logged on that the machine is going down, but it does little real work. If you specify a time other than now, shutdown creates a file called /etc/nologin; when this file is present, the system prohibits logins by anyone except the superuser.1

    reboot và halt cư xử khác nhau

    Ward cảnh báo một điểm gây nhầm: các chương trình reboot và halt cư xử khác nhau tuỳ vào cách chúng được gọi. Mặc định, chúng gọi shutdown với tuỳ chọn -r hay -h. Nhưng nếu hệ thống đã ở runlevel halt hay reboot rồi, các chương trình này bảo nhân tự tắt ngay lập tức.1 Nếu bạn thật sự muốn tắt máy gấp, bất chấp hư hại tiềm tàng từ một lần tắt mất trật tự, dùng tuỳ chọn -f (force).1

    Đừng rút điện giữa chừng

    Quá trình tắt mất vài giây, và Ward nói thẳng: bạn nên tránh reset hay ngắt nguồn một máy trong lúc đang tắt.1 Nhìn vào tám bước ở trên thì rõ vì sao — bước 7, sync, là chỗ dữ liệu trong bộ đệm cuối cùng mới thực sự chạm tới đĩa.

  2. initramfs

    Initramfs — cái nêm không gian người dùng đặt trước không gian người dùng Một hệ thống tệp giả, dựng tạm trong bộ nhớ initramfs — a user-space wedge in front of user space

    Ward gọi initramfs là thành phần luôn có phần gây bối rối của tiến trình khởi động Linux, và đưa một hình ảnh gọn: hãy nghĩ về nó như một cái nêm không gian người dùng nhỏ đặt phía trước phần khởi động chế độ người dùng bình thường.1 Vấn đề nó giải quyết bắt nguồn từ sự đa dạng của phần cứng lưu trữ: nhân Linux không nói chuyện với giao diện BIOS của PC hay EFI để lấy dữ liệu từ đĩa, nên để gắn được hệ thống tệp gốc, nó cần trình điều khiển hỗ trợ cho cơ chế lưu trữ bên dưới.1

    Nhân cần đọc ổ đĩa, nhưng chương trình đọc ổ đĩa lại nằm trên ổ đĩa. Vòng luẩn quẩn. Cách gỡ: gói sẵn vài chương trình cần thiết vào một túi nhỏ, nạp túi ấy vào bộ nhớ trước. Nhớ nhé: muốn mở tủ thì chìa khoá phải để ngoài tủ.

    Ward calls initramfs the component that has always been somewhat confounding in the Linux boot process, and gives a compact image: think of it as a little user-space wedge that goes in front of the normal user mode start.1 The problem it solves stems from the variety of storage hardware: the Linux kernel does not talk to the PC BIOS interface or EFI to get data from disks, so to mount its root filesystem it needs driver support for the underlying storage mechanism.1

    Cái vòng luẩn quẩnThe chicken-and-egg problem Ví dụ Ward đưa: nếu gốc nằm trên một dàn RAID nối với một bộ điều khiển của bên thứ ba, nhân cần trình điều khiển cho bộ điều khiển ấy trước đã. Nhưng có quá nhiều trình điều khiển bộ điều khiển lưu trữ tới mức các distro không thể gộp hết vào nhân, nên nhiều trình điều khiển được xuất xưởng dưới dạng mô-đun nạp được. Mà mô-đun nạp được là tệp — và nếu nhân chưa gắn được hệ thống tệp nào thì nó không nạp được các mô-đun trình điều khiển nó cần.1 Chìa khoá tủ lại nằm trong tủ. Đó chính là vấn đề. Ward's example: if the root is on a RAID array connected to a third-party controller, the kernel needs that controller's driver first. But there are so many storage controller drivers that distributions can't include them all in their kernels, so many ship as loadable modules. And loadable modules are files — if your kernel doesn't have a filesystem mounted in the first place, it can't load the driver modules it needs.1

    Cách gỡ, từng bước

    Giải pháp là gom một bộ sưu tập nhỏ các mô-đun trình điều khiển nhân cùng vài tiện ích khác vào một kho lưu trữ. Bộ nạp khởi động nạp kho này vào bộ nhớ trước khi chạy nhân. Khi khởi động, nhân đọc nội dung kho vào một hệ thống tệp RAM tạm thời — chính là initramfs — gắn nó tại /, và thực hiện bàn giao sang chế độ người dùng cho init trên initramfs. Rồi các tiện ích trong initramfs cho phép nhân nạp các mô-đun trình điều khiển cần thiết cho hệ thống tệp gốc thật. Cuối cùng, các tiện ích gắn hệ thống tệp gốc thật và khởi động init thật.1

    Bên trong nó có gì

    Ward nói các hiện thực rất khác nhau và luôn tiến hoá: trên một số distro, init trên initramfs là một kịch bản shell khá đơn giản, khởi động một udevd để nạp trình điều khiển, rồi gắn gốc thật và thực thi init ở đó. Trên các distro dùng systemd, bạn thường thấy cả một bản cài systemd đầy đủ ở đó, không có tệp cấu hình unit nào và chỉ vài tệp cấu hình udevd.1 Một mảnh đặc biệt đáng chú ý là cú “xoay trục” (pivot) gần cuối tiến trình init trên initramfs: phần này chịu trách nhiệm xoá nội dung hệ thống tệp tạm — để tiết kiệm bộ nhớ — và chuyển vĩnh viễn sang gốc thật.1

  3. initrd vs initramfs

    Bỏ qua được, và hai cái tên cho hai thứ khác nhau Có thể bỏ nó đi không? You can skip it — and two names for two different things

    Một đặc điểm cơ bản của hệ thống tệp RAM ban đầu mà cho tới nay vẫn không đổi là khả năng bỏ qua nó nếu bạn không cần. Nghĩa là nếu nhân của bạn có đủ mọi trình điều khiển cần để gắn hệ thống tệp gốc, bạn có thể bỏ hệ thống tệp RAM ban đầu khỏi cấu hình bộ nạp khởi động — và khi thành công, việc loại bỏ nó rút ngắn thời gian khởi động một chút.1

    Nếu nhân đã biết cách đọc ổ đĩa của bạn rồi thì cái túi tạm kia không cần nữa, và bỏ nó đi máy còn khởi động nhanh hơn chút. Nhưng đừng thử bừa. Nhớ nhé: bỏ được, nhưng phải chắc là nhân đọc được đĩa đã.

    One basic characteristic of the initial RAM filesystem that has so far remained unchanged is the ability to bypass it if you don't need it. If your kernel has all the drivers it needs to mount your root filesystem, you can omit the initial RAM filesystem from your boot loader configuration — and when successful, eliminating it slightly shortens boot time.1

    Cách thử an toànThe safe way to try Ward gợi ý thử ngay lúc khởi động bằng trình soạn thảo trình đơn GRUB để xoá dòng initrd — và khuyên rõ: tốt nhất đừng thử nghiệm bằng cách sửa tệp cấu hình GRUB, vì bạn có thể mắc lỗi khó sửa. Ông cũng ghi rằng việc bỏ qua hệ thống tệp RAM ban đầu đã dần khó hơn một chút, bởi các tính năng như gắn theo UUID có thể không dùng được với nhân distro chung chung.1 Thử bằng trình đơn lúc khởi động, đừng sửa thẳng vào tệp cấu hình. Ward suggests trying it at boot time via the GRUB menu editor to remove the initrd line — and advises clearly that it's best not to experiment by changing the GRUB configuration file, as you can make a mistake that's difficult to repair. He also notes that bypassing the initial RAM filesystem has gradually become a little more difficult, because features such as mount-by-UUID may not be available with generic distribution kernels.1

    Hai thuật ngữ, một sự lẫn lộn

    Ward đặt hẳn một ghi chú để tách hai khái niệm: thuật ngữ initial RAM filesystem (initramfs) chỉ hiện thực dùng kho lưu trữ cpio làm nguồn cho hệ thống tệp tạm. Có một phiên bản cũ hơn gọi là initial RAM disk, hay initrd, dùng một ảnh đĩa làm cơ sở cho hệ thống tệp tạm — cách này đã rơi vào quên lãng vì duy trì một kho cpio dễ hơn nhiều. Tuy nhiên, bạn sẽ thường thấy thuật ngữ initrd được dùng để chỉ một hệ thống tệp RAM ban đầu dựa trên cpio; các tên tệp và tệp cấu hình thường vẫn chứa chữ initrd.121

    Mở ra xem, và dựng lại

    Bạn có thể kiểm tra nội dung hệ thống tệp RAM ban đầu của mình, nhưng phải làm chút việc thám tử: phần lớn hệ thống ngày nay dùng kho lưu trữ tạo bởi mkinitramfs, mà bạn có thể giải nén bằng unmkinitramfs; số khác có thể là kho cpio nén kiểu cũ.122 Ward nói thẳng rằng bạn thường sẽ không tự tạo hệ thống tệp RAM ban đầu của riêng mình, vì đó là một quá trình tỉ mỉ; có một số tiện ích để tạo ảnh, và distro của bạn nhiều khả năng đã có sẵn một cái — hai trong số phổ biến nhất là mkinitramfs và dracut.123

  4. rescue & single-user mode

    Ảnh live và chế độ một người dùng — vì sao Ward chọn cái thứ nhất Khi máy hỏng thì làm gì Live images and single-user mode — why Ward prefers the former

    Khi có gì đó trục trặc với hệ thống, Ward nói cách xử lý đầu tiên của bạn thường là khởi động hệ thống bằng một ảnh “live” của một distro, hoặc bằng một ảnh cứu hộ chuyên dụng như SystemRescueCD, đặt trên phương tiện tháo rời được. Một ảnh live đơn giản là một hệ thống Linux có thể khởi động và chạy mà không cần quá trình cài đặt; ảnh cài đặt của hầu hết distro cũng kiêm luôn vai trò ảnh live.124

    Máy hỏng không vào được? Hãy khởi động máy từ một chiếc USB có sẵn hệ điều hành. Nó chạy độc lập, không đụng tới ổ cứng hỏng, và từ đó bạn sửa được. Nhớ nhé: giữ sẵn một chiếc USB cứu hộ.

    When something goes wrong with the system, Ward says your first recourse is usually to boot with a distribution's "live" image or a dedicated rescue image such as SystemRescueCD on removable media. A live image is simply a Linux system that can boot and run without an installation process; most distributions' installation images double as live images.124

    Bốn việc thường làmThe four common tasks Ward liệt kê các tác vụ thường gặp để sửa một hệ thống: kiểm tra các hệ thống tệp sau một lần hệ thống sập; đặt lại một mật khẩu bị quên; sửa vấn đề trong các tệp quan trọng như /etc/fstab và /etc/passwd; và khôi phục từ bản sao lưu sau một lần sập.1 Bốn việc hay phải làm: kiểm tra ổ đĩa, đặt lại mật khẩu, sửa tệp cấu hình hỏng, và phục hồi từ bản sao lưu. Ward lists the common tasks for fixing a system: checking filesystems after a system crash; resetting a forgotten password; fixing problems in critical files such as /etc/fstab and /etc/passwd; and restoring from backups after a crash.1

    Chế độ một người dùng

    Một lựa chọn khác để khởi động nhanh tới một trạng thái dùng được là chế độ một người dùng (single-user mode): ý tưởng là hệ thống khởi động nhanh tới một shell root thay vì đi qua toàn bộ mớ dịch vụ. Trong System V init, chế độ một người dùng thường là runlevel 1; trong systemd, nó được biểu diễn bằng rescue.target. Bạn thường vào chế độ này bằng tham số -s cho bộ nạp khởi động, và có thể cần gõ mật khẩu root để vào.1

    Vì sao ảnh live gần như luôn tốt hơn

    Ward kết luận rất rõ ràng: vấn đề lớn nhất của chế độ một người dùng là nó không cho bạn nhiều tiện nghi — mạng gần như chắc chắn không dùng được (và nếu có thì cũng khó dùng), bạn không có giao diện đồ hoạ, và terminal của bạn thậm chí có thể không hoạt động đúng. Vì lý do đó, ảnh live gần như luôn được coi là lựa chọn tốt hơn.1

Đí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.

“Phụ thuộc cũng có nghĩa là thứ tự” "A dependency also means an order"

Ngộ nhận: viết Requires=bar.service trong foo.service là đã bảo systemd khởi động bar xong rồi mới tới foo.

Bản văn nói: cú pháp phụ thuộc chưa hề chỉ định thứ tự; kích hoạt phần lớn service unit có phụ thuộc Requires hay Wants khiến các unit ấy khởi động cùng lúc, và đó là tối ưu.1 Muốn có thứ tự, bạn phải dùng Before hoặc After.1

Misconception: writing Requires=bar.service in foo.service tells systemd to finish starting bar before foo.

The text says: the dependency syntax does not specify order; activating most service units with Requires or Wants dependencies causes them to start at the same time, which is optimal.1 For ordering you must use Before or After.1

“Bật (enable) một dịch vụ là khởi động nó” "Enabling a service starts it"

Ngộ nhận: systemctl enable và systemctl start là hai cách nói cùng một việc.

Bản văn nói: Ward đặt hẳn một ghi chú — bật một unit không kích hoạt nó.1 Tác dụng của việc bật chỉ là tạo một liên kết tượng trưng trong thư mục con .wants tương ứng với unit phụ thuộc, và việc bật tồn tại qua các lần khởi động lại.1

Misconception: systemctl enable and systemctl start are two ways of saying the same thing.

The text says: Ward writes a note for exactly this — enabling a unit does not activate it.1 The effect of enabling is only to create a symbolic link in the .wants subdirectory of the dependent unit, and enabling survives reboots.1

“Chế độ tương thích System V cho tôi tốc độ của systemd” "System V compatibility gives me systemd's speed"

Ngộ nhận: kịch bản init cũ chạy dưới systemd thì cũng được song song hoá như unit gốc.

Bản văn nói: “đừng trông chờ phép màu nào từ chế độ tương thích System V; nó vẫn phải chạy các kịch bản init tuần tự”.1 Cái bạn nhận được là khả năng quản lý — dùng systemctl để khởi động lại hay xem trạng thái — chứ không phải tốc độ.1

Misconception: old init scripts running under systemd get parallelized like native units.

The text says: "don't expect any miracles from System V compatibility mode; it still must run the init scripts serially."1 What you gain is manageability — using systemctl to restart the service or view its status — not speed.1

“initramfs là một phần của nhân” "initramfs is part of the kernel"

Ngộ nhận: initramfs thuộc về giai đoạn nhân, nên không liên quan gì tới không gian người dùng.

Bản văn nói: Ward mô tả nó đúng như một cái nêm không gian người dùng nhỏ đặt phía trước phần khởi động chế độ người dùng bình thường, và nhân thực hiện bàn giao sang chế độ người dùng cho init trên initramfs.1 Nó là không gian người dùng — chỉ là một không gian người dùng tạm, nằm trong RAM, sẽ bị xoá ở cú xoay trục cuối.1

Misconception: initramfs belongs to the kernel phase and has nothing to do with user space.

The text says: Ward describes it precisely as a little user-space wedge that goes in front of the normal user mode start, and the kernel performs the user-mode handoff to the init on the initramfs.1 It is user space — just a temporary one in RAM, wiped at the final pivot.1

Tự kiểm tra Self-check

Bạn đã nắm cách không gian người dùng khởi động chưa? Thử trả lời xem nào Do you have user-space startup 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. Không gian người dùng khởi động theo đại thể thứ tự nào, và vì sao thứ tự ấy không còn là một chuỗi cứng trên systemd?

    Gợi ý sâu hơn: nêu năm bước Ward liệt kê, rồi giải thích “kích hoạt unit bất cứ khi nào chúng sẵn sàng” nghĩa là gì.

  2. Ba câu hỏi nào cho biết máy bạn đang chạy hiện thực init nào?

    Gợi ý sâu hơn: thư mục nào chỉ tới systemd, và tệp nào chỉ tới System V init?

  3. Vì sao đồ thị phụ thuộc của systemd không phải là một cây?

    Gợi ý sâu hơn: điều gì xảy ra khi một unit muộn phụ thuộc vào nhiều unit sớm hơn?

  4. Phân biệt Requires, Wants, Requisite và Conflicts — và nói vì sao tài liệu khuyên dùng Wants.

    Gợi ý sâu hơn: kiểu nào lan truyền thất bại, và điều đó dẫn tới nghịch cảnh gì trong ví dụ dấu nhắc đăng nhập?

  5. Trong cặp echo.socket và echo@.service, cái gì nối hai unit với nhau?

    Gợi ý sâu hơn: Accept=true thay đổi điều gì, và khi nào thì bạn không nên đặt dấu @?

  6. Với cùng một cơ chế socket unit, làm sao systemd vừa dùng để trì hoãn khởi động vừa dùng để tăng tốc khởi động?

    Gợi ý sâu hơn: trong Hình 6-3, ai tiếp quản Unit R, và vào lúc nào?

  7. Một tên tệp như S99httpd trong rc5.d mã hoá những thông tin gì?

    Gợi ý sâu hơn: chữ K nghĩa là gì, và vì sao đổi tên thành _S99httpd lại an toàn hơn xoá?

  8. Vì sao initramfs tồn tại, và khi nào bạn có thể bỏ nó đi?

    Gợi ý sâu hơn: nêu cái vòng luẩn quẩn giữa mô-đun trình điều khiển và hệ thống tệp gốc.

  9. Kể bốn bước đầu của chuỗi tắt máy, và cho biết bước nào ghi dữ liệu đệm ra đĩa.

    Gợi ý sâu hơn: tệp /etc/nologin xuất hiện khi nào, và nó làm gì?

  10. Vì sao Ward coi ảnh live gần như luôn tốt hơn chế độ một người dùng?

    Gợi ý sâu hơn: chế độ một người dùng tương ứng với runlevel nào, và với target nào trong systemd?

  1. Sau khi nhân xong việc, chương trình nào chạy đầu tiên?

  2. Một “unit” là gì? Kể hai loại unit.

  3. Lệnh nào dùng để bật, tắt và hỏi thăm một dịch vụ?

  4. “Cần nhau” và “ai trước ai” có phải một thứ không?

  5. Vì sao có khi máy chỉ bật một dịch vụ khi có người gõ cửa?

  6. Tắt máy đúng cách thì dùng lệnh gì?

  7. Máy hỏng không vào được thì bạn làm gì trước tiên?

  1. In roughly what order does user space start, and why is that order no longer a rigid sequence under systemd?

  2. Which three checks tell you which init implementation your machine runs?

  3. Why is systemd's dependency graph not a tree?

  4. Distinguish Requires, Wants, Requisite and Conflicts — and say why the documentation recommends Wants.

  5. In the pair echo.socket and echo@.service, what links the two units together?

  6. How does the same socket-unit machinery serve both to delay a startup and to speed one up?

  7. What information does a filename like S99httpd in rc5.d encode?

  8. Why does initramfs exist, and when can you drop it?

  9. Name the first four steps of the shutdown sequence, and say which step flushes buffered data to disk.

  10. Why does Ward consider live images nearly always preferable to single-user mode?

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

Điểm nhân khởi chạy init là chỗ bạn nhìn thấy phần còn lại của hệ thống tự dựng lên thành một tổng thể — và từ đó trở đi, hiểu và thay đổi quá trình khởi động không gian người dùng không đòi hỏi lập trình mức thấp.1

Nhân mở cửa hàng, còn init gọi người vào làm. Từ lúc này, mọi thứ đều nằm ở tầng bạn xem và sửa được. Nhớ nhé: phần thú vị nhất bắt đầu sau khi nhân xong việc.

The point where the kernel starts init is where you can see how the rest of the system builds up as a whole — and from there on, understanding and changing the user-space startup requires no low-level programming.1