开机自启动
设置程序开机自启动
开机自启动项的实现在ubuntu以及linux操作系统中一般采用systemd;在docker中一般采用supervisor来实现。
systemd
systemd是Ubuntu系统中非常重要的一个组件,可以提高系统的稳定性、安全性和可维护性。具体的来看systemd是一种用于管理Linux操作系统的系统和服务的守护进程,具有非常重要的作用:
- 启动和停止服务:systemd可用于管理系统中运行的所有服务,包括网络、文件系统、进程和应用程序。
- 管理系统进程:systemd可以在系统启动时自动启动特定的进程,也可以监控进程的运行状态并在必要时重新启动它们。
- 控制系统挂起和恢复:systemd可以监控系统的状态并在需要时进行挂起、休眠或恢复操作。
- 日志记录和故障排除:systemd提供了一个统一的日志系统,可以轻松地查看和分析系统日志,有助于诊断和解决故障。
- 定时任务管理:systemd的timer单元可以执行定时任务,比如定期备份系统数据等。
设置Python/Cpp程序在系统开机后自动启动
要在Ubuntu系统下将Python程序设置为开机自启动并在后台运行,可以按照以下步骤操作:
创建一个shell脚本文件
在Ubuntu系统中,可以使用sudo nano命令创建一个shell脚本文件,例如:
sudo nano /usr/local/bin/myprogram.sh
在打开的文本编辑器中,输入以下内容:
- 一个使用服务开机后自动启动python程序的例子
#!/bin/bash
/usr/bin/python3 /path/to/myprogram.py &
# /usr/bin/python3 : 表示Python解释器的路径,
# /path/to/myprogram.py : 表示Python程序的路径。
# & : 在脚本末尾添加一个&符号可以让程序在后台运行
给shell脚本文件添加执行权限
# 给刚刚创建的shell脚本文件添加执行权限:
sudo chmod +x /usr/local/bin/myprogram.sh
创建一个systemd服务文件
执行以下命令,将创建一个systemd服务文件,该文件用来描述服务以告诉systemd如何来启动和停止它。
sudo nano /etc/systemd/system/myprogram.service
在打开的文本编辑器中,输入以下内容:
[Unit]
Description=My Python Program
After=multi-user.target
[Service]
Type=idle
ExecStart=/bin/bash /usr/local/bin/myprogram.sh
[Install]
WantedBy=multi-user.target
主要参数解释: [Unit] : 配置服务中的一个节,主要用来定义服务单元。该节下有以下几个属性可以设置:Description:指定服务的描述信息。
Documentation:指定服务的文档地址。Requires:指定服务的依赖关系,表示该服务依赖于指定的服务。Wants:指定服务的依赖关系,表示该服务希望指定的服务运行,但不是必须的。After:指定服务的启动顺序,表示该服务应该在指定的服务之后启动。Before:指定服务的启动顺序,表示该服务应该在指定的服务之前启动。Conflicts:指定服务的冲突关系,表示该服务与指定的服务不能同时运行。
[Service] : 配置服务中的一个节,主要用来定义服务属性。该节下有以下几个属性可以设置:Type:指定服务的进程类型,可选值包括simple、forking、oneshot、dbus和notify等。User:指定服务运行的用户。Group:指定服务运行的用户组ExecStart:指定服务启动时要执行的命令或脚本。ExecStop:指定服务停止时要执行的命令或脚本。WorkingDirectory:指定服务的工作目录。PIDFile:指定服务进程的PID文件路径。Restart:指定服务重启的行为,设定为no: 服务退出后不会自动重新启动。always: 无论退出原因如何,服务都将自动重新启动。on-success: 仅在服务以退出状态0(成功)退出时才自动重新启动。 on-failure: 仅在服务以退出状态非0(失败)退出时才自动重新启动。on-abnormal: 仅在服务以异常退出状态(如由信号导致的退出)退出时才自动重新启动。on-abort: 仅在服务以中止退出状态(如由程序自己退出)退出时才自动重新启动。on-watchdog: 仅在服务超时退出时才自动重新启动。需要使用WatchdogSec选项来启用看门狗定时器。可以使用逗号分隔符将多个选项组合在一起。例如,Restart=on-failure,always表示在服务以失败退出时重新启动服务,同时也会在服务因其他原因退出时自动重新启动。。TimeoutStartSec:指定服务启动超时时间。TimeoutStopSec:指定服务停止超时时间。ExecStartPre:设定延迟启动。
ExecStartPre = /bin/sleep 30 # 延迟30秒启动
Restart= always #
[Install] : 配置服务中的一个节,主要用来指定如何安装该服务。该节下有以下几个属性可以设置:WantedBy:指定服务的启动级别(target),该级别被激活时会自动启动该服务。RequiredBy:指定服务的依赖关系,当指定的服务被启动时,该服务也会被自动启动。Also:指定其他启动级别,该服务也应该在这些级别下自动启动。Alias:指定该服务的别名,可以使用别名来启动或停止该服务。 “After” : 使用"After=multi-user.target"指令可以告诉systemd,在"multi-user.target"目标单元启动之后才启动当前服务。这通常是有用的,因为在启动某些服务之前,可能需要先加载其他服务和组件。使用"After=multi-user.target"指令可以确保你的服务在系统加载所有必要组件之后才启动,从而确保服务能够正常运行。“multi-user.target” 是Linux系统中一个特殊的目标单元(Target Unit),它定义了系统在启动后进入的主要多用户模式。在Linux系统中,系统启动时会按照特定的顺序加载各种服务和系统组件,以便在启动完成后提供完整的系统功能。每个服务和组件都会被分配到一个或多个目标单元,这些目标单元指定了它们应该在什么时候加载和启动。“multi-user.target"是一个重要的目标单元,它指定了在多用户模式下启动系统时需要加载的服务和组件。当系统启动时,它会首先加载基本的系统服务和组件,然后进入"multi-user.target"目标单元,该目标单元会启动大量额外的服务和组件,以提供完整的多用户系统环境。在systemd服务配置文件中,After=network.target是用于指定服务所依赖的其他服务的一个指令,它表示该服务应该在网络服务启动之后才能启动。这样可以确保该服务所需的网络资源可用,并且可以避免在网络服务还未启动时启动该服务可能导致的问题。除了network.target之外,还有一些其他的选项可以使用,如:multi-user.target:表示服务应该在系统完成多用户模式启动之后启动。graphical.target:表示服务应该在系统完成图形模式启动之后启动。remote-fs.target:表示服务应该在远程文件系统挂载之后启动。在服务配置文件中,可以使用多个After=指令来指定多个依赖服务。需要注意的是,使用After=指令仅表示服务的启动顺序,而不表示服务之间的依赖关系,因此如果服务之间存在依赖关系,还需要使用Requires=或Wants=指令来指定。需要指出的是,After=指令仅用于指定启动顺序,而不会自动启动所依赖的服务。如果依赖的服务还没有启动,那么该服务将无法正常启动,需要手动启动或者通过其他方式自动启动。
“Type” : 在systemd服务配置文件中,“Type=idle"是一种指令,用于指定服务的启动类型"Type=idle"指令表示,服务应该在系统空闲时启动。这意味着,当系统完成所有必要的启动任务并进入稳定状态时,服务将在后台启动,而不会阻止其他服务或进程的启动。使用"idle"类型可以确保你的服务不会干扰系统启动过程,同时也可以避免在系统启动时出现任何冲突或问题。通常,“Type=idle"指令适用于启动后台任务或后台服务,这些任务或服务可以在系统启动完成后运行,并且不需要立即启动。需要注意的是,如果你的服务需要立即启动并在系统启动时就处于运行状态,则不应该使用"idle"类型。相反,你应该使用"Type=simple"或"Type=forking"类型,具体取决于你的服务如何启动和运行。“Type=simple"指令表示,服务启动时将直接运行一个进程,该进程将成为服务的主进程,服务将一直运行,直到收到关闭信号为止。这种类型通常用于简单的服务,它们只需要一个单独的进程来运行。“Type=forking"指令表示,服务启动时将首先运行一个父进程,然后父进程将创建一个或多个子进程来运行服务。父进程将立即退出,而子进程将成为服务的主进程,服务将一直运行,直到收到关闭信号为止。这种类型通常用于需要创建多个进程的服务。需要注意的是,如果你的服务需要在后台运行,并且不需要使用额外的子进程或线程,那么你应该使用"Type=simple"类型。如果你的服务需要使用多个子进程或线程来完成任务,那么你应该使用"Type=forking"类型。在配置服务时,选择正确的启动类型非常重要,因为它将直接影响服务的启动和运行方式。
WantedBy : WantedBy是systemd服务配置文件中的一个指令,用于指定哪个目标(target)需要该服务。它表示如果某个目标被激活,那么该服务也会被激活。 systemd中有很多目标,例如multi-user.target、graphical.target等。这些目标定义了系统启动时需要启动哪些服务。通过将WantedBy指令设置为目标,可以让systemd在启动该目标时自动启动该服务。例如:在本页例子中,服务将在multi-user.target目标被激活时自动启动。当系统启动到多用户模式时,该目标就会被激活,从而自动启动该服务。需要注意的是,每个服务只能指定一个WantedBy目标,但可以指定多个RequiredBy目标,用于指定该服务必须依赖哪些目标。
重新加载systemd守护程序
重新加载systemd守护程序以用来更新服务列表,设置好service文件后一定要执行下面这三个语句,以使得系统可以正常启动服务。
# 刷新守护程序服务列表
sudo systemctl daemon-reload
# 启动服务
sudo systemctl start my_program.service
# 为了确保服务在系统启动时能够自动启动,需要使用以下命令将服务添加到systemd启动项中
sudo systemctl enable my_program.service
服务运行状态查看及操作
# 为了确保服务在系统启动时能够自动启动,需要使用以下命令将服务添加到systemd启动项中
sudo systemctl enable my_program.service
# 查看服务运行状态
sudo systemctl status my_program.service
# 启动服务
sudo systemctl start my_program.service
# 重新启动服务
sudo systemctl restart my_program.service
# 停止服务
sudo systemctl stop my_program.service
# 禁止服务开机自启动
sudo systemctl disable my_program.service
# 删除启动服务文件
sudo rm /etc/systemd/system/my_program.service
查看系统日志
在Ubuntu系统上,可以使用journalctl命令查看系统日志。
sudo journalctl
# 查看最近N行系统日志
sudo journalctl -n N
# 查看某个服务的启动日志
sudo journalctl -u my_program.service
# 查看某个级别的日志 ,level可以是err,warning,info
sudo journalctl -p error
问题处理
- 服务启动后查看服务日志状态处于inactice或idel状态
如果你在检查服务状态时发现服务状态是"inactive”,则表示该服务已经启动但是目前处于非活动状态。这可能是因为服务没有成功启动或服务已经完成了其任务并已经停止,下面是一些可能导致服务处于"inactive"状态的原因:
服务启动失败:如果服务无法启动,它将会停留在"inactive"状态。你可以查看系统日志来查找有关为什么服务启动失败的详细信息。
服务已经完成了其任务并已经停止:有些服务只需要在启动时运行一次,并在完成任务后自动停止。这些服务也会显示为"inactive"状态。
服务被手动停止:如果你手动停止了服务,它将变为"inactive"状态。
服务依赖项未满足:某些服务需要满足其他服务或条件才能成功启动。如果服务依赖项未满足,服务将无法启动并停留在"inactive"状态。
如果服务处于"inactive"状态,请使用sudo journalctl 指令检查系统日志以查找有关服务状态的详细信息,并尝试排除可能导致服务无法启动的原因。
启动服务后如何禁止程序向终端输出数据
要在启动服务后不向终端输出数据,可以将标准输出(stdout)和标准错误(stderr)流重定向到文件或/dev/null。以下是一些方法:
重定向到文件可以将标准输出和标准错误流重定向到文件中,这样所有输出都将写入该文件,而不会出现在终端中。例如,可以使用以下命令将标准输出和标准错误流重定向到/var/log/my_service.log文件中:
sudo systemctl start my_service.service > /var/log/my_service.log 2>&1 # > /var/log/my_service.log将标准输出重定向到文件中,2>&1将标准错误流重定向到标准输出流中,这样标准错误输出也将写入该文件。这个命令将程序的标准输出重定向到文件 my_service.log,然后将标准错误输出也重定向到与标准输出相同的位置,即文件 my_service.log。
重定向到/dev/null可以将标准输出和标准错误流重定向到/dev/null设备文件中,这样所有输出都将被丢弃而不会出现在终端中。例如,可以使用以下命令将标准输出和标准错误流重定向到/dev/null中:
sudo systemctl start my_service.service /dev/null 2>&1
# > /dev/null将标准输出重定向到/dev/null中,2>&1将标准错误流重定向到标准输出流中,这样标准错误输出也将被丢弃。在Linux和其他类Unix系统中,2>&1 是一种输出重定向符号,它的作用是将标准错误输出(stderr)重定向到标准输出(stdout)。更具体地说,数字 2 表示标准错误输出文件描述符(file descriptor),而数字 1 表示标准输出文件描述符。在Linux系统中,标准输出文件描述符的默认值是 1,标准错误输出文件描述符的默认值是 2。因此,2>&1 的意思是将标准错误输出重定向到与标准输出相同的位置,也就是说,标准输出和标准错误输出都会被发送到同一个位置。这通常用于将错误消息和普通输出消息一起输出到文件或者屏幕上,以便更方便地查看和分析。
> ```
## 让service在依赖启动之后再启动
可以在/etc/systemd/system/自定义名字.service中添加`After`和`Requires`选项,例如:
[Unit] Description=myservice After=network.target Requires=network.target
[Service] Type=simple ExecStart=/path/to/myservice
[Install] WantedBy=multi-user.target
在这个例子中,After和Requires选项指定了服务依赖于network.target服务。这意味着,系统必须在网络服务完全启动后才能启动这个服务。
常用After选项:
network.target:在网络服务启动后启动。 syslog.target:在syslog服务启动后启动。 multi-user.target:在多用户模式启动后启动。 remote-fs.target:在远程文件系统启动后启动。 local-fs.target:在本地文件系统启动后启动。 sshd.service:在ssh服务启动后启动。
## 让service在系统启动一段时间之后再启动
我们可以通过使用systemd提供的一个叫做`自定义名字.timer`的服务来实现在系统稳定后执行某个操作的功能。`systemd.timer`是一个定时器,可以在指定的时间间隔后运行一个命令或者启动一个systemd服务。
下面是一个简单的步骤,以使得系统在稳定后运行一个service服务:
- 创建一个新的`systemd`定时器配置文件,例如`/etc/systemd/system/自定义名字.timer`。
- 编辑配置文件,指定定时器的运行方式,以及触发器与要执行的命令或服务。例如,以下是一个示例配置文件:
[Unit] Description=Run 自定义名字.service two minutes after system boot [Timer] OnBootSec=2min Unit=自定义名字.service [Install] WantedBy=timers.target
在这个例子中,`OnBootSec`选项指定了在系统启动后2分钟后运行命令,`Unit`选项指定了要运行的服务或脚本。在本例中,`自定义名字.service`是要启动的服务名。
****
### 注意事项
- 每次修改service服务之后,都需要重新加载服务配置文件,以使之生效。```
systemctl daemon-reload systemctl enable 自定义名字.timer
- 在systemd中,timer和service必须以相同的名称前缀命名,例如在上面的示例中,`自定义名字.timer`和`自定义名字.service`应该是相对应的。
- OnBootSec可用项
OnBootSec=30s:30秒后启动。 OnBootSec=5min:5分钟后启动。 OnBootSec=1h30min:1小时30分钟后启动。 OnBootSec=2days:2天后启动。
- 其他和时间相关的选项
OnCalendar: Allows you to schedule the timer to run on specific dates and times. You can use this option to run a script at a specific time every day, week, month, or year. For example, OnCalendar=--* 10:30:00 would run the timer at 10:30 AM every day.
OnUnitActiveSec and OnUnitInactiveSec: These options allow you to schedule the timer to run a certain amount of time after the associated unit becomes active or inactive. For example, OnUnitActiveSec=apache2.service would run the timer 5 minutes after the Apache web server starts.
RandomizedDelaySec: This option adds a random delay to the timer’s start time to prevent all instances of the same timer from running at exactly the same time. For example, RandomizedDelaySec=10min would add a random delay of up to 10 minutes to the timer’s start time.
# supervisor