目录
在《DevOps(十)Jenkins实战之发布Django开发Web应用》的博文中,我们学习了创建一个简单的Jenkins脚本用来发布Django开发Web应用,在Jenkins任务执行的时候会有一个问题,就是git拉取代码以后,启动django应用以后会卡住,不会执行后面的步骤了,jenkins一直在等待django应用执行的结果,导致后面的任务无法执行。怎么解决这个问题呢?我们需要引进一个工具Supervisor,这个工具是用来管理进程,一般和Python应用一起配合使用,可以确保django应用在服务器后台运行。本篇博文当中我们首先介绍Supervisor,然后用给大家演示修改Jenkins脚本,优化这个发布任务。
Supervisor是一个用Python编写的客户端/服务器系统,用于监控和控制UNIX-like操作系统上的多个进程。它主要用于管理长时间运行的后台进程,并且广泛应用于Python web应用程序(如Django、Flask等)的生产环境中。
Supervisor 可以通过 Python 的包管理工具 pip 安装。首先确保你的系统中安装了 Python 和 pip。
sudo apt-get install python-pip # Debian/Ubuntu
然后使用 pip 安装 Supervisor:
sudo pip install supervisor
安装完成后,你需要创建一个配置文件。Supervisor 提供了一个工具 echo_supervisord_conf
,用于生成默认的配置文件:
echo_supervisord_conf > /etc/supervisord.conf
你可以将此文件放在任何地方,但通常放在 /etc/supervisord.conf
。
打开 /etc/supervisord.conf
,进行以下基本配置:
[unix_http_server]: 配置http服务器,用于内部通信。
- ;http://localhost:9001
- file=/tmp/supervisor.sock ; (the path to the socket file)
[supervisord]: 主进程的日志配置。
- logfile=/var/log/supervisor/supervisord.log ; (main log file path)
- logfile_maxbytes=50MB ; (max log file bytes b4 rotation)
- logfile_backups=10 ; (num of main logfile rotation backups)
- loglevel=info ; (logging level)
- pidfile=/var/run/supervisord.pid ; (pidfile path)
[supervisorctl]: 控制工具的配置。
serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket
[program:x]: 定义要管理的程序。
- [program:yourprogramname]
- command=/path/to/command ; the program (relative uses PATH, can take args)
- autostart=true ; start at supervisord start (default: true)
- autorestart=true ; retstart at unexpected quit (default: true)
- stderr_logfile=/var/log/yourprogramname/err.log
- stdout_logfile=/var/log/yourprogramname/out.log
配置文件设置完成后,可以使用以下命令启动 Supervisor:
supervisord -c /etc/supervisord.conf
supervisorctl
是一个命令行客户端工具,用于与 Supervisord 交互。一些基本的命令包括:
- supervisorctl status # 查看所有程序的状态
- supervisorctl stop all # 停止所有程序
- supervisorctl start all # 启动所有程序
- supervisorctl restart all # 重启所有程序
- supervisorctl update # 重新载入配置文件并添加/删除管理的程序
我们这次在源码增加一个Supervisor的配置django.conf文件,然后git将所有源码拉下来以后,将源码拷到一个python应用发布的目录比如/opt/HelloWorld,然后将django.conf复制到/etc/supervisor/conf.d/目录,然后重新载入配置文件,重启django应用。具体步骤如下:
在源码根目录新建一个配置文件django.conf,内容如下:
- [program:django]
- command=python manage.py runserver 0.0.0.0:8081
- directory=/opt/HelloWorld
- user=jenkins
- autostart=true
- autorestart=true
- stderr_logfile=/var/log/django/django.err.log
- stdout_logfile=/var/log/django/django.out.log
这个配置是在 Supervisor 配置文件中定义的,用于管理一个名为 "django" 的程序。这里,配置指定了如何启动、运行、监控和记录 Django 应用的日志。下面是每个配置项的详细解释:
[program:django]: 这一行定义了一个新的程序部分,名为 "django"。在 Supervisor 中,每个被管理的程序都需要在配置文件中以 [program:name]
的形式独立设置。
command: 指定启动程序的命令。在这个例子中,命令是 python manage.py runserver 0.0.0.0:8000
,这是启动 Django 开发服务器的标准方式,监听所有可用 IP 的 8000 端口。注意,实际生产环境中不推荐使用 Django 自带的开发服务器,而应该使用像 Gunicorn 或 uWSGI 这样的生产级应用服务器。
directory: 设置程序执行时的工作目录。对于这个 Django 应用,工作目录被设置为 /opt/HelloWorld
。Supervisor 会在启动程序前切换到这个目录。
user: 指定运行该程序的用户。这里配置为 jenkins
,意味着 Django 应用将以 jenkins
用户的权限运行。这有助于限制程序的权限,增加系统的安全性。
autostart: 表示 Supervisor 会在启动时自动启动这个程序。设置为 true
,确保每次 Supervisor 启动时,Django 应用也会自动启动。
autorestart: 配置程序在退出时是否自动重启。设置为 true
,意味着如果 Django 应用意外停止或崩溃,Supervisor 会自动重新启动它。
stderr_logfile: 指定标准错误流的日志文件路径。在这个配置中,所有标准错误输出将被重定向到 /var/log/django/django.err.log
。这对于调试和记录错误非常有用。
stdout_logfile: 指定标准输出流的日志文件路径。在这个配置中,所有标准输出将被记录在 /var/log/django/django.out.log
。这可以帮助您审查程序的运行输出。
这个配置是一个典型的例子,展示了如何使用 Supervisor 来管理一个 Django 应用。通过这种方式,您可以确保应用的持续运行,并且能够在出现问题时迅速响应。在设置完这些配置后,您需要确保相应的日志目录存在,并且 jenkins
用户有权写入这些目录。
注意:需要在jenkins服务器创建/var/log/django目录,并给这个目录jenkin所有权。完成脚本以后,提交发布到gitlab。
打开jenkins管理界面,选择前面我们创建的jenkins任务HelloWorld。
点击配置按钮,进入配置界面。
编写jenkins脚本,然后保存。
Jenkins脚本代码如下:
- pipeline {
- agent any
-
- stages {
- stage('Checkout') {
- steps {
- git branch: 'main', credentialsId: 'sean', url: 'http://gitlab.povison-pro.com/Sean/helloworld.git'
- }
- }
-
- stage('Stop Application') {
- steps {
- script {
- // 检查 Django 服务是否存在
- def serviceStatus = sh(script: "sudo supervisorctl status django || true", returnStdout: true).trim()
- if (serviceStatus.contains("RUNNING")) {
- // 如果服务正在运行,尝试停止它
- sh 'sudo supervisorctl stop django'
- } else {
- echo "Django process not running or does not exist."
- }
- }
- }
- }
-
- stage('Prepare Deployment') {
- steps {
- // 清理旧代码并复制新代码到 /opt/HelloWorld
- sh 'sudo rm -rf /opt/HelloWorld/*'
- sh 'sudo cp -R . /opt/HelloWorld'
- }
- }
-
- stage('Configure Supervisor') {
- steps {
- // 假设 django.conf 已经准备好,在源码根目录
- sh 'sudo cp /opt/HelloWorld/django.conf /etc/supervisor/conf.d/django.conf'
- sh 'sudo supervisorctl reread'
- sh 'sudo supervisorctl update'
- }
- }
-
- stage('Restart Application') {
- steps {
- sh 'sudo supervisorctl restart django'
- }
- }
- }
-
- post {
- always {
- // 清理工作,可选
- echo 'Build completed.'
- }
- }
- }
上面 Jenkins Pipeline 脚本的详细解析:
声明和代理
pipeline
: 声明这是一个 Jenkins Pipeline 脚本。agent any
: 指定 Pipeline 可以在任何可用的 Jenkins Agent 上运行。阶段定义
Checkout 阶段
branch
: 指定要克隆的分支名称。credentialsId
: 指定用于访问 Git 仓库的凭证 ID。url
: 指定 Git 仓库的 URL。Stop Application 阶段
script
块执行 Groovy 代码:
serviceStatus
: 运行 supervisorctl status django
命令检查 Django 服务状态,并使用 || true
忽略可能的错误。serviceStatus
包含 "RUNNING",则使用 supervisorctl stop django
命令停止 Django 服务。Prepare Deployment 阶段
sh
步骤执行 shell 命令:
sudo rm -rf /opt/HelloWorld/*
: 删除 /opt/HelloWorld/
目录中的所有文件。sudo cp -R . /opt/HelloWorld
: 将 Jenkins 工作空间中的所有文件复制到 /opt/HelloWorld/
目录。Configure Supervisor 阶段
sh
步骤执行 shell 命令:
sudo cp /opt/HelloWorld/django.conf /etc/supervisor/conf.d/django.conf
: 将 django.conf
文件复制到 supervisord 配置目录。sudo supervisorctl reread
: 重新读取 supervisord 配置文件。sudo supervisorctl update
: 更新 supervisord 进程。Restart Application 阶段
sh
步骤执行 shell 命令:
sudo supervisorctl restart django
: 重启 django
进程。后处理 (Post)
always
: 无论 Pipeline 执行成功或失败,都会执行此块中的步骤。echo 'Build completed.'
: 输出信息表示构建已完成。这个 Jenkins Pipeline 脚本实现了以下功能:
/opt/HelloWorld/
目录。请根据您的实际环境和需求调整脚本,例如文件路径、Git 仓库 URL、凭证 ID 和 supervisord 配置。
执行这个修改保存后的jenkins任务,我们看到任务执行成功了。
然后在浏览器访问一下这个页面,http://192.168.110.170:8081/hello/就能看到我们想要的页面了。