我们要将一个脚本进行开机自启,本文主要介绍配置服务器 service 的方法。
Systemd 服务的内容主要分为三个部分,控制单元(unit)的定义、服务(service)的定义、以及安装部分。
Systemd 是系统启动和服务器守护进程管理器,负责在系统启动或运行时,激活系统资源,服务器进程和其它进程。
systemd 被设计用来改进sysvinit的缺点,它和 ubuntu 的 upstart 是竞争对手,预计会取代它们。systemd 的很多概念来源于苹果的 launchd 。创始人 Lennart 是 redhat 员工,但 systemd 不是 redhat 项目。
systemd 的目标是:尽可能启动更少进程;尽可能将更多进程并行启动。 systemd 尽可能减少对 shell 脚本的依赖。传统 sysvinit 使用 inittab 来决定运行哪些 shell 脚本,大量使用 shell 脚本被认为是效率低下无法并行的原因。 systemd 使用了 Linux 专属技术,不再顾及 POSIX 兼容,一度谣传 Debian 为了它的 BSD 项目将不会使用 systemd 。
注意:Wants 字段与 Requires 字段只涉及依赖关系,与启动顺序无关,默认情况下是同时启动。
注意:After 和 Before 字段只涉及启动顺序,不涉及依赖关系。
若Type不为oneshot,配置中ExecStart只能执行一条命令
配置中多个相同配置会选择最后一个,下面结果是 execstart2
[Service]
ExecStart = /bin/echo execstart1
ExecStart = /bin/echo execstart2
所有的启动设置之前,都可以加上一个连词号(-),表示”抑制错误”,即发生错误的时候,不影响其他命令的执行
EnvironmentFile = -/etc/sysconfig/aaaaaa
表示即使 /etc/sysconfig/aaaaaa 文件不存在,也不会抛出错误。
WantedBy:表示该服务所在的 Target(服务组)
首先,进入/usr/lib/systemd/system/
目录,新建服务脚本。
若没有该目录可自行建立。
cd /usr/lib/systemd/system/
sudo vim my_t265.service
然后按照上述规则写入脚本
[Unit]
...
[Service]
...
[Install]
...
设置自启动,实质就是在 /etc/systemd/system/multi-user.target.wants/ 添加服务文件的链接。
systemctl enable my_265.service
若代码无错误,会输出如下结果:
Created symlink /etc/systemd/system/multi-user.target.wants/my_t265.service → /lib/systemd/system/my_t265.service.
表示在执行$ sudo systemctl enable my_t265.service
命令以后,在/lib/systemd/system/
目录新建了一个名为 my_t265.service
的配置文件文件,并建立了一个链接文件 /etc/systemd/system/multi-user.target.wants/my_t265.service
链接到 /lib/systemd/system/my_t265.service
文件。
当系统启动时,会去寻找 /etc/systemd/system/multi-user.target.wants/ 目录下面的 XXX.service 配置文件去启动相应的进程。
执行以下命令
sudo systemctl start xxxx.service
输出结果示例
my_program.service - /home/pi/program fan_ctrl.py
Loaded: loaded (/lib/systemd/system/my_program.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2021-11-29 15:33:18 CST; 3s ago
Process: 4157 ExecStartPost=/bin/echo 123456 (code=exited, status=0/SUCCESS)
Main PID: 4156 (sudo)
Tasks: 2 (limit: 4599)
Memory: 3.5M
CGroup: /system.slice/my_program.service
├─4156 /usr/bin/sudo python3 /home/pi/program/fan_ctrl.py
└─4158 python3 /home/pi/program/fan_ctrl.py
11月 29 15:33:18 pi-virtual-machine systemd[1]: Starting /home/pi/program fan_ctrl.py...
11月 29 15:33:18 pi-virtual-machine echo[4157]: 123456
11月 29 15:33:18 pi-virtual-machine systemd[1]: Started /home/pi/program fan_ctrl.py.
11月 29 15:33:18 pi-virtual-machine sudo[4156]: root : TTY=unknown ; PWD=/ ; USER=root ; COMMAND=/usr/bin/python3 >
11月 29 15:33:18 pi-virtual-machine sudo[4156]: pam_unix(sudo:session): session opened for user root by (uid=0)
Loaded:配置文件的位置,是否设为开机启动
Active:running 表示正在运行
Main PID:主进程ID
Status:由应用本身提供的软件当前状态
CGroup:应用的所有子进程
日志块:应用的日志
运行以下代码
sudo systemctl status xxxx.service
输出结果示例
(Opencv4.5.3) ubuntu@ubuntu:~$ sudo systemctl status my_t265.service
● my_t265.service - My_T265 Service
Loaded: loaded (/lib/systemd/system/my_t265.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2022-05-14 21:52:44 CST; 1min 23s ago
Main PID: 861 (python3)
Tasks: 10 (limit: 9251)
CGroup: /system.slice/my_t265.service
└─861 /usr/bin/python3 /home/ubuntu/Desktop/code_coordinate/T265.py
May 14 21:54:10 ubuntu python3[861]: X: 0, Y: 0, Z: 0
May 14 21:54:10 ubuntu python3[861]: X: 0, Y: 0, Z: 0
May 14 21:54:10 ubuntu python3[861]: X: 0, Y: 0, Z: 0
May 14 21:54:10 ubuntu python3[861]: X: 0, Y: 0, Z: 0
May 14 21:54:10 ubuntu python3[861]: X: 0, Y: 0, Z: 0
May 14 21:54:10 ubuntu python3[861]: X: 0, Y: 0, Z: 0
May 14 21:54:10 ubuntu python3[861]: X: 0, Y: 0, Z: 0
May 14 21:54:10 ubuntu python3[861]: X: 0, Y: 0, Z: 0
May 14 21:54:10 ubuntu python3[861]: X: 0, Y: 0, Z: 0
May 14 21:54:10 ubuntu python3[861]: X: 0, Y: 0, Z: 0
[Unit]
Description = My_T265 Service
After = my_usb.service
[Service]
#Environment=SYSTEMD_LOG_LEVEL=debug
Type = simple
WorkingDirectory = /home/ubuntu/Desktop/code_coordinate
ExecStart = python3 /home/ubuntu/Desktop/code_coordinate/T265.py
Restart = always
[Install]
WantedBy = multi-user.target
想要在单个 Service 下执行多个ExecStart命令,必须将 Type 设置为 oneshot。
oneshot 顾名思义,打一枪换一个地方。所以这种服务类型就是启动,完成,没进程了。oneshot 与 simple 类似,不同之处在于, 只有在该服务的主服务进程退出之后,systemd 才会认为该服务启动完成,才会开始启动后继单元。 此种类型的服务通常需要设置 RemainAfterExit= 选项。 当 Type= 与 ExecStart= 都没有设置时, Type=oneshot 就是默认值。oneshot常用于如文件系统的检查与挂载等,只需在开机的时候执行一次。
树莓派开机重刷USB口
(Opencv4.5.3) ubuntu@ubuntu:/usr/lib/systemd/system$ cat my_usb.service
[Unity]
Description = restart USB
[Service]
Type = oneshot
ExecStart = sudo uhubctl -l 2 -a cycle -p 1-4
[Install]
WantedBy=multi-user.target
systemctl is-enabled servicename.service #查询服务是否开机启动
systemctl enable *.service #开机运行服务
systemctl disable *.service #取消开机运行
systemctl start *.service #启动服务
systemctl stop *.service #停止服务
systemctl restart *.service #重启服务
systemctl reload *.service #重新加载服务配置文件
systemctl status *.service #查询服务运行状态
# 重新加载配置文件
$ sudo systemctl daemon-reload
# 重启相关服务
$ sudo systemctl restart my_program.service
这里列举几个常用的方法,详细可看最后推荐资料。
Systemd被诟病的很多的点之一就是出现问题之后很难确认原因,其实在很早的时候systemd就提供了debug的方法,这里介绍常用的一种方式,并结合一个常见的很容易忽视的问题来进行说明。
#对象文件:
/etc/systemd/system.conf
#修改内容
LogLevel=debug
设定例
(Opencv4.5.3) ubuntu@ubuntu:~$ cat /etc/systemd/system.conf
# 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.
#
# Entries in this file show the compile time defaults.
# You can change settings by editing this file.
# Defaults can be restored by simply deleting this file.
#
# See systemd-system.conf(5) for details.
[Manager]
LogLevel=debug
#LogLevel=info
#LogTarget=journal-or-kmsg
#LogColor=yes
#LogLocation=no
#DumpCore=yes
#ShowStatus=yes
#CrashChangeVT=no
#CrashShell=no
#CrashReboot=no
#CtrlAltDelBurstAction=reboot-force
#CPUAffinity=1 2
#NUMAPolicy=default
#NUMAMask=
#RuntimeWatchdogSec=0
#RebootWatchdogSec=10min
#ShutdownWatchdogSec=10min
#KExecWatchdogSec=0
#WatchdogDevice=
#CapabilityBoundingSet=
#NoNewPrivileges=no
#SystemCallArchitectures=
#TimerSlackNSec=
#StatusUnitFormat=description
#DefaultTimerAccuracySec=1min
#DefaultStandardOutput=journal
#DefaultStandardError=inherit
#DefaultTimeoutStartSec=90s
#DefaultTimeoutStopSec=90s
#DefaultTimeoutAbortSec=
#DefaultRestartSec=100ms
#DefaultStartLimitIntervalSec=10s
#DefaultStartLimitBurst=5
#DefaultEnvironment=
#DefaultCPUAccounting=no
#DefaultIOAccounting=no
#DefaultIPAccounting=no
#DefaultBlockIOAccounting=no
#DefaultMemoryAccounting=yes
#DefaultTasksAccounting=yes
#DefaultTasksMax=
#DefaultLimitCPU=
#DefaultLimitFSIZE=
#DefaultLimitDATA=
#DefaultLimitSTACK=
#DefaultLimitCORE=
#DefaultLimitRSS=
#DefaultLimitNOFILE=1024:524288
#DefaultLimitAS=
#DefaultLimitNPROC=
#DefaultLimitMEMLOCK=
#DefaultLimitLOCKS=
#DefaultLimitSIGPENDING=
#DefaultLimitMSGQUEUE=
#DefaultLimitNICE=
#DefaultLimitRTPRIO=
#DefaultLimitRTTIME=
重启操作系统
(Opencv4.5.3) ubuntu@ubuntu:/usr/lib/systemd/system$ cat my_t265.service
[Unit]
Description = My_T265 Service
After = my_usb.service
[Service]
Environment=SYSTEMD_LOG_LEVEL=debug
Type = simple
WorkingDirectory = /home/ubuntu/Desktop/code_coordinate
ExecStart = python3 /home/ubuntu/Desktop/code_coordinate/T265.py
Restart = always
[Install]
WantedBy = multi-user.target
在此启动测试用的服务
sudo systemctl daemon-reload
sudo systemctl restart my_t265.service
使用 status 或者 journalctl 均可看到更加详细的输出结果。
(Opencv4.5.3) ubuntu@ubuntu:/usr/lib/systemd/system$ systemctl status my_t265
Warning: The unit file, source configuration file or drop-ins of my_t265.service changed on disk. Run 'systemctl daemon-reload' to reload units.
● my_t265.service - My_T265 Service
Loaded: loaded (/lib/systemd/system/my_t265.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2022-05-14 20:57:17 CST; 8s ago
Main PID: 2519 (python3)
Tasks: 4 (limit: 9251)
CGroup: /system.slice/my_t265.service
└─2519 /usr/bin/python3 /home/ubuntu/Desktop/code_coordinate/T265.py
May 14 20:57:17 ubuntu systemd[1]: Stopped My_T265 Service.
May 14 20:57:17 ubuntu systemd[1]: my_t265.service: Converting job my_t265.service/restart -> my_t265.service/start
May 14 20:57:17 ubuntu systemd[1]: my_t265.service: Failed to set 'blkio.weight' attribute on '/system.slice/my_t265.service' to '500': No such file or directory
May 14 20:57:17 ubuntu systemd[1]: my_t265.service: Passing 0 fds to service
May 14 20:57:17 ubuntu systemd[1]: my_t265.service: About to execute: /usr/bin/python3 /home/ubuntu/Desktop/code_coordinate/T265.py
May 14 20:57:17 ubuntu systemd[1]: my_t265.service: Forked /usr/bin/python3 as 2519
May 14 20:57:17 ubuntu systemd[1]: my_t265.service: Changed dead -> running
May 14 20:57:17 ubuntu systemd[1]: my_t265.service: Job 3488 my_t265.service/start finished, result=done
May 14 20:57:17 ubuntu systemd[1]: Started My_T265 Service.
May 14 20:57:17 ubuntu systemd[2519]: my_t265.service: Executing: /usr/bin/python3 /home/ubuntu/Desktop/code_coordinate/T265.py
(Opencv4.5.3) ubuntu@ubuntu:/usr/lib/systemd/system$ journalctl -u my_t265
-- Logs begin at Thu 2022-04-14 20:00:41 CST, end at Sat 2022-05-14 20:58:14 CST. --
May 14 18:23:40 ubuntu systemd[1]: Started My_T265 Service.
May 14 18:24:51 ubuntu python3[766]: Traceback (most recent call last):
May 14 18:24:51 ubuntu python3[766]: File "/home/ubuntu/Desktop/code_coordinate/T265.py", line 11, in <module>
May 14 18:24:51 ubuntu python3[766]: pipe.start(cfg)
May 14 18:24:51 ubuntu python3[766]: RuntimeError: No device connected
May 14 18:24:52 ubuntu systemd[1]: my_t265.service: Main process exited, code=exited, status=1/FAILURE
May 14 18:24:52 ubuntu systemd[1]: my_t265.service: Failed with result 'exit-code'.
May 14 18:24:52 ubuntu systemd[1]: my_t265.service: Scheduled restart job, restart counter is at 1.
May 14 18:24:52 ubuntu systemd[1]: Stopped My_T265 Service.
May 14 18:24:52 ubuntu systemd[1]: Started My_T265 Service.
May 14 18:25:33 ubuntu python3[1052]: Traceback (most recent call last):
May 14 18:25:33 ubuntu python3[1052]: File "/home/ubuntu/Desktop/code_coordinate/T265.py", line 11, in <module>
May 14 18:25:33 ubuntu python3[1052]: pipe.start(cfg)
May 14 18:25:33 ubuntu python3[1052]: RuntimeError: No device connected
May 14 18:25:33 ubuntu systemd[1]: my_t265.service: Main process exited, code=exited, status=1/FAILURE
May 14 18:25:33 ubuntu systemd[1]: my_t265.service: Failed with result 'exit-code'.
May 14 18:25:34 ubuntu systemd[1]: my_t265.service: Scheduled restart job, restart counter is at 2.
May 14 18:25:34 ubuntu systemd[1]: Stopped My_T265 Service.
May 14 18:25:34 ubuntu systemd[1]: Started My_T265 Service.
May 14 18:26:15 ubuntu python3[1092]: Traceback (most recent call last):
May 14 18:26:15 ubuntu python3[1092]: File "/home/ubuntu/Desktop/code_coordinate/T265.py", line 11, in <module>
May 14 18:26:15 ubuntu python3[1092]: pipe.start(cfg)
May 14 18:26:15 ubuntu python3[1092]: RuntimeError: No device connected
May 14 18:26:15 ubuntu systemd[1]: my_t265.service: Main process exited, code=exited, status=1/FAILURE
May 14 18:26:15 ubuntu systemd[1]: my_t265.service: Failed with result 'exit-code'.
May 14 18:26:15 ubuntu systemd[1]: my_t265.service: Scheduled restart job, restart counter is at 3.
May 14 18:26:15 ubuntu systemd[1]: Stopped My_T265 Service.
May 14 18:26:15 ubuntu systemd[1]: Started My_T265 Service.
May 14 18:26:25 ubuntu python3[1344]: X: 0, Y: 0, Z: 0
May 14 18:26:25 ubuntu python3[1344]: X: 0, Y: 0, Z: 0
May 14 18:26:25 ubuntu python3[1344]: X: 0, Y: 0, Z: 0
May 14 18:26:25 ubuntu python3[1344]: X: 0, Y: 0, Z: 0
May 14 18:26:25 ubuntu python3[1344]: X: 0, Y: 0, Z: 0
systemctl get-default
multi-user.target 为命令行模式
graphical.target 为图形模式
systemctl list-dependencies multi-user.target
systemctl isolate shutdown.target
shutdown.target 就是关机状态
常用的 Target 有两个:一个是 multi-user.target,表示多用户命令行状态;另一个是 graphical.target,表示图形用户状态,它依赖于 multi-user.target。
>>> systemctl set-default graphical.target #图形模式
>>> systemctl set-default multi-user.target #命令行模式
17.3 systemctl 针对 service 类型的配置文件 | 鸟哥的 Linux 私房菜:基础学习篇 第四版
systemd.service 中文手册
systemd-analyze
树莓派(Debian)配置自定义 Service 实现开机自启
树莓派4B Ubuntu 21.04 开机自动运行 python 脚本
Ubuntu20.04查看开机自启动及其设置开机自启(设置rc.local)
编写systemd service文件