如何在Linux服务器上后台持久运行Gunicorn

news2025/2/23 13:10:56

如何在Linux服务器上后台持久运行Gunicorn

  • **问题概述**
  • **解决方案一:使用`nohup`命令**
  • **解决方案二:使用`systemd`服务**
    • **创建`systemd`服务文件**
    • **修改`systemd`服务文件以使用虚拟环境**
    • 日志管理
    • **激活并启动服务:**
    • 如何设置用户和组
      • **确认用户和组存在**
      • 如何赋予用户和组对应用程序目录和所需资源有正确的权限
      • 如何查看我的目前系统中的用户和组
  • **结论**

问题概述

在使用SSH远程连接到服务器并在终端启动**gunicorn时,关闭SSH窗口后常常导致gunicorn**进程终止,这导致无法访问API接口,尽管端口侦听似乎仍在进行。

解决方案一:使用nohup命令

nohup命令可用于在退出登录或关闭终端后继续运行进程。要使用nohup,您可以在命令前加上**nohup,并在命令最后添加&**,将进程放入后台运行。

nohup gunicorn -w 4 --bind 0.0.0.0:6666 --reload run:app --timeout 120 --access-logfile - --error-logfile - &

这个命令将**gunicorn的输出重定向到一个名为nohup.out的文件中,即使SSH会话关闭,gunicorn**进程也会继续运行。

解决方案二:使用systemd服务

创建systemd服务文件

创建一个新的服务文件**/etc/systemd/system/gunicorn.service(服务文件名你可以自己定义,例如answerai.service)**,文件内容如下:

[Unit]
Description=gunicorn daemon for my web application
After=network.target

[Service]
User=myuser
Group=mygroup
WorkingDirectory=/path/to/your/app
ExecStart=/path/to/your/virtualenv/bin/gunicorn --workers 4 --bind 0.0.0.0:6666 run:app
StandardOutput=append:/path/to/your/logs/gunicorn.out
StandardError=append:/path/to/your/logs/gunicorn.err

[Install]
WantedBy=multi-user.target

替换**myusermygroup/path/to/your/app/path/to/your/virtualenv/bin/gunicorn**为您的实际信息。

在这个文件中:

  • 我们设定了描述和在网络服务启动之后启动**gunicorn**。

  • 在**[Service]**部分,我们定义了运行服务的用户(myuser)和组(mygroup),服务的工作目录(/path/to/your/app),以及启动命令。

  • **ExecStart行指定了启动服务时要执行的命令。在这里,我们告诉gunicorn**使用4个工作进程

    ExecStart 中的命令实际上定义了如何启动 gunicorn 以及它将如何与您的应用程序进行通信。这里有两种常见的绑定方式:

    1. 绑定到一个 UNIX 套接字:

      ExecStart=/var/www/myapp/venv/bin/gunicorn --workers 4 --bind unix:/var/www/myapp/myapp.sock myapp.wsgi:application
      

      这条命令将 gunicorn 绑定到一个 UNIX 套接字文件 myapp.sock。这种方式在与 Nginx 等 Web 服务器配合时很常见,因为它们可以直接通过 UNIX 套接字与 gunicorn 通信,这比 TCP 套接字更高效,因为它们不需要进行网络堆栈的额外处理。

    2. 绑定到 TCP 端口:

      ExecStart=/path/to/your/virtualenv/bin/gunicorn --workers 4 --bind 0.0.0.0:6666 run:app
      

      这条命令将 gunicorn 绑定到所有接口的 6666 端口。这种方式在您直接通过 HTTP 访问 gunicorn 时很有用,或者在测试环境中很常见,因为它允许从任何 IP 地址通过指定端口访问应用程序。

      选择哪种方式取决于您的部署需求和安全考虑。UNIX 套接字通常更安全,因为它们在文件系统中作为文件存在,不对外暴露端口,而且通常会配合 Web 服务器一起使用。如果您直接使用 TCP 端口绑定,那么可能需要考虑使用防火墙规则来限制对该端口的访问。

  • 最后,在**[Install]**部分,我们定义了这个服务将如何被安装和启动,这里是在多用户目标下。

    在**systemd服务文件中的[Install]部分,WantedBy是一个指令,它定义了当该服务被enable时应该被哪个“目标”(target)所拉起。目标是systemd**中用于定义系统启动过程中的不同阶段的一个单位。

    **multi-user.target是一个目标,它相当于传统的运行级别(runlevel)。它通常用于设置一个多用户的文本模式环境,没有图形界面,但网络服务已启动并可以使用。当您设置一个服务WantedBy=multi-user.target并启用它(使用systemctl enable命令)时,您告诉systemd**在达到多用户文本模式时,也就是系统启动过程中达到相应的点时,应该启动这个服务。

    简单来说,**WantedBy=multi-user.target**确保了您的服务会在系统启动到多用户运行级别时自动启动。这是大多数后台服务的标准配置,使得在系统启动时无需手动启动服务。

修改systemd服务文件以使用虚拟环境

如果您需要在Python虚拟环境中运行**gunicorn,您应该在systemd服务文件的ExecStart命令中指定虚拟环境中的gunicorn**可执行文件的完整路径。这样,服务在启动时会使用虚拟环境中的Python和依赖包。

您的服务文件中的**ExecStart**部分应该看起来像这样:

[Service]
...
ExecStart=/path/to/your/virtualenv/bin/gunicorn --workers 4 --bind 0.0.0.0:6666 run:app
...

在这里,**/path/to/your/virtualenv/bin/gunicorn是您虚拟环境中gunicorn的完整路径。您需要将/path/to/your/virtualenv**替换为您的虚拟环境实际所在的路径。

举例说明:

假设您的虚拟环境位于**/home/myuser/myappenv,并且您的应用程序目录是/home/myuser/myapp**。服务文件可能会是这样的:

[Unit]
Description=gunicorn daemon for myapp web application
After=network.target

[Service]
User=myuser
Group=myuser
WorkingDirectory=/home/myuser/myapp
ExecStart=/home/myuser/myappenv/bin/gunicorn --access-logfile - --workers 4 --bind 0.0.0.0:6666 myapp.wsgi:application

[Install]
WantedBy=multi-user.target

这里的关键是确保**ExecStart指向了虚拟环境中的gunicorn**。

日志管理

使用**systemd来管理gunicorn服务时,systemd本身提供了日志管理功能,它会自动处理服务的输出,并存储在系统的日志中,可以通过journalctl命令来访问。因此,如果您使用systemd,通常不需要nohup来重定向输出到文件中,systemd**会更好地为您服务。

不过,如果您仍然想要将**gunicorn的输出重定向到特定的文件,您可以在systemd服务文件的[Service]部分使用StandardOutputStandardError**指令来指定输出和错误日志的路径。

例如:

[Service]
...
ExecStart=/path/to/your/virtualenv/bin/gunicorn --workers 4 --bind 0.0.0.0:6666 run:app
StandardOutput=append:/path/to/your/logs/gunicorn.out
StandardError=append:/path/to/your/logs/gunicorn.err
...

这里,StandardOutput=append:/path/to/your/logs/gunicorn.out指令将会把stdout输出追加到指定的文件中,StandardError=append:/path/to/your/logs/gunicorn.err则将错误信息追加到另一个文件。您需要确保这些文件是可写的,并且gunicorn运行的用户(在[Service]部分指定的User)具有写入这些文件的权限。

请注意,使用**append是在systemd较新版本中引入的选项,如果您的系统中的systemd版本不支持,您可能需要去掉append:**并直接写文件路径。

此外,如果您想保留使用**nohup的原始方法并重定向输出到文件,那么您就不需要systemd服务。您只需在命令行中启动gunicorn**,如下所示:

nohup /path/to/your/virtualenv/bin/gunicorn --workers 4 --bind 0.0.0.0:6666 run:app > /path/to/your/logs/gunicorn.out 2>&1 &

在这里,>是将标准输出(stdout)重定向到文件,2>&1是将标准错误(stderr)也重定向到同一个文件中。结尾的**&是将进程放到后台运行。这样做,即使SSH会话关闭,gunicorn进程也会继续运行,并且它的输出会被记录到/path/to/your/logs/gunicorn.out**文件中。

激活并启动服务:

在创建和配置好服务文件之后,以下命令将帮助您管理服务:

# 重新加载systemd以识别新的服务
sudo systemctl daemon-reload

# 启动gunicorn服务
sudo systemctl start gunicorn.service

# 设置gunicorn服务开机启动
sudo systemctl enable gunicorn.service

# 检查gunicorn服务的状态
sudo systemctl status gunicorn.service

# 查看gunicorn服务的日志
journalctl -u gunicorn.service

这样一来,您的**gunicorn**进程就会在指定的Python虚拟环境中运行,而且即使在SSH会话关闭后也能持续运行。

如何设置用户和组

确认用户和组存在

在您的**systemd服务文件中指定的用户(User)和组(Group**)应该是系统中已存在的。使用以下命令查看系统中的用户和组:

  • 查看所有用户:cat /etc/passwdgetent passwd
  • 查看所有组:cat /etc/groupgetent group

如果需要,您可以创建一个新的用户和组:

sudo adduser myuser
sudo addgroup mygroup
sudo adduser myuser mygroup

确保这个用户和组对应用程序目录和所需资源有正确的权限。

在Linux系统中,当您创建一个新用户时,默认情况下,系统会为该用户创建一个同名的用户组,并且这个用户会自动成为那个组的成员。这个默认组被称为用户的"主组"(primary group)。每个文件都有一个所有者和一个组,且新文件的默认组设置通常是其所有者的主组。

然而,如果您需要让用户属于额外的组,您需要手动将用户添加到这些组中。这就是**sudo adduser myuser mygroup命令的作用。它将用户myuser添加到组mygroup**,作为它的附加组(secondary group)。

这样做的原因可能是:

  • 权限共享:如果您希望**myuser能够访问由mygroup**组拥有的文件或目录,您需要将该用户添加到该组。
  • 应用需求:某些应用程序可能要求用户必须属于特定的组才能运行。
  • 安全控制:通过将用户分配给特定的组,您可以更细粒度地控制用户的权限,而不是给予他们更广泛的权限。

所以,最后这步**sudo adduser myuser mygroup是为了确保myuser不仅拥有其主组的权限,还能够获取其他组如mygroup的组权限。如果mygroup**是您创建的特定目的的组,您需要执行这个命令来实现这一点。如果不需要额外的组权限,这一步则不是必需的。

如何赋予用户和组对应用程序目录和所需资源有正确的权限

  1. 更改所有者: 使用 chown 命令将您的应用目录的所有权更改为正确的用户和组。

    sudo chown -R 用户名:组名 /应用目录路径
    

    替换 用户名组名 为实际的用户名和组名,/应用目录路径 为您的应用实际所在的路径。

  2. 设置权限: 使用 chmod 命令为目录设置权限。

    • 让用户有完全的权限:

      sudo chmod -R 700 /应用目录路径
      
    • 让组有读取和执行权限:

      sudo chmod -R 750 /应用目录路径
      
    • 验证权限
      使用**ls -l**命令来验证权限和所有权是否正确设置。

      ls -l /path/to/your/app
      
    • 测试权限
      切换到您的**gunicorn**用户,尝试读取和写入应用程序目录中的文件。

      sudo -u myuser -g mygroup touch /path/to/your/app/testfile
      

    如果命令执行没有错误,表示权限设置正确。

    确保在设置权限时,您明白每个权限的含义,以及为什么要分配它们。不恰当的权限设置可能会导致安全风险,特别是在生产环境中。通常,最佳实践是赋予最小必要权限,以避免潜在的安全问题。

    需要注意的是:

    root 用户在Linux系统中具有最高权限。root 能够访问和操作系统上的所有文件和命令,无论这些文件的权限设置是什么。这意味着即使一个文件的权限被设置为只允许特定用户访问,root 用户仍然可以操作这个文件。

    当您使用 root 用户时,您需要特别小心,因为具有这样的权限也意味着您能够执行任何可能对系统造成损害的操作。所以通常建议对于日常操作使用普通用户,并仅在需要进行系统级更改时使用 root 权限。

在这里插入图片描述

如何查看我的目前系统中的用户和组

您可以通过几个不同的命令在Linux系统中查看存在的用户和组。

查看用户列表:

  1. 查看**/etc/passwd**文件,这个文件包含了系统上每个用户的信息:

    cat /etc/passwd
    
  2. 使用**getent**命令:

    getent passwd
    

这些命令会列出所有用户,其中每一行代表一个用户,行中的第一个字段是用户名。

查看组列表:

  1. 查看**/etc/group**文件,这个文件包含了系统上每个组的信息:

    cat /etc/group
    
  2. 使用**getent**命令:

    getent group
    

这些命令会列出所有组,其中每一行代表一个组,行中的第一个字段是组名。

结论

无论您选择**nohup还是systemd,关键是确保您的gunicorn进程在后台稳定运行,并且能够在系统重启后自动启动。systemd提供了一个更强大和可配置的解决方案,适合生产环境。而nohup**是一个快速且简单的临时解决方案,适合开发或测试环境。请确保使用正确的用户和组,并为服务和日志文件设置适当的权限。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1199342.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【博士每天一篇文献-算法】A pseudo-inverse decomposition-based self-organizing modular echo

阅读时间:2023-11-6 1 介绍 年份:2022 作者:王雷,北京信息科技大学自动化学院 期刊: Applied Soft Computing 引用量:12 提出了一种基于伪逆分解的自组织模块化回声状态(PDSM-ESN&#xff09…

基于python+django的美食餐厅点餐订餐网站

运行环境 开发语言:Python python框架:django 软件版本:python3.7 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:PyCharm/vscode 前端框架:vue.js 项目介绍 本论文主要论述了如何使用python语言开发…

asp.net员工管理系统VS开发sqlserver数据库web结构c#编程包括出差、请假、考勤

一、源码特点 asp.net员工管理系统是一套完善的web设计管理系统(主要包括出差、请假、考勤基础业务管理),系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为vs2010 ,数据库为sqlserver2008&a…

Http状态码502常见原因及排错思路(实战)

Http状态码502常见原因及排错思路 502表示Bad Gateway。当Nginx返回502错误时,通常表示Nginx作为代理服务器无法从上游服务器(如:我们的后端服务器地址)获取有效的响应。导致这种情况的原因有很多: 后端服务器故障ngin…

在 WSL 上启用 NVIDIA CUDA

环境要求 Windows 11 或 Windows 10 版本 21H2特定版本的GPU驱动: 安装支持 NVIDIA CUDA 的 WSL 驱动程序: https://www.nvidia.com/download/index.aspx具体安装哪个版本,查阅:https://docs.nvidia.com/cuda/wsl-user-guide/in…

从虚拟机下载开始的kubeSphere安装

目录 一、虚拟机安装 二、镜像下载安装 1、镜像下载 2、虚拟机创建 3、虚拟机系统安装 三、虚拟机配置 1、IP固定 2、配置yum阿里源 3、关闭防火墙 4、 关闭selinux 5、 禁止swap交换 6、内核参数修改 7、设置kubernetes源 四、docker安装 五、虚拟机分组 六、…

Linux之IPC通信共享内存(一次拷贝)与消息队列、管道、信号量、socket(两次拷贝)总结(六十二)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…

【蓝桥杯选拔赛真题18】C++病毒繁殖 第十二届蓝桥杯青少年创意编程大赛C++编程选拔赛真题解析

目录 C/C++病毒繁殖 一、题目要求 1、编程实现 2、输入输出 二、算法分析 <

微信小程序入门及开发准备,申请测试号以及小程序开发的两种方式,目录结构说明

目录 1. 介绍 1.1 优点 1.2 开发方式 2. 开发准备 2.1 申请 2.2 申请测试号 2.2 小程序开发的两种方式 2.3 开发工具 3. 开发一个demo 3.1 创建项目 3.2 配置 3.3 常用框架 3.3 目录结构说明 3.4 新建组件 1. 介绍 1.1 优点 是一种不需要下载安装即可使用的应用…

【LeetCode】每日一题 2023_11_12 每日一题 Range 模块

文章目录 刷题前唠嗑题目&#xff1a;Range 模块题目描述代码与解题思路 刷题前唠嗑 LeetCode? 启动&#xff01;&#xff01;&#xff01; 嗯&#xff1f;怎么是 hard&#xff0c;好长&#xff0c;可恶&#xff0c;看不懂&#xff0c;怎么办 题目&#xff1a;Range 模块 题…

邻接矩阵储存图实现深度优先遍历(C++)

目录 基本要求&#xff1a; 图的结构体&#xff1a; 图的构造&#xff1a; 图的深度优先&#xff08;DFS&#xff09;&#xff1a; 图的打印输出&#xff1a; 完整代码&#xff1a; 测试数据&#xff1a; 运行结果&#xff1a; 通过给出的图的顶点和边的信息&#xff0c…

Apache和Nginx实现虚拟主机的3种方式

目录 首先介绍一下Apache和nginx&#xff1a; Nginx和Apache的不同之处&#xff1a; 虚拟主机 准备工作 Apache实现&#xff1a; 方法1&#xff1a;使用不同的ip来实现 方法2&#xff1a;使用相同的ip&#xff0c;不同的端口来实现 方法3&#xff1a;使用相同的ip&…

【C++基础 】类和对象(上)

C基础 类和对象&#xff08;上&#xff09; 1.面向过程和面向对象初步认识2.类的引入3.类的定义4.类的访问限定符及封装4.1 访问限定符4.2 封装 5.类的作用域6.类的实例化7.类对象模型7.1 如何计算类对象的大小7.2 类对象的存储方式猜测7.3 结构体内存对齐规则 8.this指针8.1 t…

人工智能领域200例教程专栏—学习人工智能的指南宝典

&#x1f389;&#x1f38a;&#x1f389; 你的技术旅程将在这里启航&#xff01; &#x1f680; 本专栏&#xff1a;人工智能领域200例教程专栏 从基础到实践&#xff0c;深入学习。无论你是初学者还是经验丰富的老手&#xff0c;对于本专栏案例和项目实践都有参考学习意义。 …

2023 年最新 Alipay 支付包商户接入实现 Java 网站在线支付功能(详细指南教程)

支付宝商户注册申请 若您的材料在电脑端&#xff0c;或企业/单位要求在电脑端操作。您的材料在手机端且方便在支付宝App中管理企业信息&#xff0c;可参阅《手机端开通企业支付宝-操作手册》开通企业支付宝。电脑端准备材料并使用个人支付宝扫码验证身份后开始注册。

二叉树的遍历(先序,中序,后序,层序)

目录 1.先序遍历1.代码实现 2.中序遍历1.代码实现 3.后序遍历1.代码实现 4.遍历算法的应用5.层序遍历1.算法思想2.代码实现 6.由遍历序列构造二叉树 1.先序遍历 根左右。 1.代码实现 若二叉树为空&#xff0c;则什么也不做; 若二叉树非空: ①访问根结点; ②先序遍历左子树; ③先…

Rt-Thread 移植6--多线程(KF32)

6.1 就绪列表 6.1.1 线程就绪优先级组 线程优先级表的索引对应的线程的优先级。 为了快速的找到线程在线程优先级表的插入和移出的位置&#xff0c;RT-Thread专门设计了一个线程就绪优先级组。线程就绪优先组是一个32位的整型数&#xff0c;每一个位对应一个优先级&#xff…

Leetcode—69.x的平方根【简单】

2023每日刷题&#xff08;二十七&#xff09; Leetcode—69.x的平方根 直接法实现代码 int mySqrt(int x) {long long i 0;while(i * i < x) {i;}if(i * i > x) {return i - 1;}return i; }运行结果 二分法实现代码 int mySqrt(int x) {long long left 0, right (l…

数据拟合、参数估计、插值等数据处理算法

介绍 数据拟合&#xff1a; 数据拟合是通过选择或构建合适的函数模型&#xff0c;将给定的数据点与该函数模型进行匹配和拟合的过程。常见的数据拟合方法包括最小二乘法和非线性最小二乘法。最小二乘法通过最小化实际数据与拟合函数的残差平方和来求解最优拟合参数。非线性最小…