Ubuntu下开机自启动脚本 init supervisor systemd

引言:在linux的使用过程中,我们经常会碰到需要将某个自定义的应用程序设置为开机自启动、批量管理、出错重启等,今天我们就Ubuntu下软件的自启动相关只是做一个汇总。

首先,Ubuntu下开机自启动管理方法有多种,比如基于 1) init 、2) supervisor、 3) systemd

initsupervisorsystemd
性质系统层面Python 编写的应用程序系统管理
易用性★☆☆☆☆★★★★★★★★☆☆
稳定性---
依赖-

init

在centos5、centos6中,linux的启动一直采用init进程来进行管理。从centos7开始,放弃了采用init进程,从而使用systemd来代替init进程。
对于init进程来说有两个缺点:

  • 启动时间长。init进程是串行启动,只有前一个进程启动完,才会启动下一个进程。
  • 启动脚本复杂。init进程只是执行启动脚本,不管其他事情。脚本需要自己处理各种情况,这往往使得脚本变得很长。

supervisor

优点

  • 任何用户都可以管理进程,不需要成为超级用户;
  • 具有良好的web界面来管理流程;
  • 适用于任何系统发行版,无论老版本还是新版本;
  • 更灵活的管理过程(例如:组,顺序优先级);

systemd

优点

  • 如今的发行版本都在系统中内置了 systemd,不需要额外的安装依赖。
  • 易于使用,没有学习曲线,可以像系统服务一样进行管理。

使用

unit

systemd管理着许多的资源,可以认为每一个资源就是unit(单元)unit由其相关的配置文件进行标识、识别和配置;文件中主要包含了系统服务、监听的socket、保存的快照以及其他与init相关的信息。这些配置文件主要保存在

/etc/systemd/system  # 存放系统启动的默认级别及启动的unit的软连接,优先级最高。

/run/systemd/system,# 系统执行过程中产生的服务脚本,优先级次之。

/usr/lib/systemd/system # 存放系统上所有的启动文件。优先级最低

Systemd 默认从目录 /etc/systemd/system/读取配置文件。但是,里面存放的大部分文件都是符号链接,指向目录 /usr/lib/systemd/system/,真正的配置文件存放在这个个目录。

unit常见类型
类型解释
service unit文件扩展名为.service ,用于定义系统服务
target unit文件扩展名为.target ,用于模拟实现"运行级别"
device unit文件扩展名为.device ,用于定义内核识别的设备
mount unit文件扩展名为.mount ,定义文件系统挂载点
sokect unit文件扩展名为.socket ,用于标识进程间通信用到的socket文件
snapshot unit文件扩展名为.snapshot ,用于实现管理系统快照
swap unit文件扩展名为.swap ,用于标识swap设备
automount unit文件扩展名为.automount ,文件系统自动挂载点设备
path unit文件扩展名为.path ,用于定义文件系统中的文件和目录
管控unit单元
启动、停止、重启等服务(service类型)
#启动httpd服务
[root@bogon ~]# systemctl start httpd.service

#停止httpd服务
[root@bogon ~]# systemctl stop httpd.service

#重启httpd服务
[root@bogon ~]# systemctl restart httpd.service

#条件式重启httpd服务(只会在服务运行的时候才会重启服务)
[root@bogon ~]# systemctl try-restart httpd.service

#重新加载httpd服务的配置文件
[root@bogon ~]# systemctl reload httpd.service

查看 Unit 的状态
[root@bogon ~]# systemctl status httpd.service
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
   Active: active (running) since 四 2019-04-18 22:09:06 CST; 1min 30s ago
     Docs: man:httpd(8)
           man:apachectl(8)
  Process: 8147 ExecReload=/usr/sbin/httpd $OPTIONS -k graceful (code=exited, status=0/SUCCESS)
 Main PID: 8136 (httpd)
   Status: "Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec"
   CGroup: /system.slice/httpd.service
           ├─8136 /usr/sbin/httpd -DFOREGROUND
           ├─8149 /usr/sbin/httpd -DFOREGROUND
           ├─8150 /usr/sbin/httpd -DFOREGROUND
           ├─8151 /usr/sbin/httpd -DFOREGROUND
           ├─8152 /usr/sbin/httpd -DFOREGROUND
           └─8153 /usr/sbin/httpd -DFOREGROUND

4月 18 22:09:06 bogon systemd[1]: Starting The Apache HTTP Server...
4月 18 22:09:06 bogon systemd[1]: Started The Apache HTTP Server.
4月 18 22:09:22 bogon systemd[1]: Reloading The Apache HTTP Server.
4月 18 22:09:22 bogon systemd[1]: Reloaded The Apache HTTP Server.

状态解释
active(running)正在运行
active(exited)服务执行一次退出,不在执行其它程序
active(waitting)等待运行的服务,在其它程序执行结束后可以运行
active(dead)未启动状态
#查看某服务当前激活与否的状态
[root@bogon ~]# systemctl is-active httpd.service
active

#查看所有已激活服务的状态
[root@bogon ~]# systemctl list-units --type service

#查看所有服务的状态
[root@bogon ~]# systemctl list-units --type service -all

#查看服务的依赖关系
[root@bogon ~]# systemctl list-dependencies httpd.service
查看、设置服务开机状态
#设置httpd服务开机启动
[root@bogon ~]# systemctl enable httpd.service
Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service.

#禁止httpd服务开机启动
[root@bogon ~]# systemctl disable httpd.service
Removed symlink /etc/systemd/system/multi-user.target.wants/httpd.service.

#查看httpd服务能否开机启动
[root@bogon ~]# systemctl is-enabled httpd.service
disabled

#禁止httpd服务设定为开机启动
[root@bogon ~]# systemctl mask httpd.service
Created symlink from /etc/systemd/system/httpd.service to /dev/null.

#取消禁止httpd服务开机启动
[root@bogon ~]# systemctl unmask httpd.service
Removed symlink /etc/systemd/system/httpd.service.
unit文件配置信息(service类型)
[root@bogon ~]# vim /usr/lib/systemd/system/httpd.service 
  1 [Unit]
  2 Description=The Apache HTTP Server
  3 After=network.target remote-fs.target nss-lookup.target
  4 Documentation=man:httpd(8)
  5 Documentation=man:apachectl(8)
  6 
  7 [Service]
  8 Type=notify
  9 EnvironmentFile=/etc/sysconfig/httpd
 10 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND
 11 ExecReload=/usr/sbin/httpd $OPTIONS -k graceful
 12 ExecStop=/bin/kill -WINCH ${MAINPID}
 13 # We want systemd to give httpd some time to finish gracefully, but still want
 14 # it to kill httpd after TimeoutStopSec if something went wrong during the
 15 # graceful stop. Normally, Systemd sends SIGTERM signal right after the
 16 # ExecStop, which would kill httpd. We are sending useless SIGCONT here to give
 17 # httpd time to finish.
 18 KillSignal=SIGCONT
 19 PrivateTmp=true
 20 
 21 [Install]
 22 WantedBy=multi-user.target
service unit信息组成

service类型的unit通常由以下三个字段组成:

[unit]:

定义与unit类型无关的通用选项;用于提供unit类型的描述信息、unit行为以及依赖关系。

unit常用选项:
Description:描述信息,意义性描述

After:定义unit的启动顺序。表示当前unit应该晚于哪些unit启动;其功能与before相反

Requies:依赖到的其它的unit,强依赖,如果被依赖的unit无法启动时,那么该unit无法激活

Wants:依赖到的其它的unit,弱依赖,如果被依赖的unit无法启动时,那么该unit也会正常激活

Conflicts:定义units间的冲突关系
[service]:

定义与特定类型相关的专用选项,只有service类型的unit才有这个字段

service字段的常用选项:
Type:用于定义影响ExecStart及相关参数的额功能的unit进程启动类型;具有以下几个值:

Type=simple:默认值,执行Execstart指定的命令,	启动主进程。systemd 认为该服务将立即启动,服务进程不会 fork。如果该服务要启动其他服务,不要使用此类型启动,除非该服务是 socket 激活型;

Type=forking:以fork方式从父进程创建子进程,父进程在创建后立即退出。systemd 认为当该服务进程 fork,且父进程退出后服务启动成功。对于常规的守护进程(daemon),除非你确定此启动方式无法满足需求, 使用此类型启动即可。使用此启动类型应同时指定 PIDFile=,以便 systemd 能够跟踪服务的主进程。

Type=oneshot:一次性进程,systemd会等当前服务退出后,在进行往下执行。这一选项适用于只执行一项任务、随后立即退出的服务。可能需要同时设置 RemainAfterExit = yes 使得 systemd 在服务进程退出之后仍然认为服务处于激活状态。

Type=dbus:当前服务通过d-bus启动。若以此方式启动,当指定的 BusName 出现在 DBus 系统总线上时,systemd 认为服务就绪。

Type=notify:当前服务启动完毕,会告知systemd,继续往下执行

Type=idle:若有其它服务执行完毕,当前服务才会执行

PIDFile:pid 文件路径;

PrivateTmp:True 表示给服务分配独立的临时空间;

ExecStart:启动当前服务的命令

ExecStartPre:启动当前服务之前执行的命令。启动前要做什么,比如测试一下配置文件是否正常;

ExecStartPost:启动当前服务之后执行的命令

ExecReload:重启当前服务时执行的命令

ExecStop:停止当前服务时执行的命令

ExecStopPost:停止当前服务之后执行的命令

RestartSec:自定义当前服务重启间隔的秒数

Restart:定义何种情况 Systemd 会自动重启当前服务,可能的值包括always(总是重启)、on-success、on-failure、on-abnormal、on-abort、on-watchdog

TimeoutSec:定义systemd停止当前服务等待的秒数

Environment:指定环境变量,如果不指定,想让它默认区使用系统环境变量会出错。格式:Environment='key1=val1' 'key2=val2'

RestartPreventExitStatus=143 137 SIGTERM SIGKILL  # 意思是退出情况只要符合以下4种情况中任意一种时候,则不再进行重启
1、exit code为143
2、exit code为137
3、信号为TERM
4、信号为KILL

User:指定用哪个用户

Group:指定用哪个组
[Install]:

通常是配置文件里的最后一个,主要用来定义如何启动以及是否开机自动启动,如下:

WantedBy:它的值是一个或多个Target,当前unit激活时,符号链接会放入/etc/systemd/system目录下面以 Target 名 + .wants后缀构成的子目录中。服务安装的用户模式,从字面上看,就是想要使用这个服务的有是谁?上文中使用的是:multi-user.target,就是指想要使用这个服务的目录是多用户。

RequiredBy:它的值是一个或多个 Target,当前 Unit 激活时,符号链接会放入/etc/systemd/system目录下面以 Target 名 + .required后缀构成的子目录中

Alias:当前 Unit 可用于启动的别名

Also:当前 Unit 激活(enable)时,会被同时激活的其他 Unit

注意:对于新创建的unit文件或修改了的unit文件,要通知systemd重载此配置文件

  # systemctl daemon-reload  

日志管理

systemd管理一切日志,用journalctl命令可以查看所有日志。日志的配置文件在/etc/journalctl.conf中

#查看所有日志(默认情况只保留本次启动的日志)
[root@bogon ~]# journalctl

#查看内核日志(不包含应用日志)
[root@bogon ~]# journalctl -k

# 查看系统本次启动的日志
$ sudo journalctl -b
$ sudo journalctl -b -0

# 查看上一次启动的日志(需更改设置)
$ sudo journalctl -b -1

# 查看指定时间的日志
$ sudo journalctl --since="2012-10-30 18:17:16"
$ sudo journalctl --since "20 min ago"
$ sudo journalctl --since yesterday
$ sudo journalctl --since "2015-01-10" --until "2015-01-11 03:00"
$ sudo journalctl --since 09:00 --until "1 hour ago"

# 显示尾部的最新10行日志
$ sudo journalctl -n

# 显示尾部指定行数的日志
$ sudo journalctl -n 20

# 实时滚动显示最新日志
$ sudo journalctl -f

# 查看指定服务的日志
$ sudo journalctl /usr/lib/systemd/systemd

# 查看指定进程的日志
$ sudo journalctl _PID=1

# 查看某个路径的脚本的日志
$ sudo journalctl /usr/bin/bash

# 查看指定用户的日志
$ sudo journalctl _UID=33 --since today

# 查看某个 Unit 的日志
$ sudo journalctl -u nginx.service
$ sudo journalctl -u nginx.service --since today

# 实时滚动显示某个 Unit 的最新日志
$ sudo journalctl -u nginx.service -f

# 合并显示多个 Unit 的日志
$ journalctl -u nginx.service -u php-fpm.service --since today

# 查看指定优先级(及其以上级别)的日志,共有8级
# 0: emerg
# 1: alert
# 2: crit
# 3: err
# 4: warning
# 5: notice
# 6: info
# 7: debug
$ sudo journalctl -p err -b

# 日志默认分页输出,--no-pager 改为正常的标准输出
$ sudo journalctl --no-pager

# 以 JSON 格式(单行)输出
$ sudo journalctl -b -u nginx.service -o json

# 以 JSON 格式(多行)输出,可读性更好
$ sudo journalctl -b -u nginx.serviceqq
 -o json-pretty

# 显示日志占据的硬盘空间
$ sudo journalctl --disk-usage

# 指定日志文件占据的最大空间
$ sudo journalctl --vacuum-size=1G

# 指定日志文件保存多久
$ sudo journalctl --vacuum-time=1years

信号

当我们去重启、停止一个进程时,并不是真正的对进程进行处理。而是要对进程发出一个信号,来告知进程我们需要对其进行什么样的处理。
查看信号的命令:

[root@bogon ~]# trap -l 

[root@bogon ~]# kill -l

[root@bogon ~]# man 7 signal

常见进程信号:

进程信号信号名称解释
1SIGHUP该信号让进程立即关闭.然后重新读取配置文件之后重启
2SIGINT程序中止信号,用于中止前台进程。相当于输出 Ctrl+C 快捷键
3SIGQUIT与SIGINT类似,但由QUIT字符(通常是Ctrl+\)来控制。进程因收到SIGQUIT退出时会产生core文件,在这个意义上类似于一个程序错误信号
8SIGFPE在发生致命的算术运算错误时发出。不仅包括浮点运算错误,还包括溢出及除数为 0 等其他所有的算术运算错误
9SIGKILL用来立即结束程序的运行。本信号不能被阻塞、处理和忽略。般用于强制中止进程
14SIGALRM时钟定时信号,计算的是实际的时间或时钟时间。alarm 函数使用该信号
15SIGTERM正常结束进程的信号,kill 命令的默认信号。如果进程已经发生了问题,那么这 个信号是无法正常中止进程的,这时我们才会尝试 SIGKILL 信号,也就是信号 9
18SIGCONT该信号可以让暂停的进程恢复执行。本信号不能被阻断
19SIGSTOP该信号可以暂停前台进程,相当于输入 Ctrl+Z 快捷键。本信号不能被阻断

ref:
systemd vs supervisord
systemd
systemd实践: 依据情况自动重启服务【转】

看来总结还是不到位,参考这篇继续完善。init,service和systemctl的区别

推荐阅读:
[linux系统启动流程]​​​​​​​(https://blog.51cto.com/9124573/1710149)

system文档

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

或许,这就是梦想吧!

如果对你有用,欢迎打赏。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值