【笔记】创建systemctl服务

在 Linux 中通过 systemctl 管理 Python 脚本作为系统服务 运行,核心是创建 systemd 服务配置文件(.service),让系统以守护进程方式启动 / 管理你的 Python 代码。以下是详细步骤,包含完整示例和避坑要点:

一、核心原理

systemd 是 Linux 系统的初始化 / 服务管理工具,systemctl 是其命令行工具。通过编写 .service 配置文件,定义 Python 脚本的运行指令、运行用户、工作目录、重启策略等,systemd 会将脚本作为系统服务托管(支持开机自启、异常重启、日志记录等)。

二、完整实现步骤

步骤 1:准备 Python 脚本

先确保 Python 脚本能在命令行手动运行(无路径、依赖问题),示例脚本 my_script.py

python 复制代码
# /root/data1/u-net/my_script.py(示例路径,替换为你的脚本路径)
import time
import logging

# 配置日志(建议输出到文件,方便排查)
logging.basicConfig(
    filename='/root/data1/u-net/script.log',  # 日志文件路径
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

if __name__ == '__main__':
    logging.info("Python 服务已启动")
    try:
        while True:  # 模拟持续运行的服务(如后台任务、接口服务等)
            logging.info("服务运行中...")
            time.sleep(10)  # 每10秒输出一次
    except Exception as e:
        logging.error(f"服务异常: {str(e)}", exc_info=True)
        raise

步骤 2:创建 systemd 服务配置文件

systemd 服务文件默认存放在 /etc/systemd/system/(系统级)或 ~/.config/systemd/user/(用户级),推荐用系统级(需 root 权限)。

创建服务文件(命名规范:xxx.service,比如 python-u-net.service):

vim /etc/systemd/system/python-u-net.service

写入以下配置(关键参数需根据你的环境修改):

bash 复制代码
[Unit]
Description=Python U-Net Service  # 服务描述(自定义)
After=network.target  # 依赖:网络启动后再启动该服务(无网络依赖可删)
Wants=network.target   # 可选:弱依赖网络服务

[Service]
# 核心配置
Type=simple  # 服务类型(simple:前台运行,适合脚本;forking:后台进程)
User=root    # 运行用户(建议用非root用户,如ubuntu,需确保该用户有脚本/日志权限)
Group=root   # 运行用户组
WorkingDirectory=/root/data1/u-net  # 脚本工作目录(脚本中相对路径的基准)
Environment="PYTHONPATH=/root/data1/u-net/envs/u-net-v0/lib/python3.10/site-packages"  # 虚拟环境PYTHONPATH(可选,若用虚拟环境)
ExecStart=/root/data1/u-net/envs/u-net-v0/bin/python3 /root/data1/u-net/my_script.py  # 启动指令(绝对路径!)
# 重启策略(异常崩溃自动重启)
Restart=on-failure  # 失败时重启(可选值:always/on-abnormal/on-failure/on-watchdog)
RestartSec=5        # 重启间隔5秒
# 日志配置(默认输出到systemd日志,也可自定义)
StandardOutput=append:/root/data1/u-net/service_stdout.log  # 标准输出重定向(可选)
StandardError=append:/root/data1/u-net/service_stderr.log   # 标准错误重定向(可选)

[Install]
WantedBy=multi-user.target  # 开机自启的目标级别(多用户模式)

配置参数关键说明

参数 作用
ExecStart 服务启动指令(必须用绝对路径 !):虚拟环境:/path/to/venv/bin/python3 /path/to/script.py系统 Python:/usr/bin/python3 /path/to/script.py
WorkingDirectory 脚本的工作目录(脚本中若用相对路径读取文件,基于此目录)
User 运行用户(避免用 root,若必须用需确认权限)
Restart 重启策略:on-failure(脚本报错 / 崩溃时重启),always(始终重启)
Environment 环境变量(如虚拟环境、CUDA 路径、自定义变量),多个变量用空格分隔

步骤 3:重载 systemd 配置并管理服务

bash 复制代码
# 1. 重载systemd配置(修改服务文件后必须执行)
systemctl daemon-reload

# 2. 启动服务(替换为你的服务名,如python-u-net)
systemctl start python-u-net

# 3. 设置开机自启(可选,建议开启)
systemctl enable python-u-net

# 4. 查看服务状态(验证是否启动成功)
systemctl status python-u-net

步骤 4:验证与排查

(1)查看服务状态

正常启动会显示 active (running)

bash 复制代码
systemctl status python-u-net
# 输出示例:
# ● python-u-net.service - Python U-Net Service
#    Loaded: loaded (/etc/systemd/system/python-u-net.service; enabled; vendor preset: enabled)
#    Active: active (running) since Wed 2025-12-10 10:00:00 CST; 10s ago
#  Main PID: 12345 (python3)
#     Tasks: 10 (limit: 4915)
#    Memory: 100.0M
#    CGroup: /system.slice/python-u-net.service
#            └─12345 /root/data1/u-net/envs/u-net-v0/bin/python3 /root/data1/u-net/my_script.py

(2)查看服务日志(关键排错手段)

bash 复制代码
# 实时查看日志(-f 跟踪最新输出)
journalctl -u python-u-net -f

# 查看最近100行日志
journalctl -u python-u-net -n 100

# 按时间筛选日志(比如今天的)
journalctl -u python-u-net --since "today"

(3)其他常用命令

bash 复制代码
# 停止服务
systemctl stop python-u-net

# 重启服务
systemctl restart python-u-net

# 禁用开机自启
systemctl disable python-u-net

# 检查服务文件语法错误
systemd-analyze verify /etc/systemd/system/python-u-net.service

三、关键避坑要点

1. 绝对路径!绝对路径!绝对路径!

  • ExecStart 中的 Python 解释器路径:用 which python3(系统 Python)或 ~/venv/bin/python3(虚拟环境)确认绝对路径,禁止用 python3python (可能指向错误版本)
  • 脚本路径、日志路径、工作目录均用绝对路径(避免相对路径导致找不到文件)。

2. 虚拟环境适配

若你的 Python 脚本依赖虚拟环境,ExecStart 必须用虚拟环境内的 Python 解释器(如示例中的 /root/data1/u-net/envs/u-net-v0/bin/python3),而非系统 Python。

3. 权限问题

  • 运行用户(User=)需有:脚本文件的读权限 、日志文件 / 目录的写权限 、虚拟环境目录的读权限
  • 若用非 root 用户,避免脚本 / 日志路径在 /root/ 下(普通用户无权限)。

4. 脚本持续运行

若你的 Python 脚本是 "一次性执行"(而非循环 / 后台服务),systemd 会启动后立即退出。解决方法:

  • 脚本中加无限循环(如示例中的 while True);
  • 若需一次性执行,修改 Service 段:
bash 复制代码
Type=oneshot
RemainAfterExit=yes  # 执行完后仍标记为active

5. CUDA/GPU 环境适配

若脚本依赖 GPU,需在 Environment 中配置 CUDA 环境变量(避免服务启动时找不到 CUDA):

bash 复制代码
Environment="CUDA_HOME=/usr/local/cuda-11.6"
Environment="PATH=/usr/local/cuda-11.6/bin:$PATH"
Environment="LD_LIBRARY_PATH=/usr/local/cuda-11.6/lib64:$LD_LIBRARY_PATH"

四、示例:完整的服务文件

bash 复制代码
[Unit]
Description=U-Net Python Service
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/root/data1/u-net
Environment="PYTHONPATH=/root/data1/u-net/envs/u-net-v0/lib/python3.10/site-packages"
Environment="CUDA_HOME=/usr/local/cuda-11.6"
Environment="LD_LIBRARY_PATH=/usr/local/cuda-11.6/lib64:$LD_LIBRARY_PATH"
ExecStart=/root/data1/u-net/envs/u-net-v0/bin/python3 /root/data1/u-net/your_u_net_script.py
Restart=on-failure
RestartSec=5
StandardOutput=append:/root/data1/u-net/u-net.log
StandardError=append:/root/data1/u-net/u-net_error.log

[Install]
WantedBy=multi-user.target
相关推荐
不会学习?11 分钟前
大二元旦,2025最后一天
经验分享·笔记
郝学胜-神的一滴20 分钟前
Linux进程与线程控制原语对比:双刃出鞘,各显锋芒
linux·服务器·开发语言·数据结构·c++·程序人生
山上三树26 分钟前
进程状态详解
linux·运维·服务器
山上三树28 分钟前
task_struct 详解
运维·服务器·网络
WoY202035 分钟前
本地PyCharm配置远程服务器上的python环境
服务器·python·pycharm
oMcLin36 分钟前
如何打造Linux运维监控平台:Prometheus + Grafana实战与性能优化
linux·运维·prometheus
木卫二号Coding1 小时前
jupyterlab-安装与启动
linux·运维·服务器
NULL指向我1 小时前
STM32F407VET6学习笔记14:Bootloader程序笔记
笔记·stm32·学习
fengyehongWorld1 小时前
Linux logger命令
linux·运维·服务器
伶星371 小时前
obsidian 日记按年月存放
笔记