ubuntu@ip-xxxx:/sbin$ ls -lah | grep init lrwxrwxrwx 1 root root 20 Mar 20 14:32 init -> /lib/systemd/systemd如果我们更近一步研究 init,我们可以看到它其实只是一个指向 /lib/systemd/systemd 的符号链接。所以实际上,所有的进程都是由 Systemd 运行的。
import ( "fmt" "time" ) func main() { for { fmt.Println("Hello World") time.Sleep(1 * time.Second) } }代码和可执行文件位于我的主目录中。
ubuntu@ip-xxxx:~/hello-world$ ls go.mod hello-world main.go让我们运行一下吧。
ubuntu@ip-xxxx:~/hello-world$ ./hello-world Hello World Hello World Hello World ...当它运行时,我们可以在单独的选项卡中打开 htop。
[Unit] Description=Hello World Service [Service] ExecStart=/home/ubuntu/hello-world/hello-world [Install] WantedBy=multi-user.target这里最引人注目的是 ExecStart,它告诉 Systemd 如何启动我们的服务。WantedBy 使我们可以设置程序运行所需的依赖关系。我们可以用它来声明另一个服务,但声明一个目标也很常见。
目标是单元的组,经常被用来指定你可能希望你的系统处于的某个状态,类似于 Unix 中的运行级别。在这种情况下,设置 multi-user.target 确保系统处于可以进行多用户交互的状态。在这里声明它就是告诉 Systemd,当它达到多用户目标状态时,应启动我们的 hello-world 服务。
ubuntu@ip-xxxx:~$ sudo systemctl list-dependencies multi-user.target multi-user.target ● ├─apport.service ● ├─chrony.service ● ├─console-setup.service ● ├─cron.service ● ├─dbus.service ○ ├─dmesg.service ○ ├─e2scrub_reap.service ○ ├─ec2-instance-connect.service ○ ├─grub-common.service ○ ├─grub-initrd-fallback.service ○ ├─hibinit-agent.service ○ ├─irqbalance.service ○ ├─lxd-agent.service ● ├─networkd-dispatcher.service ○ ├─open-vm-tools.service ● ├─plymouth-quit-wait.service ● ├─plymouth-quit.service ....为了节省空间,这里的输出被截断了,但你应该明白这是什么意思。注意,我们还没看到我们的 hello-world 程序列出来。我们马上就会看到的。
systemctl daemon-reload这会导致 Systemd 重新读取所有单元文件。现在 Systemd 了解了我们的单元,我们可以检查服务的状态。
# 堆代码 duidaima.com ubuntu@ip-xxxx:/etc/systemd/system$ sudo systemctl status hello-world ○ hello-world.service - Hello World Service Loaded: loaded (/etc/systemd/system/hello-world.service; enabled; vendor preset: enabled) Active: inactive (dead)目前,我们的服务处于非活动状态。让我们启动它,然后再次检查状态。
ubuntu@ip-xxxx:/etc/systemd/system$ sudo systemctl status hello-world ● hello-world.service - Hello World Service Loaded: loaded (/etc/systemd/system/hello-world.service; enabled; vendor preset: enabled) Active: active (running) since Thu 2023-07-20 20:51:37 UTC; 14s ago Main PID: 179038 (hello-world) Tasks: 3 (limit: 1141) Memory: 564.0K CPU: 3ms CGroup: /system.slice/hello-world.service └─179038 /home/ubuntu/hello-world/hello-world Jul 20 20:51:42 ip-xxxx hello-world[179038]: Hello World Jul 20 20:51:43 ip-xxxx hello-world[179038]: Hello World Jul 20 20:51:44 ip-xxxx hello-world[179038]: Hello World Jul 20 20:51:45 ip-xxxx hello-world[179038]: Hello World Jul 20 20:51:46 ip-xxxx hello-world[179038]: Hello World Jul 20 20:51:47 ip-xxxx hello-world[179038]: Hello World Jul 20 20:51:48 ip-xxxx hello-world[179038]: Hello World Jul 20 20:51:49 ip-xxxx hello-world[179038]: Hello World Jul 20 20:51:50 ip-xxxx hello-world[179038]: Hello World Jul 20 20:51:51 ip-xxxx hello-world[179038]: Hello World注意状态是如何从非激活(死亡)转变为激活(运行)。同时,也要注意,我们在状态信息下方获取到了日志的最后十行,这非常酷。我们再次查看 htop,并查看我们的 hello-world 进程在树视图中的显示位置。
ubuntu@ip-xxxx:~$ sudo systemctl list-dependencies multi-user.target multi-user.target ● ├─apport.service ● ├─chrony.service ● ├─console-setup.service ● ├─cron.service ● ├─dbus.service ○ ├─dmesg.service ○ ├─e2scrub_reap.service ○ ├─ec2-instance-connect.service ○ ├─grub-common.service ○ ├─grub-initrd-fallback.service ● ├─hello-world.service ○ ├─hibinit-agent.service ○ ├─irqbalance.service嘿,看看这,列表中的第 11 个就是我们的 hello-world.service!太好了。现在我们的服务已经在后台运行了。如果我们把它关掉会发生什么呢?
ubuntu@ip-xxxx:~$ sudo kill 179038正如我们所期望的,我们的单位变得不活跃。我们还可以在日志中看到它被停用的位置。
○ hello-world.service - Hello World Service Loaded: loaded (/etc/systemd/system/hello-world.service; enabled; vendor preset: enabled) Active: inactive (dead) since Mon 2023-07-24 19:18:25 UTC; 1min 41s ago Process: 179038 ExecStart=/home/ubuntu/hello-world/hello-world (code=killed, signal=TERM) Main PID: 179038 (code=killed, signal=TERM) CPU: 39.210s Jul 24 19:18:18 ip-xxxx hello-world[179038]: Hello World Jul 24 19:18:19 ip-xxxx hello-world[179038]: Hello World Jul 24 19:18:20 ip-xxxx hello-world[179038]: Hello World Jul 24 19:18:21 ip-xxxx hello-world[179038]: Hello World Jul 24 19:18:22 ip-xxxx hello-world[179038]: Hello World Jul 24 19:18:23 ip-xxxx hello-world[179038]: Hello World Jul 24 19:18:24 ip-xxxx hello-world[179038]: Hello World Jul 24 19:18:25 ip-xxxx hello-world[179038]: Hello World Jul 24 19:18:25 ip-xxxx systemd[1]: hello-world.service: Deactivated successfully. Jul 24 19:18:25 ip-xxxx systemd[1]: hello-world.service: Consumed 39.210s CPU time.但如果我们希望服务一直在运行呢?在这种情况下,我们可以告诉 Systemd,当服务停止时,应该重新启动它。我们需要做的就是更新我们的单元文件。
[Unit] Description=Hello World Service [Service] ExecStart=/home/ubuntu/hello-world/hello-world Restart=always [Install] WantedBy=multi-user.target现在让我们重新启动我们的服务。
_ubuntu@ip-xxxx:~$ sudo systemctl start hello-world Warning: The unit file, source configuration file or drop-ins of hello-world.service changed on disk. Run 'systemctl daemon-reload' to reload units.似乎 Systemd 检测到我们的文件已更改。这很酷。我们只需按照错误中的说明让 Systemd 重新读取单元文件即可。
_ubuntu@ip-xxxx:~$ sudo systemctl restart hello-world现在,如果你再次检查状态,它应该处于活动状态。那么我们就杀掉它吧。
ubuntu@ip-xxxx:~$ sudo kill 190646然后再次检查状态。虽然服务仍然处于活动状态,但这是因为 Systemd 在我们检查状态和发现它已停用之前,就已经将其快速重新启动了。但无需担忧,因为我们可以直接从日志中看到单元何时被停止以及何时重新启动。
ubuntu@ip-xxxx:~$ sudo systemctl status hello-world ● hello-world.service - Hello World Service Loaded: loaded (/etc/systemd/system/hello-world.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2023-07-24 19:43:23 UTC; 2s ago Main PID: 190658 (hello-world) Tasks: 3 (limit: 1141) Memory: 572.0K CPU: 1ms CGroup: /system.slice/hello-world.service └─190658 /home/ubuntu/hello-world/hello-world Jul 24 19:43:23 ip-xxxx systemd[1]: hello-world.service: Scheduled restart job, restart counter is at 1. Jul 24 19:43:23 ip-xxxx systemd[1]: Stopped Hello World Service. Jul 24 19:43:23 ip-xxxx hello-world[190658]: Hello World Jul 24 19:43:23 ip-xxxx systemd[1]: Started Hello World Service. Jul 24 19:43:24 ip-xxxx hello-world[190658]: Hello World Jul 24 19:43:25 ip-xxxx hello-world[190658]: Hello World这只是我们开始利用 Systemd 在单元文件中配置的一小部分。我们还可以为我们的服务设定资源限制,配置套接字,设定文件权限等等。
journalctl -u hello-world --since "2023-07-25 12:00:00" --until "2023-07-25 18:00:00"