mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-01-25 23:11:02 +08:00
Merge remote-tracking branch 'LCTT/master'
This commit is contained in:
commit
e55be1b770
@ -1,44 +1,48 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12257-1.html)
|
||||
[#]: subject: (How to Handle Automatic Updates in Ubuntu)
|
||||
[#]: via: (https://itsfoss.com/auto-updates-ubuntu/)
|
||||
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
|
||||
|
||||
如何在 Ubuntu 中处理自动更新
|
||||
如何在 Ubuntu 中处理自动的无人值守升级
|
||||
======
|
||||
|
||||
_**简介:本教程教你如何处理无人值守的升级,即 Ubuntu Linux 的自动系统更新。**_
|
||||
> 本教程教你如何处理无人值守的升级,即 Ubuntu Linux 的自动系统更新。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202005/27/234040fxb0nkc53pk0nxvx.jpg)
|
||||
|
||||
有时,当你尝试[关闭 Ubuntu 系统][1]时,可能看到这个阻止你关闭的页面:
|
||||
|
||||
**关机正在进行无人值守升级,请不要关闭计算机。**
|
||||
> 关机过程中正在进行无人值守升级,请不要关闭计算机。
|
||||
|
||||
![Unattended Upgrade In Progress In Ubuntu][2]
|
||||
|
||||
你可能想知道什么是“无人值守的升级”,以及它是如何在你不知情的情况下运行的。
|
||||
你可能会问这个“无人值守升级”是什么,怎么会在你不知情的情况下运行呢?
|
||||
|
||||
因为 [Ubuntu][3] 非常重视系统的安全性。默认情况下,它会每天自动检查系统更新,如果发现任何安全更新,那么会下载这些更新并自行安装。对于正常的系统和应用更新,它会通过软件更新程序通知你。
|
||||
原因是 [Ubuntu][3] 非常重视系统的安全性。默认情况下,它会每天自动检查系统更新,如果发现安全更新,它会下载这些更新并自行安装。对于正常的系统和应用更新,它会通过软件更新程序通知你。
|
||||
|
||||
由于所有这些都是在后台发生的,因此你会直到关机或者尝试自己安装应用时才会意识到。
|
||||
由于所有这些都是在后台发生的,所以在你尝试关闭系统或尝试自行安装应用程序之前,你甚至不会意识到这一点。
|
||||
|
||||
在进行这些无人值守的升级时尝试安装新软件会发生[无法获得锁的错误][4]。
|
||||
在这些无人值守的升级过程中,尝试安装新软件,会导致著名的[无法获得锁定的错误][4]。
|
||||
|
||||
![][5]
|
||||
|
||||
如你所见,自动更新带来了一些小麻烦。你可以选择禁用自动更新,但这意味着你必须一直手动检查并[更新你的 Ubuntu 系统][6]。
|
||||
|
||||
你真的需要禁用自动更新吗?
|
||||
> **你真的需要禁用自动更新吗?**
|
||||
>
|
||||
> 请注意,这是一项安全功能。Linux 实际上允许你禁用系统中的所有功能,甚至禁用这些安全功能。
|
||||
>
|
||||
> 但是我认为,作为普通用户,**你不应该禁用自动更新**。毕竟,它可以确保你的系统安全。
|
||||
>
|
||||
> 为了确保系统的安全性,你可以忍受自动更新所带来的小麻烦。
|
||||
|
||||
请注意,这是一项安全功能。Linux 实际上允许你禁用系统中的所有功能,甚至禁用这些安全功能。
|
||||
但是我认为,作为普通用户,_**你不应禁用自动更新**_。毕竟,它可以确保你的系统安全。
|
||||
为了确保系统的安全性,你可以忍受自动更新所带来的小麻烦。
|
||||
现在,你已经收到警告,还是觉得承担手动更新系统的额外任务更好,那么让我们看看如何处理自动更新。
|
||||
|
||||
现在,你已经收到警告,并认为最好承担手动更新系统的额外任务,让我们看看如何处理自动更新。
|
||||
|
||||
与往常一样,有两种方法可以做到:GUI 和命令行。 我将向您=你展示两种方法。
|
||||
与往常一样,有两种方法可以做到:GUI 和命令行。 我将向你展示两种方法。
|
||||
|
||||
我在这里使用 Ubuntu 20.04,但是这些步骤对 Ubuntu 18.04 和任何其他 Ubuntu 版本均有效。
|
||||
|
||||
@ -50,7 +54,7 @@ _**简介:本教程教你如何处理无人值守的升级,即 Ubuntu Linux
|
||||
|
||||
在此处,进入“更新”选项卡。查找“自动检查更新”。默认情况下,它设置为“每日”。
|
||||
|
||||
你可以将其更改为“从不”,你的系统将永远不会检查更新。如果不检查更新,它将不会找到要安装的新更新。
|
||||
你可以将其更改为“从不”,你的系统将永远不会检查更新。如果不检查更新,它就不会找到要安装的新的更新。
|
||||
|
||||
![Disable Auto Updates in Ubuntu Completely][8]
|
||||
|
||||
@ -58,13 +62,13 @@ _**简介:本教程教你如何处理无人值守的升级,即 Ubuntu Linux
|
||||
|
||||
#### 在 Ubuntu 中处理自动更新的更好方法
|
||||
|
||||
就个人而言,我建议让它自己检查更新。如果你不希望它自动安装更新,那么可以更改该行为以通知有关安全更新的可用性。
|
||||
就个人而言,我建议让它自己检查更新。如果你不希望它自动安装更新,那么可以更改该行为,以通知有关安全更新的可用性。
|
||||
|
||||
保持“自动检查更新”为“每日”,然后将“有安全更新时”选项更改为“立即显示”,而不是“自动下载并安装”。
|
||||
|
||||
![Get notified for security updates instead of automatically installing them][9]
|
||||
|
||||
这样,它会检查是否有更新,而不是在后台自动安装更新,软件更新程序会通知你更新可用于系统。你的系统已经完成正常的系统和软件更新。
|
||||
这样,它会检查是否有更新,而不是在后台自动安装更新,软件更新程序会通知你有可用于系统的更新。而你的系统已经完成正常的系统和软件更新。
|
||||
|
||||
![Get notified about security updates][10]
|
||||
|
||||
@ -76,13 +80,13 @@ _**简介:本教程教你如何处理无人值守的升级,即 Ubuntu Linux
|
||||
|
||||
### 如何在 Ubuntu 中使用命令行禁用自动更新
|
||||
|
||||
你可以在 **/etc/apt/apt.conf.d/20auto-upgrades** 中找到自动升级设置。Ubuntu 终端中的默认文本编辑器是 Nano,因此你可以使用以下命令来编辑此文件:
|
||||
你可以在 `/etc/apt/apt.conf.d/20auto-upgrades` 中找到自动升级设置。Ubuntu 终端中的默认文本编辑器是 Nano,因此你可以使用以下命令来编辑此文件:
|
||||
|
||||
```
|
||||
sudo nano /etc/apt/apt.conf.d/20auto-upgrades
|
||||
```
|
||||
|
||||
现在,如果你不希望系统自动检查更新,那么可以将 APT::Periodic::Update-Package-Lists 的值更改为 0。
|
||||
现在,如果你不希望系统自动检查更新,那么可以将 `APT::Periodic::Update-Package-Lists` 的值更改为 `"0"`。
|
||||
|
||||
```
|
||||
APT::Periodic::Update-Package-Lists "0";
|
||||
@ -96,9 +100,9 @@ APT::Periodic::Update-Package-Lists "1";
|
||||
APT::Periodic::Unattended-Upgrade "0";
|
||||
```
|
||||
|
||||
**最后**
|
||||
### 最后
|
||||
|
||||
由于某种原因,启用了自动安全更新,建议你保持这种状态。小的烦恼实际上并不值得冒险损害系统安全性。你怎么看?
|
||||
由于某种原因,启用了自动安全更新,建议你保持这种状态。这个小烦恼实际上并不值得冒险损害系统安全性。你怎么看?
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -107,7 +111,7 @@ via: https://itsfoss.com/auto-updates-ubuntu/
|
||||
作者:[Abhishek Prakash][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -0,0 +1,87 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Open Source YouTube Alternative PeerTube Needs Your Support to Launch Version 3)
|
||||
[#]: via: (https://itsfoss.com/peertube-v3-campaign/)
|
||||
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
|
||||
|
||||
Open Source YouTube Alternative PeerTube Needs Your Support to Launch Version 3
|
||||
======
|
||||
|
||||
[PeerTube][1] (developed by [Framasoft][2]) is a free and open-source decentralized alternative to YouTube somewhat like [LBRY][3]. As the name suggests, it relies on [peer-to-peer connections][4] to operate the video hosting services.
|
||||
|
||||
You can also choose to self-host your instance and also have access to videos from other instances (a federated network, just like [Mastodon][5]).
|
||||
|
||||
It is being actively developed for a few years now. And, to take it up a notch, they have decided to launch a crowdfunding campaign for the next major release.
|
||||
|
||||
The funding campaign will help them develop v3.0 of PeerTube with some amazing key features planned for the release this fall.
|
||||
|
||||
![PeerTube Instance Example][6]
|
||||
|
||||
### PeerTube: Brief Overview
|
||||
|
||||
In addition to what I just mentioned above, PeerTube is a fully-functional peer to peer video platform. The best thing about it is — it’s open-source and free. So, you can check them out on [GitHub][7] if you want.
|
||||
|
||||
You can watch their official video here:
|
||||
|
||||
**Note:** You need to be cautious about your IP address if you have concerns about that on PeerTube (try using one of the [best VPNs available][8]).
|
||||
|
||||
### PeerTube’s Crowdfunding Campaign For v3 Launch
|
||||
|
||||
You’ll be excited to know that the crowdfunding campaign of **€60,000** already managed to **get 10,000 Euros on Day 1** (at the time of writing this).
|
||||
|
||||
Now, coming to the details. The campaign aims to focus on gathering **funds for the next 6 months of development for a v3 release planned for November 2020.** It looks like a lot of work for a single full-time developer — but no matter whether they reach the funding goal, they intend to release the v3 with the existing funds they have.
|
||||
|
||||
In their [announcement post][9], PeerTube team mentioned:
|
||||
|
||||
> We feel like we need to develop it, that we have to. Imposing a condition stating « if we do not get our 60,000€, then there will not be a v3 » here, would be a lie, marketing manipulation : this is not the kind of relation we want to maintain with you.
|
||||
|
||||
Next, let’s talk about the new features they’ve planned to introduced in the next 6 months:
|
||||
|
||||
* Upon reaching the **€10,000 goal,** they plan to work on introducing a globalized video index to make it easier to search for videos across multiple instances.
|
||||
* With **€**20,000 goal, PeerTube will dedicate one month on improving the moderation tools to make the best out of it.
|
||||
* With 40,000 goal, they would work on the UX/UI of playlists. So, it will look better when you try to embed a playlist. In addition to this, the plugin system will be improved to make it easier to contribute to PeerTube’s code.
|
||||
* With the end of the campaign reaching 60,000 goal, PeerTube’s live-streaming feature will be introduced.
|
||||
|
||||
|
||||
|
||||
You can also find the details of their [roadmap on their site][10].
|
||||
|
||||
### Wrapping Up
|
||||
|
||||
The ability to have a global inter-connected video index among multiple instances is something that was needed and it will also allow you to configure your own index.
|
||||
|
||||
The content moderation tool improvement is also a huge deal because it’s not that easy to manage a decentralized network of video hosting services. While they aim to prevent censorship, a strict moderation is required to make PeerTube a comfortable place to watch videos.
|
||||
|
||||
Even though I’m not sure about how useful PeerTube’s live-streaming feature will be, at launch. It is going to be something exciting to keep an eye out for.
|
||||
|
||||
We at It’s FOSS made a token donation of 25 Euro. I would also encourage you to donate and help this open source achieve their financial goal for version 3 development.
|
||||
|
||||
[Support PeerTube][11]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/peertube-v3-campaign/
|
||||
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/ankush/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://joinpeertube.org
|
||||
[2]: https://framasoft.org/en/
|
||||
[3]: https://itsfoss.com/lbry/
|
||||
[4]: https://en.wikipedia.org/wiki/Peer-to-peer
|
||||
[5]: https://itsfoss.com/mastodon-open-source-alternative-twitter/
|
||||
[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/05/peertube-instance-screenshot.jpg?ssl=1
|
||||
[7]: https://github.com/Chocobozzz/PeerTube
|
||||
[8]: https://itsfoss.com/best-vpn-linux/
|
||||
[9]: https://framablog.org/2020/05/26/our-plans-for-peertube-v3-progressive-fundraising-live-streaming-coming-next-fall/
|
||||
[10]: https://joinpeertube.org/roadmap
|
||||
[11]: https://joinpeertube.org/roadmap#support
|
@ -1,5 +1,5 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
@ -1,198 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (How to configure your router using VTY shell)
|
||||
[#]: via: (https://opensource.com/article/20/5/vty-shell)
|
||||
[#]: author: (M Umer https://opensource.com/users/noisybotnet)
|
||||
|
||||
How to configure your router using VTY shell
|
||||
======
|
||||
Free range routing gives you options for implementing multiple
|
||||
protocols. This guide will get you started.
|
||||
![Multi-colored and directional network computer cables][1]
|
||||
|
||||
Recently, I wrote an article explaining how we can implement Open Shortest Path First (OSPF) using the [Quagga][2] routing suite. There are multiple software suites that can be used instead of Quagga to implement different routing protocols. One such option is free range routing (FRR).
|
||||
|
||||
### FRR
|
||||
|
||||
[FRR][3] is a routing software suite, which has been derived from Quagga and is distributed under GNU GPL2 license. Like Quagga, it provides implementations of all major routing protocols such as OSPF, Routing Information Protocol (RIP), Border Gateway Protocol (BGP), and Intermediate system-to-intermediate system (IS-IS) for Unix-like platforms.
|
||||
|
||||
Several companies, such as Big Switch Networks, Cumulus, Open Source Routing, and 6wind, who were behind the development of Quagga, created FRR to improve on Quagga's well-established foundations.
|
||||
|
||||
#### Architecture
|
||||
|
||||
FRR is a suite of daemons that work together to build the routing table. Each major protocol is implemented in its own daemon, and these daemons talk to the core and protocol-independent daemon Zebra, which provides kernel routing table updates, interface lookups, and redistribution of routes between different routing protocols. Each protocol-specific daemon is responsible for running the relevant protocol and building the routing table based on the information exchanged.
|
||||
|
||||
![FRR architecture][4]
|
||||
|
||||
### VTY shell
|
||||
|
||||
[VTYSH][5] is an integrated shell for the FRR routing engine. It amalgamates all the CLI commands defined in each of the daemons and presents them to the user in a single shell. It provides a Cisco-like modal CLI, and many of the commands are similar to Cisco IOS commands. There are different modes to the CLI, and certain commands are only available within a specific mode.
|
||||
|
||||
### Setup
|
||||
|
||||
In this tutorial, we'll be implementing the routing information protocol (RIP) to configure dynamic routing using FRR. We can do this in two ways—either by editing the protocol daemon configuration file in an editor or by using the VTY shell. We'll be using the VTY shell in this example. Our setup includes two CentOS 7.7 hosts, named Alpha and Beta. Both hosts have two network interfaces and share access to the 192.168.122.0/24 network. We'll be advertising routes for 10.12.11.0/24 and 10.10.10.0/24 networks.
|
||||
|
||||
**For Host Alpha:**
|
||||
|
||||
* eth0 IP: 192.168.122.100/24
|
||||
* Gateway: 192.168.122.1
|
||||
* eth1 IP: 10.10.10.12/24
|
||||
|
||||
|
||||
|
||||
**For Host Beta:**
|
||||
|
||||
* eth0 IP: 192.168.122.50/24
|
||||
* Gateway: 192.168.122.1
|
||||
* eth1 IP: 10.12.11.12/24
|
||||
|
||||
|
||||
|
||||
#### Installation of package
|
||||
|
||||
First, we need to install the FRR package on both hosts; this can be done by following the instructions in the [official FRR documentation][6].
|
||||
|
||||
#### Enable IP forwarding
|
||||
|
||||
For routing, we need to enable IP forwarding on both hosts since that will performed by the Linux kernel.
|
||||
|
||||
|
||||
```
|
||||
sysctl -w net.ipv4.conf.all.forwarding = 1
|
||||
|
||||
sysctl -w net.ipv6.conf.all.forwarding = 1
|
||||
sysctl -p
|
||||
```
|
||||
|
||||
#### Enabling the RIPD daemon
|
||||
|
||||
Once installed, all the configuration files will be stored in the **/etc/frr** directory. The daemons must be explicitly enabled by editing the **/etc/frr/daemons** file. This file determines which daemons are activated when the FRR service is started. To enable a particular daemon, simply change the corresponding "no" to "yes." A subsequent service restart should start the daemon.
|
||||
|
||||
![FRR daemon restart][7]
|
||||
|
||||
#### Firewall configuration
|
||||
|
||||
Since RIP protocol uses UDP as its transport protocol and is assigned port 520, we need to allow this port in `firewalld` configuration.
|
||||
|
||||
|
||||
```
|
||||
firewall-cmd --add-port=520/udp –permanent
|
||||
|
||||
firewalld-cmd -reload
|
||||
```
|
||||
|
||||
We can now start the FRR service using:
|
||||
|
||||
|
||||
```
|
||||
`systemctl start frr`
|
||||
```
|
||||
|
||||
#### Configuration using VTY
|
||||
|
||||
Now, we need to configure RIP using the VTY shell.
|
||||
|
||||
On Host Alpha:
|
||||
|
||||
|
||||
```
|
||||
[root@alpha ~]# vtysh
|
||||
|
||||
Hello, this is FRRouting (version 7.2RPKI).
|
||||
Copyright 1996-2005 Kunihiro Ishiguro, et al.
|
||||
|
||||
alpha# configure terminal
|
||||
alpha(config)# router rip
|
||||
alpha(config-router)# network 192.168.122.0/24
|
||||
alpha(config-router)# network 10.10.10.0/24
|
||||
alpha(config-router)# route 10.10.10.5/24
|
||||
alpha(config-router)# do write
|
||||
Note: this version of vtysh never writes vtysh.conf
|
||||
Building Configuration...
|
||||
Configuration saved to /etc/frr/ripd.conf
|
||||
Configuration saved to /etc/frr/staticd.conf
|
||||
alpha(config-router)# do write memory
|
||||
Note: this version of vtysh never writes vtysh.conf
|
||||
Building Configuration...
|
||||
Configuration saved to /etc/frr/ripd.conf
|
||||
Configuration saved to /etc/frr/staticd.conf
|
||||
alpha(config-router)# exit
|
||||
```
|
||||
|
||||
Similarly, on Host Beta:
|
||||
|
||||
|
||||
```
|
||||
[root@beta ~]# vtysh
|
||||
|
||||
Hello, this is FRRouting (version 7.2RPKI).
|
||||
Copyright 1996-2005 Kunihiro Ishiguro, et al.
|
||||
|
||||
beta# configure terminal
|
||||
beta(config)# router rip
|
||||
beta(config-router)# network 192.168.122.0/24
|
||||
beta(config-router)# network 10.12.11.0/24
|
||||
beta(config-router)# do write
|
||||
Note: this version of vtysh never writes vtysh.conf
|
||||
Building Configuration...
|
||||
Configuration saved to /etc/frr/zebra.conf
|
||||
Configuration saved to /etc/frr/ripd.conf
|
||||
Configuration saved to /etc/frr/staticd.conf
|
||||
beta(config-router)# do write memory
|
||||
Note: this version of vtysh never writes vtysh.conf
|
||||
Building Configuration...
|
||||
Configuration saved to /etc/frr/zebra.conf
|
||||
Configuration saved to /etc/frr/ripd.conf
|
||||
Configuration saved to /etc/frr/staticd.conf
|
||||
beta(config-router)# exit
|
||||
```
|
||||
|
||||
Once done, check the routes on both hosts as follows:
|
||||
|
||||
|
||||
```
|
||||
[root@alpha ~]# ip route show
|
||||
default via 192.168.122.1 dev eth0 proto static metric 100
|
||||
10.10.10.0/24 dev eth1 proto kernel scope link src 10.10.10.12 metric 101
|
||||
10.12.11.0/24 via 192.168.122.50 dev eth0 proto 189 metric 20
|
||||
192.168.122.0/24 dev eth0 proto kernel scope link src 192.168.122.100 metric 100
|
||||
```
|
||||
|
||||
We can see that the routing table on Alpha contains an entry of 10.12.11.0/24 via 192.168.122.50, which was offered through RIP. Similarly, on Beta, the table contains an entry of network 10.10.10.0/24 via 192.168.122.100.
|
||||
|
||||
|
||||
```
|
||||
[root@beta ~]# ip route show
|
||||
default via 192.168.122.1 dev eth0 proto static metric 100
|
||||
10.10.10.0/24 via 192.168.122.100 dev eth0 proto 189 metric 20
|
||||
10.12.11.0/24 dev eth1 proto kernel scope link src 10.12.11.12 metric 101
|
||||
192.168.122.0/24 dev eth0 proto kernel scope link src 192.168.122.50 metric 100
|
||||
```
|
||||
|
||||
### Conclusion
|
||||
|
||||
As you can see, the setup and configuration are relatively simple. To add complexity, we can add more network interfaces to the router to provide routing for more networks. The configurations can be made by editing the configuration files in an editor, but using VTY shell provides us a frontend to all FRR daemons in a single, combined session.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/5/vty-shell
|
||||
|
||||
作者:[M Umer][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/noisybotnet
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/connections_wires_sysadmin_cable.png?itok=d5WqHmnJ (Multi-colored and directional network computer cables)
|
||||
[2]: https://opensource.com/article/20/4/quagga-linux
|
||||
[3]: https://en.wikipedia.org/wiki/FRRouting
|
||||
[4]: https://opensource.com/sites/default/files/uploads/frr_architecture.png (FRR architecture)
|
||||
[5]: http://docs.frrouting.org/projects/dev-guide/en/latest/vtysh.html
|
||||
[6]: http://docs.frrouting.org/projects/dev-guide/en/latest/building-frr-for-centos7.html
|
||||
[7]: https://opensource.com/sites/default/files/uploads/frr_daemon_restart.png (FRR daemon restart)
|
@ -0,0 +1,334 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Add nodes to your private cloud using Cloud-init)
|
||||
[#]: via: (https://opensource.com/article/20/5/create-simple-cloud-init-service-your-homelab)
|
||||
[#]: author: (Chris Collins https://opensource.com/users/clcollins)
|
||||
|
||||
Add nodes to your private cloud using Cloud-init
|
||||
======
|
||||
Make adding machines to your private cloud at home similar to how the
|
||||
major cloud providers handle it.
|
||||
![Digital images of a computer desktop][1]
|
||||
|
||||
[Cloud-init][2] is a widely utilized industry-standard method for initializing cloud instances. Cloud providers use Cloud-init to customize instances with network configuration, instance information, and even user-provided configuration directives. It is also a great tool to use in your "private cloud at home" to add a little automation to the initial setup and configuration of your homelab's virtual and physical machines—and to learn more about how large cloud providers work. For a bit more detail and background, see my previous article on [Cloud-init and why it is useful][3].
|
||||
|
||||
![A screen showing the boot process for a Linux server running Cloud-init ][4]
|
||||
|
||||
Boot process for a Linux server running Cloud-init (Chris Collins, [CC BY-SA 4.0][5])
|
||||
|
||||
Admittedly, Cloud-init is more useful for a cloud provider provisioning machines for many different clients than for a homelab run by a single sysadmin, and much of what Cloud-init solves might be a little superfluous for a homelab. However, getting it set up and learning how it works is a great way to learn more about this cloud technology, not to mention that it's a great way to configure your devices on first boot.
|
||||
|
||||
This tutorial uses Cloud-init's "NoCloud" datasource, which allows Cloud-init to be used outside a traditional cloud provider setting. This article will show you how to install Cloud-init on a client device and set up a container running a web service to respond to the client's requests. You will also learn to investigate what the client is requesting from the web service and modify the web service's container to serve a basic, static Cloud-init service.
|
||||
|
||||
### Set up Cloud-init on an existing system
|
||||
|
||||
Cloud-init probably is most useful on a new system's first boot to query for configuration data and make changes to customize the system as directed. It can be [included in a disk image for Raspberry Pis and single-board computers][6] or added to images used to provision virtual machines. For testing, it is easy to install and run Cloud-init on an existing system or to install a new system and then set up Cloud-init.
|
||||
|
||||
As a major service used by most cloud providers, Cloud-init is supported on most Linux distributions. For this example, I will be using Fedora 31 Server for the Raspberry Pi, but it can be done the same way on Raspbian, Ubuntu, CentOS, and most other distributions.
|
||||
|
||||
#### Install and enable the cloud-init services
|
||||
|
||||
On a system that you want to be a Cloud-init client, install the Cloud-init package. If you're using Fedora:
|
||||
|
||||
|
||||
```
|
||||
# Install the cloud-init package
|
||||
dnf install -y cloud-init
|
||||
```
|
||||
|
||||
Cloud-init is actually four different services (at least with systemd), and each is in charge of retrieving config data and performing configuration changes during a different part of the boot process, allowing greater flexibility in what can be done. While it is unlikely you will interact much with these services directly, it is useful to know what they are in the event you need to troubleshoot something. They are:
|
||||
|
||||
* cloud-init-local.service
|
||||
* cloud-init.service
|
||||
* cloud-config.service
|
||||
* cloud-final.service
|
||||
|
||||
|
||||
|
||||
Enable all four services:
|
||||
|
||||
|
||||
```
|
||||
# Enable the four cloud-init services
|
||||
systemctl enable cloud-init-local.service
|
||||
systemctl enable cloud-init.service
|
||||
systemctl enable cloud-config.service
|
||||
systemctl enable cloud-final.service
|
||||
```
|
||||
|
||||
#### Configure the datasource to query
|
||||
|
||||
Once the service is enabled, configure the datasource from which the client will query the config data. There are a [large number of datasource types][7], and most are configured for specific cloud providers. For your homelab, use the NoCloud datasource, which (as mentioned above) is designed for using Cloud-init without a cloud provider.
|
||||
|
||||
NoCloud allows configuration information to be included a number of ways: as key/value pairs in kernel parameters, for using a CD (or virtual CD, in the case of virtual machines) mounted at startup, in a file included on the filesystem, or, as in this example, via HTTP from a specified URL (the "NoCloud Net" option).
|
||||
|
||||
The datasource configuration can be provided via the kernel parameter or by setting it in the Cloud-init configuration file, `/etc/cloud/cloud.cfg`. The configuration file works very well for setting up Cloud-init with customized disk images or for testing on existing hosts.
|
||||
|
||||
Cloud-init will also merge configuration data from any `*.cfg` files found in `/etc/cloud/cloud.cfg.d/`, so to keep things cleaner, configure the datasource in `/etc/cloud/cloud.cfg.d/10_datasource.cfg`. Cloud-init can be told to read from an HTTP datasource with the seedfrom key by using the syntax:
|
||||
|
||||
|
||||
```
|
||||
`seedfrom: http://ip_address:port/`
|
||||
```
|
||||
|
||||
The IP address and port are the web service you will create later in this article. I used the IP of my laptop and port 8080; this can also be a DNS name.
|
||||
|
||||
Create the `/etc/cloud/cloud.cfg.d/10_datasource.cfg` file:
|
||||
|
||||
|
||||
```
|
||||
# Add the datasource:
|
||||
# /etc/cloud/cloud.cfg.d/10_datasource.cfg
|
||||
|
||||
# NOTE THE TRAILING SLASH HERE!
|
||||
datasource:
|
||||
NoCloud:
|
||||
seedfrom: <http://ip\_address:port/>
|
||||
```
|
||||
|
||||
That's it for the client setup. Now, when the client is rebooted, it will attempt to retrieve configuration data from the URL you entered in the seedfrom key and make any configuration changes that are necessary.
|
||||
|
||||
The next step is to set up a webserver to listen for client requests, so you can figure out what needs to be served.
|
||||
|
||||
### Set up a webserver to investigate client requests
|
||||
|
||||
You can create and run a webserver quickly with [Podman][8] or other container orchestration tools (like Docker or Kubernetes). This example uses Podman, but the same commands work with Docker.
|
||||
|
||||
To get started, use the Fedora:31 container image and create a Containerfile (for Docker, this would be a Dockerfile) that installs and configures Nginx. From that Containerfile, you can build a custom image and run it on the host you want to act as the Cloud-init service.
|
||||
|
||||
Create a Containerfile with the following contents:
|
||||
|
||||
|
||||
```
|
||||
FROM fedora:31
|
||||
|
||||
ENV NGINX_CONF_DIR "/etc/nginx/default.d"
|
||||
ENV NGINX_LOG_DIR "/var/log/nginx"
|
||||
ENV NGINX_CONF "/etc/nginx/nginx.conf"
|
||||
ENV WWW_DIR "/usr/share/nginx/html"
|
||||
|
||||
# Install Nginx and clear the yum cache
|
||||
RUN dnf install -y nginx \
|
||||
&& dnf clean all \
|
||||
&& rm -rf /var/cache/yum
|
||||
|
||||
# forward request and error logs to docker log collector
|
||||
RUN ln -sf /dev/stdout ${NGINX_LOG_DIR}/access.log \
|
||||
&& ln -sf /dev/stderr ${NGINX_LOG_DIR}/error.log
|
||||
|
||||
# Listen on port 8080, so root privileges are not required for podman
|
||||
RUN sed -i -E 's/(listen)([[:space:]]*)(\\[\:\:\\]\:)?80;$/\1\2\38080 default_server;/' $NGINX_CONF
|
||||
EXPOSE 8080
|
||||
|
||||
# Allow Nginx PID to be managed by non-root user
|
||||
RUN sed -i '/user nginx;/d' $NGINX_CONF
|
||||
RUN sed -i 's/pid \/run\/nginx.pid;/pid \/tmp\/nginx.pid;/' $NGINX_CONF
|
||||
|
||||
# Run as an unprivileged user
|
||||
USER 1001
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
|
||||
_Note: The example Containerfile and other files used in this example can be found in this project's [GitHub repository][9]._
|
||||
|
||||
The most important part of the Containerfile above is the section that changes how the logs are stored (writing to STDOUT rather than a file), so you can see requests coming into the server in the container logs. A few other changes enable you to run the container with Podman without root privileges and to run processes in the container without root, as well.
|
||||
|
||||
This first pass at the webserver does not serve any Cloud-init data; just use this to see what the Cloud-init client is requesting from it.
|
||||
|
||||
With the Containerfile created, use Podman to build and run a webserver image:
|
||||
|
||||
|
||||
```
|
||||
# Build the container image
|
||||
$ podman build -f Containerfile -t cloud-init:01 .
|
||||
|
||||
# Create a container from the new image, and run it
|
||||
# It will listen on port 8080
|
||||
$ podman run --rm -p 8080:8080 -it cloud-init:01
|
||||
```
|
||||
|
||||
This will run the container, leaving your terminal attached and with a pseudo-TTY. It will appear that nothing is happening at first, but requests to port 8080 of the host machine will be routed to the Nginx server inside the container, and a log message will appear in the terminal window. This can be tested with a curl command from the host machine:
|
||||
|
||||
|
||||
```
|
||||
# Use curl to send an HTTP request to the Nginx container
|
||||
$ curl <http://localhost:8080>
|
||||
```
|
||||
|
||||
After running that curl command, you should see a log message similar to this in the terminal window:
|
||||
|
||||
|
||||
```
|
||||
`127.0.0.1 - - [09/May/2020:19:25:10 +0000] "GET / HTTP/1.1" 200 5564 "-" "curl/7.66.0" "-"`
|
||||
```
|
||||
|
||||
Now comes the fun part: reboot the Cloud-init client and watch the Nginx logs to see what Cloud-init requests from the webserver when the client boots up.
|
||||
|
||||
As the client finishes its boot process, you should see log messages similar to:
|
||||
|
||||
|
||||
```
|
||||
2020/05/09 22:44:28 [error] 2#0: *4 open() "/usr/share/nginx/html/meta-data" failed (2: No such file or directory), client: 127.0.0.1, server: _, request: "GET /meta-data HTTP/1.1", host: "instance-data:8080"
|
||||
127.0.0.1 - - [09/May/2020:22:44:28 +0000] "GET /meta-data HTTP/1.1" 404 3650 "-" "Cloud-Init/17.1" "-"
|
||||
```
|
||||
|
||||
_Note: Use Ctrl+C to stop the running container._
|
||||
|
||||
You can see the request is for the /meta-data path, i.e., `http://ip_address_of_the_webserver:8080/meta-data`. This is just a GET request—Cloud-init is not POSTing (sending) any data to the webserver. It is just blindly requesting the files from the datasource URL, so it is up to the datasource to identify what the host is asking. This simple example is just sending generic data to any client, but a larger homelab will need a more sophisticated service.
|
||||
|
||||
Here, Cloud-init is requesting the [instance metadata][10] information. This file can include a lot of information about the instance itself, such as the instance ID, the hostname to assign the instance, the cloud ID—even networking information.
|
||||
|
||||
Create a basic metadata file with an instance ID and a hostname for the host, and try serving that to the Cloud-init client.
|
||||
|
||||
First, create a metadata file that can be copied into the container image:
|
||||
|
||||
|
||||
```
|
||||
instance-id: iid-local01
|
||||
local-hostname: raspberry
|
||||
hostname: raspberry
|
||||
```
|
||||
|
||||
The instance ID can be anything. However, if you change the instance ID after Cloud-init runs and the file is served to the client, it will trigger Cloud-init to run again. You can use this mechanism to update instance configurations, but you should be aware that it works that way.
|
||||
|
||||
The local-hostname and hostname keys are just that; they set the hostname information for the client when Cloud-init runs.
|
||||
|
||||
Add the following line to the Containerfile to copy the metadata file into the new image:
|
||||
|
||||
|
||||
```
|
||||
# Copy the meta-data file into the image for Nginx to serve it
|
||||
COPY meta-data ${WWW_DIR}/meta-data
|
||||
```
|
||||
|
||||
Now, rebuild the image (use a new tag for easy troubleshooting) with the metadata file, and create and run a new container with Podman:
|
||||
|
||||
|
||||
```
|
||||
# Build a new image named cloud-init:02
|
||||
podman build -f Containerfile -t cloud-init:02 .
|
||||
|
||||
# Run a new container with this new meta-data file
|
||||
podman run --rm -p 8080:8080 -it cloud-init:02
|
||||
```
|
||||
|
||||
With the new container running, reboot your Cloud-init client and watch the Nginx logs again:
|
||||
|
||||
|
||||
```
|
||||
127.0.0.1 - - [09/May/2020:22:54:32 +0000] "GET /meta-data HTTP/1.1" 200 63 "-" "Cloud-Init/17.1" "-"
|
||||
2020/05/09 22:54:32 [error] 2#0: *2 open() "/usr/share/nginx/html/user-data" failed (2: No such file or directory), client: 127.0.0.1, server: _, request: "GET /user-data HTTP/1.1", host: "instance-data:8080"
|
||||
127.0.0.1 - - [09/May/2020:22:54:32 +0000] "GET /user-data HTTP/1.1" 404 3650 "-" "Cloud-Init/17.1" "-"
|
||||
```
|
||||
|
||||
You see that this time the /meta-data path was served to the client. Success!
|
||||
|
||||
However, the client is looking for a second file at the /user-data path. This file contains configuration data provided by the instance owner, as opposed to data from the cloud provider. For a homelab, both of these are you.
|
||||
|
||||
There are a [large number of user-data modules][11] you can use to configure your instance. For this example, just use the write_files module to create some test files on the client and verify that Cloud-init is working.
|
||||
|
||||
Create a user-data file with the following content:
|
||||
|
||||
|
||||
```
|
||||
#cloud-config
|
||||
|
||||
# Create two files with example content using the write_files module
|
||||
write_files:
|
||||
- content: |
|
||||
"Does cloud-init work?"
|
||||
owner: root:root
|
||||
permissions: '0644'
|
||||
path: /srv/foo
|
||||
- content: |
|
||||
"IT SURE DOES!"
|
||||
owner: root:root
|
||||
permissions: '0644'
|
||||
path: /srv/bar
|
||||
```
|
||||
|
||||
In addition to a YAML file using the user-data modules provided by Cloud-init, you could also make this an executable script for Cloud-init to run.
|
||||
|
||||
After creating the user-data file, add the following line to the Containerfile to copy it into the image when the image is rebuilt:
|
||||
|
||||
|
||||
```
|
||||
# Copy the user-data file into the container image
|
||||
COPY user-data ${WWW_DIR}/user-data
|
||||
```
|
||||
|
||||
Rebuild the image and create and run a new container, this time with the user-data information:
|
||||
|
||||
|
||||
```
|
||||
# Build a new image named cloud-init:03
|
||||
podman build -f Containerfile -t cloud-init:03 .
|
||||
|
||||
# Run a new container with this new user-data file
|
||||
podman run --rm -p 8080:8080 -it cloud-init:03
|
||||
```
|
||||
|
||||
Now, reboot your Cloud-init client, and watch the Nginx logs on the webserver:
|
||||
|
||||
|
||||
```
|
||||
127.0.0.1 - - [09/May/2020:23:01:51 +0000] "GET /meta-data HTTP/1.1" 200 63 "-" "Cloud-Init/17.1" "-"
|
||||
127.0.0.1 - - [09/May/2020:23:01:51 +0000] "GET /user-data HTTP/1.1" 200 298 "-" "Cloud-Init/17.1" "-
|
||||
```
|
||||
|
||||
Success! This time both the metadata and user-data files were served to the Cloud-init client.
|
||||
|
||||
### Validate that Cloud-init ran
|
||||
|
||||
From the logs above, you know that Cloud-init ran on the client host and requested the metadata and user-data files, but did it do anything with them? You can validate that Cloud-init wrote the files you added in the user-data file, in the write_files section.
|
||||
|
||||
On your Cloud-init client, check the contents of the `/srv/foo` and `/srv/bar` files:
|
||||
|
||||
|
||||
```
|
||||
# cd /srv/ && ls
|
||||
bar foo
|
||||
# cat foo
|
||||
"Does cloud-init work?"
|
||||
# cat bar
|
||||
"IT SURE DOES!"
|
||||
```
|
||||
|
||||
Success! The files were written and have the content you expect.
|
||||
|
||||
As mentioned above, there are plenty of other modules that can be used to configure the host. For example, the user-data file can be configured to add packages with apt, copy SSH authorized_keys, create users and groups, configure and run configuration-management tools, and many other things. I use it in my private cloud at home to copy my authorized_keys, create a local user and group, and set up sudo permissions.
|
||||
|
||||
### What you can do next
|
||||
|
||||
Cloud-init is useful in a homelab, especially a lab focusing on cloud technologies. The simple service demonstrated in this article may not be super useful for a homelab, but now that you know how Cloud-init works, you can move on to creating a dynamic service that can configure each host with custom data, making a private cloud at home more similar to the services provided by the major cloud providers.
|
||||
|
||||
With a slightly more complicated datasource, adding new physical (or virtual) machines to your private cloud at home can be as simple as plugging them in and turning them on.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/5/create-simple-cloud-init-service-your-homelab
|
||||
|
||||
作者:[Chris Collins][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/clcollins
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/computer_desk_home_laptop_browser.png?itok=Y3UVpY0l (Digital images of a computer desktop)
|
||||
[2]: https://cloudinit.readthedocs.io/
|
||||
[3]: https://opensource.com/article/20/5/cloud-init-raspberry-pi-homelab
|
||||
[4]: https://opensource.com/sites/default/files/uploads/cloud-init.jpg (A screen showing the boot process for a Linux server running Cloud-init )
|
||||
[5]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[6]: https://opensource.com/article/20/5/disk-image-raspberry-pi
|
||||
[7]: https://cloudinit.readthedocs.io/en/latest/topics/datasources.html
|
||||
[8]: https://podman.io/
|
||||
[9]: https://github.com/clcollins/homelabCloudInit/tree/master/simpleCloudInitService/data
|
||||
[10]: https://cloudinit.readthedocs.io/en/latest/topics/instancedata.html#what-is-instance-data
|
||||
[11]: https://cloudinit.readthedocs.io/en/latest/topics/modules.html
|
567
sources/tech/20200527 Manage startup using systemd.md
Normal file
567
sources/tech/20200527 Manage startup using systemd.md
Normal file
@ -0,0 +1,567 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Manage startup using systemd)
|
||||
[#]: via: (https://opensource.com/article/20/5/manage-startup-systemd)
|
||||
[#]: author: (David Both https://opensource.com/users/dboth)
|
||||
|
||||
Manage startup using systemd
|
||||
======
|
||||
Learn how systemd determines the order services start, even though it is
|
||||
essentially a parallel system.
|
||||
![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.
|
||||
|
||||
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.
|
||||
|
||||
### Preparation
|
||||
|
||||
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
|
||||
|
||||
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:
|
||||
|
||||
|
||||
```
|
||||
#!/usr/bin/bash
|
||||
# Simple program to use for testing startup configurations
|
||||
# with systemd.
|
||||
# By David Both
|
||||
# Licensed under GPL V2
|
||||
#
|
||||
echo "###############################"
|
||||
echo "######### Hello World! ########"
|
||||
echo "###############################"
|
||||
```
|
||||
|
||||
Run this program from the command line to verify that it works correctly:
|
||||
|
||||
|
||||
```
|
||||
[root@testvm1 ~]# hello.sh
|
||||
###############################
|
||||
######### Hello World! ########
|
||||
###############################
|
||||
[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.
|
||||
|
||||
### 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:
|
||||
|
||||
|
||||
```
|
||||
# Simple service unit file to use for testing
|
||||
# startup configurations with systemd.
|
||||
# By David Both
|
||||
# Licensed under GPL V2
|
||||
#
|
||||
|
||||
[Unit]
|
||||
Description=My hello shell script
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/bin/hello.sh
|
||||
|
||||
[Install]
|
||||
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:
|
||||
|
||||
|
||||
```
|
||||
[root@testvm1 ~]# systemctl status hello.service
|
||||
● hello.service - My hello shell script
|
||||
Loaded: loaded (/etc/systemd/system/hello.service; disabled; vendor preset: disabled)
|
||||
Active: inactive (dead)
|
||||
[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.)
|
||||
|
||||
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:
|
||||
|
||||
|
||||
```
|
||||
[root@testvm1 ~]# systemctl status hello.service
|
||||
● hello.service - My hello shell script
|
||||
Loaded: loaded (/etc/systemd/system/hello.service; disabled; vendor preset: disabled)
|
||||
Active: inactive (dead)
|
||||
|
||||
May 06 08:50:09 testvm1.both.org systemd[1]: /etc/systemd/system/hello.service:12: Failed to parse service type, ignoring: neshot
|
||||
[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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
### 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:
|
||||
|
||||
|
||||
```
|
||||
[root@testvm1 ~]# systemctl start hello.service
|
||||
[root@testvm1 ~]# systemctl status hello.service
|
||||
● hello.service - My hello shell script
|
||||
Loaded: loaded (/etc/systemd/system/hello.service; disabled; vendor preset: disabled)
|
||||
Active: inactive (dead)
|
||||
|
||||
May 10 10:37:49 testvm1.both.org hello.sh[842]: ######### Hello World! ########
|
||||
May 10 10:37:49 testvm1.both.org hello.sh[842]: ###############################
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: hello.service: Succeeded.
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: Finished My hello shell script.
|
||||
May 10 10:54:45 testvm1.both.org systemd[1]: Starting My hello shell script...
|
||||
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ###############################
|
||||
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ######### Hello World! ########
|
||||
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ###############################
|
||||
May 10 10:54:45 testvm1.both.org systemd[1]: hello.service: Succeeded.
|
||||
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:
|
||||
|
||||
|
||||
```
|
||||
[root@testvm1 ~]# journalctl -t hello.sh
|
||||
<snip>
|
||||
\-- Reboot --
|
||||
May 08 15:55:47 testvm1.both.org hello.sh[840]: ###############################
|
||||
May 08 15:55:47 testvm1.both.org hello.sh[840]: ######### Hello World! ########
|
||||
May 08 15:55:47 testvm1.both.org hello.sh[840]: ###############################
|
||||
\-- Reboot --
|
||||
May 08 16:01:51 testvm1.both.org hello.sh[840]: ###############################
|
||||
May 08 16:01:51 testvm1.both.org hello.sh[840]: ######### Hello World! ########
|
||||
May 08 16:01:51 testvm1.both.org hello.sh[840]: ###############################
|
||||
\-- Reboot --
|
||||
May 10 10:37:49 testvm1.both.org hello.sh[842]: ###############################
|
||||
May 10 10:37:49 testvm1.both.org hello.sh[842]: ######### Hello World! ########
|
||||
May 10 10:37:49 testvm1.both.org hello.sh[842]: ###############################
|
||||
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ###############################
|
||||
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ######### Hello World! ########
|
||||
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:
|
||||
|
||||
|
||||
```
|
||||
[root@testvm1 ~]# journalctl -b -t systemd
|
||||
<snip>
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: Starting SYSV: Late init script for live image....
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: Started SYSV: Late init script for live image..
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: hello.service: Succeeded.
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: Finished My hello shell script.
|
||||
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:
|
||||
|
||||
|
||||
```
|
||||
[root@testvm1 ~]# journalctl -b -t systemd -g "hello"
|
||||
[root@testvm1 ~]# journalctl -b -t systemd -g "hello"
|
||||
\-- Logs begin at Tue 2020-05-05 18:11:49 EDT, end at Sun 2020-05-10 11:01:01 EDT. --
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: Starting My hello shell script...
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: hello.service: Succeeded.
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: Finished My hello shell script.
|
||||
May 10 10:54:45 testvm1.both.org systemd[1]: Starting My hello shell script...
|
||||
May 10 10:54:45 testvm1.both.org systemd[1]: hello.service: Succeeded.
|
||||
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.
|
||||
|
||||
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 "<time specification>"`.
|
||||
|
||||
The date and time will be different on your host, so be sure to use the timestamps that match the times in your journals:
|
||||
|
||||
|
||||
```
|
||||
[root@testvm1 ~]# journalctl --since="2020-05-10 10:54:00"
|
||||
May 10 10:54:35 testvm1.both.org audit: BPF prog-id=54 op=LOAD
|
||||
May 10 10:54:35 testvm1.both.org audit: BPF prog-id=55 op=LOAD
|
||||
May 10 10:54:45 testvm1.both.org systemd[1]: Starting My hello shell script...
|
||||
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ###############################
|
||||
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ######### Hello World! ########
|
||||
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ###############################
|
||||
May 10 10:54:45 testvm1.both.org systemd[1]: hello.service: Succeeded.
|
||||
May 10 10:54:45 testvm1.both.org systemd[1]: Finished My hello shell script.
|
||||
May 10 10:54:45 testvm1.both.org audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=hello comm="systemd" exe="/usr/lib/systemd"'
|
||||
May 10 10:54:45 testvm1.both.org audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=hello comm="systemd" exe="/usr/lib/systemd/"'
|
||||
May 10 10:56:00 testvm1.both.org NetworkManager[840]: <error> [1589122560.0633] dhcp4 (enp0s3): error -113 dispatching events
|
||||
May 10 10:56:00 testvm1.both.org NetworkManager[840]: <info> [1589122560.0634] dhcp4 (enp0s3): state changed bound -> fail
|
||||
<snip>
|
||||
```
|
||||
|
||||
The `since` specification skips all of the entries before that time, but there are still a lot of entries after that time that you do not need. You can also use the `until` option to trim off the entries that come a bit after the time you are interested in. I want the entire minute when the event occurred and nothing more:
|
||||
|
||||
|
||||
```
|
||||
[root@testvm1 ~]# journalctl --since="2020-05-10 10:54:35" --until="2020-05-10 10:55:00"
|
||||
\-- Logs begin at Tue 2020-05-05 18:11:49 EDT, end at Sun 2020-05-10 11:04:59 EDT. --
|
||||
May 10 10:54:35 testvm1.both.org systemd[1]: Reloading.
|
||||
May 10 10:54:35 testvm1.both.org audit: BPF prog-id=27 op=UNLOAD
|
||||
May 10 10:54:35 testvm1.both.org audit: BPF prog-id=26 op=UNLOAD
|
||||
<snip>
|
||||
ay 10 10:54:35 testvm1.both.org audit: BPF prog-id=55 op=LOAD
|
||||
May 10 10:54:45 testvm1.both.org systemd[1]: Starting My hello shell script...
|
||||
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ###############################
|
||||
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ######### Hello World! ########
|
||||
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ###############################
|
||||
May 10 10:54:45 testvm1.both.org systemd[1]: hello.service: Succeeded.
|
||||
May 10 10:54:45 testvm1.both.org systemd[1]: Finished My hello shell script.
|
||||
May 10 10:54:45 testvm1.both.org audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=hello comm="systemd" exe="/usr/lib/systemd>
|
||||
May 10 10:54:45 testvm1.both.org audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=hello comm="systemd" exe="/usr/lib/systemd/>
|
||||
lines 1-46/46 (END)
|
||||
```
|
||||
|
||||
If there were a lot of activity in this time period, you could further narrow the resulting data stream using a combination of these options:
|
||||
|
||||
|
||||
```
|
||||
[root@testvm1 ~]# journalctl --since="2020-05-10 10:54:35" --until="2020-05-10 10:55:00" -t "hello.sh"
|
||||
\-- Logs begin at Tue 2020-05-05 18:11:49 EDT, end at Sun 2020-05-10 11:10:41 EDT. --
|
||||
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ###############################
|
||||
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ######### Hello World! ########
|
||||
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ###############################
|
||||
[root@testvm1 ~]#
|
||||
```
|
||||
|
||||
Your results should be similar to mine. You can see from this series of experiments that the service executed properly.
|
||||
|
||||
### Reboot—finally
|
||||
|
||||
So far, you have not rebooted the host where you installed your service. So do that now because, after all, this how-to is about running a program at startup. First, you need to enable the service to launch during the startup sequence:
|
||||
|
||||
|
||||
```
|
||||
[root@testvm1 ~]# systemctl enable hello.service
|
||||
Created symlink /etc/systemd/system/multi-user.target.wants/hello.service → /etc/systemd/system/hello.service.
|
||||
[root@testvm1 ~]#
|
||||
```
|
||||
|
||||
Notice that the link was created in the `/etc/systemd/system/multi-user.target.wants` directory. This is because the service unit file specifies that the service is "wanted" by the `multi-user.target`.
|
||||
|
||||
Reboot, and be sure to watch the data stream during the startup sequence to see the "Hello world" message. Wait … you did not see it? Well, neither did I. Although it went by very fast, I did see systemd's message that it was starting the `hello.service`.
|
||||
|
||||
Look at the journal since the latest system boot. You can use the `less` pager's search tool to find "Hello" or "hello." I pruned many lines of data, but I left some of the surrounding journal entries, so you can get a feel for what the entries pertaining to your service look like locally:
|
||||
|
||||
|
||||
```
|
||||
[root@testvm1 ~]# journalctl -b
|
||||
<snip>
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: Listening on SSSD Kerberos Cache Manager responder socket.
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: Reached target Sockets.
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: Reached target Basic System.
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: Starting Modem Manager...
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: Starting Network Manager...
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: Starting Avahi mDNS/DNS-SD Stack...
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: Condition check resulted in Secure Boot DBX (blacklist) updater being skipped.
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: Starting My hello shell script...
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: Starting IPv4 firewall with iptables...
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: Started irqbalance daemon.
|
||||
May 10 10:37:49 testvm1.both.org audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=irqbalance comm="systemd" exe="/usr/lib/sy>"'
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: Starting LSB: Init script for live image....
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: Starting Hardware Monitoring Sensors...
|
||||
<snip>
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: Starting NTP client/server...
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: Starting SYSV: Late init script for live image....
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: Started SYSV: Late init script for live image..
|
||||
May 10 10:37:49 testvm1.both.org audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=livesys-late comm="systemd" exe="/usr/lib/>"'
|
||||
May 10 10:37:49 testvm1.both.org hello.sh[842]: ###############################
|
||||
May 10 10:37:49 testvm1.both.org hello.sh[842]: ######### Hello World! ########
|
||||
May 10 10:37:49 testvm1.both.org hello.sh[842]: ###############################
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: hello.service: Succeeded.
|
||||
May 10 10:37:49 testvm1.both.org systemd[1]: Finished My hello shell script.
|
||||
May 10 10:37:49 testvm1.both.org audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=hello comm="systemd" exe="/usr/lib/systemd>"'
|
||||
May 10 10:37:49 testvm1.both.org audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=hello comm="systemd" exe="/usr/lib/systemd/>
|
||||
May 10 10:37:50 testvm1.both.org audit: BPF prog-id=28 op=LOAD
|
||||
<snip>
|
||||
```
|
||||
|
||||
You can see that systemd started the `hello.service` unit, which ran the `hello.sh` shell script with the output recorded in the journal. If you were able to catch it during boot, you would also have seen the systemd message indicating that it was starting the script and another message indicating that the service succeeded. By looking at the first systemd message in the data stream above, you can see that systemd started your service very soon after reaching the basic system target.
|
||||
|
||||
But I would like to see the message displayed at startup as well. There is a way to make that happen: Add the following line to the `[Service]` section of the `hello.service` file:
|
||||
|
||||
|
||||
```
|
||||
`StandardOutput=journal+console`
|
||||
```
|
||||
|
||||
The `hello.service` file now looks like this:
|
||||
|
||||
|
||||
```
|
||||
# Simple service unit file to use for testing
|
||||
# startup configurations with systemd.
|
||||
# By David Both
|
||||
# Licensed under GPL V2
|
||||
#
|
||||
|
||||
[Unit]
|
||||
Description=My hello shell script
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/bin/hello.sh
|
||||
StandardOutput=journal+console
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
After adding this line, reboot the system, and watch the data stream as it scrolls up the display during the boot process. You should see the message in its little box. After the startup sequence completes, you can view the journal for the most recent boot and locate the entries for your new service.
|
||||
|
||||
### Changing the sequence
|
||||
|
||||
Now that your service is working, you can look at where it starts in the startup sequence and experiment with changing it. It is important to remember that systemd's intent is to start as many services and other unit types in parallel within each of the major targets: `basic.target`, `multi-user.target`, and `graphical.target`. You should have just seen the journal entries for the most recent boot, which should look similar to my journal in the output above.
|
||||
|
||||
Notice that systemd started your test service soon after it reached the target basic system. This is what you specified in the service unit file in the `WantedBy` line, so it is correct. Before you change anything, list the contents of the `/etc/systemd/system/multi-user.target.wants` directory, and you will see a symbolic (soft) link to the service unit file. The `[Install]` section of the service unit file specifies which target will start the service, and running the `systemctl enable hello.service` command creates the link in the appropriate "target wants" directory:
|
||||
|
||||
|
||||
```
|
||||
`hello.service -> /etc/systemd/system/hello.service`
|
||||
```
|
||||
|
||||
Certain services need to start during the `basic.target`, and others do not need to start unless the system is starting the `graphical.target`. The service in this experiment will not start in the `basic.target`—assume you do not need it to start until the `graphical.target`. So change the `WantedBy` line:
|
||||
|
||||
|
||||
```
|
||||
`WantedBy=graphical.target`
|
||||
```
|
||||
|
||||
Be sure to disable the `hello.service` and re-enable it to delete the old link and add the new one in the `graphical.targets.wants` directory. I have noticed that if I forget to disable the service before changing the target that wants it, I can run the `systemctl disable` command, and the links will be removed from both "target wants" directories. Then, I just need to re-enable the service and reboot.
|
||||
|
||||
One concern with starting services in the `graphical.target` is that if the host boots to `multi-user.target`, this service will not start automatically. That may be what you want if the service requires a GUI desktop interface, but it also may not be what you want.
|
||||
|
||||
Look at the journal entries for the `graphical.target` and the `multi-user.target` using the `-o short-monotonic` option that displays seconds after kernel startup with microsecond precision:
|
||||
|
||||
|
||||
```
|
||||
`[root@testvm1 ~]# journalctl -b -o short-monotonic`
|
||||
```
|
||||
|
||||
Some results for `multi-user.target`:
|
||||
|
||||
|
||||
```
|
||||
[ 17.264730] testvm1.both.org systemd[1]: Starting My hello shell script...
|
||||
[ 17.265561] testvm1.both.org systemd[1]: Starting IPv4 firewall with iptables...
|
||||
<SNIP>
|
||||
[ 19.478468] testvm1.both.org systemd[1]: Starting LSB: Init script for live image....
|
||||
[ 19.507359] testvm1.both.org iptables.init[844]: iptables: Applying firewall rules: [ OK ]
|
||||
[ 19.507835] testvm1.both.org hello.sh[843]: ###############################
|
||||
[ 19.507835] testvm1.both.org hello.sh[843]: ######### Hello World! ########
|
||||
[ 19.507835] testvm1.both.org hello.sh[843]: ###############################
|
||||
<SNIP>
|
||||
[ 21.482481] testvm1.both.org systemd[1]: hello.service: Succeeded.
|
||||
[ 21.482550] testvm1.both.org smartd[856]: Opened configuration file /etc/smartmontools/smartd.conf
|
||||
[ 21.482605] testvm1.both.org systemd[1]: Finished My hello shell script.
|
||||
```
|
||||
|
||||
And some results for `graphical.target`:
|
||||
|
||||
|
||||
```
|
||||
[ 19.436815] testvm1.both.org systemd[1]: Starting My hello shell script...
|
||||
[ 19.437070] testvm1.both.org systemd[1]: Starting IPv4 firewall with iptables...
|
||||
<SNIP>
|
||||
[ 19.612614] testvm1.both.org hello.sh[841]: ###############################
|
||||
[ 19.612614] testvm1.both.org hello.sh[841]: ######### Hello World! ########
|
||||
[ 19.612614] testvm1.both.org hello.sh[841]: ###############################
|
||||
[ 19.629455] testvm1.both.org audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=hello comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
|
||||
[ 19.629569] testvm1.both.org audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=hello comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
|
||||
[ 19.629682] testvm1.both.org systemd[1]: hello.service: Succeeded.
|
||||
[ 19.629782] testvm1.both.org systemd[1]: Finished My hello shell script.
|
||||
```
|
||||
|
||||
Despite having the `graphical.target` "want" in the unit file, the `hello.service` unit runs about 19.5 or 19.6 seconds into startup. But `hello.service` starts at about 17.24 seconds in the `multi-user.target` and 19.43 seconds in the graphical target.
|
||||
|
||||
What does this mean? Look at the `/etc/systemd/system/default.target` link. The contents of that file show that systemd first starts the default target, `graphical.target`, which then pulls in the `multi-user.target`:
|
||||
|
||||
|
||||
```
|
||||
[root@testvm1 system]# cat default.target
|
||||
# SPDX-License-Identifier: LGPL-2.1+
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Unit]
|
||||
Description=Graphical Interface
|
||||
Documentation=man:systemd.special(7)
|
||||
Requires=multi-user.target
|
||||
Wants=display-manager.service
|
||||
Conflicts=rescue.service rescue.target
|
||||
After=multi-user.target rescue.service rescue.target display-manager.service
|
||||
AllowIsolate=yes
|
||||
[root@testvm1 system]#
|
||||
```
|
||||
|
||||
Whether it starts the service with the `graphical.target` or the `multi-user.target`, the `hello.service` unit runs at about 19.5 or 19.6 seconds into startup. Based on this and the journal results (especially the ones using the monotonic output), you know that both of these targets are starting in parallel. Look at one more thing from the journal output:
|
||||
|
||||
|
||||
```
|
||||
[ 28.397330] testvm1.both.org systemd[1]: Reached target Multi-User System.
|
||||
[ 28.397431] testvm1.both.org systemd[1]: Reached target Graphical Interface.
|
||||
```
|
||||
|
||||
Both targets finish at almost the same time. This is consistent because the `graphical.target` pulls in the `multi-user.target` and cannot finish until the `multi.user target` is reached, i.e., finished. But **hello.service** finishes much earlier than this.
|
||||
|
||||
What all this means is that these two targets start up pretty much in parallel. If you explore the journal entries, you will see various targets and services from each of those primary targets starting mostly in parallel. It is clear that the `multi-user.target` does not need to complete before the `graphical.target` starts. Therefore, simply using these primary targets to sequence the startup does not work very well, although it can be useful for ensuring that units are started only when they are needed for the `graphical.target`.
|
||||
|
||||
Before continuing, revert the `hello.service` unit file to `WantedBy=multi-user.target` (if it is not already.)
|
||||
|
||||
### Ensure a service starts after the network is running
|
||||
|
||||
A common startup sequence issue is ensuring that a unit starts after the network is up and running. The Freedesktop.org article [_Running services after the network is up_][11] says there is no real consensus on when a network is considered "up." However, the article provides three options, and the one that meets the needs of a fully operational network is `network-online.target`. Just be aware that `network.target` is used during shutdown rather than startup, so it will not do you any good when you are trying to sequence the startup.
|
||||
|
||||
Before making any other changes, be sure to examine the journal and verify that the `hello.service` unit starts well before the network. You can look for the `network-online.target` in the journal to check.
|
||||
|
||||
Your service does not really require the network service, but you can use it as an avatar for one that does.
|
||||
|
||||
Because setting `WantedBy=graphical.target` does not ensure that the service will be started after the network is up and running, you need another way to ensure that it is. Fortunately, there is an easy way to do this. Add the following two lines to the `[Unit]` section of the `hello.service` unit file:
|
||||
|
||||
|
||||
```
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
```
|
||||
|
||||
Both of these entries are required to make this work. Reboot the host and look for the location of entries for your service in the journals:
|
||||
|
||||
|
||||
```
|
||||
[ 26.083121] testvm1.both.org NetworkManager[842]: <info> [1589227764.0293] device (enp0s3): Activation: successful, device activated.
|
||||
[ 26.083349] testvm1.both.org NetworkManager[842]: <info> [1589227764.0301] manager: NetworkManager state is now CONNECTED_GLOBAL
|
||||
[ 26.085818] testvm1.both.org NetworkManager[842]: <info> [1589227764.0331] manager: startup complete
|
||||
[ 26.089911] testvm1.both.org systemd[1]: Finished Network Manager Wait Online.
|
||||
[ 26.090254] testvm1.both.org systemd[1]: Reached target Network is Online.
|
||||
[ 26.090399] testvm1.both.org audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=NetworkManager-wait-online comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? termina>"'
|
||||
[ 26.091991] testvm1.both.org systemd[1]: Starting My hello shell script...
|
||||
[ 26.095864] testvm1.both.org sssd[be[implicit_files]][1007]: Starting up
|
||||
[ 26.290539] testvm1.both.org systemd[1]: Condition check resulted in Login and scanning of iSCSI devices being skipped.
|
||||
[ 26.291075] testvm1.both.org systemd[1]: Reached target Remote File Systems (Pre).
|
||||
[ 26.291154] testvm1.both.org systemd[1]: Reached target Remote File Systems.
|
||||
[ 26.292671] testvm1.both.org systemd[1]: Starting Notify NFS peers of a restart...
|
||||
[ 26.294897] testvm1.both.org systemd[1]: iscsi.service: Unit cannot be reloaded because it is inactive.
|
||||
[ 26.304682] testvm1.both.org hello.sh[1010]: ###############################
|
||||
[ 26.304682] testvm1.both.org hello.sh[1010]: ######### Hello World! ########
|
||||
[ 26.304682] testvm1.both.org hello.sh[1010]: ###############################
|
||||
[ 26.306569] testvm1.both.org audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=hello comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
|
||||
[ 26.306669] testvm1.both.org audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=hello comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
|
||||
[ 26.306772] testvm1.both.org systemd[1]: hello.service: Succeeded.
|
||||
[ 26.306862] testvm1.both.org systemd[1]: Finished My hello shell script.
|
||||
[ 26.584966] testvm1.both.org sm-notify[1011]: Version 2.4.3 starting
|
||||
```
|
||||
|
||||
This confirms that the `hello.service` unit started after the `network-online.target`. This is exactly what you want. You may also have seen the "Hello World" message as it passed by during startup. Notice also that the timestamp is about six seconds later in the startup than it was before.
|
||||
|
||||
### The best way to define the start sequence
|
||||
|
||||
This article explored Linux startup with systemd and unit files and journals in greater detail and discovered what happens when errors are introduced into the service file. As a sysadmin, I find that this type of experimentation helps me understand the behaviors of a program or service when it breaks, and breaking things intentionally is a good way to learn in a safe environment.
|
||||
|
||||
As the experiments in this article proved, just adding a service unit to either the `multi-user.target` or the `graphical.target` does not define its place in the start sequence. It merely determines whether a unit starts as part of a graphical environment or not. The reality is that the startup targets `multi-user.target` and `graphical.target`—and all of their Wants and Requires—start up pretty much in parallel. The best way to ensure that a unit starts in a specific order is to determine the unit it is dependent on and configure the new unit to "Want" and "After" the unit upon which it is dependent.
|
||||
|
||||
### Resources
|
||||
|
||||
There is a great deal of information about systemd available on the internet, but much is terse, obtuse, or even misleading. In addition to the resources mentioned in this article, the following webpages offer more detailed and reliable information about systemd startup.
|
||||
|
||||
* The Fedora Project has a good, practical [guide to systemd][12]. It has pretty much everything you need to know in order to configure, manage, and maintain a Fedora computer using systemd.
|
||||
* The Fedora Project also has a good [cheat sheet][13] that cross-references the old SystemV commands to comparable systemd ones.
|
||||
* For detailed technical information about systemd and the reasons for creating it, check out [Freedesktop.org][14]'s [description of systemd][15].
|
||||
* [Linux.com][16]'s "More systemd fun" offers more advanced systemd [information and tips][17].
|
||||
|
||||
|
||||
|
||||
There is also a series of deeply technical articles for Linux sysadmins by Lennart Poettering, the designer and primary developer of systemd. These articles were written between April 2010 and September 2011, but they are just as relevant now as they were then. Much of everything else good that has been written about systemd and its ecosystem is based on these papers.
|
||||
|
||||
* [Rethinking PID 1][18]
|
||||
* [systemd for Administrators, Part I][19]
|
||||
* [systemd for Administrators, Part II][20]
|
||||
* [systemd for Administrators, Part III][21]
|
||||
* [systemd for Administrators, Part IV][22]
|
||||
* [systemd for Administrators, Part V][23]
|
||||
* [systemd for Administrators, Part VI][24]
|
||||
* [systemd for Administrators, Part VII][25]
|
||||
* [systemd for Administrators, Part VIII][26]
|
||||
* [systemd for Administrators, Part IX][27]
|
||||
* [systemd for Administrators, Part X][28]
|
||||
* [systemd for Administrators, Part XI][29]
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/5/manage-startup-systemd
|
||||
|
||||
作者:[David Both][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/dboth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/linux_penguin_green.png?itok=ENdVzW22 (Penguin with green background)
|
||||
[2]: https://opensource.com/article/20/4/systemd
|
||||
[3]: https://opensource.com/article/20/5/systemd-units
|
||||
[4]: https://opensource.com/article/20/5/systemd-startup
|
||||
[5]: https://chmodcommand.com/chmod-700/
|
||||
[6]: https://opensource.com/life/16/10/introduction-linux-filesystems
|
||||
[7]: https://chmodcommand.com/chmod-644/
|
||||
[8]: https://chmodcommand.com/chmod-640/
|
||||
[9]: http://man7.org/linux/man-pages/man5/systemd.service.5.html
|
||||
[10]: tmp.bYMHU00BHs#resources
|
||||
[11]: https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/
|
||||
[12]: https://docs.fedoraproject.org/en-US/quick-docs/understanding-and-administering-systemd/index.html
|
||||
[13]: https://fedoraproject.org/wiki/SysVinit_to_Systemd_Cheatsheet
|
||||
[14]: http://Freedesktop.org
|
||||
[15]: http://www.freedesktop.org/wiki/Software/systemd
|
||||
[16]: http://Linux.com
|
||||
[17]: https://www.linux.com/training-tutorials/more-systemd-fun-blame-game-and-stopping-services-prejudice/
|
||||
[18]: http://0pointer.de/blog/projects/systemd.html
|
||||
[19]: http://0pointer.de/blog/projects/systemd-for-admins-1.html
|
||||
[20]: http://0pointer.de/blog/projects/systemd-for-admins-2.html
|
||||
[21]: http://0pointer.de/blog/projects/systemd-for-admins-3.html
|
||||
[22]: http://0pointer.de/blog/projects/systemd-for-admins-4.html
|
||||
[23]: http://0pointer.de/blog/projects/three-levels-of-off.html
|
||||
[24]: http://0pointer.de/blog/projects/changing-roots
|
||||
[25]: http://0pointer.de/blog/projects/blame-game.html
|
||||
[26]: http://0pointer.de/blog/projects/the-new-configuration-files.html
|
||||
[27]: http://0pointer.de/blog/projects/on-etc-sysinit.html
|
||||
[28]: http://0pointer.de/blog/projects/instances.html
|
||||
[29]: http://0pointer.de/blog/projects/inetd.html
|
@ -0,0 +1,246 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Getting Started With Nano Text Editor [Beginner’s Guide])
|
||||
[#]: via: (https://itsfoss.com/nano-editor-guide/)
|
||||
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
|
||||
|
||||
Getting Started With Nano Text Editor [Beginner’s Guide]
|
||||
======
|
||||
|
||||
[Nano][1] is the default [terminal-based text editor][2] in Ubuntu and many other Linux distributions. Though it is less complicated to use than the likes of [Vim][3] and [Emacs][4], it doesn’t mean Nano cannot be overwhelming to use.
|
||||
|
||||
In this beginner’s guide, I’ll show you how to use the Nano text editor. I am also going to include a downloadable PDF cheat sheet at the end of the article so that you can refer to it for practicing and mastering Nano editor commands.
|
||||
|
||||
If you are just interested in a quick summary of Nano keyboard shortcuts, please expand the next section.
|
||||
|
||||
Essential Nano keyboard shortcuts (click to expand)
|
||||
|
||||
**Shortcut** | **Description**
|
||||
---|---
|
||||
nano filename | Open file for editing in Nano
|
||||
Arrow keys | Move cursor up, down, left and right
|
||||
Ctrl+A, Ctrl+E | Move cursor to start and end of the line
|
||||
Ctrl+Y/Ctrl+V | Move page up and down
|
||||
Ctrl+_ | Move cursor to a certain location
|
||||
Alt+A and then use arrow key | Set a marker and select text
|
||||
Alt+6 | Copy the selected text
|
||||
Ctrl+K | Cut the selected text
|
||||
Ctrl+U | Paste the selected text
|
||||
Ctrl+6 | Cancel the selection
|
||||
Ctrl+K | Cut/delete entire line
|
||||
Alt+U | Undo last action
|
||||
Alt+E | Redo last action
|
||||
Ctrl+W, Alt+W | Search for text, move to next match
|
||||
Ctrl+\ | Search and replace
|
||||
Ctrl+O | Save the modification
|
||||
Ctrl+X | Exit the editor
|
||||
|
||||
### How to use Nano text editor
|
||||
|
||||
![][5]
|
||||
|
||||
I presume that you have Nano editor installed on your system already. If not, please your distribution’s package manager to install it.
|
||||
|
||||
#### Getting familiar with the Nano editor interface
|
||||
|
||||
If you’ve ever [used Vim][6] or Emacs, you’ll notice that using Nano is a lot simpler. You can start writing or editing text straightaway.
|
||||
|
||||
Nano editor also shows important keyboard shortcuts you need to use for editing at the bottom of the editor. This way you won’t get stuck at [exiting the editor like Vim][7].
|
||||
|
||||
The wider your terminal window, the more shortcuts it shows.
|
||||
|
||||
![Nano Editor Interface][8]
|
||||
|
||||
You should get familiar with the symbols in Nano.
|
||||
|
||||
* The caret symbol (^) means Ctrl key
|
||||
* The M character mean the Alt key
|
||||
|
||||
|
||||
|
||||
When it says “^X Exit”, it means to use Ctrl+X keys to exit the editor. When it says “M-U Undo”, it means use Alt+U key to undo your last action.
|
||||
|
||||
#### Open or create a file for editing in Nano
|
||||
|
||||
You can open a file for editing in Nano like this:
|
||||
|
||||
```
|
||||
nano my_file
|
||||
```
|
||||
|
||||
If the file doesn’t exist, it will still open the editor and when you exit, you’ll have the option for saving the text to my_file.
|
||||
|
||||
You may also open a new file without any name (like new document) with Nano like this:
|
||||
|
||||
```
|
||||
nano
|
||||
```
|
||||
|
||||
#### Basic editing
|
||||
|
||||
You can start writing or modifying the text straightaway in Nano. There are no special insert mode or anything of that sort. It is almost like using a regular text editor, at least for writing and editing.
|
||||
|
||||
As soon as you modify anything in the file, you’ll notice that it reflects this information on the editor.
|
||||
|
||||
![][9]
|
||||
|
||||
Nothing is saved immediately to the file automatically unless you explicitly do so. When you exit the editor using Ctrl+X keyboard shortcut, you’ll be asked whether you want to save your modified text to the file or not.
|
||||
|
||||
#### Moving around in the editor
|
||||
|
||||
Mouse click doesn’t work here. Use the arrow keys to move up and down, left and right.
|
||||
|
||||
You can use the Home key or Ctrl+A to move to the beginning of a line and End key or Ctrl+E to move to the end of a line. Ctrl+Y/Page Up and Ctrl+V/Page Down keys can be used to scroll by pages.
|
||||
|
||||
If you want to go a specific location like last line, first line, to a certain text, use Ctrl+_ key combination. This will show you some options you can use at the bottom of the editor.
|
||||
|
||||
![Jump to a specific line in Nano][10]
|
||||
|
||||
#### Cut, copy and paste in Nano editor
|
||||
|
||||
If you don’t want to spend too much time remembering the shortcuts, use mouse.
|
||||
|
||||
Select a text with mouse and then use the right click menu to copy the text. You may also use the Ctrl+Shift+C [keyboard shortcut in Ubuntu][11] terminal. Similarly, you can use the right click and select paste from the menu or use the Ctrl+Shift+V key combination.
|
||||
|
||||
**Nano specific shortcuts for copy and pasting**
|
||||
|
||||
Nano also provides its own shortcuts for cutting and pasting text but that could become confusing for beginners.
|
||||
|
||||
Move your cursor to the beginning of the text you want to copy. Press Alt+A to set a marker. Now use the arrow keys to highlight the selection. Once you have selected the desired text, you can Alt+6 key to copy the selected text or use Ctrl+K to cut the selected text. Use Ctrl+6 to cancel the selection.
|
||||
|
||||
Once you have copied or cut the selected text, you can use Ctrl+U to paste it.
|
||||
|
||||
![][12]
|
||||
|
||||
#### Delete text or lines in Nano
|
||||
|
||||
There is no dedicated option for deletion in Nano. You may use the Backspace or Delete key to delete one character at a time. Press them repeatedly or hold them to delete multiple characters.
|
||||
|
||||
You can also use the Ctrl+K keys that cuts the entire line. If you don’t paste it anywhere, it’s as good as deleting a line.
|
||||
|
||||
If you want to delete multiple lines, you may use Ctrl+K on all of them one by one.
|
||||
|
||||
Another option is to use the marker (Ctrl+a). Set the marker and move the arrow to select a portion of text. Use Ctrl+K to cut the text. No need to paste it and the selected text will be deleted (in a way).
|
||||
|
||||
#### Undo or redo your last action
|
||||
|
||||
Cut the wrong line? Pasted the wrong text selection? It’s easy to make such silly mistakes and it’s easy to correct those silly mistakes.
|
||||
|
||||
You can undo and redo your last actions using:
|
||||
|
||||
* Alt+U : Undo
|
||||
* Alt +E : Redo
|
||||
|
||||
|
||||
|
||||
You can repeat these key combinations to undo or redo multiple times.
|
||||
|
||||
#### Search and replace
|
||||
|
||||
If you want to search for a certain text, use Ctrl+W and then enter the term you want to search and press enter. The cursor will move to the first match. To go to the next match, use Alt+W keys.
|
||||
|
||||
![][13]
|
||||
|
||||
By default, the search is case-insensitive. You can also use regex for the search terms.
|
||||
|
||||
If you want to replace the searched term, use Ctr+\ keys and then enter the search term and press enter key. Next it will ask for the term you want to replace the searched items with.
|
||||
|
||||
![][14]
|
||||
|
||||
The cursor will move to the first match and Nano will ask for your conformation for replacing the matched text. Use Y or N to confirm or deny respectively. Using either of Y or N will move to the next match. You may also use A to replace all matches.
|
||||
|
||||
![][15]
|
||||
|
||||
#### Save your file while editing (without exiting)
|
||||
|
||||
In a graphical editor, you are probable used to of saving your changes from time to time. In Nano, you can use Ctrl+O to save your changes you made to the file. It also works with a new, unnamed file.
|
||||
|
||||
![][16]
|
||||
|
||||
Nano actually shows this keyboard shortcut at the bottom but it’s not obvious. It says “^O Write Out” which actually means to use Ctrl+O (it is letter O, not number zero) to save your current work. Not everyone can figure that out.
|
||||
|
||||
In a graphical text editor, you probably use Ctrl+S to save your changes. Old habits die hard but it could cause trouble. Out of habit, if you accidentally press Ctrl+S to save your file, you’ll notice that the terminal freezes and you can do nothing.
|
||||
|
||||
If you accidentally press Ctrl+S press Ctrl+Q nothing can be more scary than a frozen terminal and losing the work.
|
||||
|
||||
#### Save and exit Nano editor
|
||||
|
||||
To exit the editor, press Ctrl+X keys. When you do that, it will give you the option to save the file, or discard the file or cancel the exit process.
|
||||
|
||||
![][17]
|
||||
|
||||
If you want to save the modified file as a new file (save as function in usual editors), you can do that as well. When you press Ctrl+X to exit and then Y to save the changes, it gives the option to which file it should save the changes. You can change the file name at this point.
|
||||
|
||||
You’ll need to have ‘write permission’ on the file you are editing if you want to save the modifications to the file.
|
||||
|
||||
#### Forgot keyboard shortcut? Use help
|
||||
|
||||
Like any other terminal based text editor, Nano relies heavily on keyboard shortcuts. Though it displays several useful shortcuts on the bottom of the editor, you cannot see all of them.
|
||||
|
||||
It is not possible to remember all the shortcuts, specially in the beginning. What you can do is to use the Ctrl+G keys to bring up the detailed help menu. The help menu lists all the keyboard shortcuts.
|
||||
|
||||
![][18]
|
||||
|
||||
#### Always look at the bottom of the Nano editor
|
||||
|
||||
If you are using Nano, you’ll notice that it displays important information at the bottom. This includes the keyboard shortcuts that will be used in the scenario. It also shows the last action you performed.
|
||||
|
||||
![][19]
|
||||
|
||||
If you get too comfortable with Nano, you can get more screen for editing the text by disabling the shortcuts displayed at the bottom. You can use Alt+X keys for that. I don’t recommend doing it, to be honest. Pressing Alt+X brings the shortcut display back.
|
||||
|
||||
### Download Nano cheatsheet [PDF]
|
||||
|
||||
There are a lot more shortcuts and editing options in Nano. I am not going to overwhelm you by mentioning them all.
|
||||
|
||||
Here’s a quick summary of the important Nano keyboard shortcuts you should rememeber. Download link is under the image.
|
||||
|
||||
![][20]
|
||||
|
||||
[Download Nano Cheat Sheet (free PDF)][21]
|
||||
|
||||
You can download the cheatsheet, print it and keep at your desk. It will help you in remembering and mastering the shortcuts.
|
||||
|
||||
I hope you find this beginner’s guide to Nano text editor helpful. If you liked it, please share it on Reddit, [Hacker News][22] or in various [Linux forums][23] you frequently visit.
|
||||
|
||||
I welcome your questions and suggestions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/nano-editor-guide/
|
||||
|
||||
作者:[Abhishek Prakash][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/abhishek/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.nano-editor.org/
|
||||
[2]: https://itsfoss.com/command-line-text-editors-linux/
|
||||
[3]: https://www.vim.org/
|
||||
[4]: https://www.gnu.org/software/emacs/
|
||||
[5]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/05/nano-editor-guide.png?ssl=1
|
||||
[6]: https://itsfoss.com/pro-vim-tips/
|
||||
[7]: https://itsfoss.com/how-to-exit-vim/
|
||||
[8]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/05/nano-editor-interface.png?ssl=1
|
||||
[9]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/05/nano-modified-text.png?ssl=1
|
||||
[10]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/05/nano-editor-jump-to-line.png?ssl=1
|
||||
[11]: https://itsfoss.com/ubuntu-shortcuts/
|
||||
[12]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/05/nano-editor-set-mark.png?ssl=1
|
||||
[13]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/05/nano-search-text.png?ssl=1
|
||||
[14]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/05/nano-editor-search-replace.png?ssl=1
|
||||
[15]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/05/nano-editor-search-replace-confirm.png?ssl=1
|
||||
[16]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/05/nano-editor-save-while-writing.png?ssl=1
|
||||
[17]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/05/nano-editor-save-and-exit.png?ssl=1
|
||||
[18]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/05/nano-editor-help-menu.png?ssl=1
|
||||
[19]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/05/nano-editor-hints.png?ssl=1
|
||||
[20]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/05/nano-cheatsheet.png?ssl=1
|
||||
[21]: https://itsfoss.com/wp-content/uploads/2020/05/Nano-Cheat-Sheet.pdf
|
||||
[22]: https://news.ycombinator.com/
|
||||
[23]: https://itsfoss.community/
|
@ -0,0 +1,198 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (How to configure your router using VTY shell)
|
||||
[#]: via: (https://opensource.com/article/20/5/vty-shell)
|
||||
[#]: author: (M Umer https://opensource.com/users/noisybotnet)
|
||||
|
||||
如何使用 VTY Shell 配置路由器
|
||||
======
|
||||
FRR(free range routing)给了你实现多种协议的选择。本指南将帮助你入门。
|
||||
![Multi-colored and directional network computer cables][1]
|
||||
|
||||
最近,我写了一篇文章,解释了如何使用 [Quagga][2] 路由套件实现开放式最短路径优先(OSPF)。可以使用多个软件套件代替 Quagga 来实现不同的路由协议。其中一种是 FRR。
|
||||
|
||||
### FRR
|
||||
|
||||
[FRR][3] 是一个路由软件套件,它衍生自 Quagga,并在 GNU GPL2 许可下分发。与 Quagga 一样,它为类 Unix 平台提供了所有主要路由协议的实现,例如 OSPF,路由信息协议 (RIP),边界网关协议 (BGP) 和中间系统到中间系统 (IS-IS)。
|
||||
|
||||
背后开发 Quagga 的一些公司,例如 Big Switch Networks、Cumulus、Open Source Routing 和 6wind,创建了 FRR 以改善 Quagga 的良好基础。
|
||||
|
||||
|
||||
#### 体系结构
|
||||
|
||||
FRR是一组守护程序,它们可以共同构建路由表。每个主协议都在其自己的守护程序中实现,并且这些守护程序与独立于协议的核心守护程序 Zebra 通信,后者提供内核路由表更新、接口查找以及不同路由协议之间路由的重新分配。每个特定协议的守护程序负责运行相关协议并根据交换的信息构建路由表。
|
||||
|
||||
![FRR architecture][4]
|
||||
|
||||
### VTY shell
|
||||
|
||||
[VTYSH][5] 是 FRR 路由引擎的集成 shell。它将每个守护程序中定义的所有 CLI 命令合并,并在单个 shell 中将它们呈现给用户。它提供了类似于 Cisco 的命令行模式,并且许多命令与 Cisco IOS 命令相似。CLI 有不同的模式,某些命令仅在特定模式下可用。
|
||||
|
||||
### 设置
|
||||
|
||||
在本教程中,我们将使用 FRR 配置动态路由来实现路由信息协议(RIP)。我们可以通过两种方式来做到这一点:在编辑器中编辑协议守护程序配置文件或使用 VTY Shell。在此例中,我们将使用 VTY shell。我们的设置包括两个名为 Alpha 和 Beta 的 CentOS 7.7 主机。这两台主机都有两个网络接口,并共享对 192.168.122.0/24 网络的访问。我们将广播 10.12.11.0/24 和 10.10.10.0/24 网络的路由。
|
||||
|
||||
**对于主机 Alpha:**
|
||||
|
||||
* eth0 IP: 192.168.122.100/24
|
||||
* Gateway: 192.168.122.1
|
||||
* eth1 IP: 10.10.10.12/24
|
||||
|
||||
|
||||
|
||||
**对于主机 Beta:**
|
||||
|
||||
* eth0 IP: 192.168.122.50/24
|
||||
* Gateway: 192.168.122.1
|
||||
* eth1 IP: 10.12.11.12/24
|
||||
|
||||
|
||||
|
||||
#### 安装软件包
|
||||
|
||||
首先,我们需要在两台主机上都安装 FRR 软件包。可以按照[官方 FRR 文档][6]中的说明进行操作。
|
||||
|
||||
#### 启用 IP 转发
|
||||
|
||||
对于路由,我们需要在两台主机上都启用 IP 转发,因为这将由 Linux 内核执行。
|
||||
|
||||
|
||||
```
|
||||
sysctl -w net.ipv4.conf.all.forwarding = 1
|
||||
|
||||
sysctl -w net.ipv6.conf.all.forwarding = 1
|
||||
sysctl -p
|
||||
```
|
||||
|
||||
#### 启用 RIPD 守护程序
|
||||
|
||||
安装后,所有配置文件将保存在 **/etc/frr** 目录中。 必须通过编辑 **/etc/frr/daemons** 文件显式启用守护程序。 该文件确定启动 FRR 服务时激活哪些守护程序。 要启用特定的守护程序,只需将相应的 “no” 改为 “yes”。 之后的服务重启将启动守护程序。
|
||||
|
||||
![FRR daemon restart][7]
|
||||
|
||||
#### 防火墙配置
|
||||
|
||||
由于 RIP 协议使用 UDP 作为传输协议,并被分配了 520 端口,因此我们需要在 `firewalld` 配置中允许该端口。
|
||||
|
||||
|
||||
```
|
||||
firewall-cmd --add-port=520/udp –permanent
|
||||
|
||||
firewalld-cmd -reload
|
||||
```
|
||||
|
||||
现在,我们可以使用以下命令启动 FRR 服务:
|
||||
|
||||
|
||||
```
|
||||
`systemctl start frr`
|
||||
```
|
||||
|
||||
#### 使用 VTY 进行配置
|
||||
|
||||
现在,我们需要使用 VTY Shell 配置 RIP。
|
||||
|
||||
在主机 Alpha 上:
|
||||
|
||||
|
||||
```
|
||||
[root@alpha ~]# vtysh
|
||||
|
||||
Hello, this is FRRouting (version 7.2RPKI).
|
||||
Copyright 1996-2005 Kunihiro Ishiguro, et al.
|
||||
|
||||
alpha# configure terminal
|
||||
alpha(config)# router rip
|
||||
alpha(config-router)# network 192.168.122.0/24
|
||||
alpha(config-router)# network 10.10.10.0/24
|
||||
alpha(config-router)# route 10.10.10.5/24
|
||||
alpha(config-router)# do write
|
||||
Note: this version of vtysh never writes vtysh.conf
|
||||
Building Configuration...
|
||||
Configuration saved to /etc/frr/ripd.conf
|
||||
Configuration saved to /etc/frr/staticd.conf
|
||||
alpha(config-router)# do write memory
|
||||
Note: this version of vtysh never writes vtysh.conf
|
||||
Building Configuration...
|
||||
Configuration saved to /etc/frr/ripd.conf
|
||||
Configuration saved to /etc/frr/staticd.conf
|
||||
alpha(config-router)# exit
|
||||
```
|
||||
|
||||
类似地,在主机 Beta 上:
|
||||
|
||||
|
||||
```
|
||||
[root@beta ~]# vtysh
|
||||
|
||||
Hello, this is FRRouting (version 7.2RPKI).
|
||||
Copyright 1996-2005 Kunihiro Ishiguro, et al.
|
||||
|
||||
beta# configure terminal
|
||||
beta(config)# router rip
|
||||
beta(config-router)# network 192.168.122.0/24
|
||||
beta(config-router)# network 10.12.11.0/24
|
||||
beta(config-router)# do write
|
||||
Note: this version of vtysh never writes vtysh.conf
|
||||
Building Configuration...
|
||||
Configuration saved to /etc/frr/zebra.conf
|
||||
Configuration saved to /etc/frr/ripd.conf
|
||||
Configuration saved to /etc/frr/staticd.conf
|
||||
beta(config-router)# do write memory
|
||||
Note: this version of vtysh never writes vtysh.conf
|
||||
Building Configuration...
|
||||
Configuration saved to /etc/frr/zebra.conf
|
||||
Configuration saved to /etc/frr/ripd.conf
|
||||
Configuration saved to /etc/frr/staticd.conf
|
||||
beta(config-router)# exit
|
||||
```
|
||||
|
||||
完成后,像下面这样检查两台主机路由:
|
||||
|
||||
|
||||
```
|
||||
[root@alpha ~]# ip route show
|
||||
default via 192.168.122.1 dev eth0 proto static metric 100
|
||||
10.10.10.0/24 dev eth1 proto kernel scope link src 10.10.10.12 metric 101
|
||||
10.12.11.0/24 via 192.168.122.50 dev eth0 proto 189 metric 20
|
||||
192.168.122.0/24 dev eth0 proto kernel scope link src 192.168.122.100 metric 100
|
||||
```
|
||||
|
||||
我们可以看到 Alpha 上的路由表通过 192.168.122.50 包含了 10.12.11.0/24 的条目,它是通过 RIP 提供的。类似地,在 Beta 上,该表通过 192.168.122.100 包含了 10.10.10.0/24 的条目。
|
||||
|
||||
|
||||
```
|
||||
[root@beta ~]# ip route show
|
||||
default via 192.168.122.1 dev eth0 proto static metric 100
|
||||
10.10.10.0/24 via 192.168.122.100 dev eth0 proto 189 metric 20
|
||||
10.12.11.0/24 dev eth1 proto kernel scope link src 10.12.11.12 metric 101
|
||||
192.168.122.0/24 dev eth0 proto kernel scope link src 192.168.122.50 metric 100
|
||||
```
|
||||
|
||||
### 总结
|
||||
|
||||
如你所见,设置和配置相对简单。 要增加复杂性,我们可以向路由器添加更多的网络接口,以为更多的网络提供路由。可以在编辑器中编辑配置文件来进行配置,但是使用 VTY Shell 在单个组合会话中为我们提供了所有 FRR 守护程序的前端。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/5/vty-shell
|
||||
|
||||
作者:[M Umer][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/noisybotnet
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/connections_wires_sysadmin_cable.png?itok=d5WqHmnJ (Multi-colored and directional network computer cables)
|
||||
[2]: https://opensource.com/article/20/4/quagga-linux
|
||||
[3]: https://en.wikipedia.org/wiki/FRRouting
|
||||
[4]: https://opensource.com/sites/default/files/uploads/frr_architecture.png (FRR architecture)
|
||||
[5]: http://docs.frrouting.org/projects/dev-guide/en/latest/vtysh.html
|
||||
[6]: http://docs.frrouting.org/projects/dev-guide/en/latest/building-frr-for-centos7.html
|
||||
[7]: https://opensource.com/sites/default/files/uploads/frr_daemon_restart.png (FRR daemon restart)
|
Loading…
Reference in New Issue
Block a user