Linux开机启动配置文件SYSTEMD UNIT文件
开机启动的配置方式有多种,这里只介绍下通过systemctl方式启动,大部分都是翻译自Redhat官方文档。其他方式的启动自行查阅,现在我的强迫症越来越严重了,不舒服的东西要统统排斥~~!
References:
- https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/system_administrators_guide/sect-managing_services_with_systemd-unit_files Redhat文档
- https://wiki.archlinux.org/index.php/systemd_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87) ArchLinux文档
- https://www.raspberrypi.org/documentation/linux/usage/systemd.md 树莓派文档
- https://www.freedesktop.org/wiki/Software/systemd/ systemd介绍
- https://www.dynacont.net/documentation/linux/Useful_SystemD_commands/ 不同启动方式的简单比较
- http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-commands.html 阮一峰文章
其实之前也是查阅过各种各样的文章,但一直没有一个清晰的概念。这次看了官方文档之后,终于有些明白了,于是分享(估计也没人看,呜呜~~)一下。
systemd是一套Linux系统的基本构建块。它提供了一个系统和服务管理器,它以PID 1运行并启动系统的其余部分。它是一个系统守护进程(system daemon),在Unix/Linux下,它们是小写的,后缀为小写d。由于systemd管理系统(manages the system),因此称为systemd。就这么简单。
首先来说下使用systemd之后控制程序的方式:
$ sudo systemctl start foo.service 启动程序
$ sudo systemctl stop foo.service 停止程序
$ sudo systemctl enable foo.service 设置程序开机启动
$ sudo systemctl disable foo.service 禁止程序开机自启
$ sudo systemctl restart foo.service 重启程序
$ sudo systemctl status foo.service 查看程序运行状态
$ sudo systemctl is-enabled foo.service; echo $? 查看程序是否设置为开机自启,0-enabled 1-disabled
命令最后的.service可以省略不写。下面说明怎么设置开机启动:
创建一个service
创建一个如下的.service文件,比如
foo.service
[Unit] Description=My service After=network.target [Service] ExecStart=/usr/bin/python3 -u main.py WorkingDirectory=/home/pi/myscript StandardOutput=inherit StandardError=inherit Restart=always User=pi [Install] WantedBy=multi-user.target
在这个例子中,service将会在工作目录
/home/pi/myscript
运行python3,目录中应该包含文件main.py
。但是不仅限于python程序,只要将ExecStart后改成任何你想运行的程序或脚本都可以。配置文件具体内容在下面会介绍。移动文件
将这个.service文件以root身份移动到/etc/systemd/system
,例如$ sudo cp foo.service /etc/systemd/system/foo.service
- 使用service
移动之后就可以通过上文的控制命令启动或者停止service了。
配置文件的详细比较复杂,如果需要很细节的配置还是要查阅官方文档,没什么比官方文档更完整的了。下文摘取一些个人人文比较常用或者重要的说明一下:
文件结构:
name | Description |
---|---|
[Unit] | 包含不依赖于Unit类型的通用选项。这些选项提供Unit描述,指定Unit的行为,并设置与其他Unit的依赖关系。 |
[unit type] | 如果Unit具有特定类型的指令,则这些指令将按照以单元类型命名的部分进行分组。例如,service unit文件包含[Service]部分。 |
[Install] | 包含Unit使用systemctl enable和disable命令安装的信息。 |
- [Unit] 部分选项
Option | Description |
---|---|
Description | 一个有意义的描述,这段文本会显示在systemctl status命令后的输出中。 |
Documentation | 提供unit引用文档的URI列表。 |
After | 定义unit的启动顺序,只有在指定的unit启动之后,此unit才会启动。与Requires不同,After不会明确激活制定的unit(博主注:即在指定的unit启动后,不会主动触发此unit,等待系统在某个合适的时间自动触发)。Before选项和After相反。 |
Requires | 配置对其他的unit的依赖,列出的unit将会随着此unit一起被激活。有任何依赖的unit启动失败,此unit都不会被激活。 |
Wants | 配置比Requires弱的依赖。列出的unit即使未启动成功,也不会影响此unit的激活。这是建立自定义unit依赖的推荐方式。 |
Conflicts | 配置冲突,和Requires相反。 |
- [Service] 部分选项
Option | Description |
---|---|
Type | 配置unit进程的启动类型,类型将影响ExecStart的功能和相关选项。 类型应是如下之一: simple – 默认值,启动ExecStart的进程就是service的主进程。systemd认为该服务将立即启动。服务进程不会fork。如果该服务要启动其他服务,不要使用此类型启动,除非该服务是socket 激活型。 forking – 启动ExecStart的进程会生成一个子进程,子进程会成为service的主进程。启动完成后,父进程退出。使用此启动类型应同时指定PIDFile=,以便systemd能够跟踪服务的主进程。(博主注:Debian中通过apt安装的nginx启动配置就是fork方式) oneshot – 此类型和simple类似,但是会在启动后续unit之前退出。这一选项适用于只执行一项任务、随后立即退出的服务。可能需要同时设置RemainAfterExit=yes 使得systemd在服务进程退出之后仍然认为服务处于激活状态。 dbus – 此类型和simple类似,但后续unit仅在主进程获得D-Bus名称后启动。即当指定的BusName出现在DBus系统总线上时,systemd认为服务就绪。 notify – 此类型和simple类似,但是后续unit仅在sd_notify()函数发送通知消息后启动。即约定服务会在就绪后向systemd发送一个信号。 idle – 类似于simple,service二进制文件的实际执行被延后,直到所有的任务都处理完。这避免了状态输出和service的shell输出混合。 |
ExecStart | 指定 unit start 时需要执行的命令或脚本。ExecStartPre和ExecStartPost指定在ExecStart执行之前和之后需要执行的命令或脚本。Type=oneshot允许指定多条自定义命令,然后顺序执行。 |
ExecStop | 指定 unit stop 时需要执行的命令或脚本 |
ExecReload | 指定当 unit reload 时需要执行的命令或脚本。 |
Restart | 启用此选项后,service将在进程退出后重新启动,但通过systemctl命令停止的除外。 |
RemainAfterExit | 如果设置为true,即使退出所有进程,该service也会被视为激活状态。默认值为false,当设置Type=oneshot时,此选项特别有用。 |
- [Install] 部分选项
Option | Description |
---|---|
Alias | 为unit提供以空格分隔的别名列表。大部分的systemctl命令,除了systemctl enable,可以使用别名而不是实际的unit名字。 |
RequiredBy | 依赖于此unit的列表。当此unit设置为开机启动时,RequiredBy列表中的unit会增加一个对此unit的Require依赖。 |
WantedBy | 弱依赖于此unit的列表。当此unit设置为开机启动时,WantedBy列表中的unit会增加一个对此unit的Want依赖。 |
Also | 指定要与此unit一起安装或卸载的unit。 |
DefaultInstance | 仅限已实例化的unit,此选项指定开机启动unit的默认实例。详见:“Working with Instantiated Units” |
手动翻译还是有点累,和文档比起来很少,但是总的来说常用的都包含了,这里感谢Arch Linux,文档写的太全了,基本只要看文档就能解决问题,而且汉化很不错,看起来轻松加愉快。
因为实际使用基本不会全部选项都用到,下面给出一个我自己用的模板供参考:
[Unit]
Description=My service # 描述
After=network.target # 在网络模块启动之后,启动此service,关于target参考Linux的运行级别
[Service]
Type=idle # 启动类型,在系统启动工作完成后启动
ExecStart=/usr/bin/python3 -u main.py # 执行程序
WorkingDirectory=/home/pi/myscript # 工作目录 程序将会在此目录下执行
StandardOutput=inherit # 标准输出 继承自系统
StandardError=inherit # 标准错误输出 继承自系统
Restart=always # 自动重启
RestartSec=60 # 自动重启前等待时间
[Install]
WantedBy=multi-user.target # 该服务所在的target