From a9550ff9be04e30054a284c012a091868d9c2488 Mon Sep 17 00:00:00 2001 From: tt67wq Date: Wed, 12 May 2021 19:49:32 +0800 Subject: [PATCH] translate done: 20200527 Manage startup using systemd.md --- .../20200527 Manage startup using systemd.md | 195 ++++++++++-------- 1 file changed, 106 insertions(+), 89 deletions(-) rename {sources => translated}/tech/20200527 Manage startup using systemd.md (50%) diff --git a/sources/tech/20200527 Manage startup using systemd.md b/translated/tech/20200527 Manage startup using systemd.md similarity index 50% rename from sources/tech/20200527 Manage startup using systemd.md rename to translated/tech/20200527 Manage startup using systemd.md index 7fd6467528..4a2dd3fa6f 100644 --- a/sources/tech/20200527 Manage startup using systemd.md +++ b/translated/tech/20200527 Manage startup using systemd.md @@ -7,27 +7,28 @@ [#]: via: (https://opensource.com/article/20/5/manage-startup-systemd) [#]: author: (David Both https://opensource.com/users/dboth) -Manage startup using systemd +使用 systemd 来管理启动项 ====== -Learn how systemd determines the order services start, even though it is -essentially a parallel system. +了解 systemd 是怎样决定服务启动顺序,即使它本质上是个并行系统。 ![Penguin with green background][1] -While setting up a Linux system recently, I wanted to know how to ensure that dependencies for services and other units were up and running before those dependent services and units start. Specifically, I needed more knowledge of how systemd manages the startup sequence, especially in determining the order services are started in what is essentially a parallel system. -You may know that SystemV (systemd's predecessor, as I explained in the [first article][2] in this series) orders the startup sequence by naming the startup scripts with an SXX prefix, where XX is a number from 00 to 99. SystemV then uses the sort order by name and runs each start script in sequence for the desired runlevel. +最近在设置 Linux 系统时,我想知道如何确保服务和其他单元的依赖关系在这些依赖服务和单元启动之前就已经启动并运行了。我需要更多 systemd 如何管理启动程序的相关知识,特别是关于本质上的并行系统中决定服务启动顺序方面。 -But systemd uses unit files, which can be created or modified by a sysadmin, to define subroutines for not only initialization but also for regular operation. In the [third article][3] in this series, I explained how to create a mount unit file. In this fifth article, I demonstrate how to create a different type of unit file—a service unit file that runs a program at startup. You can also change certain configuration settings in the unit file and use the systemd journal to view the location of your changes in the startup sequence. +你可能知道 SystemV(systemd 的前身,我在这个系列的[第一篇文章 ][2] 中解释过)通过 SXX 前缀命名启动脚本来决定启动顺序,XX 是一个 00-99 的数字。然后 SystemV 利用文件名来排序,然后为目标运行等级执行队列中每个启动脚本。 -### Preparation +但是 systemd 使用单元文件来定义子程序,单元文件可被系统管理员创建或编辑,这些文件不仅可以用于初始化时也可以用于常规操作。在这个系列的[第三篇文章 ][3] 中,我解释了如何创建一个挂载单元文件。在第五篇文章中,我解释了如何创建一种不同的单元文件--在启动时执行一个程序的服务单元文件。你也可以修改单元文件中某些配置,然后通过 systemd 日志去查看你的修改在启动序列中的位置。 -Make sure you have removed `rhgb` and `quiet` from the `GRUB_CMDLINE_LINUX=` line in the `/etc/default/grub` file, as I showed in the [second article][4] in this series. This enables you to observe the Linux startup message stream, which you'll need for some of the experiments in this article. +### 准备工作 -### The program +先确认你已经在 `/etc/default/grub` 文件中的 `GRUB_CMDLINE_LINUX=` 这行移除了 `rhgb` 和 `quiet`,如同我在这个系列的[第二篇文章 ][4] 中展示的那样。这让你能够查看 Linux 启动信息流,你在这篇文章中部分实验中需要用到。 -In this tutorial, you will create a simple program that enables you to observe a message during startup on the console and later in the systemd journal. -Create the shell program `/usr/local/bin/hello.sh` and add the following content. You want to ensure that the result is visible during startup and that you can easily find it when looking through the systemd journal. You will use a version of the "Hello world" program with some bars around it, so it stands out. Make sure the file is executable and has user and group ownership by root with [700 permissions][5] for security: +### 程序 + +在本教程中,你会创建一个简单的程序让你能够在命令行和后续的 systemd 日志中查看启动时的信息。 + +创建一个 shell 程序 `/usr/local/bin/hello.sh` 然后添加下述内容。你想确保执行结果在启动时是可见的,可以轻松的在 systemd 日志中找到它。你会使用一版携带一些方格的 "Hello world" 程序,这样它会非常显眼。为了确保这个文件是可执行的,且为了安全起见,它需要 root 的用户和组所有权和 [700 权限 ][5]。 ``` @@ -42,7 +43,7 @@ echo "######### Hello World! ########" echo "###############################" ``` -Run this program from the command line to verify that it works correctly: +在命令行中执行这个程序来检查它能否正常运行。 ``` @@ -53,11 +54,11 @@ Run this program from the command line to verify that it works correctly: [root@testvm1 ~]# ``` -This program could be created in any scripting or compiled language. The `hello.sh` program could also be located in other places based on the [Linux filesystem hierarchical structure][6] (FHS). I place it in the `/usr/local/bin` directory so that it can be easily run from the command line without having to prepend a path when I type the command. I find that many of the shell programs I create need to be run from the command line and by other tools such as systemd. +这个程序可以用任意脚本或编译语言实现。`hello.sh` 程序可以被放在 [Linux 文件系统层级结构 ][6] (FHS) 上的任意位置。我把它放在 `/usr/local/bin` 目录下,这样它可以直接在命令行中执行而不必在打命令的时候前面带上路径。我发现我创建的很多 shell 程序需要在命令行和其他工具(如 systemd) 运行。 -### The service unit file +### 服务单元文件 -Create the service unit file `/etc/systemd/system/hello.service` with the following content. This file does not need to be executable, but for security, it does need user and group ownership by root and [644][7] or [640][8] permissions: +创建服务单元文件 `/etc/systemd/system/hello.service`,写入下述内容。这个文件不一定是要可执行的,但是为了安全起见,它需要 root 的用户和组所有权和 [644][7] 或 [640][8] 权限。 ``` @@ -78,7 +79,7 @@ ExecStart=/usr/local/bin/hello.sh WantedBy=multi-user.target ``` -Verify that the service unit file performs as expected by viewing the service status. Any syntactical errors will show up here: +通过查看服务状态来确认服务单元文件能如期运行。如有任何语法问题,这里会显示错误。 ``` @@ -89,11 +90,12 @@ Verify that the service unit file performs as expected by viewing the service st [root@testvm1 ~]# ``` -You can run this "oneshot" service type multiple times without problems. The oneshot type is intended for services where the program launched by the service unit file is the main process and must complete before systemd starts any dependent process. -There are seven service types, and you can find an explanation of each (along with the other parts of a service unit file) in the [systemd.service(5)][9] man page. (You can also find more information in the [resources][10] at the end of this article.) +你可以运行这类 "oneshot" 类型的服务多次而不会有问题。onehot 类型服务适用于服务单元文件启动的程序是主进程,必须在 systemd 启动任何依赖进程之前完成的服务。 -As curious as I am, I wanted to see what an error might look like. So, I deleted the "o" from the `Type=oneshot` line, so it looked like `Type=neshot`, and ran the command again: +共有 9 种服务类型,你可以在 [systemd.service(5)][9] 的 man 手册上找到每一种(以及服务单元文件的其他部分)的详细解释。(你也可以在文章末尾的[资料 ][10] 中找到更多信息)。 + +出于好奇,我想看看错误是什么样子的。所以我从 `Type=oneshot` 这行删了字母 "o",现在它看起来是这样 `Type=neshot`,现在再次执行命令: ``` @@ -106,19 +108,19 @@ May 06 08:50:09 testvm1.both.org systemd[1]: /etc/systemd/system/hello.service:1 [root@testvm1 ~]# ``` -These results told me precisely where the error was and made it very easy to resolve the problem. +执行结果明确地告诉我错误在哪,这样解决错误变得十分容易。 -Just be aware that even after you restore the `hello.service` file to its original form, the error will persist. Although a reboot will clear the error, you should not have to do that, so I went looking for a method to clear out persistent errors like this. I have encountered service errors that require the command `systemctl daemon-reload` to reset an error condition, but that did not work in this case. The error messages that can be fixed with this command always seem to have a statement to that effect, so you know to run it. +需要注意的是即使在你保存了 `hello.service` 文件为它原来的形式之后,错误依然存在。即使重启机器能消除这个错误,但你不必这么做,所以我去找了一个清理这类持久性错误的方法。我曾遇到有些错误需要 `systemctl daemon-relad` 命令来重置错误状态,但是这个例子不在此列。可以用这个命令修复的错误似乎总是有一个这样的声明,所以你知道要运行它。 -It is, however, recommended that you run `systemctl daemon-reload` after changing a unit file or creating a new one. This notifies systemd that the changes have been made, and it can prevent certain types of issues with managing altered services or units. Go ahead and run this command. +然而,每次修改或新建一个单元文件之后执行 `systemctl daemon-reload` 确实是值得推荐的做法。它提醒 systemd 有修改发生,而且它可以防止某些与管理服务或单元相关的问题。所以继续去执行这条命令吧。 -After correcting the misspelling in the service unit file, a simple `systemctl restart hello.service` cleared the error. Experiment a bit by introducing some other errors into the `hello.service` file to see what kinds of results you get. +在修改完服务单元文件中的拼写错误后,一个简单的 `systemctl restart hello.service` 命令就可以清除错误。实验下通过添加一些其他的错误至 `hello.service` 文件来看看会得到怎样的结果。 -### Start the service +### 启动服务 -Now you are ready to start the new service and check the status to see the result. Although you probably did a restart in the previous section, you can start or restart a oneshot service as many times as you want since it runs once and then exits. +现在你已经准备好启动这个新服务,通过检查状态来查看结果。尽管你可能之前已经重启过,你仍然可以启动或重启这个单发服务任意次,因为它只运行一次就退出了。 -Go ahead and start the service (as shown below), and then check the status. Depending upon how much you experimented with errors, your results may differ from mine: +继续启动这个服务(如下所示),然后检查状态。你的结果可能和我的有区别,取决于你做了多少试错实验。 ``` @@ -141,9 +143,11 @@ May 10 10:54:45 testvm1.both.org systemd[1]: Finished My hello shell script. [root@testvm1 ~]# ``` -Notice in the status command's output that the systemd messages indicate that the `hello.sh` script started and the service completed. You can also see the output from the script. This display is generated from the journal entries of the most recent invocations of the service. Try starting the service several times, and then run the status command again to see what I mean. -You should also look at the journal contents directly; there are multiple ways to do this. One way is to specify the record type identifier, in this case, the name of the shell script. This shows the journal entries for previous reboots as well as the current session. As you can see, I have been researching and testing for this article for some time now: +从状态检查命令的输出中我们可以看到,systemd 日志表明 `hello.sh` 启动然后服务结束了。你也可以看到脚本的输出。该输出是根据服务的最近调用的日志记录生成的,试试看多启动几次这个服务,然后再看状态命令的输出就能理解我所说的。 + + +你也应该直接查看日志内容,有很多种方法可以实现。一种办法是指定记录类型标识符,在这个例子中就是 shell 脚本的名字。它会展示前几次重启和当前会话的日志记录。如你所见,我已经为这篇文章做了挺长一段时间的研究测试了。 ``` @@ -167,7 +171,10 @@ May 10 10:54:45 testvm1.both.org hello.sh[1380]: ############################### [root@testvm1 ~]# ``` -To locate the systemd records for the `hello.service` unit, you can search on systemd. You can use **G+Enter** to page to the end of the journal entries and then scroll back to locate the ones you are interested in. Use the `-b` option to show only the entries for the most recent startup: + +为了定位 `hello.service` 单元的 systemd 记录,你可以在 systemd 中搜索。你可以使用 **G+Enter** 来翻页到日志记录 +记录的末尾,然后用回滚来找到你感兴趣的日志。使用 `-b` 选项仅展示最近启动的记录 +记录。 ``` @@ -181,7 +188,8 @@ May 10 10:37:50 testvm1.both.org systemd[1]: Starting D-Bus System Message Bus.. May 10 10:37:50 testvm1.both.org systemd[1]: Started D-Bus System Message Bus. ``` -I copied a few other journal entries to give you an idea of what you might find. This command spews all of the journal lines pertaining to systemd—109,183 lines when I wrote this. That is a lot of data to sort through. You can use the pager's search facility, which is usually `less`, or you can use the built-in `grep` feature. The `-g` (or `--grep=`) option uses Perl-compatible regular expressions: + +我拷贝了一些其他的日志记录,让你对你可能找到的东西有所了解。这条命令泼出所有属于 systemd 的日志内容--当我写这里时是 109 至 183 行。有很多数据需要整理。你可以使用页面的搜索功能,通常是 `less` 或者你可以使用内置的 `grep` 特性。`-g`( 或 `--grep=`) 选项可以使用兼容 Perl 的正则表达式。 ``` @@ -197,11 +205,12 @@ May 10 10:54:45 testvm1.both.org systemd[1]: Finished My hello shell script. [root@testvm1 ~]# ``` -You could use the standard GNU `grep` command, but that would not show the log metadata in the first line. +你可以使用标准的 GNU`grep` 命令,但是这不会展示日志首行的元数据。 -If you do not want to see just the journal entries pertaining to your `hello` service, you can narrow things down a bit by specifying a time range. For example, I will start with the beginning time of `10:54:00` on my test VM, which was the start of the minute the entries above are from. ****Note that the `--since=` option must be enclosed in quotes and that this option can also be expressed as `-S "