在服务器上运行 Python 脚本时,一个常见但脆弱的方法是使用 python3 my_app.py &。这种方式虽然能让程序在后台运行,但它存在致命的缺点:一旦程序因错误崩溃,或者服务器重启,进程就会永久终止,需要手动重新启动。这对于需要 7x24 小时运行的服务是不可接受的。
为了解决这个问题,我们可以使用 systemd——现代 Linux 发行版(如 Ubuntu 16.04+、CentOS 7+)内置的系统和服务管理器。systemd 可以像守护神一样守护你的程序,实现自动启动、失败重启、日志管理等关键功能,是专业部署的黄金标准。
本文将手把手教你如何为你的 Python 程序创建一个 systemd 服务。
第一步:准备你的 Python 程序 #
在开始之前,请确保:
- 你的 Python 程序(例如
my_app.py)可以在服务器上无误地运行。 - 记下你的 Python 解释器和脚本的绝对路径。
- 查找 Python 解释器的绝对路径:
which python3(可能会返回/usr/bin/python3或/usr/local/bin/python3等) - 查找脚本所在的目录路径。
- 查找 Python 解释器的绝对路径:
第二步:创建 systemd 服务文件 (.service)
#
systemd 通过后缀为 .service 的配置文件来管理服务。这些文件通常存放在 /etc/systemd/system/ 目录下。
-
创建服务文件。我们将为服务取一个有意义的名字,例如
my-python-app.service。使用你喜欢的文本编辑器(如nano或vim)创建它:sudo nano /etc/systemd/system/my-python-app.service -
编写配置内容。将以下模板内容复制到文件中,然后我们会逐一解释每个指令的含义。
[Unit] Description=A description for your Python application After=network.target [Service] User=your_username Group=your_groupname WorkingDirectory=/path/to/your/project ExecStart=/path/to/your/python3 /path/to/your/project/my_app.py Restart=on-failure RestartSec=5s [Install] WantedBy=multi-user.target
第三步:理解配置文件的每一部分 #
让我们来详细解析这个配置文件的每个部分和指令:
-
[Unit]部分: 定义了服务的基本信息和依赖关系。Description: 服务的简短描述,会在你查看服务状态时显示。After=network.target: 指定此服务应该在网络服务准备好之后再启动。对于需要网络连接的程序(如 Web 服务、API),这是一个必须的设置。
-
[Service]部分: 定义了服务的核心行为。User: **(重要)**指定运行此服务的用户。为了安全,强烈建议使用一个非root的普通用户。如果你的程序不需要特殊权限,不要使用root。Group: 指定运行此服务的用户组(可选,但推荐)。WorkingDirectory: 指定脚本的工作目录。这非常重要,因为你的 Python 代码中任何相对路径的文件读写(如打开配置文件、写入日志)都将以此目录为基准。ExecStart: (核心)定义启动服务的完整命令。这里必须使用绝对路径指定 Python 解释器和你的脚本。Restart=on-failure: 这是实现稳定性的关键!它告诉systemd,如果进程非正常退出(即返回非 0 的退出码,通常意味着发生错误),就自动重启它。你也可以设置为always,这样即使用户手动停止,它也会被重启。RestartSec=5s: 在尝试重启前等待 5 秒。这可以防止因程序快速连续崩溃而耗尽系统资源。
-
[Install]部分: 定义了服务的安装信息。WantedBy=multi-user.target: 这意味着当你执行systemctl enable my-python-app.service时,服务会被设置为在系统进入多用户模式(即正常开机后)时自动启动。
第四步:实战案例 - 部署 Gemini UI 应用 #
现在,让我们应用这些知识,看看你提供的 gemini.service 配置。假设我们将服务文件命名为 gemini-ui.service。
配置文件 (/etc/systemd/system/gemini-ui.service):
[Unit]
Description=My Python Application
# 确保在网络服务启动后再启动你的应用
After=network.target
[Service]
# 运行此服务的用户
User=root
# 你的Python项目所在的目录
WorkingDirectory=/root/codes/gemini-2.0-flash-exp-ui
# 启动命令,请使用绝对路径!
# 可以用 which python3 命令找到python3的绝对路径
ExecStart=/usr/local/bin/python3 gemini_image_ui_base64.py
# 在失败时自动重启
Restart=on-failure
# 重启间隔
RestartSec=5s
[Install]
WantedBy=multi-user.target
配置分析:
- 这个配置非常标准且实用。它正确地设置了工作目录和启动命令。
WorkingDirectory设置为/root/codes/gemini-2.0-flash-exp-ui,这意味着gemini_image_ui_base64.py中所有相对路径的操作都会在这个目录下进行。ExecStart使用了绝对路径/usr/local/bin/python3,这是一个好习惯。- 安全提示:
User=root意味着程序拥有服务器的最高权限。如果此程序存在任何安全漏洞,可能会对整个系统造成风险。如果程序不需要 root 权限(例如,它不监听 1024 以下的端口),建议创建一个专用用户来运行它,以提高安全性。
第五步:管理你的服务 #
在你创建并保存了 .service 文件后,就可以使用 systemctl 命令来管理你的服务了。
-
重载
systemd配置: 每次创建或修改.service文件后,你都必须运行此命令来让systemd重新加载配置。sudo systemctl daemon-reload -
启动服务:
sudo systemctl start gemini-ui.service -
查看服务状态(最常用的命令): 这是排查问题的首要工具!它会显示服务是否正在运行、进程ID (PID) 以及最新的几行日志输出。
sudo systemctl status gemini-ui.service- 如果看到
Active: active (running),恭喜你,服务运行正常! - 如果看到
Active: failed,说明启动失败,你需要查看下方的日志来找出原因。
- 如果看到
-
设置开机自启动: 要让服务在服务器重启后自动运行,你需要“启用”它。
sudo systemctl enable gemini-ui.service(对应的,禁用开机自启是
sudo systemctl disable gemini-ui.service) -
停止服务:
sudo systemctl stop gemini-ui.service -
重启服务: 当你修改了 Python 代码并想让它生效时,使用此命令。
sudo systemctl restart gemini-ui.service
第六步:查看日志 #
systemd 有自己强大的日志系统 journald。你可以用 journalctl 命令方便地查看你的程序的所有输出(包括 print 语句和错误信息)。
-
查看服务的全部日志:
sudo journalctl -u gemini-ui.service -
实时查看日志(类似
tail -f): 这个命令在调试时非常有用,可以实时看到程序的输出。sudo journalctl -u gemini-ui.service -f -
查看最新的100行日志:
sudo journalctl -u gemini-ui.service -n 100
总结 #
通过以上步骤,你已经成功地将一个简单的 Python 脚本转变成了一个健壮、可靠、可管理的系统服务。从此以后,你再也无需担心程序崩溃或服务器重启导致的服务中断。这是从“能用”到“可靠”的关键一步。