当前位置:   article > 正文

Ubuntu系统中Python脚本的开机自启动以及持续检测运行状态_ubuntu开机自启动python程序

ubuntu开机自启动python程序


需求:系统为ubuntu18.04,只要服务器是开机状态,python脚本aProgramThatNeedsToRunAllTheTime.py(名字为啥这么长和丑是有原因的)就必须是在运行的状态。

主要参考了【Ubuntu】Ubuntu18.04默认没有/etc/rc.local,需要手动配置:ubuntu18.04不再使用 inited 管理系统,改用 systemd。systemd中也有rc.local服务,需要手动开启。

systemd是linux系统第一个运行的程序,相当于以前的init进程,pid=1。也可以理解为systemd是初始化整个系统所需的资源,负责启用和管理系统的各种服务。

rc.local是ubuntu的开机自启动的配置文件,执行的时机:在系统所有服务启动后开始执行rc.local中的配置,在ubuntu18.04中,默认rc.local服务器并没有启动。

1. 实现原理

systemd默认会读取/etc/systemd/system下的配置文件。一般系统安装完后在/lib/systemd/system/下会有rc-local.service文件,将该文件软链接到/etc/systemd/system下,然后创建rc.local文件,将需要开机自启动的脚本(命名为start.py)运行命令写入,则开机后start.py脚本即可运行,start.py脚本用于检查aProgramThatNeedsToRunAllTheTime.py脚本是否在运行,未在运行则马上启动它。

2. 创建service软链接

将/lib/systemd/system/rc-local.service 链接到/etc/systemd/system/目录下面来

ln -fs /lib/systemd/system/rc-local.service /etc/systemd/system/rc-local.service
  • 1

3. 修改service文件内容

一般正常的启动文件主要分为三部分
[Unit]段:启动顺序与依赖关系
[Service]段:启动行为如何启动,启动类型
[Install]段:定义如何安装这个配置文件,即怎样做到开机启动
由于ubuntu18.04默认rc.local服务器不启动,所以默认文件里面是缺少了Install段的

sudo vim /etc/systemd/system/rc-local.service
  • 1

在文件末尾加上Install段

[Install]
WantedBy=multi-user.target
Alias=rc-local.service
  • 1
  • 2
  • 3

4. 创建/etc/rc.local文件

sudo touch /etc/rc.local
  • 1

给rc.local添加可执行权限

sudo chmod 777 /etc/rc.local
  • 1

编辑/etc/rc.local文件,将start.py脚本的运行写入

sudo vim /etc/rc.local
  • 1

nohup英文全称no hang up(不挂起),用于在系统后台不挂断地运行命令,退出终端不会影响程序的运行
&表示把该命令以后台的job的形式运行
2>&1表示将标准错误2重定向到标准输出&1,标准输出&1再被重定向输入到指定的log文件中
0-stdin(standard input,标准输入)
1-stdout(standard output,标准输出)
2-stderr(standard error,标准错误输出)

#!/bin/bash
nohup /opt/anaconda3/envs/py39/bin/python -u /home/zy/starter.py > /home/zy/starter_out.log 2>&1 &
  • 1
  • 2

注:此时的文件必须都使用绝对路径

5. starter.py文件对目标python脚本进行状态的检查、启动

脚本中都需要使用绝对路径

# -*- coding:utf-8 -*-

import os
from loguru import logger
import time, datetime

def execCmd(cmd):
    r = os.popen(cmd)
    text = r.read()
    r.close()
    return text

def doSomething():
	# 避免输出日志被覆盖
	now = datetime.datetime.now()
    os.system(f'nohup /opt/anaconda3/envs/py39/bin/python -u /home/zy/aProgramThatNeedsToRunAllTheTime.py > /home/zy/out_{now.strftime("%Y_%m_%d_%H_%M_%S")}.log 2>&1 &')

def kill_program(texts, num):
    for i in range(num - 2):
        Id = texts[i]
        os.system('kill -9 ' + Id)
 
if __name__ == '__main__':
    while True:
        # ps -ef是linux查看进程信息指令,|是管道符号导向到grep去查找特定的进程,最后一个|是导向grep过滤掉grep进程:因为grep查看程序名也是进程,会混到查询信息里
        # python脚本的名字最好复杂点,这样能避免检测到同名程序
        programIsRunningCmd="ps -ef|grep aProgramThatNeedsToRunAllTheTime.py|grep -v grep|awk '{print $2}'"    
        programIsRunningCmdAns = execCmd(programIsRunningCmd)    #调用函数执行指令,并返回指令查询出的信息
        ansLine = programIsRunningCmdAns.split('\n')    #将查出的信息用换行符‘\n’分开
        #判断如果返回行数>0则说明python脚本程序已经在运行,打印提示信息结束程序,否则运行脚本代码doSomething()
        if len(ansLine) == 1:
            # ansLine:['']表示程序未运行,执行doSomething启动它
            doSomething()
        elif len(ansLine) == 2:
            # ansLine:['1420', '']表示程序正在运行,第一个元素为程序的PID
            logger.info("The program is working.")
        elif len(ansLine) > 2:
            # 可能还会出现该脚本同时被运行了好几个进程
            logger.info(f"There are {len(ansLine) - 1} programs running!")
            logger.info(ansLine)
            # kill_program(ansLine, len(ansLine))
        else:
            logger.info(f"Error:the length of programIsRunningCmdAns.split('\n') is {len(ansLine)}")
        # 每过一分钟就检测一次程序是否在正常运行
        time.sleep(60)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/55034
推荐阅读
相关标签
  

闽ICP备14008679号