【笔记】创建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
相关推荐
meng_ser27 分钟前
基于Linux内核模块的进程与内存监控工具(CentOS 7实现)
linux·运维·centos
诸葛思颖28 分钟前
Beta 分布学习笔记
笔记·学习·概率论
北岛寒沫30 分钟前
北京大学国家发展研究院 经济学辅修 经济学原理课程笔记(第六课 生产可能性曲线、机会成本与交易)
经验分享·笔记
北岛寒沫30 分钟前
北京大学国家发展研究院 经济学辅修 经济学原理课程笔记(第五课 福利经济学)
经验分享·笔记
Heavydrink30 分钟前
Java项目部署云服务器详细教程
java·服务器·开发语言
离离茶30 分钟前
【笔记2-9】ESP32:mqtt通信
笔记
水天需01031 分钟前
ps 命令全面详解
linux·服务器·网络
Lethehong32 分钟前
算力新标杆:昇腾Atlas 800T NPU实战Llama-2-7b全流程评测与技术解析
运维·服务器·数据库·llama-2-7b·昇腾atlas 800t
云霄星乖乖的果冻32 分钟前
02预备知识——李沐《动手学深度学习》个人笔记
人工智能·笔记·深度学习