0

0

如何在Linux中用户服务 Linux systemctl --user模式

P粉602998670

P粉602998670

发布时间:2025-08-29 11:44:01

|

726人浏览过

|

来源于php中文网

原创

使用systemctl --user可在无root权限下管理用户级服务,通过创建~/.config/systemd/user/目录下的.service文件,定义服务的启动命令、工作目录、重启策略等,并用systemctl --user enable/start启用和启动服务,结合journalctl --user调试日志,实现安全、隔离的个人服务管理。

如何在linux中用户服务 linux systemctl --user模式

在Linux中,如果你想管理那些只为你当前用户会话运行的服务,而不是系统全局的服务,

systemctl --user
模式是你的最佳选择。它允许你在不涉及
root
权限的情况下,为你的用户账户启动、停止、启用或禁用守护进程和后台任务,提供了一个非常个人化且隔离的服务管理环境。

解决方案

要在Linux中使用

systemctl --user
模式管理用户服务,核心流程涉及创建服务文件、将其放置在正确的位置,然后通过
systemctl --user
命令进行操作。

首先,你需要为你的服务创建一个

.service
文件。这些文件通常存放在
~/.config/systemd/user/
目录下。如果这个目录不存在,你可以手动创建它:

mkdir -p ~/.config/systemd/user/

然后,用你喜欢的文本编辑器创建一个服务文件,比如

my-app.service

# ~/.config/systemd/user/my-app.service
[Unit]
Description=我的个人应用后台服务
After=network.target # 如果你的服务依赖网络

[Service]
ExecStart=/usr/bin/python3 /home/youruser/scripts/my_app_daemon.py # 替换为你的实际命令
WorkingDirectory=/home/youruser/scripts/ # 服务的工作目录
Restart=on-failure # 服务失败时自动重启
Type=simple # 最常见的服务类型

[Install]
WantedBy=default.target # 当用户登录时,此服务会被拉起

保存文件后,你需要让

systemd
知道这个新服务:

systemctl --user daemon-reload

接着,你可以启用并启动你的服务:

systemctl --user enable my-app.service # 设置开机启动(用户登录后)
systemctl --user start my-app.service  # 立即启动服务

要检查服务状态:

systemctl --user status my-app.service

停止服务:

systemctl --user stop my-app.service

禁用服务(使其不再开机启动):

systemctl --user disable my-app.service

为什么我需要使用
systemctl --user
而不是传统的
systemctl

我个人一直觉得,

systemctl --user
模式简直是Linux桌面环境和个人开发者的福音。传统的
systemctl
命令,你懂的,那是为整个系统服务的,它管理着从网络、日志到各种系统守护进程的一切,需要
root
权限。这模式,对我这种喜欢在自己地盘折腾的人来说,好处是显而易见的。

首先,也是最重要的一点,是权限隔离。你的服务以你自己的用户身份运行,而不是

root
。这意味着你的服务即便出了问题,比如被攻击或者代码有漏洞,它也只能在你自己的用户权限范围内搞破坏,不会影响到系统的核心安全。这对于跑一些自己写的脚本、开发中的应用,或者一些第三方工具,是极其安全的。你不需要每次都输入
sudo
,也不用担心不小心把系统搞砸。

其次,它提供了用户会话级别的生命周期管理。很多时候,我们有些服务只希望在自己登录的时候运行,比如一个个人通知守护进程、一个本地的同步工具、或者一个临时的开发服务器。

systemctl --user
就能完美地做到这一点。服务会随着你的登录而启动,随着你登出而停止。当然,如果你希望服务在你登出后依然运行,可以通过
loginctl enable-linger <你的用户名>
来启用“会话保持”功能,这在远程连接或者需要长期运行个人服务时非常有用。

再者,避免了系统级别的“污染”。你不需要把你的个人服务文件扔到

/etc/systemd/system/
这种系统目录里,所有配置都安安静静地躺在你的用户目录下 (
~/.config/systemd/user/
)。这样一来,你的个人配置和系统配置泾渭分明,管理起来也更清晰,升级系统或者迁移用户配置时也方便得多。这对于保持系统整洁,减少潜在的冲突,是很有价值的。对我来说,这就像是给我的用户账户开辟了一个专属的“服务沙盒”,想怎么玩就怎么玩,不用担心影响到“大局”。

如何编写一个基本的
systemctl --user
服务文件?

编写一个

systemctl --user
服务文件,说实话,和写系统级别的
systemd
服务文件大同小异,只是你需要关注一些用户环境特有的细节。一个服务文件通常由几个关键的段落组成,每个段落都有其特定的作用。

易优cms汽车车辆租赁源码1.7.2
易优cms汽车车辆租赁源码1.7.2

由于疫情等原因大家都开始习惯了通过互联网上租车服务的信息多方面,且获取方式简便,不管是婚庆用车、旅游租车、还是短租等租车业务。越来越多租车企业都开始主动把租车业务推向给潜在需求客户,所以如何设计一个租车网站,以便在同行中脱颖而出就重要了,易优cms针对租车行业市场需求、目标客户、盈利模式等,进行策划、设计、制作,建设一个符合用户与搜索引擎需求的租车网站源码。 网站首页

下载

我们拿一个简单的例子来说明,假设你有一个Python脚本

~/scripts/hello.py
,它只是每隔几秒打印一条消息到一个日志文件里,你想让它在你登录后自动运行。

# ~/scripts/hello.py
import time
import datetime

log_file = "/home/youruser/logs/hello_service.log" # 确保目录存在

def main():
    with open(log_file, "a") as f:
        f.write(f"[{datetime.datetime.now()}] Hello from my user service!\n")
    time.sleep(5)

if __name__ == "__main__":
    while True:
        main()

然后,这是对应的

~/.config/systemd/user/hello-world.service
文件:

[Unit]
Description=我的用户级Hello World服务
Documentation=https://example.com/hello-world-docs
After=network-online.target # 如果你的服务需要网络,可以加这个

[Service]
ExecStart=/usr/bin/python3 /home/youruser/scripts/hello.py
WorkingDirectory=/home/youruser/scripts/
StandardOutput=file:/home/youruser/logs/hello-world-stdout.log # 标准输出重定向
StandardError=file:/home/youruser/logs/hello-world-stderr.log # 标准错误重定向
Restart=always # 任何情况下都尝试重启
RestartSec=5s # 重启前等待5秒
Type=simple # 这是最常见的类型,表示ExecStart是主进程

[Install]
WantedBy=default.target # 表示这个服务应该在用户会话的默认目标中启动

解析一下关键部分:

  • [Unit]
    段落:
    • Description
      : 这是服务的简短描述,用
      systemctl status
      查看时会显示。
    • Documentation
      : 可以放一个链接,指向服务的文档,挺方便的。
    • After
      : 定义了服务启动的顺序。
      network-online.target
      意味着这个服务会在网络连接可用后才尝试启动。
  • [Service]
    段落:
    • ExecStart
      : 这是核心,指定了服务启动时要执行的命令。务必使用绝对路径,因为用户服务的环境可能不如你的交互式shell那么丰富。
    • WorkingDirectory
      : 服务执行时的当前工作目录。这对于那些依赖相对路径来寻找文件或配置的服务很重要。
    • StandardOutput
      /
      StandardError
      : 我个人喜欢把服务的标准输出和错误重定向到独立的文件,这样日志看起来更清晰,也方便调试。当然,你也可以让它们直接输出到
      journalctl
    • Restart
      : 这个参数很有用。
      always
      表示无论服务如何退出(成功、失败、信号),都会尝试重启。还有
      on-failure
      on-success
      等选项。
    • RestartSec
      : 配合
      Restart
      使用,定义重启前的等待时间。
    • Type
      :
      simple
      是最直接的,
      ExecStart
      命令就是主进程。如果你的命令会fork出子进程然后主进程退出(比如一些传统的守护进程),你可能需要
      Type=forking
  • [Install]
    段落:
    • WantedBy=default.target
      : 这个是让
      systemctl --user enable
      命令知道,当用户会话的
      default.target
      启动时(通常就是用户登录时),这个服务应该被拉起。

记住,每次修改服务文件后,都要运行

systemctl --user daemon-reload
,然后
systemctl --user start your-service.service
或者
systemctl --user restart your-service.service
来应用更改。

调试
systemctl --user
服务时有哪些常见问题和技巧?

调试

systemctl --user
服务,说实话,和调试系统服务有共通之处,但也有它自己的一些“脾气”。我刚开始接触的时候,也踩了不少坑,所以有些经验我觉得分享出来挺有用的。

最最核心的调试工具,没有之一,就是

journalctl --user -u <服务名称>.service
。当你发现服务启动失败,或者行为不符合预期时,第一件事就是查看日志。它会告诉你服务启动时遇到了什么错误,比如找不到命令、权限不足、配置错误等等。如果你没有重定向
StandardOutput
StandardError
到文件,那么所有服务的输出都会在这里。

journalctl --user -u hello-world.service -f # -f 实时跟踪日志

一个小插曲:我曾遇到过一个服务,在命令行里跑得好好的,一放到

systemctl --user
里就崩,后来才发现是路径问题。用户服务的环境和你在终端里敲命令的环境可能不一样,比如
PATH
环境变量可能不包含你习惯的一些路径。所以,我的建议是:在
ExecStart
中,尽量使用命令的绝对路径,比如
ExecStart=/usr/bin/python3 ...
而不是
ExecStart=python3 ...
。这能省去很多不必要的麻烦。

权限问题也是常客。确保你的

ExecStart
中执行的脚本或程序拥有执行权限 (
chmod +x script.sh
),并且它需要访问的任何文件或目录,你的用户都有读写权限。这听起来很基础,但往往是新手容易忽略的地方。

环境变量。有时候你的服务需要一些特定的环境变量才能正常工作。用户服务默认继承的环境变量是有限的。你可以在

[Service]
段落中明确设置它们:

[Service]
Environment="MY_API_KEY=your_secret_key"
Environment="DEBUG_MODE=true"
ExecStart=/usr/bin/your_app

如果你的服务在用户登出后就停止了,但你希望它继续运行,那很可能是你没有启用

linger
模式。默认情况下,用户会话结束(比如你关闭了终端或者登出)时,所有用户服务都会被终止。要让服务在你登出后继续运行,你需要为你的用户启用
linger

loginctl enable-linger your_username

你可以通过

loginctl show-user your_username
来检查
linger
状态。这对于那些需要在后台持续运行的个人服务器或同步任务非常关键。

最后,注意

Type
参数的选择。大部分情况下
Type=simple
就够了。但如果你的程序在启动时会
fork()
出一个子进程,然后父进程退出,那么你可能需要
Type=forking
,并且可能需要设置
PIDFile
来帮助
systemd
跟踪主进程。如果选择错误,
systemd
可能会认为你的服务已经停止了,或者无法正确管理它。

调试过程中,保持耐心,一步步地排查,通常都能找到问题所在。

journalctl
永远是你的好朋友。

相关专题

更多
python开发工具
python开发工具

php中文网为大家提供各种python开发工具,好的开发工具,可帮助开发者攻克编程学习中的基础障碍,理解每一行源代码在程序执行时在计算机中的过程。php中文网还为大家带来python相关课程以及相关文章等内容,供大家免费下载使用。

769

2023.06.15

python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

661

2023.07.20

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

764

2023.07.25

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

639

2023.07.31

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

1305

2023.08.03

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

549

2023.08.04

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

579

2023.08.04

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

709

2023.08.11

Java JVM 原理与性能调优实战
Java JVM 原理与性能调优实战

本专题系统讲解 Java 虚拟机(JVM)的核心工作原理与性能调优方法,包括 JVM 内存结构、对象创建与回收流程、垃圾回收器(Serial、CMS、G1、ZGC)对比分析、常见内存泄漏与性能瓶颈排查,以及 JVM 参数调优与监控工具(jstat、jmap、jvisualvm)的实战使用。通过真实案例,帮助学习者掌握 Java 应用在生产环境中的性能分析与优化能力。

19

2026.01.20

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7.5万人学习

Git 教程
Git 教程

共21课时 | 2.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号