动态

详情 返回 返回

【Linux】《how linux work》第六章 用户空間如何啓動 - 动态 详情

Chapter 6. How User Space Starts(第 6 章 用户空間如何啓動)

The point where the kernel starts its first user-space process, init, is significant—not just because that’s where the 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. Prior to this point, the kernel executes a well-controlled path of execution defined by a relatively small number of software developers. User space is far more modular. It’s much easier to see what goes into the user space startup and operation. For the adventurous, it’s also relatively easy to change the user space startup because doing so requires no low-level programming.

內核開始其第一個用户空間進程init的地方非常重要,不僅因為這是內存和CPU最終準備好進行正常系統操作的地方,還因為你可以看到整個系統是如何構建起來的。

在這一點之前,內核執行的是由相對較少的軟件開發人員定義的良好控制的執行路徑。

用户空間要模塊化得多。

很容易看到用户空間啓動和運行中涉及的內容。

對於冒險者來説,改變用户空間啓動也相對容易,因為這不需要低級編程。

User space starts in roughly this order:

  1. init
  2. Essential low-level services such as udevd and syslogd
  3. Network configuration
  4. Mid- and high-level services (cron, printing, and so on)
  5. Login prompts, GUIs, and other high-level applications

用户空間大致按以下順序開始:

  1. init
  2. 基本的低級服務,如udev和syslogd
  3. 網絡配置
  4. 中高級服務(cron、打印等)
  5. 登錄提示、GUI和其他高級應用程序

6.1 Introduction to init( init 簡介)

The init program is a user-space program like any other program on the Linux system, and you’ll find it in /sbin along with many of the other system binaries. Its main purpose is to start and stop the essential service processes on the system, but newer versions have more responsibilities.

init程序是Linux系統中的一個用户空間程序,與系統中的其他程序一樣,你可以在/sbin目錄下找到它,與許多其他系統二進制文件一起。

它的主要目的是啓動和停止系統上的必要服務進程,但較新的版本有更多的責任。

There are three major implementations of init in Linux distributions:

Linux發行版中有三個主要的init實現:

o System V init. A traditional sequenced init (Sys V, usually pronounced “sys-five”). Red Hat Enterprise Linux and several other distributions use this version.
o systemd. The emerging standard for init. Many distributions have moved to systemd, and most that have not yet done so are planning to move to it.
o Upstart. The init on Ubuntu installations. However, as of this writing, Ubuntu has also planned to migrate to systemd.

  • System V init。傳統的順序init(Sys V,通常發音為“sys-five”)。Red Hat Enterprise Linux和其他幾個發行版使用這個版本。
  • systemd。正在興起的init標準。許多發行版已經轉向systemd,大多數尚未轉向的發行版也計劃轉向它。
  • Upstart。Ubuntu安裝中的init。然而,截至本文撰寫時,Ubuntu也計劃遷移到systemd。

There are various other versions of init as well, especially on embedded platforms. For example, Android has its own init. The BSDs also have their version of init, but you are unlikely to see them on a modern Linux machine. (Some distributions have also modified the System V init configuration to resemble the BSD style.)

還有其他各種各樣的init版本,尤其是在嵌入式平台上。

例如,Android有自己的init。

BSD也有它們自己的init版本,但你不太可能在現代Linux機器上看到它們。

(一些發行版還修改了System V init配置以類似BSD風格。)

There are many different implementations of init because System V init and other older versions relied on a sequence that performed only one startup task at a time. Under this scheme, it is relatively easy to resolve dependencies. However, performance isn’t terribly good, because two parts of the boot sequence cannot normally run at once. Another limitation is that you can only start a fixed set of services as defined by the boot sequence: When you plug in new hardware or need a service that isn’t already running, there is no standardized way to coordinate the new components with init. systemd and Upstart attempt to remedy the performance issue by allowing many services to start in parallel thereby speeding up the boot process. Their implementations are quite different, though:

有許多不同的init實現,因為System V init和其他舊版本依賴於一次只執行一個啓動任務的順序。

在這種方案下,解決依賴關係相對容易。

然而,性能並不是特別好,因為引導序列的兩個部分通常不能同時運行。

另一個限制是,你只能啓動由引導序列定義的一組固定服務:當你插入新硬件或需要一個尚未運行的服務時,沒有標準化的方法來協調新組件與init。

systemd和Upstart試圖通過允許許多服務並行啓動來解決性能問題,從而加快引導過程。

然而,它們的實現方式有很大的不同:

o systemd is goal oriented. You define a target that you want to achieve, along with its dependencies, and when you want to reach the target. systemd satisfies the dependencies and resolves the target. systemd can also defer the start of a service until it is absolutely needed.
o Upstart is reactionary. It receives events and, based on those events, runs jobs that can in turn produce more events, causing Upstart to run more jobs, and so on.

  • systemd是目標導向的。你定義一個目標,以及它的依賴關係和你想要達到目標的時間。systemd滿足依賴關係並解決目標。systemd還可以推遲啓動服務,直到絕對需要時再啓動。
  • Upstart是反應式的。它接收事件,並根據這些事件運行作業,這些作業又可以產生更多的事件,導致Upstart運行更多的作業,依此類推。

The systemd and Upstart init systems also offer a more advanced way to start and track services. In traditional init systems, service daemons are expected to start themselves from scripts. A script runs a daemon program, which detaches itself from the script and runs autonomously. To find the PID of a service daemon, you need to use ps or some other mechanism specific to the service. In contrast, Upstart and systemd can manage individual service daemons from the beginning, giving the user more power and insight into exactly what is running on the system

systemd和Upstart init系統還提供了更高級的啓動和跟蹤服務的方式。

在傳統的init系統中,服務守護進程被期望從腳本中啓動自己。

一個腳本運行一個守護程序,守護程序從腳本中分離出來並自主運行。

要找到一個服務守護進程的PID,你需要使用ps或其他特定於該服務的機制。

相比之下,Upstart和systemd可以從一開始就管理單個服務守護進程,給用户更多的權力和了解系統上正在運行的內容。

Because the new init systems are not script-centric, configuring services for them also tends to be easier. In particular, System V init scripts tend to contain many similar commands designed to start, stop, and restart services. You don’t need all of this redundancy with systemd and Upstart, which allow you to concentrate on the services themselves, rather than their scripts

因為新的init系統不是以腳本為中心,所以為它們配置服務也更容易。

特別是,System V init腳本通常包含許多類似的命令,用於啓動、停止和重新啓動服務。

但是,使用systemd和Upstart,你不需要所有這些冗餘,可以專注於服務本身,而不是它們的腳本。

Finally, systemd and Upstart both offer some level of on-demand services. Rather than trying to start all the services that may be necessary at boot time (as the System V init would do), they start some services only when needed. This idea is not really new; this was done with the traditional inetd daemon, but the new implementations are more sophisticated.

最後,systemd和Upstart都提供了一定程度的按需服務。

它們不會嘗試在啓動時啓動所有可能需要的服務(像System V init那樣),而是隻在需要時啓動一些服務。

這個想法並不是真正新的;傳統的inetd守護進程就是這樣做的,但新的實現更加複雜。

Both systemd and Upstart offer some System V backward compatibility. For example, both support the concept of runlevels

systemd和Upstart都提供了一些System V的向後兼容性。例如,它們都支持運行級的概念。

6.2 System V Runlevels(系統 V 運行級別)

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, which is denoted by a number from 0 through 6. A system spends most of its time in a single runlevel, but when you shut the machine down, init switches to a different runlevel in order to terminate the system services in an orderly fashion and to tell the kernel to stop

在Linux系統上的任何時刻,都會運行一定的基本進程(如crond和udevd)。

在System V init中,這種機器的狀態被稱為運行級別,用數字0到6表示。系統大部分時間都在一個運行級別上運行,但當你關閉機器時,init會切換到另一個運行級別,以有序地終止系統服務並告訴內核停止運行。

You can check your system’s runlevel with the who -r command. A system running Upstart responds with something like this:

你可以用who -r命令檢查系統的運行級別。

一個運行Upstart的系統會返回類似以下的結果:

$ who -r
run-level 2 2015-09-06 08:37

This output tells us that the current runlevel is 2, as well as the date and time that the runlevel was established.

這個輸出告訴我們當前的運行級別是2,以及運行級別建立的日期和時間。

Runlevels serve various purposes, but the most common one is to distinguish between system startup, shutdown, single-user mode, and console mode states. For example, Fedora-based systems traditionally used runlevels 2 through 4 for the text console; a runlevel of 5 means that the system will start a GUI login.

運行級別有各種用途,但最常見的是區分系統啓動、關閉、單用户模式和控制枱模式。

例如,基於Fedora的系統傳統上使用運行級別2到4來進行文本控制枱操作;運行級別5表示系統將啓動圖形用户登錄界面。

But runlevels are becoming a thing of the past. Even though all three init versions in this book support them, systemd and Upstart consider runlevels obsolete as end states for the system. To systemd and Upstart, runlevels exist primarily to start services that support only the System V init scripts, and the implementations are so different that even if you’re familiar with one type of init, you won’t necessarily know what to do with another.

但是,運行級別正在逐漸過時。

儘管本書中的所有三個init版本都支持運行級別,但systemd和Upstart認為運行級別作為系統的終止狀態已經過時。

對於systemd和Upstart來説,運行級別主要存在於用於支持System V init腳本的服務啓動,而且兩者的實現方式差異很大,即使你熟悉一種init類型,你也不一定知道如何處理另一種類型的init。

6.3 Identifying Your init( 確定您的倡議)

Before proceeding, you need to determine your system’s version of init. If you’re not sure, check your system as follows:

在繼續之前,您需要確定您的系統的init版本。如果您不確定,請按照以下方式檢查您的系統:

o If your system has /usr/lib/systemd and /etc/systemd directories, you have systemd. Go to 6.4 systemd.
o If you have an /etc/init directory that contains several .conf files, you’re probably running Upstart (unless you’re running Debian 7, in which case you probably have System V init). Go to 6.5 Upstart.
o If neither of the above is true, but you have an /etc/inittab file, you’re probably running System V init. Go to 6.6 System V init.

  • 如果您的系統具有/usr/lib/systemd/etc/systemd目錄,則表示您使用的是systemd。請轉到6.4 systemd。
  • 如果您有一個包含多個.conf文件的/etc/init目錄,則您可能正在運行Upstart(除非您運行的是Debian 7,那麼您可能使用的是System V init)。請轉到6.5 Upstart。
  • 如果以上兩種情況都不成立,但您有一個/etc/inittab文件,則您可能正在運行System V init。請轉到6.6 System V init。

If your system has manual pages installed, viewing the init(8) manual page should help identify your version.

如果您的系統安裝了手冊頁,查看init(8)手冊頁應該有助於確定您的版本。

6.4 systemd(systemd)

The systemd init is one of the newest init implementations on Linux. In addition to handling the regular boot process, systemd aims to incorporate a number of standard Unix services such as cron and inetd. As such, it takes some inspiration from Apple’s launchd. One of its most significant features is its ability to defer the start of services and operating system features until they are necessary.

systemd init是Linux上最新的init實現之一。

除了處理常規的引導過程外,systemd還旨在整合一些標準的Unix服務,如cron和inetd。

因此,它在某種程度上受到了蘋果的launchd的啓發。

它最重要的特點之一是能夠推遲服務和操作系統功能的啓動,直到它們被需要為止。

There are so many systemd features that it can be very difficult to know where to start learning the basics.

systemd有很多功能,因此很難知道從哪裏開始學習基礎知識。

Let’s outline what happens when systemd runs at boot time:

讓我們概述一下systemd在啓動時的運行過程:

  1. systemd loads its configuration.
  2. systemd determines its boot goal, which is usually named default.target.
  3. systemd determines all of the dependencies of the default boot goal, dependencies of these dependencies,
    and so on.
  4. systemd activates the dependencies and the boot goal.
  5. After boot, systemd can react to system events (such as uevents) and activate additional components.
  6. systemd加載其配置。
  7. systemd確定其引導目標,通常被命名為default.target。
  8. systemd確定默認引導目標的所有依賴關係,以及這些依賴關係的依賴關係,以此類推。
  9. systemd激活依賴關係和引導目標。
  10. 引導完成後,systemd可以對系統事件(如uevents)做出反應,並激活其他組件。

When starting services, systemd does not follow a rigid sequence. As with other modern init systems, there is a considerable amount of flexibility in the systemd bootup process. Most systemd configurations deliberately try to avoid any kind of startup sequence, preferring to use other methods to resolve strict dependencies.

在啓動服務時,systemd不會遵循嚴格的順序。

與其他現代init系統一樣,systemd的啓動過程具有相當大的靈活性。

大多數systemd配置有意避免任何啓動順序,而是更傾向於使用其他方法來解決嚴格的依賴關係。

6.4.1 Units and Unit Types(單位和單位類型)

One of the most interesting things about systemd is that it does not just operate processes and services; it can also mount filesystems, monitor network sockets, run timers, and more. Each type of capability is called a unit type, and each specific capability is called a unit. When you turn on a unit, you activate it.

systemd 最有趣的一點是,它不僅能運行進程和服務,還能掛載文件系統、監控網絡套接字、運行定時器等。

每一種功能都被稱為一個單元類型,而每一種特定的功能都被稱為一個單元。

當你打開一個單元時,你就激活了它。

Rather than describe all of the unit types (you’ll find them in the systemd(1) manual page), here’s a look at a few of the unit types that perform the boot-time tasks required in any Unix system:

這裏不對所有單元類型進行描述(你可以在 systemd(1) 手冊中找到它們),而是介紹幾種執行任何 Unix 系統所需的啓動時任務的單元類型:

o Service units. Control the traditional service daemons on a Unix system.
o Mount units. Control the attachment of filesystems to the system.
o Target units. Control other units, usually by grouping them.

o 服務單元。控制 Unix 系統中的傳統服務守護進程。
o 掛載單元。控制文件系統與系統的連接。
o 目標單元。控制其他單元,通常是將它們分組。

The default boot goal is usually a target unit that groups together a number of service and mount units as dependencies. As a result, it’s easy to get a partial picture of what’s going to happen when you boot, and you can even create a dependency tree diagram with the systemctl dot command. You’ll find the tree to be quite large on a typical system, because many units don’t run by default.

默認啓動目標通常是一個目標單元,它將許多服務和掛載單元作為依賴關係組合在一起。

因此,很容易就能瞭解啓動時將發生的部分情況,甚至可以使用 systemctl dot 命令創建依賴關係樹圖。

在典型的系統中,由於許多單元默認情況下並不運行,因此依賴關係樹會非常龐大。

Figure 6-1 shows a part of the dependency tree for the default.target unit found on a Fedora system. When you activate that unit, all of the units below it on the tree also activate.

圖 6-1 顯示了 Fedora 系統中 default.target 單元的部分依賴關係樹。當您激活該單元時,它下面的所有單元也會激活。

Figure 6-1. Unit dependency tree

Figure 6-1. Unit dependency tree

圖6-1 單元依賴樹

6.4.2 systemd Dependencies(systemd 依賴關係)

Boot-time and operational dependencies are more complicated than they may seem at first because strict dependencies are too inflexible. For example, imagine a scenario in which you want to display a login prompt after starting a database server, so you define a dependency from the login prompt to the database server. However, if the database server fails, the login prompt will also fail due to that dependency, and you won’t even be able to log in to your machine to fix it.

啓動時和運行時的依賴關係比起初看起來要複雜得多,因為嚴格的依賴關係過於死板。

例如,想象一種情況,你希望在啓動數據庫服務器後顯示登錄提示符,所以你定義了一個從登錄提示符到數據庫服務器的依賴關係。

然而,如果數據庫服務器失敗,由於這個依賴關係,登錄提示符也會失敗,你甚至無法登錄到機器上進行修復。

Unix boot-time tasks are fairly fault tolerant and can often fail without causing serious problems for standard services. For example, if a data disk for a system was removed but its /etc/fstab entry remained, the initial filesystem mount would fail. However, that failure typically wouldn’t seriously affect standard operating system operation.

Unix啓動時的任務相當容錯,並且通常可以在標準服務中出現問題時失敗而不會造成嚴重問題。

例如,如果一個系統的數據磁盤被移除,但其/etc/fstab條目仍然存在,初始文件系統掛載將失敗。

然而,這種失敗通常不會對標準操作系統運行產生嚴重影響。

To accommodate the need for flexibility and fault tolerance, systemd offers a myriad of dependency types and styles. We’ll label them by their keyword syntax, and but we won’t go into details about configuration syntax until 6.4.3 systemd Configuration. Let’s first look at the basic types:

為了滿足靈活性和容錯性的需求,systemd提供了多種類型和風格的依賴關係。

我們將通過它們的關鍵字語法進行標記,但在6.4.3 systemd配置之前,我們不會詳細介紹配置語法。

讓我們首先看一下基本類型:

o Requires Strict dependencies. When activating a unit with a Requires dependency unit, systemd attempts to activate the dependency unit. If the dependency unit fails, systemd deactivates the dependent unit.
o Wants. Dependencies for activation only. Upon activating a unit, systemd activates the unit’s Wants dependencies, but it doesn’t care if those dependencies fail.
o Requisite. Units that must already be active. Before activating a unit with a Requisite dependency, systemd first checks the status of the dependency. If the dependency has not been activated, systemd fails on activation of the unit with the dependency.
o Conflicts. Negative dependencies. When activating a unit with a Conflict dependency, systemd
automatically deactivates the dependency if it is active. Simultaneous activation of two conflicting units fails.

o Requires 嚴格依賴關係。在激活具有Requires依賴關係的單元時,systemd嘗試激活依賴單元。如果依賴單元失敗,systemd會停用依賴單元。
o Wants 只用於激活的依賴關係。在激活單元時,systemd會激活該單元的Wants依賴關係,但不關心這些依賴關係是否失敗。
o Requisite 必須已經激活的單元。在激活具有Requisite依賴關係的單元之前,systemd首先檢查依賴的狀態。如果依賴尚未激活,systemd在激活具有該依賴關係的單元時失敗。
o Conflicts 負依賴關係。在激活具有Conflict依賴關係的單元時,如果該依賴關係處於激活狀態,systemd會自動停用該依賴關係。兩個相互衝突的單元同時激活會失敗。

NOTE The Wants dependency type is especially significant because it does not propagate failures to other units. The systemd documentation states that this is the way you should specify dependencies if possible, and it’s easy to see why. This behavior produces a much more robust system, similar to that of a traditional init.

注意 Wants 依賴類型特別重要,因為它不會將失敗傳播給其他單元。systemd文檔指出,如果可能的話,這是您應該指定依賴關係的方式,很容易理解為什麼。這種行為產生了一個更加健壯的系統,類似於傳統的init系統。

You can also attach dependencies “in reverse.” For example, in order to add Unit A as a Wants dependency to Unit B, you don’t have to add the Wants in Unit B’s configuration. Instead, you can install it as a WantedBy in Unit A’s configuration. The same is true of the RequiredBy dependency. The configuration for (and result of) a “By” dependency is slightly more involved than just editing a configuration file; see Enabling Units and the [Install] Section

您還可以“反向”附加依賴關係。例如,為了將單元A作為單元B的Wants依賴關係添加,您不必在單元B的配置中添加Wants。

相反,您可以將其安裝為單元A配置中的WantedBy。RequiredBy依賴關係也是如此。

一個“By”依賴關係的配置(和結果)比僅僅編輯一個配置文件要稍微複雜一些,請參閲啓用單元和[Install]部分。

You can view a unit’s dependencies with the systemctl command, as long as you specify a type of dependency, such as Wants or Requires:

您可以使用systemctl命令查看單元的依賴關係,只要指定依賴類型,例如Wants或Requires:

systemctl show -p type unit

Ordering(訂購)

None of the dependency syntax that you’ve seen so far explicitly specifies order. By default, activating a unit with a Requires or Wants causes systemd to activate all of these dependencies at the same time as the first unit. This is optimal, because you want to start as many services as possible as quickly as possible to reduce boot time. However, there are situations when one unit must start after another. For instance, in the system that Figure 6-1 is based on, the default.target unit is set to start after multi-user.service (this order distinction is not shown in the figure).

迄今為止,您所見到的所有依賴語法都沒有明確指定順序。

默認情況下,通過Requires或Wants激活一個單元會導致systemd同時激活所有這些依賴項,與第一個單元同時進行。這是最優的,因為您希望儘快啓動儘可能多的服務,以減少啓動時間。

然而,在某些情況下,一個單元必須在另一個單元之後啓動。

例如,在基於圖6-1的系統中,默認的目標單元設置為在multi-user.service之後啓動(此順序區別未在圖中顯示)。

To activate units in a particular order, you can use the following dependency modifiers:

為了按特定順序激活單元,您可以使用以下依賴修飾符:

o Before. The current unit will activate before the listed unit(s). For example, if Before=bar.target appears in foo.target, systemd activates foo.target before bar.target.
o After. The current unit activates after the listed unit(s).
Conditional Dependencies Several dependency condition keywords operate on various operation system states rather than systemd units. For example:
o ConditionPathExists=p: True if the (file) path p exists in the system.
o ConditionPathIsDirectory=p: True if p is a directory.
o ConditionFileNotEmpty=p: True if p is a file and it’s not zero-length.

o Before。當前單元將在列出的單元之前激活。例如,如果foo.target中出現Before=bar.target,systemd會在激活bar.target之前激活foo.target。
o After。當前單元在列出的單元之後激活。
條件依賴性。幾個依賴條件關鍵字適用於各種操作系統狀態,而不是systemd單元。例如:
o ConditionPathExists=p:如果系統中存在(文件)路徑p,則為True。
o ConditionPathIsDirectory=p:如果p是一個目錄,則為True。
o ConditionFileNotEmpty=p:如果p是一個文件且不為空,則為True。

If a conditional dependency in a unit is false when systemd tries to activate the unit, the unit does not activate, though this applies only to the unit in which it appears. Therefore, if you activate a unit that has a condition dependency as well as some other unit dependencies, systemd attempts to activate the unit dependencies regardless of whether the condition is true or false.

如果在systemd嘗試激活單元時,單元中的條件依賴性為假,則不會激活該單元,儘管這僅適用於出現條件依賴性的單元。因此,如果您激活具有條件依賴性以及其他單元依賴性的單元,systemd會嘗試激活單元依賴性,而不管條件是真還是假。

Other dependencies are primarily variations on the preceding. For example, the RequiresOverridable dependency is just like Requires when running normally, but it acts like a Wants dependency if a unit is manually activated. (For a full list, see the systemd.unit(5) manual page.)

其他依賴性主要是前述依賴性的變體。例如,RequiresOverridable依賴性在正常運行時與Requires完全相同,但如果手動激活單元,則會像Wants依賴性一樣起作用。(有關完整列表,請參閲systemd.unit(5)手冊頁。)

Now that you’ve seen some of the a few pieces of the systemd configuration, let’s look at some actual unit files and how to work with them.

現在,您已經看到了一些systemd配置的一些片段,讓我們來看一些實際的單元文件以及如何使用它們。

6.4.3 systemd Configuration(systemd 配置)

The systemd configuration files are spread among many directories across the system, so you typically won’t find the files for all of the units on a system in one place. That said, there are two main directories for systemd configuration: the system unit directory (globally configured, usually /usr/lib/systemd/system) and a system configuration directory (local definitions, usually /etc/systemd/system).

systemd的配置文件分佈在系統的許多目錄中,所以你通常不會在一個地方找到所有單元的文件。

話雖如此,systemd配置有兩個主要目錄:系統單元目錄(全局配置,通常為/usr/lib/systemd/system)和系統配置目錄(本地定義,通常為/etc/systemd/system)。

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. So when given the choice between modifying something in /usr and /etc, always change /etc.

為了避免混淆,請遵循這個規則:避免對系統單元目錄進行更改,因為你的發行版會為你維護它。將本地更改放在系統配置目錄中。

所以當你在/usr和/etc之間做出選擇時,總是選擇更改/etc。

NOTE You can check the current systemd configuration search path (including precedence) with this command:

注意:你可以使用以下命令檢查當前的systemd配置搜索路徑(包括優先級):

systemctl -p UnitPath show

However, this particular setting comes from a third source: pkg-config settings. To see the system unit and configuration directories on your system, use the following commands:

然而,這個特定的設置來自第三方來源:pkg-config設置。要查看系統上的系統單元和配置目錄,請使用以下命令:

$ pkg-config systemd –-variable=systemdsystemunitdir
$ pkg-config systemd --variable=systemdsystemconfdir

Unit Files(單位文件)

Unit files are derived from the XDG Desktop Entry Specification (for .desktop files, which are very similar to .ini files on Microsoft systems), with section names in brackets ([]) and variable and value assignments (options) in each section.

單元文件源於 XDG 桌面輸入規範(用於 .desktop 文件,與微軟系統上的 .ini 文件非常相似),括號([])中包含部分名稱,每個部分中包含變量和值分配(選項)。

Consider the example unit file media.mount in /usr/lib/systemd/system, which is standard on Fedora installations. This file represents the /media tmpfs filesystem, which is a container directory for mounting removable media.

以 /usr/lib/systemd/system 中的單元文件 media.mount 為例,它是 Fedora 安裝程序的標準配置。該文件表示 /media tmpfs 文件系統,它是掛載可移動媒體的容器目錄。

[Unit]
Description=Media Directory
Before=local-fs.target
[Mount]
What=tmpfs
Where=/media
Type=tmpfs
Options=mode=755,nosuid,nodev,noexec

There are two sections here. The [Unit] section gives some details about the unit and contains description and dependency information. In particular, this unit is set to activate before the local-fs.target unit.

這裏有兩個部分。[Unit] 部分提供了有關單元的一些詳細信息,包括描述和依賴信息。特別是,該單元設置為在 local-fs.target 單元之前激活。

The [Mount] section details the unit as being a mount unit, and it gives the details on the mount point, the type of filesystem, and the mount options as described in 4.2.6 Filesystem Mount Options. The What= variable identifies the device or UUID of the device to mount. Here, it’s set to tmpfs because this filesystem does not have a device. (For a full list of mount unit options, see the systemd.mount(5) manual page.)

[Mount] 部分詳細説明了該單元作為掛載單元,並提供了有關掛載點、文件系統類型和掛載選項的詳細信息,如 4.2.6 文件系統掛載選項中所述。

What= 變量標識要掛載的設備或設備的 UUID。

在這裏,它設置為 tmpfs,因為該文件系統沒有設備。(有關掛載單元選項的完整列表,請參閲 systemd.mount(5) 手冊頁。)

Many other unit configuration files are similarly straightforward. For example, the service unit file sshd.service enables secure shell logins:

許多其他單元配置文件同樣簡單明瞭。例如,服務單元文件 sshd.service 啓用安全 shell 登錄:

[Unit]
Description=OpenSSH server daemon
After=syslog.target network.target auditd.service
[Service]
EnvironmentFile=/etc/sysconfig/sshd
ExecStartPre=/usr/sbin/sshd-keygen
ExecStart=/usr/sbin/sshd -D $OPTIONS
ExecReload=/bin/kill -HUP $MAINPID
[Install]
WantedBy=multi-user.target

Because this is a service target, you’ll find the details about the service in the [Service] section, including how to prepare, start, and reload the service. You’ll find a complete listing in the systemd.service(5) manual page (and in systemd.exec(5)), as well as in the discussion of process tracking in 6.4.6 systemd Process Tracking and Synchronization.

因為這是一個服務目標,你可以在[Service]部分找到有關服務的詳細信息,包括如何準備、啓動和重新加載服務。

你可以在systemd.service(5)手冊頁(以及systemd.exec(5)手冊頁)和6.4.6節systemd進程跟蹤和同步的討論中找到完整的列表。

Enabling Units and the [Install] Section(啓用單元和[Install]部分)

The [Install] section in the sshd.service unit file is important because it helps us to understand how to use systemd’s WantedBy and RequiredBy dependency options. It’s actually a mechanism for enabling units without modifying any configuration files. During normal operation, systemd ignores the [Install] section. However, consider the case when sshd.service is disabled on your system and you would like to turn it on. When you enable a unit, systemd reads the [Install] section; in this case, enabling the sshd.service unit causes systemd to see the WantedBy dependency for multi-user.target. In response, systemd creates a symbolic link to sshd.service in the system configuration directory as follows:

sshd.service單元文件中的[Install]部分很重要,因為它幫助我們理解如何使用systemd的WantedBy和RequiredBy依賴選項。實際上,它是一種在不修改任何配置文件的情況下啓用單元的機制。在正常操作中,systemd會忽略[Install]部分。然而,考慮一種情況,即sshd.service在您的系統上被禁用並且您想要啓用它。當您啓用一個單元時,systemd會讀取[Install]部分;在這種情況下,啓用sshd.service單元會使systemd看到對multi-user.target的WantedBy依賴。作為響應,systemd會在系統配置目錄中創建一個指向sshd.service的符號鏈接,具體如下:

ln -s '/usr/lib/systemd/system/sshd.service' 
'/etc/systemd/system/multi-user.
target.wants/sshd.service'

Notice that the symbolic link is placed into a subdirectory corresponding to the dependent unit (multiuser.target in this case

請注意,符號鏈接被放置在與依賴單元對應的子目錄中(在本例中是multi-user.target)。

The [Install] section is usually responsible for the the .wants and .requires directories in the system configuration directory (/etc/systemd/system). However, there are also .wants directories in the unit configuration directory (/usr/lib/systemd/system), and you may also add links that don’t correspond to [Install] sections in the unit files. These manual additions are a simple way to add a dependency without modifying a unit file that may be overwritten in the future (by a software upgrade, for instance).

[Install] 部分通常負責系統配置目錄(/etc/systemd/system)中的 .wants 和 .requires 目錄。然而,在單元配置目錄(/usr/lib/systemd/system)中也有 .wants 目錄,您也可以添加與單元文件中的 [Install] 部分不對應的鏈接。這些手動添加的鏈接是一種簡單的方式,可以在不修改將來可能被覆蓋的單元文件的情況下添加依賴關係(例如,軟件升級)。

NOTE Enabling a unit is different from activating a unit. When you enable a unit, you are installing it into systemd’s configuration, making semipermanent changes that will survive a reboot. But you don’t always need to explicitly enable a unit. If the unit file has an [Install] section, you must enable it with systemctl enable; otherwise, the existence of the file is enough to enable it. When you activate a unit with systemctl start, you’re just turning it on in the current runtime environment. In addition, enabling a unit does not activate it.

注意:啓用單元與激活單元是不同的。當您啓用一個單元時,您正在將其安裝到 systemd 的配置中,進行半永久性的更改,這些更改將在重啓後保留。但您並不總是需要顯式地啓用一個單元。如果單元文件有一個 [Install] 部分,您必須使用 systemctl enable 命令來啓用它;否則,文件的存在就足以啓用它。當您使用 systemctl start 命令激活一個單元時,您只是在當前的運行時環境中啓動它。此外,啓用一個單元並不會激活它。

Variables and Specifiers(變量和指示符)

The sshd.service unit file also shows use of variables—specifically, the $OPTIONS and $MAINPID
environment variables that are passed in by systemd. $OPTIONS are options that you can pass to sshd when you activate the unit with systemctl, and $MAINPID is the tracked process of the service (see 6.4.6 systemd Process Tracking and Synchronization).

sshd.service 單元文件還顯示了變量的使用,具體來説是 systemd 傳遞的 $OPTIONS 和 $MAINPID 環境變量。

$ OPTIONS 是您在使用 systemctl 激活單元時可以傳遞給 sshd 的選項,$MAINPID 是服務的跟蹤進程(請參閲 6.4.6 systemd 進程跟蹤和同步)。

A specifier is another variable-like feature often found in unit files. Specifiers start with a percent (%). For example, the %n specifier is the current unit name, and the %H specifier is the current hostname.

指示符是單元文件中常見的另一個類似變量的特性。

指示符以百分號(%)開頭。例如,%n 指示符是當前單元的名稱,%H 指示符是當前主機名。

NOTE
The unit name can contain some interesting specifiers. You can parameterize a single unit file in order to spawn multiple copies of a service, such as getty processes running on tty1, tty2, and so on. To use these specifiers, add the @ symbol to the end of the unit name. For getty, create a unit file named getty@.service, which allows you to refer to units such as getty@tty1 and getty@tty2. Anything after the @ is called the instance, and when processing the unit file, systemd expands the %I specifier to the instance. You can see this in action with the getty@.service unit files that come with most distributions running systemd.

注意:

單元名稱可以包含一些有趣的指示符。

您可以通過參數化單個單元文件來生成多個服務的副本,例如在 tty1、tty2 等上運行的 getty 進程。要使用這些指示符,請在單元名稱的末尾添加 @ 符號。

對於 getty,創建一個名為 getty@.service 的單元文件,這樣您就可以引用 getty@tty1 和 getty@tty2 等單元。

@ 後面的任何內容都稱為實例,當處理單元文件時,systemd 會將 %I 指示符擴展為實例。

在大多數運行 systemd 的發行版中,可以通過 getty@.service 單元文件看到這一點。

6.4.4 systemd Operation(systemd 操作)

You’ll interact with systemd primarily through the systemctl command, which allows you to activate and deactivate services, list status, reload the configuration, and much more.

您將主要通過systemctl命令與systemd進行交互,該命令允許您激活和停用服務,列出狀態,重新加載配置等等。

The most essential basic commands deal with obtaining unit information. For example, to view a list of active units on your system, issue a list-units command. (This is actually the default command for systemctl, so you don’t really need the list-units part.):

最基本的命令涉及獲取單元信息。例如,要查看系統上活動單元的列表,請發出list-units命令(實際上,這是systemctl的默認命令,所以您實際上不需要list-units部分):

$ systemctl list-units

The output format is typical of a Unix information-listing command. For example, the header and the line for media.mount would look like this:

輸出格式是典型的Unix信息列表命令。

例如,標題和media.mount行將如下所示:

UNIT LOAD ACTIVE SUB JOB DESCRIPTION
media.mount loaded active mounted Media Directory

This command produces a lot of output, because a typical system has numerous active units, but it will still be abridged because systemctl truncates any really large unit names. To see the full names of the units, use the --full option, and to see all units (not just active), use the --all option.

該命令會產生大量輸出,因為典型的系統有很多活動單元,但它仍然會被截斷,因為systemctl會截斷任何非常大的單元名稱。要查看單元的完整名稱,請使用--full選項,要查看所有單元(而不僅僅是活動單元),請使用--all選項。

A particularly useful systemctl operation is getting the status of a unit. For example, here is a typical status command and its output:

一個特別有用的systemctl操作是獲取單元的狀態。例如,這是一個典型的狀態命令及其輸出:

$ systemctl status media.mount
media.mount - Media Directory
 Loaded: loaded (/usr/lib/systemd/system/media.mount; static)
 Active: active (mounted) since Wed, 13 May 2015 11:14:55 -0800;
37min ago
 Where: /media
 What: tmpfs
 Process: 331 ExecMount=/bin/mount tmpfs /media -t tmpfs -o
mode=755,nosuid,nodev,noexec (code=exited, status=0/SUCCESS)
 CGroup: name=systemd:/system/media.mount

Notice that there is much more information output here than you would see on any traditional init system. You get not only the state of the unit but also the exact command used to perform the mount, its PID, and its exit status.

請注意,這裏輸出的信息比您在任何傳統init系統上看到的信息要多得多。您不僅可以獲得單元的狀態,還可以獲得執行掛載所使用的確切命令、其PID和退出狀態。

One of the most interesting pieces of the output is the control group name. In the preceding example, the control group doesn’t include any information other than the name systemd:/system/media.mount because the unit’s processes have already terminated. However, if you get the status of a service unit such as NetworkManager.service, you’ll also see the process tree of the control group. You can view control groups without the rest of the unit status with the systemd-cgls command. You’ll learn more about control groups in 6.4.6 systemd Process Tracking and Synchronization.

輸出中最有趣的部分之一是控制組名稱。在前面的示例中,控制組除了名稱systemd:/system/media.mount之外沒有包含任何其他信息,因為單元的進程已經終止。但是,如果您獲取服務單元(如NetworkManager.service)的狀態,還將看到控制組的進程樹。您可以使用systemd-cgls命令查看控制組而不包含單元狀態的其他部分。有關控制組的更多信息,請參見6.4.6節systemd進程跟蹤和同步。

The status command also displays recent information from the unit’s journal (a log that records diagnostic information for each unit). You can view a unit’s entire journal with this command:

狀態命令還會顯示單元日誌(記錄每個單元的診斷信息的日誌)中的最新信息。您可以使用以下命令查看單元的完整日誌:

$ journalctl _SYSTEMD_UNIT=unit

(This syntax is a bit odd because journalctl can access the logs of more than just a systemd unit.) To activate, deactivate, and restart units, use the systemd start, stop, and restart commands. However, if you’ve changed a unit configuration file, you can tell systemd to reload the file in one of two ways:

(這種語法有點奇怪,因為journalctl可以訪問不僅僅是systemd單元的日誌。)要激活、停用和重新啓動單元,請使用systemd start、stop和restart命令。但是,如果您更改了單元配置文件,可以通過以下兩種方式告訴systemd重新加載文件:

image.png

Requests to activate, reactivate, and restart units are known as jobs in systemd, and they are essentially unit state changes. You can check the current jobs on a system with

在 systemd 中,激活、重新激活和重啓單元的請求被稱為作業,它們本質上是單元狀態的改變。你可以使用

$ systemctl list-jobs

If a system has been running for some time, you can reasonably expect there to be no active jobs on it because all of the activations should be complete. However, at boot time, you can sometimes log in fast enough to see some units start so slowly that they are not yet fully active. For example:

如果一個系統已經運行了一段時間,你可以合理地預期它不會有任何活動工作,因為所有的激活都應該已經完成。

不過,在啓動時,有時登錄速度會很快,以至於某些單元啓動緩慢,尚未完全激活。例如

JOB UNIT TYPE STATE
 1 graphical.target start waiting
 2 multi-user.target start waiting
71 systemd-...nlevel.service start waiting
75 sm-client.service start waiting
76 sendmail.service start running
120 systemd-...ead-done.timer start waiting

In this case, job 76, the sendmail.service unit startup, is taking a really long time. The other listed jobs are in a waiting state, most likely because they’re all waiting for job 76. When sendmail.service finishes starting and becomes fully active, job 76 will complete, the rest of the jobs will also complete, and the job list will be empty.

在這種情況下,作業76,即sendmail.service單元的啓動,花費了很長時間。其他列出的作業處於等待狀態,很可能是因為它們都在等待作業76。當sendmail.service完成啓動並完全激活時,作業76將完成,其餘的作業也將完成,作業列表將為空。

NOTE The term job can be confusing, especially because Upstart, another init system described in this chapter, uses the word job to (roughly) refer to what systemd calls a unit. It’s important to remember that although a systemd job associated with a unit will terminate, the unit itself can be active and running afterwards, especially in the case of service units.

注意 術語“作業”可能會令人困惑,特別是因為本章中描述的另一個初始化系統Upstart使用“作業”一詞(大致)指的是systemd所稱的“單元”。重要的是要記住,儘管與一個單元相關聯的systemd作業將終止,但該單元本身在服務單元的情況下可能仍然處於活動狀態並繼續運行。

See 6.7 Shutting Down Your System for how to shut down and reboot the system.

請參閲6.7關機和重啓系統瞭解如何關閉和重啓系統。

6.4.5 Adding Units to systemd(向systemd添加單元)

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

向systemd添加單元主要是創建、激活和可能啓用單元文件的問題。通常應將自己的單元文件放在系統配置目錄/etc/systemd/system中,以免與發行版提供的文件混淆,並且在升級時不會被髮行版覆蓋。

Because it’s easy to create target units that don’t do anything and don’t interfere with anything, you should try it. Here’s how to create two targets, one with a dependency on the other:

由於很容易創建不執行任何操作且不干擾任何內容的目標單元,建議您嘗試一下。以下是創建兩個目標的方法,其中一個依賴於另一個:

1. Create a unit file named test1.target:
2. [Unit] Description=test 1
3. Create a test2.target file with a dependency on test1.target:
4. [Unit]
5. Description=test 2
6. Wants=test1.target
7. Activate the test2.target unit (remember that the dependency in test2.target causes systemd to activate test1.target when you do this): 

    # systemctl start test2.target
7. Verify that both units are active:
8. # systemctl status test1.target test2.target
9. test1.target - test 1
10. Loaded: loaded (/etc/systemd/system/test1.target; static)
11. Active: active since Thu, 12 Nov 2015 15:42:34 -0800; 10s ago
12.
13. test2.target - test 2
14. Loaded: loaded (/etc/systemd/system/test2.target; static)
 Active: active since Thu, 12 Nov 2015 15:42:34 -0800; 10s ago

NOTE If your unit file has an [Install] section, “enable” the unit before activating it:

systemctl enable unit

注意 如果設備文件中有 [安裝] 部分,請在激活前 "啓用 "設備:

systemctl enable unit

Try this with the preceding example. Remove the dependency from test2.target and add an [Install] section to test1.target containing WantedBy=test2.target.

用前面的例子試試看。刪除 test2.target 中的依賴關係,並在 test1.target 中添加包含 WantedBy=test2.target 的 [Install] 部分。

Removing Units(刪除單元)

To remove a unit, follow these steps:

要刪除單元,請按照以下步驟操作

  1. Deactivate the unit if necessary:
  2. 必要時停用單元:
# systemctl stop unit
  1. If the unit has an [Install] section, disable the unit to remove any dependent symbolic links:
  2. 如果設備有 [安裝] 部分,則禁用設備以刪除任何依賴的符號鏈接:
  3. # systemctl disable unit
  4. Remove the unit file, if you like.
  5. 如果需要,刪除單元文件。

    6.4.6 systemd Process Tracking and Synchronization(systemd 進程跟蹤和同步)

systemd wants a reasonable amount of information and control over every process that it starts. The main problem that it faces is that a service can start in different ways; it may fork new instances of itself or even daemonize and detach itself from the original process.

systemd希望對其啓動的每個進程都能獲得合理的信息和控制權。它面臨的主要問題是,一個服務可以以不同的方式啓動;它可以fork出新的實例,甚至可以守護進程化並與原始進程分離。

To minimize the work that a package developer or administrator needs to do in order to create a working unit file, systemd uses control groups (cgroups), an optional Linux kernel feature that allows for finer tracking of a process hierarchy. If you’ve worked with Upstart before, you know that you have to do a little extra work to figure out what the main process is for a service. In systemd, you don’t have to worry about how many times a process forks—just whether it forks. Use the Type option in your service unit file to indicate its startup behavior. There are two basic startup styles:

為了最大限度地減少軟件包開發人員或管理員為創建一個可工作的單元文件所需的工作量,systemd使用控制組(cgroups),這是一個可選的Linux內核功能,允許更精細地跟蹤進程層次結構。如果你之前使用過Upstart,你會知道你需要額外的工作來確定一個服務的主進程。在systemd中,你不需要擔心進程fork的次數,只需要關注它是否fork。在你的服務單元文件中使用Type選項來指示其啓動行為。有兩種基本的啓動方式:

o Type=simple The service process doesn’t fork.
o Type=forking The service forks, and systemd expects the original service process to terminate. Upon termination, systemd assumes that the service is ready.

  • Type=simple:服務進程不會fork。
  • Type=forking:服務進行fork,並且systemd期望原始服務進程終止。在終止後,systemd假設服務已準備就緒。

The Type=simple option doesn’t account for the fact that a service may take some time to set up, and systemd doesn’t know when to start any dependencies that absolutely require such a service to be ready. One way to deal with this is to use delayed startup (see 6.4.7 systemd On-Demand and Resource-Parallelized Startup). However, some Type startup styles can indicate that the service itself will notify systemd when it is ready:

Type=simple選項並不考慮一個服務可能需要一些時間來進行設置,而systemd不知道何時啓動任何絕對需要此類服務準備就緒的依賴項。處理這個問題的一種方式是使用延遲啓動(參見6.4.7 systemd按需和資源並行啓動)。然而,某些Type啓動方式可以表示服務本身將在準備就緒時通知systemd:

o Type=notify The service sends a notification specific to systemd (with the sd_notify() function call) when it’s ready.
o Type=dbus The service registers itself on the D-bus (Desktop Bus) when it’s ready.

  • Type=notify:服務在準備就緒時向systemd發送特定的通知(使用sd_notify()函數調用)。
  • Type=dbus:服務在準備就緒時在D-bus(桌面總線)上註冊自己。

Another service startup style is specified with Type=oneshot; here the service process actually terminates completely when it’s finished. With such a service, you will almost certainly need to add a RemainAfterExit=yes option so that systemd will still regard the service as active even after its processes terminate.

另一種服務啓動方式是通過Type=oneshot指定;在這種情況下,服務進程在完成後會完全終止。對於這樣的服務,你幾乎肯定需要添加RemainAfterExit=yes選項,以便systemd在其進程終止後仍將該服務視為活動狀態。

Finally, there’s one last style: Type=idle. This simply instructs systemd not to start the service until there are no active jobs. The idea here is just to delay a service start until other services have started to keep the system load down, or to keep services from stepping on one another’s output. (Remember, once a service has started, the systemd job that started the service terminates.)

最後,還有一種類型:Type=idle。這僅僅是告訴systemd在沒有活動作業時不要啓動該服務。這裏的想法是僅在其他服務啓動後才延遲啓動服務,以保持系統負載低,或者防止服務互相干擾輸出。(記住,一旦服務啓動,啓動該服務的systemd作業就會終止。)

6.4.7 systemd On-Demand and Resource-Parallelized Startup(systemd 按需和資源並行啓動)

One of systemd’s most significant features is its ability to delay a unit startup until it is absolutely needed. The setup typically works like this:

systemd最重要的功能之一是能夠延遲啓動一個單元,直到絕對需要它為止。通常的設置如下:

  1. You create a systemd unit (call it Unit A) for the system service that you’d like to provide, as normal.
  2. You identify a system resource such as a network port/socket, file, or device that Unit A uses to offer its services.
  3. You create another systemd unit, Unit R, to represent that resource. These units have special types such as socket units, path units, and device units.
  4. 創建一個systemd單元(稱之為單元A),用於提供系統服務,與正常的方式一樣。
  5. 識別一個系統資源,比如網絡端口/套接字、文件或設備,單元A用來提供其服務。
  6. 創建另一個systemd單元,單元R,用來表示該資源。這些單元有特殊的類型,如套接字單元、路徑單元和設備單元。

Operationally, it goes like this:

運行時,步驟如下:

  1. Upon activation of Unit R, systemd monitors the resource.
  2. When anything tries to access the resource, systemd blocks the resource, and the input to the resource is buffered.
  3. systemd activates Unit A.
  4. When the service from Unit A is ready, it takes control of the resource, reads the buffered input, and runs normally.
  5. 在激活單元R時,systemd監控該資源。
  6. 當有任何東西試圖訪問該資源時,systemd阻塞該資源,並將輸入緩衝。
  7. systemd激活單元A。
  8. 當來自單元A的服務準備就緒時,它接管該資源,讀取緩衝的輸入,並正常運行。

There are a few concerns:

有幾個注意事項:

o You must make sure that your resource unit covers every resource that the service provides. This normally isn’t a problem, as most services have just one point of access.
o You need to make sure your resource unit is tied to the service unit that it represents. This can be implicit or explicit, and in some cases, many options represent different ways for systemd to perform the handoff to the service unit.
o Not all servers know how to interface with the units that systemd can provide.

o 您必須確保資源單元涵蓋了服務提供的每個資源。通常情況下,這不是問題,因為大多數服務只有一個訪問點。
o 您需要確保資源單元與它所代表的服務單元有關聯。這可以是隱式的或顯式的,並且在某些情況下,許多選項表示systemd執行向服務單元交接的不同方式。
o 並非所有服務器都知道如何與systemd提供的單元進行接口。

If you already know what utilities like inetd, xinetd, and automount do, you’ll see that there are a lot of similarities. Indeed, the concept is nothing new (and in fact, systemd includes support for automount units). We’ll go over an example of a socket unit in An Example Socket Unit and Service. But let’s first take a look at how these resource units help you at boot time.

如果您已經瞭解了類似inetd、xinetd和automount等實用程序的功能,您會發現它們有很多相似之處。

事實上,這個概念並不新鮮(實際上,systemd包含了對automount單元的支持)。

我們將在《一個套接字單元和服務的示例》中介紹一個套接字單元的示例。

但首先,讓我們看看這些資源單元如何在啓動時幫助您。

Boot Optimization with Auxiliary Units(帶輔助裝置的啓動優化)

A common style of unit activation in systemd attempts to simplify dependency order and speed up boot time. It’s similar to on-demand startup in that a service unit and an auxiliary unit represent the service unit’s offered resource, except that in this case systemd starts the service unit as soon as it activates the auxiliary unit.

systemd中常見的單元激活方式旨在簡化依賴順序並加快啓動時間。

它類似於按需啓動,其中一個服務單元和一個輔助單元代表服務單元提供的資源,不同之處在於在這種情況下,systemd在激活輔助單元時立即啓動服務單元。

The reasoning behind this scheme is that essential boot-time service units such as syslog and dbus take some time to start, and many other units depend on them. However, systemd can offer a unit’s essential resource (such as a socket unit) very quickly, and then it can immediately activate not only the essential unit but also any units that depend on the essential resource. Once the essential unit is ready, it takes control of the resource.

這種方案背後的原因是,像syslog和dbus這樣的必要啓動服務單元需要一些時間來啓動,並且許多其他單元依賴於它們。

然而,systemd可以非常快速地提供一個單元的必要資源(如套接字單元),然後它可以立即激活不僅是必要單元,還有任何依賴於必要資源的單元。

一旦必要單元準備就緒,它將控制該資源。

Figure 6-2 shows how this might work in a traditional system. In this boot timeline, Service E provides an essential Resource R. Services A, B, and C depend on this resource and must wait until Service E has started. When booting, the system takes quite a long time to get around to starting Service C.

圖6-2展示了這在傳統系統中的工作原理。在這個啓動時間軸中,服務E提供了一個必要的資源R。

服務A、B和C依賴於這個資源,並且必須等待服務E啓動。

在啓動時,系統需要相當長的時間才能開始啓動服務C。

Figure 6-2. Sequential boot timeline with a resource dependency

Figure 6-2. Sequential boot timeline with a resource dependency

圖 6-2. 具有資源依賴性的順序啓動時間表

Figure 6-3 shows an equivalent systemd boot configuration. The services are represented by Units A, B, C, and E, and a new Unit R represents the resource that Unit E provides. Because systemd can provide an interface for Unit R while Unit E starts, Units A, B, C, and E can all be started at the same time. Unit E takes over for Unit R when ready. (An interesting point here is that Units A, B, and C may not need to explicitly access Unit R before they finish their startup, as Unit B in the figure demonstrates.)

圖 6-3 顯示了一個等效的 systemd 啓動配置。單元 A、B、C 和 E 代表服務,新單元 R 代表單元 E 提供的資源。

由於 systemd 可以在單元 E 啓動時為單元 R 提供接口,因此單元 A、B、C 和 E 可以同時啓動。

當準備就緒時,單元 E 將接替單元 R。

(這裏有趣的一點是,單元 A、B 和 C 在完成啓動前可能不需要顯式訪問單元 R,如圖中單元 B 所示)。

Figure 6-3. systemd boot timeline with a resource unit

Figure 6-3. systemd boot timeline with a resource unit

圖 6-3. 使用資源單元的 systemd 啓動時間線

NOTE When parallelizing startup like this, there is a chance that your system may slow down temporarily due to a large number of units starting at once.

注意 在進行類似的並行啓動時,由於大量單元同時啓動,系統可能會暫時變慢。

The takeaway is that, although you’re not creating an on-demand unit startup in this case, you’re using the same features that make on-demand startup possible. For common real-life examples, see the syslog and DBus configuration units on a machine running systemd; they’re very likely to be parallelized in this way.

這裏要説明的是,雖然在這種情況下你並沒有創建按需單元啓動,但你使用的是使按需啓動成為可能的相同功能。有關常見的實際例子,請參閲運行 systemd 的機器上的 syslog 和 DBus 配置單元;它們很可能以這種方式並行運行。

An Example Socket Unit and Service(套接字單元和服務示例)

We’ll now look at an example, a simple network echo service that uses a socket unit. This is somewhat advanced material, and you may not really understand it until you’ve read the discussion of TCP, ports, and listening in Chapter 9 and sockets in Chapter 10, so feel free to skip this and come back later

現在我們來看一個使用套接字單元的簡單網絡回聲服務示例。這部分內容有些高深,在閲讀過第 9 章中關於 TCP、端口和監聽的討論以及第 10 章中關於套接字的討論之後,你可能才會真正理解,所以請跳過這部分內容,稍後再來看。

The idea behind this service is that when a network client connects to the service, the service repeats anything that the client sends back to the client. The unit will listen on TCP port 22222. We’ll call it the echo service and start with a socket unit, represented by the following echo.socket unit file:

這項服務背後的理念是,當網絡客户端連接到服務時,服務會將客户端發送的任何內容重複發送給客户端。設備將監聽 TCP 端口 22222。我們將其稱為 echo 服務,並從一個套接字單元開始,用下面的 echo.socket 單元文件表示:

[Unit]
Description=echo socket
[Socket]
ListenStream=22222
Accept=yes

Note that there’s no mention of the service unit that this socket supports inside the unit file. So what is the corresponding service unit file?

請注意,單元文件中並沒有提及該插座支持的服務單元。那麼相應的服務單元文件是什麼呢?

Its name is echo@.service. The link is done by naming convention; if a service unit file has the same prefix as a .socket file (in this case, echo), systemd knows to activate that service unit when there’s activity on the socket unit. In this case, systemd creates an instance of echo@.service when there’s activity on echo.socket.

它的名稱是 echo@.service。這種鏈接是通過命名約定實現的;如果服務單元文件的前綴與 .socket 文件(本例中為 echo)相同,systemd 就會在套接字單元有活動時激活該服務單元。在這種情況下,當 echo.socket 上有活動時,systemd 就會創建 echo@.service 實例。

Here is the echo@.service unit file:

下面是 echo@.service 單元文件:

[Unit]
Description=echo service
[Service]
ExecStart=-/bin/cat
StandardInput=socket

NOTE If you don’t like the implicit activation of units based on the prefixes, or you need to create an activation mechanism between two units with different prefixes, you can use an explicit option in the unit defining your resource. For example, use Socket=bar.socket inside foo.service to have bar.socket hand its socket to foo.service.

注意:如果你不喜歡基於前綴的單位的隱式激活,或者你需要在具有不同前綴的兩個單位之間創建一個激活機制,你可以在定義資源的單位中使用顯式選項。例如,在 foo.service 中使用 Socket=bar.socket,以便 bar.socket 將其套接字傳遞給 foo.service。

To get this example service unit running, you need to start the echo.socket unit behind it, like this:

要運行這個示例服務單元,需要啓動它後面的 echo.socket 單元,如下所示:

# systemctl start echo.socket

Now you can test the service by connecting to your local port 22222. When the following telnet command connects, type anything and press ENTER. The service repeats what you typed back to you:

現在可以連接本地端口 22222 測試服務。

當以下 telnet 命令連接後,鍵入任何內容並按 ENTER 鍵。服務會重複你輸入的內容:

$ telnet localhost 22222

Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hi there.
Hi there.

When you’re bored with this, press CTRL-] on a line by itself, and then CTRL-D. To stop the service, stop the socket unit:

當你覺得無聊時,在一行上按 CTRL-],然後按 CTRL-D。

要停止服務,請停止插座單元:

# systemctl stop echo.socket
Instances and Handoff(實例和交接)

Because the echo@.service unit supports multiple simultaneous instances, there’s an @ in the name (recall from Note that @ signifies parameterization). Why would you want multiple instances? The reason is that you may have more than one network client connecting to the service at the same time, and each connection should have its own instance.

因為echo@.service單元支持多個同時實例,所以名稱中有一個@符號(請回憶一下@表示參數化的意思)。為什麼需要多個實例?原因是您可能有多個網絡客户端同時連接到服務,每個連接都應該有自己的實例。

In this case, the service unit must support multiple instances because of the Accept option in echo.socket. That option instructs systemd not only to listen on the port, but also to accept incoming connections and pass the incoming connections on to the service unit, with each connection a separate instance. Each instance reads data from the connection as standard input, but it doesn’t necessarily need to know that the data is coming from a network connection.

在這種情況下,由於echo.socket中的Accept選項,服務單元必須支持多個實例。該選項指示systemd不僅監聽端口,還接受傳入連接並將傳入連接傳遞給服務單元,每個連接都是一個單獨的實例。每個實例從連接中讀取數據作為標準輸入,但它不一定需要知道數據來自網絡連接。

NOTE Most network connections require more flexibility than just a simple gateway to standard input and output, so don’t expect to be able to create network services with a service unit file like the echo@.service unit file shown here.

注意:大多數網絡連接需要比簡單的標準輸入和輸出網關更多的靈活性,因此不要指望能夠像這裏顯示的echo@.service單元文件那樣創建網絡服務。

Although the service unit could do all of the work of accepting the connection, it wouldn’t have the @ in its name if it did. In that case, it would take complete control of the socket, and systemd wouldn’t attempt to listen on the network port again until the service unit has finished.

雖然服務單元可以完成接受連接的所有工作,但如果是這樣,它的名稱中就不會有@符號。在這種情況下,它將完全控制套接字,直到服務單元完成後,systemd才會再次嘗試監聽網絡端口。

The many different resources and options for handoff to service units make it difficult to provide a categorical summary. Also, the documentation for the options is spread out over several manual pages. The ones to check for the resource-oriented units are systemd.socket(5), systemd.path(5), and systemd.device(5). One document that’s often overlooked for service units is systemd.exec(5), which contains information about how the service unit can expect to receive a resource upon activation.

對於交接到服務單元的許多不同資源和選項,很難提供一個分類總結。

此外,有關這些選項的文檔分散在幾個手冊頁面上。需要檢查的資源導向單元的文檔有systemd.socket(5)、systemd.path(5)和systemd.device(5)。

對於服務單元,經常被忽視的一個文檔是systemd.exec(5),其中包含了關於服務單元如何在激活時接收資源的信息。

6.4.8 systemd System V Compatibility(systemd 系統 V 兼容性)

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. It works like this:

一個將systemd與其他新一代init系統區分開來的特點是,它試圖更完整地跟蹤由System V兼容的init腳本啓動的服務。其工作方式如下:

  1. First, 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 would be 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.
  6. 首先,systemd激活runlevel< N>.target,其中N是運行級別。
  7. 對於/etc/rc< N>.d中的每個符號鏈接,systemd識別出/etc/init.d中的腳本。
  8. systemd將腳本名稱與服務單元關聯起來(例如,/etc/init.d/foo將變為foo.service)。
  9. systemd激活服務單元,並根據rc< N>.d中腳本的名稱使用start或stop參數運行腳本。
  10. systemd嘗試將腳本中的任何進程與服務單元關聯起來。

Because systemd makes the association with a service unit name, you can use systemctl to restart the service or view its status. But don’t expect any miracles from System V compatibility mode; it still must run the init scripts serially, for example.

由於systemd將關聯與服務單元名稱,您可以使用systemctl來重新啓動服務或查看其狀態。但不要對System V兼容模式抱有太高期望;例如,它仍然必須按順序運行init腳本。

6.4.9 systemd Auxiliary Programs(systemd 輔助程序)

When starting out with systemd, you may notice the exceptionally large number of programs in /lib/systemd. These are primarily support programs for units. For example, udevd is part of systemd, and you’ll find it there as systemd-udevd. Another, the systemd-fsck program, works as a middleman between systemd and fsck.

在開始使用systemd時,您可能會注意到/lib/systemd目錄中異常龐大的程序數量。

這些程序主要是單位的支持程序。

例如,udevd是systemd的一部分,您會在那裏找到它作為systemd-udevd。

另一個例子是systemd-fsck程序,它在systemd和fsck之間充當中間人。

Many of these programs exist because they contain notification mechanisms that the standard system utilities lack. Often, they simply run the standard system utilities and notify systemd of the results. (After all, it would be silly to try to reimplement all of fsck inside systemd.)

這些程序中的許多存在是因為它們包含了標準系統工具所缺少的通知機制。

通常情況下,它們只是運行標準系統工具並通知systemd結果。

(畢竟,在systemd內部重新實現所有的fsck將是愚蠢的。)

NOTE One other interesting aspect of these programs is that they are written in C, because one goal of systemd is to reduce the number of shell scripts on a system. There is some debate as to whether it’s a good idea to do so (after all, many of these programs could probably be written as shell scripts), but as long as everything works and does so reliably, securely, and reasonably quickly, there’s little reason to bother taking sides.

注意這些程序的另一個有趣之處是它們是用C編寫的,因為systemd的一個目標是減少系統上的shell腳本數量。

關於是否這樣做是個好主意存在一些爭議(畢竟,許多這些程序可能可以用shell腳本編寫),但只要一切正常且可靠、安全、相對快速地運行,就沒有理由去糾結。

When you see a program in /lib/systemd that you can’t identify, see the manual page. There’s a good chance that the manual page will not only describe the utility but also describe the type of unit that it’s meant to augment.

當您在/lib/systemd中看到一個無法識別的程序時,請查看其手冊頁。

很有可能手冊頁不僅描述了該實用程序,還描述了它所用於擴展的單位類型。

If you’re not running (or interested in) Upstart, skip ahead to 6.6 System V init for an overview of the System V init process.

如果您不在運行(或對)Upstart感興趣,請跳到6.6節System V init,瞭解System V init過程的概述。

6.5 Upstart(後起之秀)

The Upstart version of init revolves around jobs and events. Jobs are startup and runtime actions for Upstart to perform (such as system services and configuration), and events are messages that Upstart receives from itself or other processes (such as udevd). Upstart works by starting jobs in response to events.

Upstart版本的init圍繞着作業(jobs)和事件(events)展開。

作業是Upstart執行的啓動和運行時操作(例如系統服務和配置),而事件是Upstart從自身或其他進程接收到的消息(例如udev)。

Upstart通過響應事件來啓動作業。

To get an idea of how this works, consider the udev job for starting the udevd daemon. Its configuration file is typically /etc/init/udev.conf, which includes the following:

為了瞭解這個過程是如何工作的,可以考慮啓動udev守護進程的udev作業。

它的配置文件通常是/etc/init/udev.conf,包含以下內容:

start on virtual-filesystems
stop on runlevel [06]

These lines mean that Upstart starts the udev job upon receiving the virtual-filesystems event, and it stops the job upon receiving a runlevel event with an argument of 0 or 6.

這幾行的意思是,Upstart 在收到 virtual-filesystems 事件時啓動 udev 作業,並在收到參數為 0 或 6 的 runlevel 事件時停止作業。

There are many variations on events and their arguments. For example, Upstart can react to events emitted in response to job status, such as the started udev event emitted by the udev job above. But before explaining jobs in detail, here’s a high-level overview of how Upstart works.

事件及其參數有很多變化。例如,Upstart 可以對響應作業狀態的事件做出反應,如上述由 udev 作業發出的已啓動 udev 事件。

在詳細解釋作業之前,我們先來了解一下 Upstart 的工作原理。

6.5.1 Upstart Initialization Procedure(啓動初始化程序)

Upon startup, Upstart does the following:

在啓動時,Upstart執行以下操作:

  1. Loads its configuration and the job configuration files in /etc/init.
  2. Emits the startup event.
  3. Runs jobs configured to start upon receiving the startup event.
  4. These initial jobs emit their own events, triggering more jobs and events.
  5. 加載其配置和位於/etc/init目錄下的作業配置文件。
  6. 發出啓動事件。
  7. 運行配置為在接收到啓動事件後啓動的作業。
  8. 這些初始作業會發出自己的事件,從而觸發更多的作業和事件。

Upon finishing all jobs associated with a normal startup, Upstart continues to monitor and react to events during the entire system uptime.

在完成與正常啓動相關的所有作業後,Upstart會繼續監視並響應整個系統的運行時間內發生的事件。

Most Upstart installations run like this:

大多數Upstart安裝都是以以下方式運行的:

  1. The most significant job that Upstart runs in response to the startup event is mountall. This job
    attaches all necessary local and virtual filesystems to the currently running system so that everything else can run.
  2. The mountall job emits a number of events, including filesystem, virtual-filesystems, local-filesystems, remote-filesystems, and all-swaps, among others. These events indicate that the important filesystems on the system are now attached and ready.
  3. In response to these events, Upstart starts a number of essential service jobs. For example, udev starts in response to the virtual-filesystems event, and dbus starts in response to the localfilesystems event.
  4. Among the essential service jobs, Upstart starts the network-interfaces job, usually in response to the local-filesystems event and udevd being ready.
  5. The network-interfaces job emits the static-network-up event.
  6. Upstart runs the rc-sysinit job in response to the filesystem and static-network-up events. This job is responsible for maintaining the system’s current runlevel, and when started for the first time without a runlevel, it switches the system to the default runlevel by emitting a runlevel event.
  7. Upstart runs most of the other startup jobs on the system in response to the runlevel event and the new runlevel.
  8. Upstart對啓動事件的響應中最重要的作業是mountall。該作業會將所有必要的本地和虛擬文件系統附加到當前運行的系統,以便其他所有內容都能運行。
  9. mountall作業會發出多個事件,包括filesystem、virtual-filesystems、local-filesystems、remote-filesystems和all-swaps等。這些事件表示系統上的重要文件系統現在已經附加並準備就緒。
  10. 作為對這些事件的響應,Upstart會啓動一些基本的服務作業。例如,udev會在虛擬文件系統事件發生時啓動,dbus會在本地文件系統事件發生時啓動。
  11. 在基本的服務作業中,Upstart會啓動network-interfaces作業,通常是在本地文件系統事件和udev準備就緒時啓動。
  12. network-interfaces作業會發出static-network-up事件。
  13. Upstart會在文件系統和static-network-up事件的響應中運行rc-sysinit作業。該作業負責維護系統的當前運行級別,並在第一次啓動時沒有運行級別時通過發出一個runlevel事件將系統切換到默認運行級別。
  14. Upstart會在runlevel事件和新的運行級別的響應中運行系統上的大多數其他啓動作業。

The process can become complicated because it’s not always clear where events originate. Upstart emits only a few events, and the rest come from jobs. Job configuration files usually declare the events that they will emit, but the details of how the job emits the events are usually not in the Upstart job configuration files.

這個過程可能變得複雜,因為不總是清楚事件的來源。

Upstart只發出少量的事件,其餘的事件都來自作業。

作業配置文件通常聲明它們將要發出的事件,但作業如何發出事件的詳細信息通常不在Upstart作業配置文件中。

To get to the bottom of things, you’ll often have to dig. For example, consider the static-network-up event. The network-interface.conf job configuration file says that it emits this event, but it doesn’t say where. It turns out that the event stems from the ifup command, which this job runs when initializing a network interface in the /etc/network/if-up.d/upstart script.

要深入瞭解情況,通常需要進行深入挖掘。

例如,考慮static-network-up事件。

network-interface.conf作業配置文件表示它會發出此事件,但沒有説明事件的來源。

事實證明,該事件源自ifup命令,在初始化/etc/network/if-up.d/upstart腳本中運行此作業時。

NOTE Though all of this is documented (the ifup.d directory is in the interfaces(5) manual page referenced by the ifup(8) manual page), it can be challenging to find out how this all works just by reading the documentation. It’s usually faster to grep the event name in a lot of configuration files to see what comes up, then to try to piece everything back together from there.

注意:儘管所有這些都有文檔記錄(ifup.d目錄在ifup(8)手冊頁引用的interfaces(5)手冊頁中有説明),但僅通過閲讀文檔來了解所有這些是有挑戰性的。

通常更快的方法是在許多配置文件中使用grep命令搜索事件名稱,然後從中嘗試將所有內容拼湊在一起。

One issue with Upstart is that there’s currently no clear way to view events. You can turn its log priority to debug, which will cause it to log everything that comes in (typically to /var/log/syslog), but the copious amount of extraneous information in this file makes it difficult to determine an event’s context.

Upstart的一個問題是目前沒有明確的方法來查看事件。

您可以將其日誌優先級設置為debug,這將導致它記錄所有收到的內容(通常記錄在/var/log/syslog中),但是該文件中大量的無關信息使得很難確定事件的上下文。

6.5.2 Upstart Jobs

Each file in the Upstart /etc/init configuration directory corresponds to a job, and the main configuration file for each job has a .conf extension. For example, /etc/init/mountall.conf defines the mountall job.

Upstart /etc/init配置目錄中的每個文件對應一個作業,每個作業的主配置文件都有一個.conf擴展名。例如,/etc/init/mountall.conf定義了mountall作業。

There are two primary kinds of Upstart jobs:

Upstart作業主要有兩種類型:

o Task jobs. These are jobs with a clear end. For example, mountall is a task job because it terminates when finished mounting filesystems.
o Service jobs. These jobs have no defined stop. Servers (daemons) such as udevd, database servers, and web servers are all service jobs.

  • 任務作業。這些作業有明確的結束點。例如,mountall是一個任務作業,因為在完成掛載文件系統後會終止。
  • 服務作業。這些作業沒有定義的停止點。諸如udevd、數據庫服務器和Web服務器等服務器(守護進程)都屬於服務作業。

A third kind of job is an abstract job. Think of this as a kind of virtual service job. Abstract jobs exist only in Upstart and start nothing by themselves, but they are sometimes used as management tools for other jobs because other jobs can start and stop based on the events coming from an abstract job.

第三種作業是抽象作業。可以將其視為一種虛擬的服務作業。抽象作業僅存在於Upstart中,並且本身不啓動任何內容,但有時被用作其他作業的管理工具,因為其他作業可以根據來自抽象作業的事件進行啓動和停止。

Viewing Jobs(查看作業)

You can view Upstart jobs and job status with the initctl command. To get an overview of what’s happening on your system, run:

可以使用initctl命令查看Upstart作業和作業狀態。要獲取系統上正在發生的情況概述,請運行:

$ initctl list

You’ll get a lot of output, so let’s just look at two sample jobs that might appear in a typical listing. Here’s a simple example of a task job status:

mountall stop/waiting

This indicates that the mountall task job has a status of stop/waiting, meaning that it’s not running. (Unfortunately, as of this writing, you can’t use the status to determine whether a job already ran or not because stop/waiting also applies to jobs that have never run.)

這表明 mountall 任務作業的狀態是停止/等待,即沒有運行。(遺憾的是,截至本文撰寫時,您還不能使用狀態來判斷任務是否已運行,因為停止/等待也適用於從未運行過的任務)。

Service jobs that have associated processes appear in the status listing as follows:

有相關進程的服務任務在狀態列表中顯示如下:

tty1 start/running, process 1634

This line shows that the tty1 job is running and that process ID 1634 is performing the job. (Not all service jobs have associated processes.)

這一行顯示了tty1作業正在運行,並且進程ID 1634正在執行該作業。

(並非所有的服務作業都有關聯的進程。)

NOTE If you know a job’s name, you can view its status directly with initctl status job.

注意:如果您知道作業的名稱,可以使用initctl status job命令直接查看其狀態。

The status portion of the initctl output (e.g., stop/waiting) can be confusing. The left-hand side (before the /) is the goal, or what the job is supposed to be working toward, such as start or stop. The righthand side is the current job state, or what the job is doing right now, such as waiting or running. For example, in the preceding listing, the tty1 job has the status start/running, meaning that its goal is to start. The state of running indicates that it has started successfully. (For service jobs, the running state is nominal.)

initctl輸出的狀態部分(例如stop/waiting)可能會讓人感到困惑。

左側(斜槓之前)是目標,即作業應該朝着什麼方向努力,例如start或stop。

右側是當前作業狀態,即作業當前正在做什麼,例如waiting或running。

例如,在前面的列表中,tty1作業的狀態是start/running,表示它的目標是啓動。

running狀態表示它已經成功啓動。

(對於服務作業來説,running狀態是正常的。)

The mountall case is a bit different because task jobs don’t remain running. The stop/waiting status usually indicates that the job started and completed its task. Upon completing its task, it moved from a start to a stop goal, and it is now waiting for further commands from Upstart.

mountall情況有些不同,因為任務作業不會保持運行狀態。

stop/waiting狀態通常表示作業已經啓動並完成了任務。

完成任務後,它從start目標轉變為stop目標,現在正在等待Upstart的進一步命令。

Unfortunately, as mentioned earlier, because jobs that have never started also have an Upstart stop/waiting status, you can’t really tell whether a job has run or never started unless you enable debugging and look at the logs, as described in 6.5.5 Upstart Logs.

不幸的是,正如前面提到的,由於從未啓動的作業也具有Upstart的stop/waiting狀態,因此除非您啓用調試並查看日誌(如6.5.5 Upstart日誌中所述),否則無法確定作業是否運行或從未啓動。

NOTE You won’t see jobs running on your system that were started with Upstart’s System V compatibility feature.

注意:使用Upstart的System V兼容性功能啓動的系統上不會看到正在運行的作業。

Job State Transitions

There are many job states, but there’s a set way to move between them. For example, here’s how a typical job starts:

有許多工作狀態,但在它們之間有一種固定的轉換方式。

例如,以下是一個典型工作的開始過程:

  1. All jobs begin in the stop/waiting status.
  2. When a user or a system event starts a job, the job’s goal changes from stop to start.
  3. Upstart changes the job’s state from waiting to starting, so the status is now start/starting.
  4. Upstart emits a starting job event.
  5. The job performs whatever it needs to do for the starting state.
  6. Upstart changes the job’s state from starting to pre-start and emits the pre-start job event.
  7. The job works its way through several more states until it hits the running state.
  8. Upstart emits a started job event.
  9. 所有工作都從停止/等待狀態開始。
  10. 當用户或系統事件啓動一個工作時,工作的目標從停止變為啓動。
  11. Upstart將工作的狀態從等待改變為啓動中,因此狀態現在是啓動/正在啓動。
  12. Upstart發出一個啓動工作事件。
  13. 工作執行啓動狀態所需的操作。
  14. Upstart將工作的狀態從啓動中改變為預啓動,併發出預啓動工作事件。
  15. 工作通過幾個其他狀態逐步進行,直到達到運行狀態。
  16. Upstart發出一個已啓動工作事件

Task termination involves a similar set of state changes and events. (See the upstart-events(7) manual page for details on all of the states and transitions in both goals.)

任務終止涉及一系列類似的狀態變化和事件。

(有關目標中所有狀態和轉換的詳細信息,請參閲upstart-events(7)手冊頁。)

6.5.3 Upstart Configuration

Let’s examine the two configuration files: one for the task job mountall and the other for the service job tty1. Like all Upstart configuration files, the configuration files are in /etc/init, and they are named mountall.conf and tty1.conf. The configuration files are organized into smaller pieces called stanzas. Each stanza starts with a leading keyword, such as description or start.

讓我們來看一下兩個配置文件:一個是用於任務作業mountall的配置文件,另一個是用於服務作業tty1的配置文件。

與所有Upstart配置文件一樣,這些配置文件位於/etc/init目錄下,分別命名為mountall.conf和tty1.conf。

配置文件被組織成稱為段落的較小部分。

每個段落以一個關鍵詞開頭,例如description或start。

To get started, open the mountall.conf file on your system. Look for a line like this in the first stanza:

首先,打開您系統上的mountall.conf文件。在第一個段落中找到類似以下內容的行:

description "Mount filesystems on boot"

This stanza gives a short text description of the job.

這個段落提供了對作業的簡短文本描述。

Next you’ll see a few stanzas describing how the mountall job starts:

接下來,您將看到幾個描述mountall作業如何啓動的段落:

start on startup
stop on starting rcS

Here, the first line tells Upstart to start the job upon receiving the startup event (the initial event that Upstart emits). The second line tells Upstart to terminate the job upon receiving the rcS event, when the system goes into single-user mode.

這裏,第一行告訴Upstart在接收到啓動事件(Upstart發出的初始事件)時啓動作業。

第二行告訴Upstart在接收到rcS事件時終止作業,當系統進入單用户模式時。

The next two lines tell Upstart how the mountall job behaves:

接下來的兩行告訴Upstart mountall作業的行為方式:

expect daemon
task

The task stanza tells Upstart that this is a task job, so the job should complete at some point. The expect stanza is tricky. It means that the mountall job will spawn a daemon that will operate independently of the original job script. Upstart needs to know this because it must know when the daemon terminates in order to correctly signal that the mountall job has terminated. (We’ll discuss this in more detail in Process Tracking and the Upstart expect Stanza.)

任務段落告訴Upstart這是一個任務作業,所以作業應該在某個時間點完成。

期望段落比較棘手。它意味着mountall作業將會生成一個獨立於原始作業腳本的守護進程。

Upstart需要知道這一點,因為它必須知道守護進程何時終止,以便正確地發出mountall作業已終止的信號。

(我們將在進程追蹤和Upstart期望段落的更多細節中討論這一點。)

The mountall.conf file continues with several emits stanzas, indicating events that the jobs produce:

mountall.conf文件繼續使用了幾個發出事件的段落,指示作業產生的事件:

emits virtual-filesystems
emits local-filesystems
emits remote-filesystems
emits all-swaps
emits filesystem
emits mounting
emits mounted

NOTE As mentioned in 6.5.1 Upstart Initialization Procedure, even though these lines are present, this is not the actual source of the events. You’ll need to hunt through the job script to find them.

注意:正如在6.5.1 Upstart初始化過程中提到的那樣,儘管這些行存在,但這並不是事件的實際來源。你需要查找作業腳本以找到它們。

You may also see a console stanza stating where Upstart should send the output:

您還可能會看到一個控制枱段落,指示Upstart應該將輸出發送到哪裏:

console output

With the output parameter, Upstart sends the mountall job’s output to the system’s console.

通過輸出參數,Upstart 會將 mountall 作業的輸出發送到系統控制枱。

Now you’ll see the details of the job itself—in this case, with a script stanza:

現在,你將看到作業本身的詳細信息--在本例中,是一個腳本節:

script
 . /etc/default/rcS
 [ -f /forcefsck ] && force_fsck="--force-fsck"
 [ "$FSCKFIX" = "yes" ] && fsck_fix="-fsck-fix"
 # set $LANG so that messages appearing in plymouth are translated
 if [ -r /etc/default/locale ]; then
 . /etc/default/locale
 export LANG LANGUAGE LC_MESSAGES LC_ALL
 fi
 exec mountall --daemon $force_fsck $fsck_fix
end script

This is a shell script (see Chapter 11), most of which is preparatory— setting locale and determining whether an fsck is necessary. The exec mountall command near the bottom of this script is where the real action happens. This command mounts the filesystems and emits the job’s events when finished.

這是一個shell腳本(見第11章),其中大部分是準備工作 - 設置區域設置並確定是否需要進行fsck。

在腳本底部附近的exec mountall命令是真正的操作發生的地方。

該命令在完成後掛載文件系統併發出作業的事件。

A Service Job: tty1(一個服務作業:tty1)

The service job tty1 is much simpler; it controls a virtual console login prompt. Its entire configuration file, tty1.conf, looks like this:

服務作業tty1要簡單得多;它控制一個虛擬控制枱登錄提示符。

它的整個配置文件tty1.conf如下所示:

start on stopped rc RUNLEVEL=[2345] and (
 not-container or
 container CONTAINER=lxc or
 container CONTAINER=lxc-libvirt)
 stop on runlevel [!2345]
respawn
exec /sbin/getty -8 38400 tty1

The most complicated part of this job is actually when it starts, but for now, ignore the container lines and concentrate on this portion:

實際上,這項工作最複雜的部分是在開始時,但現在,請忽略容器線,將注意力集中在這一部分:

start on stopped rc RUNLEVEL=[2345]

This part tells Upstart to activate the job upon receiving a stopped rc event from Upstart when the rc task job has run and terminated. To make the condition true, the rc job must also set the RUNLEVEL environment variable to a value from 2 through 5 (see 6.5.6 Upstart Runlevels and System V Compatibility).

這部分告訴Upstart在接收到來自Upstart的停止rc事件時激活作業,當rc任務作業運行並終止時。

為了使條件成立,rc作業還必須將RUNLEVEL環境變量設置為2到5之間的值(參見6.5.6 Upstart運行級別和System V兼容性)。

NOTE Other jobs that start on runlevels aren’t so picky. For example, you might see this instead:

注意:其他在運行級別上啓動的作業並不那麼挑剔。例如,你可能會看到下面這樣的情況:

start on runlevel [2345]

The only real difference between these last two start stanzas is timing; this example activates the job as soon as the runlevel is set, while the prior one waits until the System V stuff finishes.

這最後兩個啓動段落之間唯一的真正區別在於時間;這個例子在運行級別設置後立即激活作業,而前一個則等到System V的相關操作完成後才開始。

The container configuration is there because Upstart not only runs directly on top of the Linux kernel on real hardware, but it can also run in virtual environments or containers. Some of these environments do not have virtual consoles, and you don’t want to run getty on a console that doesn’t exist.

容器配置的原因是因為Upstart不僅直接在真實硬件上的Linux內核上運行,還可以在虛擬環境或容器中運行。

其中一些環境沒有虛擬控制枱,而你又不希望在不存在的控制枱上運行getty。

Stopping the tty1 job is straightforward:

停止tty1作業很簡單:

stop on runlevel [!2345]

This stop stanza tells Upstart to terminate the job whenever the run-level is not 2 through 5 (for example, during system shutdown).

只要運行級別不是 2 到 5(例如,在系統關機時),stop stanza 就會告訴 Upstart 終止作業。

The exec stanza at the bottom is the command to run:

底部的 exec stanza 是要運行的命令:

exec /sbin/getty -8 38400 tty1

This stanza is much like the script stanza that you saw for the mountall job, except that the tty1 job has no complicated setup to perform—it’s easy to start with a single line. In this case, we’re running the login prompt program getty on /dev/tty1, which is the first virtual console (the one you get when you press CTRL-ALT-F1 in graphics mode).

這一節與你在mountall作業中看到的腳本節非常相似,只是tty1作業沒有複雜的設置要執行 - 只需要一行即可開始。

在這種情況下,我們在/dev/tty1上運行登錄提示程序getty,它是第一個虛擬控制枱(當你在圖形模式下按下CTRL-ALT-F1時會出現)。

The respawn stanza instructs Upstart to restart the tty1 job if the job terminates. In this case, Upstart runs a new getty for a new login prompt when you log out of the virtual console.

respawn節指示Upstart在作業終止時重新啓動tty1作業。

在這種情況下,當您從虛擬控制枱註銷時,Upstart會運行一個新的getty以獲取新的登錄提示。

Those are the basics of Upstart configuration. You’ll find much more detail in the init(5) manual page and online resources, but one stanza requires special attention. The expect stanza is discussed next.

這些是Upstart配置的基礎知識。

您將在init(5)手冊頁面和在線資源中找到更多詳細信息,但有一個節需要特別注意。

下面將討論expect節。

Process Tracking and the Upstart expect Stanza(進程跟蹤和Upstart的expect Stanza)

Because Upstart tracks processes in jobs once they’ve started (so that it can terminate and restart them efficiently), it wants to know which processes are relevant to each job. This can be a difficult task, because in the traditional Unix startup scheme, processes fork from others during startup to become daemons, and the main process for a job may start after one or two forks. Without proper process tracking, Upstart won’t be able to finalize its job startup, or it may track the incorrect PID for the job.

因為Upstart在作業啓動後會跟蹤進程(以便能夠高效地終止和重新啓動它們),所以它想要知道哪些進程與每個作業相關。

這是一項困難的任務,因為在傳統的Unix啓動方案中,進程在啓動過程中從其他進程中分叉出來成為守護進程,而作業的主進程可能在一兩次分叉後啓動。

如果沒有正確的進程跟蹤,Upstart將無法完成作業的啓動,或者可能跟蹤到錯誤的作業進程ID。

You tell Upstart how a job behaves with the expect stanza. There are four basic possibilities:

使用expect stanza來告訴Upstart作業的行為方式。有四種基本情況:

o No expect stanza The main job process does not fork. Track the main process.
o expect fork The process forks once. Track the forked process.
o expect daemon The process forks twice. Track the second fork.
o expect stop The job’s main process will raise a SIGSTOP signal to indicate that it is ready. (This is rare.)

o 沒有expect stanza 主作業進程不會分叉。跟蹤主進程。
o expect fork 進程分叉一次。跟蹤分叉出來的進程。
o expect daemon 進程分叉兩次。跟蹤第二次分叉出來的進程。
o expect stop 作業的主進程會發出SIGSTOP信號以表示它已準備好。(這種情況很少見。)

For Upstart and other modern versions of init, such as systemd, the ideal case is the first one (no expect stanza), because the main job process doesn’t have to include any of its own startup and shutdown mechanics.

對於Upstart和其他現代版本的init(如systemd)來説,理想情況是第一種情況(沒有expect stanza),因為主作業進程不需要包含任何自己的啓動和關閉機制。

In other words, it doesn’t need to bother with forking or detaching itself from a current terminal—nuisances that Unix systems developers have had to deal with for years.

換句話説,它不需要在當前終端上進行分叉或分離——這些是Unix系統開發人員多年來必須處理的麻煩事。

Many traditional service daemons already include debugging-style options that tell the main process to not fork. Examples include the Secure Shell daemon, sshd, and its -D option. A look at the /etc/init/ssh.conf startup stanzas reveals a simple configuration to start sshd, prevent rapid respawning, and eliminate spurious output to stderr:

許多傳統的服務守護進程已經包含了告訴主進程不要分叉的調試選項。

例如,Secure Shell守護進程sshd及其-D選項。

查看/etc/init/ssh.conf啓動stanza可以看到一個簡單的配置,用於啓動sshd,防止快速重啓,並消除stderr上的雜散輸出:

respawn
respawn limit 10 5
umask 022
# 'sshd -D' leaks stderr and confuses things in conjunction with 'console 
log'
console none
--snip--
exec /usr/sbin/sshd -D

Among jobs that require an expect stanza, expect fork is the most common. For example, here’s the startup portion of the /etc/init/cron.conf file:

在需要 expect stanza 的工作中,expect fork 是最常見的。

例如,下面是 /etc/init/cron.conf 文件的啓動部分:

expect fork
respawn
exec cron

A simple job startup like this usually indicates a well-behaved, stable daemon.

像這樣的簡單工作啓動通常表明守護進程很乖、很穩定。

NOTE It’s worth reading more about the expect stanza on the upstart.ubuntu.com site because it relates directly to process life span. For example, you can trace the life of a process and its system calls, including fork(), with the strace command.

注:值得在 upstart.ubuntu.com 網站上閲讀更多有關 expect stanza 的內容,因為它與進程壽命直接相關。

例如,你可以使用 strace 命令跟蹤進程的生命週期及其系統調用,包括 fork()。

6.5.4 Upstart Operation(Upstart操作)

In addition to the list and status commands described in 6.5.2 Upstart Jobs, you can also use the initctl utility to control Upstart and its jobs. You should read the initctl(8) manual page at some point, but for now let’s look at the essentials.

除了6.5.2 Upstart作業中描述的列表和狀態命令之外,您還可以使用initctl實用程序來控制Upstart及其作業。

您應該在某個時間點閲讀initctl(8)手冊頁,但現在讓我們看一下基本操作。

To start an Upstart job, use initctl start:

要啓動一個Upstart作業,請使用initctl start命令:

# initctl start job

To stop a job, use initctl stop:

要停止作業,請使用 initctl stop:

# initctl stop job

To restart a job:

要重新啓動作業:

# initctl restart job

If you need to emit an event to Upstart, you can do it manually with:

如果需要向 Upstart 發送一個事件,可以手動執行:

# initctl emit event

You can also add environment variables to the emitted event by adding key=value parameters after event.

你也可以在事件後添加 key=value 參數,將環境變量添加到發出的事件中。

NOTE You can’t start and stop individual services that started via Upstart’s System V compatibility feature. See 6.6.1 System V init: Startup Command Sequence for more on how to do this in a System V init script.

注意:無法啓動和停止通過 Upstart 的 System V 兼容功能啓動的單個服務。有關在 System V init 腳本中如何執行此操作的更多信息,請參閲 6.6.1 System V init:啓動命令序列。

There are many ways to disable an Upstart job so that it will not start at boot time, but the most maintainable one is to determine the name of the job’s configuration file (usually /etc/init/.conf ) and then create a new file called /etc/init/.override containing only the line:

有許多方法可以禁用 Upstart 作業,使其在啓動時不會啓動,但最可維護的方法是確定作業配置文件的名稱(通常為 /etc/init/.conf),然後創建一個名為 /etc/init/.override 的新文件,其中只包含一行:

manual

Now the only way that the job will start is by running initctl start job.

現在,啓動作業的唯一方法就是運行 initctl start job。

The primary advantage to this method is that it’s easily reversible. To reenable the job at boot, remove the .override file.

這種方法的主要優點是很容易逆轉。要在啓動時重新啓用作業,只需刪除 .override 文件。

6.5.5 Upstart Logs

There are two basic kinds of logs in Upstart: service job logs, and diagnostic messages that Upstart itself produces. Service job logs record the standard output and standard error of the scripts and daemons that run the services. These messages, recorded in /var/log/upstart, are in addition to the standard syslog messages that a service may produce. (You’ll learn more about syslog in Chapter 7.) It’s hard to categorize what goes into these logs because there are no standards, but the most common contents are startup and shutdown messages, as well as emergency error messages. Many services produce no messages at all because they send everything to syslog or their own logging facility.

在Upstart中有兩種基本類型的日誌:服務作業日誌和Upstart本身生成的診斷消息。

服務作業日誌記錄運行服務的腳本和守護進程的標準輸出和標準錯誤。

這些消息記錄在/var/log/upstart中,並且是服務可能生成的標準syslog消息的補充。

(關於syslog的更多信息請參見第7章)。

很難對這些日誌中包含的內容進行分類,因為沒有標準,但最常見的內容是啓動和關閉消息,以及緊急錯誤消息。

許多服務根本不產生任何消息,因為它們將所有內容都發送到syslog或它們自己的日誌記錄設施。

Upstart’s own diagnostic log can contain information about when it starts and reloads, as well as certain information about jobs and events. This diagnostic log goes to the kernel syslog utility. On Ubuntu, you’ll usually find this log in the /var/log/kern.log file and the catchall /var/log/syslog file.

Upstart自己的診斷日誌可能包含有關啓動和重新加載的信息,以及有關作業和事件的某些信息。

這個診斷日誌發送到內核syslog實用程序。

在Ubuntu上,您通常會在/var/log/kern.log文件和萬能的/var/log/syslog文件中找到這個日誌。

That said, by default, Upstart logs little to nothing, so to see anything at all in the logs, you must change the Upstart log priority. The name of the default priority is message. To log events and job changes on a running system, change the log priority to info:

話雖如此,默認情況下,Upstart幾乎不記錄任何內容,所以要在日誌中看到任何內容,您必須更改Upstart日誌優先級。

默認優先級的名稱是message。

要記錄正在運行的系統上的事件和作業更改,請將日誌優先級更改為info:

# initctl log-priority info

Keep in mind that this won’t be permanent and the priority will reset after a reboot. To have Upstart log everything when it starts, add a --verbose parameter as a boot parameter, as described in 5.5 GRUB Introduction.

請注意,這不是永久性的,重啓後優先級將重置。

要讓 Upstart 在啓動時記錄所有內容,可在啓動參數中添加 --verbose 參數,如 5.5 GRUB 介紹中所述。

6.5.6 Upstart Runlevels and System V Compatibility(啓動運行級別和系統 V 兼容性)

So far, we’ve touched upon a few places where Upstart supports the idea of System V runlevels and mentioned that it has the ability to run System V startup scripts as a job. Here’s a more detailed overview of how it works on Ubuntu systems:

到目前為止,我們已經涉及了Upstart支持System V運行級別的幾個地方,並提到它能夠將System V啓動腳本作為作業運行的能力。

下面是關於它在Ubuntu系統上的更詳細概述:

  1. The rc-sysinit job runs, usually after getting the filesystem and static-network-up events. Before it runs, there is no runlevel.
  2. The rc-sysinit job determines which runlevel to enter. Usually, the run-level is the default, but it can also parse an older /etc/inittab file or take the runlevel from a kernel parameter (in /proc/cmdline).
  3. The rc-sysinit job runs telinit to switch the runlevel. The command emits a runlevel event, specifying the runlevel in the RUNLEVEL environment variable.
  4. Upstart receives the runlevel event. A number of jobs are configured to start on the runlevel event paired with a certain runlevel, and Upstart sets these in motion.
  5. One of the runlevel-activated task jobs, rc, is responsible for running the System V start. In order to do so, the rc job runs /etc/init.d/rc, just as System V init would (see 6.6 System V init).
  6. Once the rc job terminates, Upstart can start a number of other jobs upon receiving the stopped rc event (such as the tty1 job in A Service Job: tty1).
  7. rc-sysinit作業在獲取文件系統和靜態網絡連接事件後運行,通常是在這些事件之後運行。在它運行之前,還沒有運行級別。
  8. rc-sysinit作業確定要進入的運行級別。通常情況下,運行級別是默認的,但也可以解析舊的/etc/inittab文件或從內核參數(在/proc/cmdline中)獲取運行級別。
  9. rc-sysinit作業運行telinit來切換運行級別。該命令會發出一個運行級別事件,並在RUNLEVEL環境變量中指定運行級別。
  10. Upstart接收到運行級別事件。許多作業被配置為在特定運行級別的運行級別事件上啓動,並且Upstart啓動這些作業。
  11. 運行級別激活的任務作業之一,rc,負責運行System V啓動。為了做到這一點,rc作業運行/etc/init.d/rc,就像System V init一樣(參見6.6 System V init)。
  12. 一旦rc作業終止,Upstart可以在接收到停止的rc事件後啓動其他一些作業(例如在A Service Job: tty1中的tty1作業)。

Notice that although Upstart treats the runlevel no differently than any other event, many of the job configuration files on most Upstart systems refer to the runlevel.

請注意,儘管Upstart對待運行級別與其他事件沒有任何區別,但大多數Upstart系統上的作業配置文件都與運行級別有關。

In any case, there is a critical point during boot when the filesystems are mounted and when most of the important system initialization is done. At this point, the system is ready to start higher-level system services such as graphical display managers and database servers. A runlevel event is handy for marking this point. You could configure Upstart to use any event as a trigger, though. One challenge comes when trying to determine which services start as Upstart jobs and which ones start in System V compatibility mode. The easiest way to find out is to look in your runlevel’s System V link farm (see 6.6.2 The System V init Link Farm). For example, if your runlevel is 2, look in /etc/rc2.d; anything there is likely running in System V compatibility mode.

無論如何,在啓動過程中有一個關鍵點,即文件系統被掛載並完成大部分重要的系統初始化。

此時,系統已準備好啓動更高級別的系統服務,如圖形顯示管理器和數據庫服務器。

運行級別事件對於標記此點非常有用。

不過,您可以配置Upstart使用任何事件作為觸發器。

當嘗試確定哪些服務作為Upstart作業啓動,哪些作為System V兼容模式啓動時,可能會遇到一個挑戰。

找出方法是查看運行級別的System V鏈接目錄(參見6.6.2 System V init鏈接目錄)。

例如,如果您的運行級別是2,請查看/etc/rc2.d;那裏的任何內容都很可能是以System V兼容模式運行的。

NOTE One stumbling block may be the presence of dummy scripts in /etc/init.d. For any Upstart service job, there may also be a System V–style script for that service in /etc/init.d, but that script won’t do anything other than tell you that the service has been converted to an Upstart job. There also won’t be a link to the script in the System V link directory. If you run into a dummy script, find out the Upstart job name, and use initctl to control the job.

注意:一個障礙可能是/etc/init.d中存在虛擬腳本。對於任何Upstart服務作業,可能還有一個System V風格的腳本在/etc/init.d中,但該腳本除了告訴您該服務已轉換為Upstart作業外,不會執行任何其他操作。

在System V鏈接目錄中也不會有指向該腳本的鏈接。如果遇到虛擬腳本,請找出Upstart作業名稱,並使用initctl來控制該作業。

6.6 System V init(系統 V 啓動)

The System V init implementation on Linux dates to the early days of Linux; its core idea is to support an orderly bootup to different runlevels with a carefully sequenced process startup. Though System V is now uncommon on most desktop installations, you may encounter System V init in Red Hat Enterprise Linux, as well as in embedded Linux environments such as routers and phones.

Linux上的System V init實現可以追溯到Linux的早期階段;其核心思想是通過仔細順序的進程啓動來支持有序的不同運行級別的啓動。

雖然在大多數桌面安裝中System V現在已經不常見,但在Red Hat Enterprise Linux以及嵌入式Linux環境(如路由器和手機)中,您可能會遇到System V init。

There are two major components to a typical System V init installation: 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 the following in your inittab file:

典型的System V init安裝有兩個主要組件:一箇中央配置文件和一個由符號鏈接組成的大型啓動腳本集合。

配置文件/etc/inittab是一切的起點。

如果您使用System V init,請在inittab文件中查找類似下面這樣的行:

id:5:initdefault: 

This indicates that the default runlevel is 5.

這表示默認運行級別為5。

All lines in inittab take the following form, with four fields separated by colons in this order:

inittab中的所有行都採用以下形式,按順序由四個用冒號分隔的字段組成:

o A unique identifier (a short string, such as id in the previous example)
o The applicable runlevel number(s)
o The action that init should take (default runlevel to 5 in the previous example)
o A command to execute (optional)

o 唯一標識符(一個短字符串,例如前面示例中的id)
o 適用的運行級別號碼
o init應該執行的操作(在前面示例中是將默認運行級別設置為5)
o 要執行的命令(可選)

To see how commands work in an inittab file, consider this line:

為了瞭解在inittab文件中命令的工作原理,考慮以下行:

l5:5:wait:/etc/rc.d/rc 5

This particular line is important because it triggers most of the system configuration and services. Here, the wait action determines when and how System V init runs the command: Run /etc/rc.d/rc 5 once when entering runlevel 5, then wait for this command to finish before doing anything else. To make a long story short, the rc 5 command executes anything in /etc/rc5.d that starts with a number (in the order of the numbers).

這一行很重要,因為它觸發了大部分系統配置和服務。

在這裏,wait操作確定System V init何時以及如何運行該命令:在進入運行級別5時運行一次/etc/rc.d/rc 5,然後等待該命令完成後再執行其他操作。

簡而言之,rc 5命令執行以數字開頭的/etc/rc5.d中的任何內容(按照數字的順序)。

The following are some of the most common inittab actions in addition to initdefault and wait.

除了initdefault和wait之外,以下是一些常見的inittab操作。

respawn(重生)

The respawn action tells init to run the command that follows and, if the command finishes executing, to run it again. You’re likely to see something like this in an inittab file:

重生操作會告訴 init 運行後面的命令,如果命令執行完畢,則再次運行該命令。你可能會在 inittab 文件中看到類似的內容:

1:2345:respawn:/sbin/mingetty tty1

The getty programs provide login prompts. The line above is used for the first virtual console (/dev/tty1), which is the one you see when you press ALT-F1 or CTRL-ALT-F1 (see 3.4.4 Terminals: /dev/tty, /dev/pts/ , and /dev/tty). The respawn action brings the login prompt back after you log out.

getty程序提供登錄提示。

上面的行用於第一個虛擬控制枱(/dev/tty1),當您按下ALT-F1或CTRL-ALT-F1時,您會看到它(參見3.4.4 終端:/dev/tty、/dev/pts/ 和 /dev/tty)。

respawn操作在您註銷後將登錄提示帶回。

ctrlaltdel

The ctrlaltdel action controls what the system does when you press CTRLALT-DEL on a virtual console. On most systems, this is some sort of reboot command, using the shutdown command (discussed in 6.7 Shutting Down Your System).

ctrlaltdel操作控制系統在虛擬控制枱上按下CTRLALT-DEL時的操作。

在大多數系統上,這是一種重新啓動命令,使用shutdown命令(在6.7 關閉系統中討論)。

sysinit

The sysinit action is the first thing that init should run when starting, before entering any runlevels.

sysinit操作是init在啓動之前應該運行的第一件事情,在進入任何運行級別之前。

NOTE For more available actions, see the inittab(5) manual page.

注意:更多可用的操作,請參閲inittab(5)手冊頁。

6.6.1 System V init: Startup Command Sequence(系統 V 啓動 啓動命令序列)

You are now ready to learn how System V init starts system services, just before it lets you log in. Recall this inittab line from earlier:

現在你可以學習 System V init 如何在讓你登錄之前啓動系統服務了。

回想一下之前的 inittab 行:

l5:5:wait:/etc/rc.d/rc 5

This small line triggers many other programs. In fact, rc stands for run commands, which many people refer to as scripts, programs, or services. But where are these commands?

這個小行觸發了許多其他程序。事實上,rc代表運行命令,許多人稱之為腳本、程序或服務。但是這些命令在哪裏呢?

The 5 in this line tells us that we’re talking about runlevel 5. The commands are probably either in /etc/rc.d/rc5.d or /etc/rc5.d. (Runlevel 1 uses rc1.d, runlevel 2 uses rc2.d, and so on.) For example, you might find the following items in the rc5.d directory:

這行中的5告訴我們我們正在談論運行級別5。

這些命令可能在/etc/rc.d/rc5.d或/etc/rc5.d中。(運行級別1使用rc1.d,運行級別2使用rc2.d,依此類推。)

例如,您可能會在rc5.d目錄中找到以下項目:

S10sysklogd S20ppp S99gpm
S12kerneld S25netstd_nfs S99httpd
S15netstd_init S30netstd_misc S99rmnologin
S18netbase S45pcmcia S99sshd
S20acct S89atd
S20logoutd S89cron

The rc 5 command starts programs in the rc5.d directory by executing the following commands in this sequence:

rc 5 命令按以下順序執行,啓動 rc5.d 目錄中的程序:

S10sysklogd start
S12kerneld start
S15netstd_init start
S18netbase start
--snip--
S99sshd start

Notice the start argument in each command. The capital S in a command name means that the command should run in start mode, and the number (00 through 99) determines where in the sequence rc starts the command. The rc*.d commands are usually shell scripts that start programs in /sbin or /usr/sbin. Normally, you can figure out what a particular command does by viewing the script with less or another pager program.

請注意每個命令中的start參數。命令名稱中的大寫S表示該命令應以啓動模式運行,而數字(00到99)確定了rc在序列中啓動命令的位置。

rc*.d命令通常是啓動/sbin或/usr/sbin中程序的shell腳本。

通常,您可以通過使用less或其他分頁程序查看腳本來弄清楚特定命令的作用。

NOTE Some rc*.d directories contain commands that start with K (for “kill,” or stop mode). In this case, rc runs the command with the stop argument instead of start. You will most likely encounter K commands in runlevels that shut down the system.

注意:某些rc*.d目錄包含以K開頭(表示“kill”或停止模式)的命令。

在這種情況下,rc會使用stop參數而不是start來運行命令。

您很可能會在關閉系統的運行級別中遇到K命令。

You can run these commands by hand. However, you normally want to do so through the init.d directory instead of the rc * .d directories, which we’ll now describe.

您可以手動運行這些命令。但是,通常您希望通過init.d目錄而不是rc*.d目錄來執行這些命令,我們將在下面進行描述。

6.6.2 The System V init Link Farm(系統 V 啓動鏈接農場)

The contents of the rc.d directories are actually symbolic links to files in yet another directory, init.d. If your goal is to interact with, add, delete, or modify services in the rc.d directories, you need to understand these symbolic links. A long listing of a directory such as rc5.d reveals a structure like this:

rc*.d目錄的內容實際上是指向另一個目錄init.d中的文件的符號鏈接。

如果你的目標是與rc*.d目錄中的服務進行交互、添加、刪除或修改,你需要理解這些符號鏈接。

像rc5.d這樣的目錄的長列表顯示了以下結構:

lrwxrwxrwx . . . S10sysklogd -> ../init.d/sysklogd
lrwxrwxrwx . . . S12kerneld -> ../init.d/kerneld
lrwxrwxrwx . . . S15netstd_init -> ../init.d/netstd_init
lrwxrwxrwx . . . S18netbase -> ../init.d/netbase
--snip--
lrwxrwxrwx . . . S99httpd -> ../init.d/httpd
--snip--

A large number of symbolic links across several subdirectories such as this is called a link farm. Linux distributions contain these links so that they can use the same startup scripts for all runlevels. This convention is not a requirement, but it simplifies organization.

一個包含大量符號鏈接的目錄結構,如此之多的鏈接被稱為鏈接農場。

Linux發行版包含這些鏈接,以便可以為所有運行級別使用相同的啓動腳本。

這種約定並非必需,但可以簡化組織結構。

Starting and Stopping Services(啓動和停止服務)

To start and stop services by hand, use the script in the init.d directory. For example, one way to start the httpd web server program manually is to run init.d/httpd start. Similarly, to kill a running service, you can use the stop argument (httpd stop, for instance).

要手動啓動和停止服務,請使用init.d目錄中的腳本。

例如,手動啓動httpd Web服務器程序的一種方法是運行init.d/httpd start命令。

同樣地,要停止正在運行的服務,可以使用stop參數(例如,httpd stop)。

Modifying the Boot Sequence(修改啓動順序)

Changing the boot sequence in System V init is normally done by modifying the link farm. The most common change is to prevent one of the commands in the init.d directory from running in a particular runlevel. You have to be careful about how you do this. For example, you might consider removing the symbolic link in the appropriate rc*.d directory. But beware: If you ever need to put the link back, you might have trouble remembering the exact name of the link. One of the best ways to do it is to add an underscore (_) at the beginning of the link name, like this:

在System V init中更改啓動順序通常是通過修改鏈接集合來完成的。

最常見的更改是阻止init.d目錄中的某個命令在特定運行級別下運行。在執行此操作時需要小心。

例如,您可以考慮刪除適當的rc*.d目錄中的符號鏈接。

但要小心:如果您需要重新添加該鏈接,您可能會忘記鏈接的確切名稱。

其中一種最好的方法是在鏈接名稱的開頭添加下劃線(_),像這樣:

# mv S99httpd _S99httpd

This change causes rc to ignore _S99httpd because the filename no longer starts with S or K, but the original name is still obvious.

這個改變導致rc忽略了_S99httpd,因為文件名不再以S或K開頭,但原始名稱仍然很明顯。

To add a service, create a script like those in the init.d directory and then create a symbolic link in the correct rc*.d directory. The easiest way is to copy and modify one of the scripts already in init.d that you understand (see Chapter 11 for more information on shell scripts).

要添加一個服務,需要創建一個類似於init.d目錄中的腳本,然後在正確的rc*.d目錄中創建一個符號鏈接。

最簡單的方法是複製並修改你已經理解的init.d中的一個腳本(有關shell腳本的更多信息,請參見第11章)。

When adding a service, choose an appropriate place in the boot sequence to start it. If the service starts too soon, it may not work, due to a dependency on some other service. For nonessential services, most systems administrators prefer numbers in the 90s, which puts the services after most of the services that came with the system.

在添加服務時,選擇一個適當的啓動順序來啓動它。

如果服務啓動得太早,可能由於對其他服務的依賴而無法正常工作。

對於非必要的服務,大多數系統管理員喜歡使用90年代的數字,這樣可以將服務放在系統自帶服務之後。

6.6.3 run-parts(運行部件)

The mechanism that System V init uses to run the init.d scripts has found its way into many Linux systems, regardless of whether 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 kind of predictable order. You can think of it as almost like a person who runs the ls command in some directory and then just runs whatever programs they see in the output.

System V init使用的機制已經在許多Linux系統中得到了應用,無論它們是否使用System V init。

這個實用程序被稱為run-parts,它的唯一功能就是按照某種可預測的順序運行給定目錄中的一系列可執行程序。

你可以把它想象成一個人在某個目錄中運行ls命令,然後按照輸出中看到的運行相應的程序。

The default behavior is to run all programs in a directory, but you often have the option to select certain programs and ignore others. In some distributions, you don’t need much control over the programs that run. For example, Fedora ships with a very simple run-parts utility

默認行為是運行目錄中的所有程序,但通常你可以選擇運行某些程序並忽略其他程序。

在某些發行版中,你不需要對運行的程序有太多控制。

例如,Fedora附帶了一個非常簡單的run-parts實用程序。

Other distributions, such as Debian and Ubuntu, have a more complicated run-parts program. Their features include the ability to run programs based on a regular expression (for example, using the S[0-9]{2} expression for running all “start” scripts in an /etc/init.d runlevel directory) and to pass arguments to the programs. These capabilities allow you to start and stop System V runlevels with a single command.

其他發行版,如Debian和Ubuntu,有一個更復雜的run-parts程序。

它們的功能包括根據正則表達式運行程序(例如,使用S[0-9]{2}表達式來運行/etc/init.d運行級別目錄中的所有“start”腳本)以及向程序傳遞參數。

這些功能使您能夠使用單個命令啓動和停止System V運行級別。

You don’t really need to understand the details of how to use run-parts; in fact, most people don’t know that run-parts even exists. The main things to remember are that it shows up in scripts from time to time and that it exists solely to run the programs in a given directory.

實際上,您不需要了解如何使用run-parts的詳細信息;

事實上,大多數人都不知道run-parts的存在。

主要需要記住的是它會偶爾出現在腳本中,並且它的存在只是為了運行給定目錄中的程序。

6.6.4 Controlling System V init(控制系統 V 啓動)

Occasionally, you’ll need to give init a little kick to tell it to switch runlevels, to reread its configuration, or to shut down the system. To control System V init, use telinit. For example, to switch to runlevel 3, enter:

有時候,你需要給init一個小小的推動,告訴它切換運行級別,重新讀取配置文件或關閉系統。要控制System V init,請使用telinit命令。例如,要切換到運行級別3,輸入以下命令:

# telinit 3

When switching runlevels, init tries to kill off any processes not in the inittab file for the new runlevel, so be careful when changing runlevels.

在切換運行級別時,init會嘗試關閉任何未在新運行級別的inittab文件中的進程,因此在更改運行級別時要小心。

When you need to add or remove jobs, or make any other change to the inittab file, you must tell init about the change and cause it to reload the file. The telinit command for this is:

當你需要添加或刪除作業,或對inittab文件進行任何其他更改時,必須告訴init這些變化並使其重新加載文件。用於此目的的telinit命令是:

# telinit q

You can also use telinit s to switch to single-user mode (see 6.9 Emergency Booting and Single-User Mode).

您也可以使用 telinit s 切換到單用户模式(參見 6.9 緊急啓動和單用户模式)。

6.7 Shutting Down Your System(關閉系統)

init controls how the system shuts down and reboots. The commands to shut down the system are the same regardless of which version of init you run. The proper way to shut down a Linux machine is to use the shutdown command.

init 控制着系統關閉和重啓的方式。無論運行哪個版本的 init,關閉系統的命令都是一樣的。關閉 Linux 機器的正確方法是使用 shutdown 命令。

There are two basic ways to use shutdown. If you halt the system, it shuts the machine down and keeps it down. To make the machine halt immediately, run this:

使用 shutdown 有兩種基本方法。如果你停止系統,它就會關閉機器並使其繼續運行。要使機器立即停止,請運行以下命令:

# shutdown -h now

On most machines and versions of Linux, a halt cuts the power to the machine. You can also reboot the machine. For a reboot, use -r instead of -h.

在大多數機器和 Linux 版本中,停止運行會切斷機器電源。您也可以重新啓動機器。重啓時,使用 -r 而不是 -h。

The shutdown process takes several seconds. You should never reset or power off a machine during this stage

關機過程需要幾秒鐘。

切勿在此階段重置或關閉機器電源。

In the preceding example, now is the time to shut down. This argument is mandatory, but there are many ways to specify the time. For example, if you want the machine to shut down sometime in the future, you can use +n, where n is the number of minutes shutdown should wait before doing its work. (For other options, see the shutdown(8) manual page.)

在前面的示例中,現在是關機的時間。

這個參數是強制性的,但也有很多指定時間的方法。

例如,如果想讓機器在未來某個時間關閉,可以使用 +n,其中 n 是 shutdown 在執行工作前應等待的分鐘數。

(有關其他選項,請參閲 shutdown(8) 手冊)。

To make the system reboot in 10 minutes, enter:

要使系統在 10 分鐘後重啓,請輸入

# shutdown -r +10

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, the shutdown command creates a file called /etc/nologin. When this file is present, the system prohibits logins by anyone except the superuser.

在Linux上,關機會通知所有登錄用户機器即將關機,但實際上並沒有做太多的工作。

如果你指定了一個非當前時間的關機時間,關機命令會創建一個名為/etc/nologin的文件。

當這個文件存在時,系統會禁止除超級用户外的任何用户登錄。

When system shutdown time finally arrives, shutdown tells init to begin the shutdown process. On systemd, it means activating the shutdown units; on Upstart, it means emitting the shutdown events; and on System V init, it means changing the runlevel to 0 or 6. Regardless of the init implementation or configuration, the procedure generally goes like this:

當系統關機時間到達時,關機命令會告訴init開始關機過程。

在systemd上,這意味着激活關機單元;在Upstart上,這意味着發出關機事件;在System V init上,這意味着將運行級別更改為0或6。

無論init的實現方式或配置如何,關機過程通常如下所示:

  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 the TERM signal doesn’t work, init uses the KILL signal on any stragglers.
  4. The system locks system files into place and makes other preparations for shutdown.
  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 to tell the kernel to reboot or stop with the reboot(2) system call. This can be done by init or an auxiliary program such as reboot, halt, or poweroff.
  9. init要求每個進程乾淨地關閉。
  10. 如果一個進程在一段時間後沒有響應,init會發送TERM信號殺死它。
  11. 如果TERM信號不起作用,init會對任何未關閉的進程發送KILL信號。
  12. 系統鎖定系統文件並做其他關機準備工作。
  13. 系統卸載除根文件系統外的所有文件系統。
  14. 系統將根文件系統重新掛載為只讀。
  15. 系統使用sync程序將所有緩衝數據寫入文件系統。
  16. 最後一步是使用reboot(2)系統調用告訴內核重新啓動或停止。這可以由init或reboot、halt、poweroff等輔助程序完成。

The reboot and halt programs behave differently depending on how they’re called, which may cause confusion. By default, these programs call shutdown with the -r or -h options. However, if the system is already at a halt or reboot runlevel, the programs tell the kernel to shut itself off immediately. If you really want to shut your machine down in a hurry, regardless of any potential damage from a disorderly shutdown, use the -f (force) option.

reboot和halt程序的行為取決於它們的調用方式,這可能會引起混淆。

默認情況下,這些程序會使用-r或-h選項調用shutdown。

然而,如果系統已經處於停機或重啓運行級別,這些程序會告訴內核立即關閉。

如果你真的想要快速關機,不考慮非正常關機可能造成的潛在損害,可以使用-f(強制)選項。

6.8 The Initial RAM Filesystem(初始 RAM 文件系統)

The Linux boot process is, for the most part, fairly straightforward. However, one component has always been somewhat confounding: initramfs, or the intitial RAM filesystem. Think of this as a little user-space wedge that goes in front of the normal user mode start. But first, let’s talk about why it exists

Linux的啓動過程在大部分情況下都相當簡單。

然而,有一個組件一直讓人感到困惑:initramfs,即初始RAM文件系統。

可以將其看作是正常用户模式啓動之前的一個小型用户空間楔子。

但首先,我們來談談它存在的原因。

The problem stems from the availability of many different kinds of storage hardware. Remember, the Linux kernel does not talk to the PC BIOS or EFI interfaces to get data from disks, so in order to mount its root filesystem, it needs driver support for the underlying storage mechanism. For example, if the root is on a RAID array connected to a third-party controller, the kernel needs the driver for that controller first. Unfortunately, there are so many storage controller drivers that distributions can’t include all of them in their kernels, so many drivers are shipped as loadable modules. But loadable modules are files, and if your kernel doesn’t have a filesystem mounted in the first place, it can’t load the driver modules that it needs.

問題源於許多不同類型的存儲硬件的可用性。

請記住,Linux內核不會直接與PC BIOS或EFI接口通信以從磁盤獲取數據,因此為了掛載其根文件系統,它需要底層存儲機制的驅動程序支持。

例如,如果根文件系統位於連接到第三方控制器的RAID陣列上,則內核首先需要該控制器的驅動程序。

不幸的是,有這麼多存儲控制器驅動程序,發行版無法將它們全部包含在內核中,因此許多驅動程序作為可加載模塊隨發行版一起提供。

但是可加載模塊是文件,如果您的內核一開始沒有掛載文件系統,它就無法加載所需的驅動程序模塊。

The workaround is to gather a small collection of kernel driver modules along with a few other utilities into an archive. The boot loader loads this archive into memory before running the kernel. Upon start, the kernel reads the contents of the archive into a temporary RAM filesystem (the initramfs), mounts it at /, and performs the user-mode handoff to the init on the initramfs. Then, the utilities included in the initramfs allow the kernel to load the necessary driver modules for the real root filesystem. Finally, the utilities mount the real root filesystem and start true init.

解決方法是將一小組內核驅動程序模塊和一些其他實用程序打包成一個存檔文件。

引導加載程序在運行內核之前將此存檔加載到內存中。

啓動時,內核將存檔的內容讀入臨時的RAM文件系統(即initramfs),在/目錄下掛載它,並將用户模式交接給initramfs上的init。

然後,initramfs中包含的實用程序允許內核加載真正的根文件系統所需的驅動程序模塊。

最後,這些實用程序會掛載真正的根文件系統並啓動真正的init。

Implementations vary and are ever evolving. On some distributions, the init on the initramfs is a fairly simple shell script that starts a udevd to load drivers, then mounts the real root and executes the init there. On distributions that use systemd, you’ll typically see an entire systemd installation there with no unit configuration files and just a few udevd configuration files.

實現方式各有不同且不斷髮展。

在某些發行版上,initramfs上的init是一個相當簡單的shell腳本,它啓動一個udev守護進程來加載驅動程序,然後掛載真正的根文件系統並在那裏執行init。

在使用systemd的發行版中,您通常會看到一個完整的systemd安裝,其中沒有單元配置文件,只有一些udev配置文件。

One basic characteristic of the initial RAM filesystem that has (so far) remained unchanged since its inception is the ability to bypass it if you don’t need it. That is, if your kernel has all the drivers it needs to mount your root filesystem, you can omit the initial RAM filesystem in your boot loader configuration. When successful, eliminating the initial RAM file-system shortens boot time, usually by a couple of seconds. Try it yourself at boot time by using the GRUB menu editor to remove the initrd line. (It’s best not to experiment by changing the GRUB configuration file, as you can make a mistake that will be difficult to repair.) Recently, it has been a little more difficult to bypass the initial RAM filesystem because features such as mount-by-UUID may not be available with generic distribution kernels.

迄今為止,初始RAM文件系統的一個基本特徵保持不變,即如果您不需要它,可以繞過它。

也就是説,如果您的內核具有掛載根文件系統所需的所有驅動程序,可以在引導加載程序配置中省略初始RAM文件系統。

成功後,省略初始RAM文件系統可以縮短啓動時間,通常可以減少幾秒鐘。

您可以在引導時嘗試使用GRUB菜單編輯器刪除initrd行來驗證。

最好不要嘗試通過更改GRUB配置文件來進行實驗,因為可能會犯一個難以修復的錯誤。

最近,繞過初始RAM文件系統變得稍微困難一些,因為通用發行版內核可能無法使用mount-by-UUID等功能。

It’s easy to see the contents of your initial RAM filesystem because, on most modern systems, they are simple gzip-compressed cpio archives (see the cpio(1) manual page). First, find the archive file by looking at your boot loader configuration (for example, grep for initrd lines in your grub.cfg configuration file). Then use cpio to dump the contents of the archive into a temporary directory somewhere and peruse the results. For example:

大多數現代系統的初始RAM文件系統的內容很容易查看,因為它們通常是簡單的gzip壓縮的cpio存檔(請參閲cpio(1)手冊頁)。

首先,通過查看引導加載程序配置文件(例如,在grub.cfg配置文件中搜索initrd行)找到存檔文件。

然後使用cpio將存檔的內容轉儲到某個臨時目錄中,並查看結果。

例如:

$ mkdir /tmp/myinitrd
$ cd /tmp/myinitrd
$ zcat /boot/initrd.img-3.2.0-34 | cpio -i --no-absolute-filenames
--snip--

One particular piece of interest is the “pivot” near the very end of the init process on the initial RAM filesystem. This part is responsible for removing the contents of the temporary filesystem (to save memory) and permanently switch to the real root.

有一個特別引人注目的部分是在初始RAM文件系統(initramfs)的最後階段的“轉折點(pivot)”。

這部分負責清除臨時文件系統的內容(以節省內存)並永久切換到真正的根目錄。

You won’t typically create your own initial RAM filesystem, as this is a painstaking process. There are a number of utilities for creating initial RAM filesystem images, and your distribution likely comes with one. Two of the most common are dracut and mkinitramfs.

通常情況下,您不會自己創建初始RAM文件系統,因為這是一個費時的過程。

有許多用於創建初始RAM文件系統鏡像的實用工具,您的發行版很可能自帶其中之一。

其中兩個最常見的工具是dracut和mkinitramfs。

NOTE The term initial RAM filesystem (initramfs) refers to the implementation that uses the cpio archive as the source of the temporary filesystem. There is an older version called the initial RAM disk, or initrd, that uses a disk image as the basis of the temporary filesystem. This has fallen into disuse because it’s much easier to maintain a cpio archive. However, you’ll often see the term initrd used to refer to a cpio-based initial RAM filesystem. Often, as in the preceding example, the filenames and configuration files will still contain initrd.

注意,術語初始RAM文件系統(initramfs)是指使用cpio存檔作為臨時文件系統的實現。

還有一個較舊的版本稱為初始RAM磁盤(initrd),它使用磁盤映像作為臨時文件系統的基礎。

由於維護cpio存檔要容易得多,因此這個版本已經不再使用。

然而,您經常會看到術語initrd用來指代基於cpio的初始RAM文件系統。

通常,如前面的示例中所示,文件名和配置文件仍會包含initrd。

6.9 Emergency Booting and Single-User Mode(緊急啓動和單用户模式)

When something goes wrong with the system, the first recourse is usually to boot the system with a distribution’s “live” image (most distributions’ installation images double as live images) or with a dedicated rescue image such as SystemRescueCd that you can put on removable media. Common tasks for fixing a system include the following:

當系統出現問題時,通常的第一步是使用發行版的“live”鏡像(大多數發行版的安裝鏡像也可以用作live鏡像)或者專用的救援鏡像(如SystemRescueCd),來引導系統。

修復系統的常見任務包括以下幾點:

o Checking filesystems after a system crash
o Resetting a forgotten root password
o Fixing problems in critical files, such as /etc/fstab and /etc/passwd
o Restoring from backups after a system crash

  • 在系統崩潰後檢查文件系統
  • 重置忘記的root密碼
  • 修復關鍵文件(如/etc/fstab和/etc/passwd)中的問題
  • 在系統崩潰後從備份中恢復

Another option for booting quickly to a usable state is single-user mode. The idea is that the system quickly boots to a root shell instead of going through the whole mess of services. In the System V init, single-user mode is usually runlevel 1, and you can also enter the mode with an -s parameter to the boot loader. You may need to type the root password to enter single-user mode.

另一種快速引導到可用狀態的選擇是單用户模式。

其思想是系統快速引導到root shell,而不是經過整個服務的混亂過程。

在System V init中,單用户模式通常是運行級別1,你也可以通過引導加載程序的-s參數進入該模式。

進入單用户模式可能需要輸入root密碼。

The biggest problem with single-user mode is that it doesn’t offer many amenities. The network almost certainly won’t be available (and if it is, it will be hard to use), you won’t have a GUI, and your terminal may not even work correctly. For this reason, live images are nearly always considered preferable.

單用户模式最大的問題是它沒有提供許多便利設施。

網絡幾乎肯定不可用(即使可用,也很難使用),你將沒有圖形界面,你的終端甚至可能無法正常工作。

因此,幾乎總是認為使用live鏡像更可取。

user avatar lenglingx 头像 wuliaodechaye 头像 sevencode 头像 chencaize 头像 lindsay_bubble 头像 tobin_blogs 头像
点赞 6 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.