最初一个版本,已经初步实现各种功能
主页连接 远程命令 django Gunicorn操作
This commit is contained in:
89
README.md
Normal file
89
README.md
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
# 服务器管理工具
|
||||||
|
|
||||||
|
一个基于PySide6的桌面应用程序,用于管理远程服务器连接和执行远程命令。
|
||||||
|
|
||||||
|
## 功能特性
|
||||||
|
|
||||||
|
### 服务器连接标签
|
||||||
|
- 自动读取同目录下的config.json配置文件
|
||||||
|
- 支持多个服务器配置的别名选择
|
||||||
|
- 自动填充服务器信息(IP地址、端口、用户名、密码、项目名称)
|
||||||
|
- Git配置(Git仓库URL、远程目录路径)
|
||||||
|
- 支持保存和更新配置文件
|
||||||
|
- SSH协议连接服务器并显示连接状态
|
||||||
|
|
||||||
|
### 远程命令标签
|
||||||
|
- **安装Git**:检查并远程安装Git(如果未安装)
|
||||||
|
- **拉取代码**:根据提供的URL拉取代码到指定路径
|
||||||
|
- 显示操作状态和结果
|
||||||
|
- 实时进度显示
|
||||||
|
|
||||||
|
## 安装和运行
|
||||||
|
|
||||||
|
### 1. 安装依赖
|
||||||
|
```bash
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 配置服务器信息
|
||||||
|
编辑`config.json`文件,添加您的服务器连接信息:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"alias": "服务器别名",
|
||||||
|
"host": "服务器IP地址",
|
||||||
|
"port": 22,
|
||||||
|
"username": "用户名",
|
||||||
|
"password": "密码",
|
||||||
|
"project_name": "项目名称"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 运行程序
|
||||||
|
```bash
|
||||||
|
python main.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## 使用说明
|
||||||
|
|
||||||
|
### 使用说明
|
||||||
|
|
||||||
|
### 服务器连接
|
||||||
|
1. 从下拉列表选择服务器别名,程序会自动填充连接信息
|
||||||
|
2. 填写Git配置信息(Git仓库URL、远程目录路径)
|
||||||
|
3. 点击"保存配置"按钮可以保存或更新服务器配置
|
||||||
|
4. 点击"连接服务器"按钮建立SSH连接
|
||||||
|
5. 连接状态会显示在界面底部
|
||||||
|
|
||||||
|
### 远程命令
|
||||||
|
1. 确保已成功连接服务器
|
||||||
|
2. **安装Git**:点击"安装Git"按钮检查并安装Git(如果未安装)
|
||||||
|
3. **拉取代码**:
|
||||||
|
- 仓库URL和项目路径会根据服务器配置自动填充
|
||||||
|
- 如需修改,可以在"仓库URL"输入框中输入Git仓库地址
|
||||||
|
- 在"项目路径"输入框中输入服务器上的目标路径
|
||||||
|
- 点击"拉取代码"按钮开始拉取代码
|
||||||
|
4. **查看目录**:点击"ls -al"按钮可以查看指定目录的详细内容
|
||||||
|
5. 操作结果会显示在输出区域
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
- 确保服务器支持SSH连接
|
||||||
|
- 确保提供的用户名和密码正确
|
||||||
|
- 确保服务器有足够的权限安装软件和创建目录
|
||||||
|
- 程序会自动检测并安装Git(如果未安装)
|
||||||
|
|
||||||
|
## 技术栈
|
||||||
|
- **GUI框架**: PySide6
|
||||||
|
- **SSH连接**: paramiko
|
||||||
|
- **日志记录**: loguru
|
||||||
|
- **目标服务器**: Ubuntu Linux
|
||||||
|
|
||||||
|
## 界面预览
|
||||||
|
程序采用现代化的界面设计,包含:\- 美观的标签页布局
|
||||||
|
- 直观的表单输入
|
||||||
|
- 实时状态反馈
|
||||||
|
- 进度条显示
|
||||||
|
- 彩色状态指示
|
||||||
BIN
__pycache__/django_tab.cpython-38.pyc
Normal file
BIN
__pycache__/django_tab.cpython-38.pyc
Normal file
Binary file not shown.
BIN
__pycache__/gunicorn_tab.cpython-38.pyc
Normal file
BIN
__pycache__/gunicorn_tab.cpython-38.pyc
Normal file
Binary file not shown.
BIN
__pycache__/remote_command_tab.cpython-38.pyc
Normal file
BIN
__pycache__/remote_command_tab.cpython-38.pyc
Normal file
Binary file not shown.
BIN
__pycache__/server_connection_tab.cpython-38.pyc
Normal file
BIN
__pycache__/server_connection_tab.cpython-38.pyc
Normal file
Binary file not shown.
BIN
__pycache__/threads.cpython-38.pyc
Normal file
BIN
__pycache__/threads.cpython-38.pyc
Normal file
Binary file not shown.
420
app.2025-08-25_22-27-02_430599.log
Normal file
420
app.2025-08-25_22-27-02_430599.log
Normal file
@@ -0,0 +1,420 @@
|
|||||||
|
2025-08-25 22:27:02.431 | INFO | __main__:<module>:445 - 应用程序启动
|
||||||
|
2025-08-25 22:27:24.671 | INFO | __main__:save_config:108 - 配置文件保存成功
|
||||||
|
2025-08-25 22:27:34.200 | INFO | __main__:run:25 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-25 22:27:34.330 | INFO | __main__:run:31 - 服务器连接成功
|
||||||
|
2025-08-25 22:29:21.628 | INFO | __main__:<module>:516 - 应用程序启动
|
||||||
|
2025-08-25 22:29:48.273 | INFO | __main__:<module>:516 - 应用程序启动
|
||||||
|
2025-08-25 22:30:19.896 | INFO | __main__:run:25 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-25 22:30:19.993 | INFO | __main__:run:31 - 服务器连接成功
|
||||||
|
2025-08-25 22:30:21.941 | INFO | __main__:run:47 - 开始检查并安装Git
|
||||||
|
2025-08-25 22:30:21.961 | INFO | __main__:run:54 - Git已安装
|
||||||
|
2025-08-25 22:30:21.962 | INFO | __main__:on_git_install_result:419 - Git安装结果: True - Git已安装
|
||||||
|
2025-08-26 21:08:59.421 | INFO | __main__:<module>:516 - 应用程序启动
|
||||||
|
2025-08-26 21:09:01.527 | INFO | __main__:run:25 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-26 21:09:01.694 | INFO | __main__:run:31 - 服务器连接成功
|
||||||
|
2025-08-26 21:09:03.832 | INFO | __main__:run:25 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-26 21:09:03.913 | INFO | __main__:run:31 - 服务器连接成功
|
||||||
|
2025-08-26 21:10:46.707 | INFO | __main__:run:47 - 开始检查并安装Git
|
||||||
|
2025-08-26 21:10:46.738 | INFO | __main__:on_git_install_result:419 - Git安装结果: True - Git已安装
|
||||||
|
2025-08-26 21:10:46.739 | INFO | __main__:run:54 - Git已安装
|
||||||
|
2025-08-26 21:10:49.648 | INFO | __main__:run:87 - 开始拉取代码: http://192.168.3.241:3000/xiaji/webstatus
|
||||||
|
2025-08-26 21:10:49.704 | INFO | __main__:run:101 - 开始克隆代码到: /home/xiaji
|
||||||
|
2025-08-26 21:10:49.757 | ERROR | __main__:run:106 - 代码拉取失败: fatal: destination path '.' already exists and is not an empty directory.
|
||||||
|
|
||||||
|
2025-08-26 21:10:49.759 | INFO | __main__:on_git_clone_result:432 - 代码拉取结果: False - 代码拉取失败: fatal: destination path '.' already exists and is not an empty directory.
|
||||||
|
|
||||||
|
2025-08-26 21:13:07.493 | INFO | __main__:<module>:528 - 应用程序启动
|
||||||
|
2025-08-26 21:15:54.714 | INFO | __main__:<module>:578 - 应用程序启动
|
||||||
|
2025-08-26 21:15:54.749 | INFO | __main__:load_git_config:491 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-26 21:15:58.440 | INFO | __main__:run:25 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-26 21:15:58.536 | INFO | __main__:run:31 - 服务器连接成功
|
||||||
|
2025-08-26 21:16:14.794 | INFO | __main__:run:87 - 开始拉取代码: https://github.com/example/statuspage.git
|
||||||
|
2025-08-26 21:16:14.859 | INFO | __main__:run:105 - 目录 /home/xiaji/ 不为空,正在清空目录
|
||||||
|
2025-08-26 21:16:14.913 | INFO | __main__:run:113 - 开始克隆代码到: /home/xiaji/
|
||||||
|
2025-08-26 21:18:30.048 | ERROR | __main__:run:118 - 代码拉取失败: Cloning into '.'...
|
||||||
|
fatal: unable to access 'https://github.com/example/statuspage.git/': Failed to connect to github.com port 443 after 135044 ms: Could not connect to server
|
||||||
|
|
||||||
|
2025-08-26 21:18:30.053 | INFO | __main__:on_git_clone_result:469 - 代码拉取结果: False - 代码拉取失败: Cloning into '.'...
|
||||||
|
fatal: unable to access 'https://github.com/example/statuspage.git/': Failed to connect to github.com port 443 after 135044 ms: Could not connect to server
|
||||||
|
|
||||||
|
2025-08-26 21:18:54.240 | INFO | __main__:save_config:153 - 配置文件保存成功
|
||||||
|
2025-08-26 21:18:57.954 | INFO | __main__:run:25 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-26 21:18:58.042 | INFO | __main__:run:31 - 服务器连接成功
|
||||||
|
2025-08-26 21:19:04.769 | INFO | __main__:run:87 - 开始拉取代码: http://192.168.3.241:3000/xiaji/webstatus
|
||||||
|
2025-08-26 21:19:04.834 | INFO | __main__:run:105 - 目录 /home/xiaji/ 不为空,正在清空目录
|
||||||
|
2025-08-26 21:19:04.884 | INFO | __main__:run:113 - 开始克隆代码到: /home/xiaji/
|
||||||
|
2025-08-26 21:19:04.979 | INFO | __main__:run:123 - 代码拉取成功到: /home/xiaji/
|
||||||
|
2025-08-26 21:19:04.981 | INFO | __main__:on_git_clone_result:469 - 代码拉取结果: True - 代码拉取成功到: /home/xiaji/
|
||||||
|
2025-08-26 21:21:31.689 | INFO | __main__:<module>:651 - 应用程序启动
|
||||||
|
2025-08-26 21:21:31.725 | INFO | __main__:load_git_config:528 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-26 21:21:41.068 | INFO | __main__:run:25 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-26 21:21:41.156 | INFO | __main__:run:31 - 服务器连接成功
|
||||||
|
2025-08-26 21:21:43.287 | INFO | __main__:run:141 - 开始列出目录内容: /home/xiaji/
|
||||||
|
2025-08-26 21:21:43.298 | INFO | __main__:run:155 - 成功列出目录内容: /home/xiaji/
|
||||||
|
2025-08-26 21:21:43.303 | INFO | __main__:on_list_directory_result:567 - 目录列表结果: True - 目录内容:
|
||||||
|
total 168
|
||||||
|
drwxr-x--- 7 xiaji xiaji 4096 Aug 26 13:21 .
|
||||||
|
drwxr-xr-x 3 root root 4096 Aug 26 2025 ..
|
||||||
|
drwx------ 2 xiaji xiaji 4096 Aug 26 13:21 .cache
|
||||||
|
-rw-rw-r-- 1 xiaji xiaji 135168 Aug 26 13:19 db.sqlite3
|
||||||
|
drwxrwxr-x 8 xiaji xiaji 4096 Aug 26 13:19 .git
|
||||||
|
-rw-rw-r-- 1 xiaji xiaji 666 Aug 26 13:19 manage.py
|
||||||
|
-rw-rw-r-- 1 xiaji xiaji 13 Aug 26 13:19 requirements.txt
|
||||||
|
drwxrwxr-x 5 xiaji xiaji 4096 Aug 26 13:19 status
|
||||||
|
drwxrwxr-x 3 xiaji xiaji 4096 Aug 26 13:19 statuspage
|
||||||
|
drwxrwxr-x 2 xiaji xiaji 4096 Aug 26 13:19 部署文件夹
|
||||||
|
|
||||||
|
2025-08-26 21:37:21.441 | INFO | __main__:<module>:1164 - 应用程序启动
|
||||||
|
2025-08-26 21:37:21.476 | INFO | __main__:load_git_config:761 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-26 21:37:21.478 | INFO | __main__:load_django_config:1073 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-26 21:37:34.833 | INFO | __main__:run:26 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-26 21:37:34.920 | INFO | __main__:run:32 - 服务器连接成功
|
||||||
|
2025-08-26 21:37:52.993 | INFO | __main__:save_config:408 - 配置文件保存成功
|
||||||
|
2025-08-26 21:38:01.208 | INFO | __main__:run:173 - 开始安装Django
|
||||||
|
2025-08-26 21:38:01.227 | ERROR | __main__:run:180 - Django安装失败: sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
|
||||||
|
sudo: a password is required
|
||||||
|
|
||||||
|
2025-08-26 21:38:01.232 | INFO | __main__:on_django_install_result:990 - Django安装结果: False - Django安装失败: sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
|
||||||
|
sudo: a password is required
|
||||||
|
|
||||||
|
2025-08-26 21:42:19.122 | INFO | __main__:<module>:1186 - 应用程序启动
|
||||||
|
2025-08-26 21:42:19.156 | INFO | __main__:load_git_config:783 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-26 21:42:19.157 | INFO | __main__:load_django_config:1095 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-26 21:42:21.426 | INFO | __main__:run:26 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-26 21:42:21.525 | INFO | __main__:run:32 - 服务器连接成功
|
||||||
|
2025-08-26 21:42:24.983 | INFO | __main__:run:173 - 开始安装Django
|
||||||
|
2025-08-26 21:42:24.993 | ERROR | __main__:run:216 - Django安装失败: bash: line 1: pip3: command not found
|
||||||
|
|
||||||
|
2025-08-26 21:42:24.997 | INFO | __main__:on_django_install_result:1012 - Django安装结果: False - Django安装失败: bash: line 1: pip3: command not found
|
||||||
|
|
||||||
|
2025-08-26 21:43:24.841 | INFO | __main__:<module>:1186 - 应用程序启动
|
||||||
|
2025-08-26 21:43:24.879 | INFO | __main__:load_git_config:783 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-26 21:43:24.881 | INFO | __main__:load_django_config:1095 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-26 21:43:26.831 | INFO | __main__:run:26 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-26 21:43:26.918 | INFO | __main__:run:32 - 服务器连接成功
|
||||||
|
2025-08-26 21:43:30.104 | INFO | __main__:run:173 - 开始安装Django
|
||||||
|
2025-08-26 21:43:30.112 | ERROR | __main__:run:216 - Django安装失败: bash: line 1: pip: command not found
|
||||||
|
|
||||||
|
2025-08-26 21:43:30.115 | INFO | __main__:on_django_install_result:1012 - Django安装结果: False - Django安装失败: bash: line 1: pip: command not found
|
||||||
|
|
||||||
|
2025-08-26 21:44:17.866 | INFO | __main__:<module>:1186 - 应用程序启动
|
||||||
|
2025-08-26 21:44:17.900 | INFO | __main__:load_git_config:783 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-26 21:44:17.901 | INFO | __main__:load_django_config:1095 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-26 21:44:19.443 | INFO | __main__:run:26 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-26 21:44:19.531 | INFO | __main__:run:32 - 服务器连接成功
|
||||||
|
2025-08-26 21:44:21.222 | INFO | __main__:run:173 - 开始安装Django
|
||||||
|
2025-08-26 21:44:21.248 | ERROR | __main__:run:216 - Django安装失败: /usr/bin/python3: No module named pip
|
||||||
|
|
||||||
|
2025-08-26 21:44:21.251 | INFO | __main__:on_django_install_result:1012 - Django安装结果: False - Django安装失败: /usr/bin/python3: No module named pip
|
||||||
|
|
||||||
|
2025-08-26 21:45:20.140 | INFO | __main__:<module>:1199 - 应用程序启动
|
||||||
|
2025-08-26 21:45:20.183 | INFO | __main__:load_git_config:796 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-26 21:45:20.184 | INFO | __main__:load_django_config:1108 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-26 21:45:22.205 | INFO | __main__:run:26 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-26 21:45:22.291 | INFO | __main__:run:32 - 服务器连接成功
|
||||||
|
2025-08-26 21:45:24.147 | INFO | __main__:run:173 - 开始安装Django
|
||||||
|
2025-08-26 21:45:24.171 | INFO | __main__:run:178 - pip未安装,正在安装pip...
|
||||||
|
2025-08-26 21:45:26.500 | ERROR | __main__:run:184 - pip安装失败: [sudo] password for xiaji: Sorry, try again.
|
||||||
|
[sudo] password for xiaji:
|
||||||
|
sudo: no password was provided
|
||||||
|
sudo: 1 incorrect password attempt
|
||||||
|
|
||||||
|
2025-08-26 21:45:26.508 | INFO | __main__:on_django_install_result:1025 - Django安装结果: False - pip安装失败: [sudo] password for xiaji: Sorry, try again.
|
||||||
|
[sudo] password for xiaji:
|
||||||
|
sudo: no password was provided
|
||||||
|
sudo: 1 incorrect password attempt
|
||||||
|
|
||||||
|
2025-08-26 21:45:52.074 | INFO | __main__:<module>:1204 - 应用程序启动
|
||||||
|
2025-08-26 21:45:52.110 | INFO | __main__:load_git_config:801 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-26 21:45:52.111 | INFO | __main__:load_django_config:1113 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-26 21:45:53.783 | INFO | __main__:run:26 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-26 21:45:53.874 | INFO | __main__:run:32 - 服务器连接成功
|
||||||
|
2025-08-26 21:45:55.539 | INFO | __main__:run:173 - 开始安装Django
|
||||||
|
2025-08-26 21:45:55.564 | INFO | __main__:run:178 - pip未安装,正在安装pip...
|
||||||
|
2025-08-26 21:45:55.629 | INFO | __main__:run:183 - ensurepip失败,尝试使用apt-get安装pip...
|
||||||
|
2025-08-26 21:45:57.544 | ERROR | __main__:run:189 - pip安装失败: [sudo] password for xiaji: Sorry, try again.
|
||||||
|
[sudo] password for xiaji:
|
||||||
|
sudo: no password was provided
|
||||||
|
sudo: 1 incorrect password attempt
|
||||||
|
|
||||||
|
2025-08-26 21:45:57.547 | INFO | __main__:on_django_install_result:1030 - Django安装结果: False - pip安装失败: [sudo] password for xiaji: Sorry, try again.
|
||||||
|
[sudo] password for xiaji:
|
||||||
|
sudo: no password was provided
|
||||||
|
sudo: 1 incorrect password attempt
|
||||||
|
|
||||||
|
2025-08-26 21:46:48.146 | INFO | __main__:<module>:1223 - 应用程序启动
|
||||||
|
2025-08-26 21:46:48.178 | INFO | __main__:load_git_config:820 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-26 21:46:48.179 | INFO | __main__:load_django_config:1132 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-26 21:46:54.255 | INFO | __main__:run:26 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-26 21:46:54.346 | INFO | __main__:run:32 - 服务器连接成功
|
||||||
|
2025-08-26 21:46:56.973 | INFO | __main__:run:173 - 开始安装Django
|
||||||
|
2025-08-26 21:46:56.997 | INFO | __main__:run:178 - pip未安装,正在安装pip...
|
||||||
|
2025-08-26 21:46:57.063 | INFO | __main__:run:183 - ensurepip失败,尝试使用get-pip.py脚本安装pip...
|
||||||
|
2025-08-26 21:47:10.268 | INFO | __main__:run:192 - get-pip.py失败,尝试使用apt-get安装pip...
|
||||||
|
2025-08-26 21:47:12.149 | ERROR | __main__:run:198 - pip安装失败: [sudo] password for xiaji: Sorry, try again.
|
||||||
|
[sudo] password for xiaji:
|
||||||
|
sudo: no password was provided
|
||||||
|
sudo: 1 incorrect password attempt
|
||||||
|
|
||||||
|
2025-08-26 21:47:12.159 | INFO | __main__:on_django_install_result:1049 - Django安装结果: False - pip安装失败: [sudo] password for xiaji: Sorry, try again.
|
||||||
|
[sudo] password for xiaji:
|
||||||
|
sudo: no password was provided
|
||||||
|
sudo: 1 incorrect password attempt
|
||||||
|
|
||||||
|
2025-08-26 21:52:21.927 | INFO | __main__:<module>:1296 - 应用程序启动
|
||||||
|
2025-08-26 21:52:21.959 | INFO | __main__:load_git_config:893 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-26 21:52:21.960 | INFO | __main__:load_django_config:1205 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-26 21:52:23.682 | INFO | __main__:run:67 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-26 21:52:23.773 | INFO | __main__:run:73 - 服务器连接成功
|
||||||
|
2025-08-26 21:52:26.898 | INFO | __main__:run:228 - 开始安装Django
|
||||||
|
2025-08-26 21:52:26.926 | INFO | __main__:run:233 - pip未安装,正在安装pip...
|
||||||
|
2025-08-26 21:52:26.995 | INFO | __main__:run:238 - ensurepip失败,尝试使用get-pip.py脚本安装pip...
|
||||||
|
2025-08-26 21:52:30.360 | INFO | __main__:run:247 - get-pip.py失败,尝试使用apt-get安装pip...
|
||||||
|
2025-08-26 21:53:57.244 | INFO | __main__:<module>:1320 - 应用程序启动
|
||||||
|
2025-08-26 21:53:57.276 | INFO | __main__:load_git_config:905 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-26 21:53:57.276 | INFO | __main__:load_django_config:1229 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-26 21:54:04.423 | INFO | __main__:run:67 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-26 21:54:04.511 | INFO | __main__:run:73 - 服务器连接成功
|
||||||
|
2025-08-26 21:54:07.059 | INFO | __main__:run:240 - 开始安装Django
|
||||||
|
2025-08-26 21:54:07.085 | INFO | __main__:run:245 - pip未安装,正在安装pip...
|
||||||
|
2025-08-26 21:54:07.150 | INFO | __main__:run:250 - ensurepip失败,尝试使用get-pip.py脚本安装pip...
|
||||||
|
2025-08-26 21:54:09.934 | INFO | __main__:run:259 - get-pip.py失败,尝试使用apt-get安装pip...
|
||||||
|
2025-08-26 21:54:14.798 | INFO | __main__:set_password:236 - 密码已设置
|
||||||
|
2025-08-26 21:54:14.798 | INFO | __main__:on_request_password:1035 - 用户通过对话框输入了sudo密码
|
||||||
|
2025-08-26 21:54:14.860 | INFO | __main__:get_sudo_password:229 - 密码输入流程完成
|
||||||
|
2025-08-26 21:54:36.123 | INFO | __main__:run:289 - pip安装成功
|
||||||
|
2025-08-26 21:54:36.524 | ERROR | __main__:run:338 - Django安装失败: error: externally-managed-environment
|
||||||
|
|
||||||
|
× This environment is externally managed
|
||||||
|
╰─> To install Python packages system-wide, try apt install
|
||||||
|
python3-xyz, where xyz is the package you are trying to
|
||||||
|
install.
|
||||||
|
|
||||||
|
If you wish to install a non-Debian-packaged Python package,
|
||||||
|
create a virtual environment using python3 -m venv path/to/venv.
|
||||||
|
Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
|
||||||
|
sure you have python3-full installed.
|
||||||
|
|
||||||
|
If you wish to install a non-Debian packaged Python application,
|
||||||
|
it may be easiest to use pipx install xyz, which will manage a
|
||||||
|
virtual environment for you. Make sure you have pipx installed.
|
||||||
|
|
||||||
|
See /usr/share/doc/python3.12/README.venv for more information.
|
||||||
|
|
||||||
|
note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
|
||||||
|
hint: See PEP 668 for the detailed specification.
|
||||||
|
|
||||||
|
2025-08-26 21:54:36.532 | INFO | __main__:on_django_install_result:1146 - Django安装结果: False - Django安装失败: error: externally-managed-environment
|
||||||
|
|
||||||
|
× This environment is externally managed
|
||||||
|
╰─> To install Python packages system-wide, try apt install
|
||||||
|
python3-xyz, where xyz is the package you are trying to
|
||||||
|
install.
|
||||||
|
|
||||||
|
If you wish to install a non-Debian-packaged Python package,
|
||||||
|
create a virtual environment using python3 -m venv path/to/venv.
|
||||||
|
Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
|
||||||
|
sure you have python3-full installed.
|
||||||
|
|
||||||
|
If you wish to install a non-Debian packaged Python application,
|
||||||
|
it may be easiest to use pipx install xyz, which will manage a
|
||||||
|
virtual environment for you. Make sure you have pipx installed.
|
||||||
|
|
||||||
|
See /usr/share/doc/python3.12/README.venv for more information.
|
||||||
|
|
||||||
|
note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
|
||||||
|
hint: See PEP 668 for the detailed specification.
|
||||||
|
|
||||||
|
2025-08-26 21:56:23.641 | INFO | __main__:<module>:1320 - 应用程序启动
|
||||||
|
2025-08-26 21:56:23.679 | INFO | __main__:load_git_config:905 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-26 21:56:23.680 | INFO | __main__:load_django_config:1229 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-26 21:56:25.450 | INFO | __main__:run:67 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-26 21:56:25.537 | INFO | __main__:run:73 - 服务器连接成功
|
||||||
|
2025-08-26 21:56:28.466 | INFO | __main__:run:240 - 开始安装Django
|
||||||
|
2025-08-26 22:00:18.695 | INFO | __main__:run:305 - Django安装成功,版本: 5.2.5
|
||||||
|
2025-08-26 22:00:18.699 | INFO | __main__:on_django_install_result:1146 - Django安装结果: True - Django安装成功,版本: 5.2.5
|
||||||
|
2025-08-26 22:00:26.706 | INFO | __main__:run:356 - 开始测试Django项目启动: /home/xiaji/
|
||||||
|
2025-08-26 22:00:26.764 | ERROR | __main__:run:371 - settings.py文件不存在: /home/xiaji//settings.py
|
||||||
|
2025-08-26 22:00:26.765 | INFO | __main__:on_django_test_result:1159 - Django测试结果: False - settings.py文件不存在: /home/xiaji//settings.py
|
||||||
|
2025-08-26 22:04:00.950 | INFO | __main__:<module>:1337 - 应用程序启动
|
||||||
|
2025-08-26 22:04:00.984 | INFO | __main__:load_git_config:922 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-26 22:04:00.985 | INFO | __main__:load_django_config:1246 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-26 22:04:02.656 | INFO | __main__:run:67 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-26 22:04:02.746 | INFO | __main__:run:73 - 服务器连接成功
|
||||||
|
2025-08-26 22:04:06.330 | INFO | __main__:run:356 - 开始测试Django项目启动: /home/xiaji/
|
||||||
|
2025-08-26 22:04:06.330 | INFO | __main__:run:359 - 正在查找settings.py文件位置...
|
||||||
|
2025-08-26 22:04:06.376 | INFO | __main__:run:366 - 找到settings.py文件: ./statuspage/settings.py
|
||||||
|
./部署文件夹/settings.py
|
||||||
|
2025-08-26 22:04:06.376 | INFO | __main__:run:367 - 项目目录: ./statuspage/settings.py
|
||||||
|
./部署文件夹
|
||||||
|
2025-08-26 22:04:06.427 | ERROR | __main__:run:374 - manage.py文件不存在: ./statuspage/settings.py
|
||||||
|
./部署文件夹/manage.py
|
||||||
|
2025-08-26 22:04:06.432 | INFO | __main__:on_django_test_result:1176 - Django测试结果: False - manage.py文件不存在: ./statuspage/settings.py
|
||||||
|
./部署文件夹/manage.py
|
||||||
|
2025-08-26 22:10:50.613 | INFO | __main__:<module>:1411 - 应用程序启动
|
||||||
|
2025-08-26 22:10:50.651 | INFO | __main__:load_git_config:961 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-26 22:10:50.652 | INFO | __main__:load_django_config:1320 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-26 22:10:51.993 | INFO | __main__:run:67 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-26 22:10:52.100 | INFO | __main__:run:73 - 服务器连接成功
|
||||||
|
2025-08-26 22:10:58.822 | INFO | __main__:run:356 - 开始测试Django项目启动: /home/xiaji/
|
||||||
|
2025-08-26 22:10:58.822 | INFO | __main__:run:359 - 正在查找settings.py文件位置...
|
||||||
|
2025-08-26 22:10:58.865 | INFO | __main__:run:366 - 找到settings.py文件: ./statuspage/settings.py
|
||||||
|
./部署文件夹/settings.py
|
||||||
|
2025-08-26 22:10:58.865 | INFO | __main__:run:367 - 项目目录: ./statuspage/settings.py
|
||||||
|
./部署文件夹
|
||||||
|
2025-08-26 22:10:58.918 | ERROR | __main__:run:374 - manage.py文件不存在: ./statuspage/settings.py
|
||||||
|
./部署文件夹/manage.py
|
||||||
|
2025-08-26 22:10:58.923 | INFO | __main__:on_django_test_result:1250 - Django测试结果: False - manage.py文件不存在: ./statuspage/settings.py
|
||||||
|
./部署文件夹/manage.py
|
||||||
|
2025-08-26 22:11:11.658 | INFO | __main__:run:183 - 开始列出目录内容: /home/xiaji/
|
||||||
|
2025-08-26 22:11:11.669 | INFO | __main__:run:197 - 成功列出目录内容: /home/xiaji/
|
||||||
|
2025-08-26 22:11:11.672 | INFO | __main__:on_list_directory_result:1000 - 目录列表结果: True - 目录内容:
|
||||||
|
total 2272
|
||||||
|
drwxr-x--- 8 xiaji xiaji 4096 Aug 26 14:00 .
|
||||||
|
drwxr-xr-x 3 root root 4096 Aug 26 2025 ..
|
||||||
|
drwx------ 3 xiaji xiaji 4096 Aug 26 13:56 .cache
|
||||||
|
-rw-rw-r-- 1 xiaji xiaji 135168 Aug 26 13:19 db.sqlite3
|
||||||
|
-rw-rw-r-- 1 xiaji xiaji 2148718 Aug 26 13:54 get-pip.py
|
||||||
|
drwxrwxr-x 8 xiaji xiaji 4096 Aug 26 13:19 .git
|
||||||
|
drwxrwxr-x 4 xiaji xiaji 4096 Aug 26 14:00 .local
|
||||||
|
-rw-rw-r-- 1 xiaji xiaji 666 Aug 26 13:19 manage.py
|
||||||
|
-rw-rw-r-- 1 xiaji xiaji 13 Aug 26 13:19 requirements.txt
|
||||||
|
drwxrwxr-x 5 xiaji xiaji 4096 Aug 26 13:19 status
|
||||||
|
drwxrwxr-x 3 xiaji xiaji 4096 Aug 26 13:19 statuspage
|
||||||
|
-rw-r--r-- 1 xiaji xiaji 0 Aug 26 13:54 .sudo_as_admin_successful
|
||||||
|
drwxrwxr-x 2 xiaji xiaji 4096 Aug 26 13:19 部署文件夹
|
||||||
|
|
||||||
|
2025-08-26 22:17:30.337 | INFO | __main__:<module>:1499 - 应用程序启动
|
||||||
|
2025-08-26 22:17:30.371 | INFO | __main__:load_git_config:1006 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-26 22:17:30.373 | INFO | __main__:load_django_config:1408 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-26 22:17:32.077 | INFO | __main__:run:67 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-26 22:17:32.167 | INFO | __main__:run:73 - 服务器连接成功
|
||||||
|
2025-08-26 22:17:38.407 | INFO | __main__:run:183 - 开始列出目录内容: /home/xiaji/
|
||||||
|
2025-08-26 22:17:38.416 | INFO | __main__:run:197 - 成功列出目录内容: /home/xiaji/
|
||||||
|
2025-08-26 22:17:38.420 | INFO | __main__:on_list_directory_result:1045 - 目录列表结果: True - 目录内容:
|
||||||
|
total 2272
|
||||||
|
drwxr-x--- 8 xiaji xiaji 4096 Aug 26 14:00 .
|
||||||
|
drwxr-xr-x 3 root root 4096 Aug 26 2025 ..
|
||||||
|
drwx------ 3 xiaji xiaji 4096 Aug 26 13:56 .cache
|
||||||
|
-rw-rw-r-- 1 xiaji xiaji 135168 Aug 26 13:19 db.sqlite3
|
||||||
|
-rw-rw-r-- 1 xiaji xiaji 2148718 Aug 26 13:54 get-pip.py
|
||||||
|
drwxrwxr-x 8 xiaji xiaji 4096 Aug 26 13:19 .git
|
||||||
|
drwxrwxr-x 4 xiaji xiaji 4096 Aug 26 14:00 .local
|
||||||
|
-rw-rw-r-- 1 xiaji xiaji 666 Aug 26 13:19 manage.py
|
||||||
|
-rw-rw-r-- 1 xiaji xiaji 13 Aug 26 13:19 requirements.txt
|
||||||
|
drwxrwxr-x 5 xiaji xiaji 4096 Aug 26 13:19 status
|
||||||
|
drwxrwxr-x 3 xiaji xiaji 4096 Aug 26 13:19 statuspage
|
||||||
|
-rw-r--r-- 1 xiaji xiaji 0 Aug 26 13:54 .sudo_as_admin_successful
|
||||||
|
drwxrwxr-x 2 xiaji xiaji 4096 Aug 26 13:19 部署文件夹
|
||||||
|
|
||||||
|
2025-08-26 22:17:43.607 | INFO | __main__:run:596 - 开始删除目录: /home/xiaji/
|
||||||
|
2025-08-26 22:17:43.792 | ERROR | __main__:run:618 - 删除目录失败: rm: cannot remove '/home/xiaji/': Permission denied
|
||||||
|
2025-08-26 22:17:43.794 | INFO | __main__:on_delete_directory_result:1088 - 删除目录结果: False - 删除目录失败: rm: cannot remove '/home/xiaji/': Permission denied
|
||||||
|
2025-08-26 22:18:25.763 | INFO | __main__:<module>:1507 - 应用程序启动
|
||||||
|
2025-08-26 22:18:25.800 | INFO | __main__:load_git_config:1014 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-26 22:18:25.801 | INFO | __main__:load_django_config:1416 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-26 22:18:27.004 | INFO | __main__:run:67 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-26 22:18:27.089 | INFO | __main__:run:73 - 服务器连接成功
|
||||||
|
2025-08-26 22:18:31.163 | INFO | __main__:run:183 - 开始列出目录内容: /home/xiaji/
|
||||||
|
2025-08-26 22:18:31.171 | INFO | __main__:run:197 - 成功列出目录内容: /home/xiaji/
|
||||||
|
2025-08-26 22:18:31.174 | INFO | __main__:on_list_directory_result:1053 - 目录列表结果: True - 目录内容:
|
||||||
|
total 12
|
||||||
|
drwxr-x--- 3 xiaji xiaji 4096 Aug 26 14:18 .
|
||||||
|
drwxr-xr-x 3 root root 4096 Aug 26 2025 ..
|
||||||
|
drwx------ 2 xiaji xiaji 4096 Aug 26 14:18 .cache
|
||||||
|
|
||||||
|
2025-08-26 22:18:36.660 | INFO | __main__:run:129 - 开始拉取代码: http://192.168.3.241:3000/xiaji/webstatus
|
||||||
|
2025-08-26 22:18:36.731 | INFO | __main__:run:147 - 目录 /home/xiaji/ 不为空,正在清空目录
|
||||||
|
2025-08-26 22:18:36.744 | INFO | __main__:run:155 - 开始克隆代码到: /home/xiaji/
|
||||||
|
2025-08-26 22:18:36.842 | INFO | __main__:run:165 - 代码拉取成功到: /home/xiaji/
|
||||||
|
2025-08-26 22:18:36.843 | INFO | __main__:on_git_clone_result:992 - 代码拉取结果: True - 代码拉取成功到: /home/xiaji/
|
||||||
|
2025-08-26 22:18:37.904 | INFO | __main__:run:183 - 开始列出目录内容: /home/xiaji/
|
||||||
|
2025-08-26 22:18:37.912 | INFO | __main__:run:197 - 成功列出目录内容: /home/xiaji/
|
||||||
|
2025-08-26 22:18:37.914 | INFO | __main__:on_list_directory_result:1053 - 目录列表结果: True - 目录内容:
|
||||||
|
total 160
|
||||||
|
drwxr-x--- 5 xiaji xiaji 4096 Aug 26 14:18 .
|
||||||
|
drwxr-xr-x 3 root root 4096 Aug 26 2025 ..
|
||||||
|
-rw-rw-r-- 1 xiaji xiaji 135168 Aug 26 14:18 db.sqlite3
|
||||||
|
drwxrwxr-x 8 xiaji xiaji 4096 Aug 26 14:18 .git
|
||||||
|
-rw-rw-r-- 1 xiaji xiaji 666 Aug 26 14:18 manage.py
|
||||||
|
-rw-rw-r-- 1 xiaji xiaji 13 Aug 26 14:18 requirements.txt
|
||||||
|
drwxrwxr-x 5 xiaji xiaji 4096 Aug 26 14:18 status
|
||||||
|
drwxrwxr-x 3 xiaji xiaji 4096 Aug 26 14:18 statuspage
|
||||||
|
|
||||||
|
2025-08-26 22:18:43.768 | INFO | __main__:run:356 - 开始测试Django项目启动: /home/xiaji/
|
||||||
|
2025-08-26 22:18:43.768 | INFO | __main__:run:359 - 正在查找settings.py文件位置...
|
||||||
|
2025-08-26 22:18:43.779 | INFO | __main__:run:366 - 找到settings.py文件: ./statuspage/settings.py
|
||||||
|
2025-08-26 22:18:43.779 | INFO | __main__:run:367 - 项目目录: ./statuspage
|
||||||
|
2025-08-26 22:18:43.828 | ERROR | __main__:run:374 - manage.py文件不存在: ./statuspage/manage.py
|
||||||
|
2025-08-26 22:18:43.828 | INFO | __main__:on_django_test_result:1346 - Django测试结果: False - manage.py文件不存在: ./statuspage/manage.py
|
||||||
|
2025-08-26 22:20:44.569 | INFO | __main__:<module>:1508 - 应用程序启动
|
||||||
|
2025-08-26 22:20:44.604 | INFO | __main__:load_git_config:1015 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-26 22:20:44.605 | INFO | __main__:load_django_config:1417 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-26 22:20:45.954 | INFO | __main__:run:67 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-26 22:20:46.049 | INFO | __main__:run:73 - 服务器连接成功
|
||||||
|
2025-08-26 22:20:48.938 | INFO | __main__:run:356 - 开始测试Django项目启动: /home/xiaji/
|
||||||
|
2025-08-26 22:20:48.938 | INFO | __main__:run:359 - 正在查找settings.py文件位置...
|
||||||
|
2025-08-26 22:20:48.947 | INFO | __main__:run:366 - 找到settings.py文件: ./statuspage/settings.py
|
||||||
|
2025-08-26 22:20:48.948 | INFO | __main__:run:367 - 项目目录: ./statuspage
|
||||||
|
2025-08-26 22:20:49.189 | ERROR | __main__:run:409 - Django服务器启动失败: Traceback (most recent call last):
|
||||||
|
File "/home/xiaji/manage.py", line 11, in main
|
||||||
|
from django.core.management import execute_from_command_line
|
||||||
|
ModuleNotFoundError: No module named 'django'
|
||||||
|
|
||||||
|
The above exception was the direct cause of the following exception:
|
||||||
|
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "/home/xiaji/manage.py", line 22, in <module>
|
||||||
|
main()
|
||||||
|
File "/home/xiaji/manage.py", line 13, in main
|
||||||
|
raise ImportError(
|
||||||
|
ImportError: Couldn't import Django. Are you sure it's installed and available on your PYTHONPATH environment variable? Did you forget to activate a virtual environment?
|
||||||
|
|
||||||
|
2025-08-26 22:20:49.197 | INFO | __main__:on_django_test_result:1347 - Django测试结果: False - Django服务器启动失败: Traceback (most recent call last):
|
||||||
|
File "/home/xiaji/manage.py", line 11, in main
|
||||||
|
from django.core.management import execute_from_command_line
|
||||||
|
ModuleNotFoundError: No module named 'django'
|
||||||
|
|
||||||
|
The above exception was the direct cause of the following exception:
|
||||||
|
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "/home/xiaji/manage.py", line 22, in <module>
|
||||||
|
main()
|
||||||
|
File "/home/xiaji/manage.py", line 13, in main
|
||||||
|
raise ImportError(
|
||||||
|
ImportError: Couldn't import Django. Are you sure it's installed and available on your PYTHONPATH environment variable? Did you forget to activate a virtual environment?
|
||||||
|
|
||||||
|
2025-08-26 22:21:07.760 | INFO | __main__:run:240 - 开始安装Django
|
||||||
|
2025-08-26 22:23:28.257 | INFO | __main__:<module>:1523 - 应用程序启动
|
||||||
|
2025-08-26 22:23:28.295 | INFO | __main__:load_git_config:1033 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-26 22:23:28.297 | INFO | __main__:load_django_config:1432 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-26 22:23:30.498 | INFO | __main__:run:67 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-26 22:23:30.588 | INFO | __main__:run:73 - 服务器连接成功
|
||||||
|
2025-08-26 22:23:46.323 | INFO | __main__:run:356 - 开始测试Django项目启动: /home/xiaji/
|
||||||
|
2025-08-26 22:23:46.324 | INFO | __main__:run:359 - 正在查找settings.py文件位置...
|
||||||
|
2025-08-26 22:23:46.332 | INFO | __main__:run:366 - 找到settings.py文件: ./statuspage/settings.py
|
||||||
|
2025-08-26 22:23:46.332 | INFO | __main__:run:367 - 项目目录: ./statuspage
|
||||||
|
2025-08-26 22:23:46.385 | INFO | __main__:run:392 - 检查Django安装状态...
|
||||||
|
2025-08-26 22:23:46.789 | ERROR | __main__:run:397 - Django未安装,请先安装Django再进行服务器测试
|
||||||
|
2025-08-26 22:23:46.795 | INFO | __main__:on_django_test_result:1362 - Django测试结果: False - Django未安装,请先安装Django再进行服务器测试
|
||||||
|
2025-08-26 22:23:48.755 | INFO | __main__:run:240 - 开始安装Django
|
||||||
|
2025-08-26 22:25:16.428 | INFO | __main__:run:305 - Django安装成功,版本: 5.2.5
|
||||||
|
2025-08-26 22:25:16.429 | INFO | __main__:on_django_install_result:1349 - Django安装结果: True - Django安装成功,版本: 5.2.5
|
||||||
|
2025-08-26 22:25:29.453 | INFO | __main__:run:356 - 开始测试Django项目启动: /home/xiaji/
|
||||||
|
2025-08-26 22:25:29.454 | INFO | __main__:run:359 - 正在查找settings.py文件位置...
|
||||||
|
2025-08-26 22:25:29.492 | INFO | __main__:run:366 - 找到settings.py文件: ./statuspage/settings.py
|
||||||
|
2025-08-26 22:25:29.493 | INFO | __main__:run:367 - 项目目录: ./statuspage
|
||||||
|
2025-08-26 22:25:29.544 | INFO | __main__:run:392 - 检查Django安装状态...
|
||||||
|
2025-08-26 22:25:40.055 | INFO | __main__:run:409 - Django服务器启动测试成功,可以在0.0.0.0:8000访问
|
||||||
|
2025-08-26 22:25:40.056 | INFO | __main__:on_django_test_result:1362 - Django测试结果: True - Django服务器启动测试成功,可以在0.0.0.0:8000访问
|
||||||
|
2025-08-26 22:26:04.003 | INFO | __main__:run:436 - 开始下载settings.py文件: /home/xiaji//settings.py
|
||||||
|
2025-08-26 22:26:04.011 | ERROR | __main__:run:443 - settings.py文件不存在: /home/xiaji//settings.py
|
||||||
|
2025-08-26 22:26:04.012 | INFO | __main__:on_download_settings_result:1387 - 下载settings.py结果: False - settings.py文件不存在: /home/xiaji//settings.py
|
||||||
|
2025-08-26 22:26:48.391 | INFO | __main__:<module>:1527 - 应用程序启动
|
||||||
|
2025-08-26 22:26:48.431 | INFO | __main__:load_git_config:1037 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-26 22:26:48.432 | INFO | __main__:load_django_config:1436 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-26 22:26:50.521 | INFO | __main__:run:67 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-26 22:26:50.608 | INFO | __main__:run:73 - 服务器连接成功
|
||||||
|
2025-08-26 22:26:53.437 | INFO | __main__:run:440 - 开始下载settings.py文件: /home/xiaji/settings.py
|
||||||
|
2025-08-26 22:26:53.446 | ERROR | __main__:run:447 - settings.py文件不存在: /home/xiaji/settings.py
|
||||||
|
2025-08-26 22:26:53.451 | INFO | __main__:on_download_settings_result:1391 - 下载settings.py结果: False - settings.py文件不存在: /home/xiaji/settings.py
|
||||||
598
app.2025-08-26_22-27-11_970736.log
Normal file
598
app.2025-08-26_22-27-11_970736.log
Normal file
@@ -0,0 +1,598 @@
|
|||||||
|
2025-08-26 22:27:11.967 | INFO | __main__:<module>:1531 - 应用程序启动
|
||||||
|
2025-08-26 22:27:12.005 | INFO | __main__:load_git_config:1041 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-26 22:27:12.006 | INFO | __main__:load_django_config:1440 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-26 22:27:13.724 | INFO | __main__:run:67 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-26 22:27:13.812 | INFO | __main__:run:73 - 服务器连接成功
|
||||||
|
2025-08-26 22:27:15.586 | INFO | __main__:run:440 - 开始下载settings.py文件: /home/xiaji/settings.py
|
||||||
|
2025-08-26 22:27:15.600 | ERROR | __main__:run:447 - settings.py文件不存在: /home/xiaji/settings.py
|
||||||
|
2025-08-26 22:27:15.603 | INFO | __main__:on_download_settings_result:1395 - 下载settings.py结果: False - settings.py文件不存在: /home/xiaji/settings.py
|
||||||
|
2025-08-27 19:34:48.208 | INFO | __main__:<module>:1533 - 应用程序启动
|
||||||
|
2025-08-27 19:34:48.252 | INFO | __main__:load_git_config:1043 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 19:34:48.253 | INFO | __main__:load_django_config:1442 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 19:34:51.243 | INFO | __main__:run:67 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 19:34:51.354 | INFO | __main__:run:73 - 服务器连接成功
|
||||||
|
2025-08-27 19:34:57.489 | INFO | __main__:run:183 - 开始列出目录内容: /home/xiaji/
|
||||||
|
2025-08-27 19:34:57.498 | INFO | __main__:run:197 - 成功列出目录内容: /home/xiaji/
|
||||||
|
2025-08-27 19:34:57.506 | INFO | __main__:on_list_directory_result:1082 - 目录列表结果: True - 目录内容:
|
||||||
|
total 168
|
||||||
|
drwxr-x--- 7 xiaji xiaji 4096 Aug 26 14:25 .
|
||||||
|
drwxr-xr-x 3 root root 4096 Aug 26 20:10 ..
|
||||||
|
drwx------ 3 xiaji xiaji 4096 Aug 26 14:21 .cache
|
||||||
|
-rw-rw-r-- 1 xiaji xiaji 135168 Aug 26 14:18 db.sqlite3
|
||||||
|
drwxrwxr-x 8 xiaji xiaji 4096 Aug 26 14:18 .git
|
||||||
|
drwxrwxr-x 4 xiaji xiaji 4096 Aug 26 14:25 .local
|
||||||
|
-rw-rw-r-- 1 xiaji xiaji 666 Aug 26 14:18 manage.py
|
||||||
|
-rw-rw-r-- 1 xiaji xiaji 13 Aug 26 14:18 requirements.txt
|
||||||
|
drwxrwxr-x 5 xiaji xiaji 4096 Aug 26 14:18 status
|
||||||
|
drwxrwxr-x 3 xiaji xiaji 4096 Aug 26 14:18 statuspage
|
||||||
|
|
||||||
|
2025-08-27 19:35:04.761 | INFO | __main__:run:356 - 开始测试Django项目启动: /home/xiaji/
|
||||||
|
2025-08-27 19:35:04.762 | INFO | __main__:run:359 - 正在查找settings.py文件位置...
|
||||||
|
2025-08-27 19:35:04.808 | INFO | __main__:run:368 - 找到settings.py文件: ./statuspage/settings.py
|
||||||
|
2025-08-27 19:35:04.809 | INFO | __main__:run:369 - 项目目录: ./statuspage
|
||||||
|
2025-08-27 19:35:04.858 | INFO | __main__:run:394 - 检查Django安装状态...
|
||||||
|
2025-08-27 19:35:14.808 | INFO | __main__:run:442 - 开始下载settings.py文件: /home/xiaji/settings.py
|
||||||
|
2025-08-27 19:35:14.817 | ERROR | __main__:run:449 - settings.py文件不存在: /home/xiaji/settings.py
|
||||||
|
2025-08-27 19:35:14.820 | INFO | __main__:on_download_settings_result:1397 - 下载settings.py结果: False - settings.py文件不存在: /home/xiaji/settings.py
|
||||||
|
2025-08-27 19:35:15.377 | INFO | __main__:run:411 - Django服务器启动测试成功,可以在0.0.0.0:8000访问
|
||||||
|
2025-08-27 19:35:15.378 | INFO | __main__:on_django_test_result:1372 - Django测试结果: True - Django服务器启动测试成功,可以在0.0.0.0:8000访问
|
||||||
|
2025-08-27 19:35:19.455 | INFO | __main__:run:442 - 开始下载settings.py文件: /home/xiaji/settings.py
|
||||||
|
2025-08-27 19:35:19.462 | ERROR | __main__:run:449 - settings.py文件不存在: /home/xiaji/settings.py
|
||||||
|
2025-08-27 19:35:19.463 | INFO | __main__:on_download_settings_result:1397 - 下载settings.py结果: False - settings.py文件不存在: /home/xiaji/settings.py
|
||||||
|
2025-08-27 19:42:20.823 | INFO | __main__:<module>:1583 - 应用程序启动
|
||||||
|
2025-08-27 19:42:20.864 | INFO | __main__:load_git_config:1043 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 19:42:20.865 | INFO | __main__:load_django_config:1492 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 19:42:22.887 | INFO | __main__:run:67 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 19:42:22.976 | INFO | __main__:run:73 - 服务器连接成功
|
||||||
|
2025-08-27 19:42:27.102 | INFO | __main__:find_and_remember_settings_path:1459 - 正在查找settings.py文件位置...
|
||||||
|
2025-08-27 19:42:27.146 | INFO | __main__:find_and_remember_settings_path:1467 - 找到并记住settings.py文件: ./statuspage/settings.py
|
||||||
|
2025-08-27 19:42:27.367 | INFO | __main__:run:442 - 开始下载settings.py文件: ./statuspage/settings.py
|
||||||
|
2025-08-27 19:42:27.424 | INFO | __main__:run:465 - settings.py文件下载成功
|
||||||
|
2025-08-27 19:42:27.431 | INFO | __main__:on_download_settings_result:1413 - settings.py已保存到本地: settings_backup_20250827_194227.py
|
||||||
|
2025-08-27 19:42:27.431 | INFO | __main__:on_download_settings_result:1421 - 下载settings.py结果: True - settings.py文件下载成功
|
||||||
|
2025-08-27 19:46:43.686 | INFO | __main__:<module>:1598 - 应用程序启动
|
||||||
|
2025-08-27 19:46:43.723 | INFO | __main__:load_git_config:1049 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 19:46:43.724 | INFO | __main__:load_django_config:1507 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 19:46:45.459 | INFO | __main__:run:67 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 19:46:45.548 | INFO | __main__:run:73 - 服务器连接成功
|
||||||
|
2025-08-27 19:46:50.814 | INFO | __main__:find_and_remember_settings_path:1474 - 正在查找settings.py文件位置...
|
||||||
|
2025-08-27 19:46:50.862 | INFO | __main__:find_and_remember_settings_path:1482 - 找到并记住settings.py文件: ./statuspage/settings.py
|
||||||
|
2025-08-27 19:46:50.864 | INFO | __main__:run:442 - 开始下载settings.py文件: ./statuspage/settings.py
|
||||||
|
2025-08-27 19:46:50.961 | INFO | __main__:run:465 - settings.py文件下载成功
|
||||||
|
2025-08-27 19:46:50.971 | INFO | __main__:on_download_settings_result:1428 - settings.py已保存到本地: settings_backup_20250827_194650.py
|
||||||
|
2025-08-27 19:46:50.971 | INFO | __main__:on_download_settings_result:1436 - 下载settings.py结果: True - settings.py文件下载成功
|
||||||
|
2025-08-27 19:55:17.865 | INFO | __main__:<module>:1695 - 应用程序启动
|
||||||
|
2025-08-27 19:55:17.899 | INFO | __main__:load_git_config:1106 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 19:55:17.900 | INFO | __main__:load_django_config:1604 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 19:55:19.882 | INFO | __main__:run:67 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 19:55:20.010 | INFO | __main__:run:73 - 服务器连接成功
|
||||||
|
2025-08-27 19:55:26.008 | INFO | __main__:run:664 - 开始设置时区为北京时区并重启服务器
|
||||||
|
2025-08-27 19:55:26.008 | INFO | __main__:run:667 - 设置时区为Asia/Shanghai...
|
||||||
|
2025-08-27 19:55:26.020 | ERROR | __main__:run:673 - 设置时区失败: sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
|
||||||
|
sudo: a password is required
|
||||||
|
2025-08-27 19:55:29.082 | INFO | __main__:on_set_timezone_and_restart_result:1214 - 设置时区和重启服务器结果: False - 设置时区失败: sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
|
||||||
|
sudo: a password is required
|
||||||
|
2025-08-27 20:02:54.904 | INFO | __main__:<module>:1728 - 应用程序启动
|
||||||
|
2025-08-27 20:02:54.944 | INFO | __main__:load_git_config:1119 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 20:02:54.945 | INFO | __main__:load_django_config:1637 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 20:02:57.393 | INFO | __main__:run:67 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 20:02:57.491 | INFO | __main__:run:73 - 服务器连接成功
|
||||||
|
2025-08-27 20:02:57.655 | INFO | __main__:run:67 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 20:02:57.751 | INFO | __main__:run:73 - 服务器连接成功
|
||||||
|
2025-08-27 20:03:03.524 | INFO | __main__:run:670 - 开始设置时区为北京时区并重启服务器
|
||||||
|
2025-08-27 20:03:07.898 | INFO | __main__:show_password_dialog:1221 - 用户已输入sudo密码
|
||||||
|
2025-08-27 20:03:07.957 | INFO | __main__:run:680 - 设置时区为Asia/Shanghai...
|
||||||
|
2025-08-27 20:03:08.099 | INFO | __main__:run:693 - 当前时区: Asia/Shanghai
|
||||||
|
2025-08-27 20:03:08.099 | INFO | __main__:run:701 - 开始重启服务器...
|
||||||
|
2025-08-27 20:03:08.172 | INFO | __main__:run:712 - 时区已设置为北京时区,服务器正在重启中...
|
||||||
|
2025-08-27 20:03:10.310 | INFO | __main__:on_set_timezone_and_restart_result:1247 - 设置时区和重启服务器结果: True - 时区已设置为北京时区,服务器正在重启中...
|
||||||
|
2025-08-27 20:03:16.568 | INFO | __main__:run:67 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 20:03:17.861 | INFO | __main__:run:73 - 服务器连接成功
|
||||||
|
2025-08-27 20:03:24.114 | INFO | __main__:run:183 - 开始列出目录内容: /home/xiaji/
|
||||||
|
2025-08-27 20:03:24.125 | INFO | __main__:run:197 - 成功列出目录内容: /home/xiaji/
|
||||||
|
2025-08-27 20:03:24.128 | INFO | __main__:on_list_directory_result:1158 - 目录列表结果: True - 目录内容:
|
||||||
|
total 168
|
||||||
|
drwxr-x--- 7 xiaji xiaji 4096 Aug 27 20:03 .
|
||||||
|
drwxr-xr-x 3 root root 4096 Aug 27 04:10 ..
|
||||||
|
drwx------ 3 xiaji xiaji 4096 Aug 26 22:21 .cache
|
||||||
|
-rw-rw-r-- 1 xiaji xiaji 135168 Aug 26 22:18 db.sqlite3
|
||||||
|
drwxrwxr-x 8 xiaji xiaji 4096 Aug 26 22:18 .git
|
||||||
|
drwxrwxr-x 4 xiaji xiaji 4096 Aug 26 22:25 .local
|
||||||
|
-rw-rw-r-- 1 xiaji xiaji 666 Aug 26 22:18 manage.py
|
||||||
|
-rw-rw-r-- 1 xiaji xiaji 13 Aug 26 22:18 requirements.txt
|
||||||
|
drwxrwxr-x 5 xiaji xiaji 4096 Aug 26 22:18 status
|
||||||
|
drwxrwxr-x 3 xiaji xiaji 4096 Aug 26 22:18 statuspage
|
||||||
|
-rw-r--r-- 1 xiaji xiaji 0 Aug 27 20:03 .sudo_as_admin_successful
|
||||||
|
|
||||||
|
2025-08-27 20:05:23.729 | INFO | __main__:find_and_remember_settings_path:1604 - 正在查找settings.py文件位置...
|
||||||
|
2025-08-27 20:05:23.974 | INFO | __main__:find_and_remember_settings_path:1612 - 找到并记住settings.py文件: ./statuspage/settings.py
|
||||||
|
2025-08-27 20:05:23.979 | INFO | __main__:run:442 - 开始下载settings.py文件: ./statuspage/settings.py
|
||||||
|
2025-08-27 20:05:24.077 | INFO | __main__:run:465 - settings.py文件下载成功
|
||||||
|
2025-08-27 20:05:24.084 | INFO | __main__:on_download_settings_result:1558 - settings.py已保存到本地: settings_backup_20250827_200524.py
|
||||||
|
2025-08-27 20:05:24.084 | INFO | __main__:on_download_settings_result:1566 - 下载settings.py结果: True - settings.py文件下载成功
|
||||||
|
2025-08-27 20:31:46.189 | INFO | __main__:run:488 - 开始上传settings.py文件: ./statuspage/settings.py
|
||||||
|
2025-08-27 20:31:46.218 | INFO | __main__:run:515 - settings.py文件上传成功,原文件已备份到: ./statuspage/settings_backup_20250827_203146.py
|
||||||
|
2025-08-27 20:31:46.219 | INFO | __main__:on_upload_settings_result:1579 - 上传settings.py结果: True - settings.py文件上传成功,原文件已备份到: ./statuspage/settings_backup_20250827_203146.py
|
||||||
|
2025-08-27 20:31:49.592 | INFO | __main__:run:356 - 开始测试Django项目启动: ./statuspage
|
||||||
|
2025-08-27 20:31:49.593 | INFO | __main__:run:359 - 正在查找settings.py文件位置...
|
||||||
|
2025-08-27 20:31:49.643 | INFO | __main__:run:368 - 找到settings.py文件: ./statuspage/settings.py
|
||||||
|
2025-08-27 20:31:49.644 | INFO | __main__:run:369 - 项目目录: ./statuspage
|
||||||
|
2025-08-27 20:31:49.693 | INFO | __main__:run:394 - 检查Django安装状态...
|
||||||
|
2025-08-27 20:32:00.301 | INFO | __main__:run:411 - Django服务器启动测试成功,可以在0.0.0.0:8000访问
|
||||||
|
2025-08-27 20:32:00.302 | INFO | __main__:on_django_test_result:1537 - Django测试结果: True - Django服务器启动测试成功,可以在0.0.0.0:8000访问
|
||||||
|
2025-08-27 20:40:39.405 | INFO | __main__:<module>:1956 - 应用程序启动
|
||||||
|
2025-08-27 20:40:39.451 | INFO | __main__:load_git_config:1243 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 20:40:39.452 | INFO | __main__:load_django_config:1865 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 20:40:41.463 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 20:40:41.555 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 20:40:46.641 | INFO | __main__:run:730 - 开始检查防火墙状态
|
||||||
|
2025-08-27 20:40:46.664 | INFO | __main__:on_check_firewall_result:1459 - 检查防火墙结果: False - 检查防火墙状态失败: sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
|
||||||
|
sudo: a password is required
|
||||||
|
2025-08-27 20:40:46.665 | ERROR | __main__:run:750 - 检查防火墙状态失败: sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
|
||||||
|
sudo: a password is required
|
||||||
|
2025-08-27 20:44:01.496 | INFO | __main__:<module>:1956 - 应用程序启动
|
||||||
|
2025-08-27 20:44:01.530 | INFO | __main__:load_git_config:1243 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 20:44:01.531 | INFO | __main__:load_django_config:1865 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 20:44:03.329 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 20:44:03.419 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 20:44:05.993 | INFO | __main__:run:730 - 开始检查防火墙状态
|
||||||
|
2025-08-27 20:44:06.007 | ERROR | __main__:run:750 - 检查防火墙状态失败: sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
|
||||||
|
sudo: a password is required
|
||||||
|
2025-08-27 20:44:06.010 | INFO | __main__:on_check_firewall_result:1459 - 检查防火墙结果: False - 检查防火墙状态失败: sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
|
||||||
|
sudo: a password is required
|
||||||
|
2025-08-27 20:45:12.537 | INFO | __main__:<module>:1989 - 应用程序启动
|
||||||
|
2025-08-27 20:45:12.575 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 20:45:12.576 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 20:45:14.242 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 20:45:14.329 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 20:45:16.464 | INFO | __main__:run:736 - 开始检查防火墙状态
|
||||||
|
2025-08-27 20:45:21.822 | INFO | __main__:show_firewall_password_dialog:1410 - 用户已输入sudo密码
|
||||||
|
2025-08-27 20:45:22.005 | INFO | __main__:run:758 - 防火墙未启动
|
||||||
|
2025-08-27 20:45:22.008 | INFO | __main__:on_check_firewall_result:1492 - 检查防火墙结果: True - 防火墙未启动
|
||||||
|
Status: inactive
|
||||||
|
2025-08-27 20:45:29.644 | INFO | __main__:find_and_remember_settings_path:1865 - 正在查找settings.py文件位置...
|
||||||
|
2025-08-27 20:45:29.691 | INFO | __main__:find_and_remember_settings_path:1873 - 找到并记住settings.py文件: ./statuspage/settings.py
|
||||||
|
2025-08-27 20:45:29.693 | INFO | __main__:run:357 - 开始测试Django项目启动: ./statuspage
|
||||||
|
2025-08-27 20:45:29.693 | INFO | __main__:run:360 - 正在查找settings.py文件位置...
|
||||||
|
2025-08-27 20:45:29.770 | INFO | __main__:run:369 - 找到settings.py文件: ./statuspage/settings.py
|
||||||
|
2025-08-27 20:45:29.771 | INFO | __main__:run:370 - 项目目录: ./statuspage
|
||||||
|
2025-08-27 20:45:29.820 | INFO | __main__:run:395 - 检查Django安装状态...
|
||||||
|
2025-08-27 20:45:40.328 | INFO | __main__:run:412 - Django服务器启动测试成功,可以在0.0.0.0:8000访问
|
||||||
|
2025-08-27 20:45:40.330 | INFO | __main__:on_django_test_result:1798 - Django测试结果: True - Django服务器启动测试成功,可以在0.0.0.0:8000访问
|
||||||
|
2025-08-27 20:45:55.132 | INFO | __main__:run:786 - 开始开放端口: 8000
|
||||||
|
2025-08-27 20:45:59.385 | INFO | __main__:show_port_password_dialog:1468 - 用户已输入sudo密码
|
||||||
|
2025-08-27 20:45:59.459 | INFO | __main__:run:796 - 开放端口 8000...
|
||||||
|
2025-08-27 20:45:59.662 | ERROR | __main__:run:820 - 验证端口开放状态失败
|
||||||
|
2025-08-27 20:46:01.666 | INFO | __main__:on_open_port_result:1508 - 开放端口结果: False - 验证端口开放状态失败
|
||||||
|
2025-08-27 20:50:38.933 | INFO | __main__:run:357 - 开始测试Django项目启动: ./statuspage
|
||||||
|
2025-08-27 20:50:38.934 | INFO | __main__:run:360 - 正在查找settings.py文件位置...
|
||||||
|
2025-08-27 20:50:38.981 | INFO | __main__:run:369 - 找到settings.py文件: ./statuspage/settings.py
|
||||||
|
2025-08-27 20:50:38.981 | INFO | __main__:run:370 - 项目目录: ./statuspage
|
||||||
|
2025-08-27 20:50:39.030 | INFO | __main__:run:395 - 检查Django安装状态...
|
||||||
|
2025-08-27 20:50:49.547 | INFO | __main__:run:412 - Django服务器启动测试成功,可以在0.0.0.0:8000访问
|
||||||
|
2025-08-27 20:50:49.548 | INFO | __main__:on_django_test_result:1798 - Django测试结果: True - Django服务器启动测试成功,可以在0.0.0.0:8000访问
|
||||||
|
2025-08-27 20:50:57.952 | INFO | __main__:run:357 - 开始测试Django项目启动: ./statuspage
|
||||||
|
2025-08-27 20:50:57.952 | INFO | __main__:run:360 - 正在查找settings.py文件位置...
|
||||||
|
2025-08-27 20:50:57.993 | INFO | __main__:run:369 - 找到settings.py文件: ./statuspage/settings.py
|
||||||
|
2025-08-27 20:50:57.994 | INFO | __main__:run:370 - 项目目录: ./statuspage
|
||||||
|
2025-08-27 20:50:58.042 | INFO | __main__:run:395 - 检查Django安装状态...
|
||||||
|
2025-08-27 20:51:08.550 | INFO | __main__:run:412 - Django服务器启动测试成功,可以在0.0.0.0:8000访问
|
||||||
|
2025-08-27 20:51:08.551 | INFO | __main__:on_django_test_result:1798 - Django测试结果: True - Django服务器启动测试成功,可以在0.0.0.0:8000访问
|
||||||
|
2025-08-27 20:51:26.381 | INFO | __main__:run:537 - 开始收集静态文件: ./statuspage
|
||||||
|
2025-08-27 20:51:26.389 | INFO | __main__:run:548 - 检查Django安装状态...
|
||||||
|
2025-08-27 20:51:27.202 | INFO | __main__:on_collect_static_result:1853 - 收集静态文件结果: True - 静态文件收集成功:
|
||||||
|
|
||||||
|
127 static files copied to '/home/xiaji/home/xiaji/static'.
|
||||||
|
|
||||||
|
2025-08-27 20:51:27.202 | INFO | __main__:run:569 - 静态文件收集成功
|
||||||
|
2025-08-27 20:52:00.408 | INFO | __main__:run:443 - 开始下载settings.py文件: ./statuspage/settings.py
|
||||||
|
2025-08-27 20:52:00.466 | INFO | __main__:run:466 - settings.py文件下载成功
|
||||||
|
2025-08-27 20:52:00.476 | INFO | __main__:on_download_settings_result:1819 - settings.py已保存到本地: settings_backup_20250827_205200.py
|
||||||
|
2025-08-27 20:52:00.476 | INFO | __main__:on_download_settings_result:1827 - 下载settings.py结果: True - settings.py文件下载成功
|
||||||
|
2025-08-27 20:52:27.642 | INFO | __main__:run:489 - 开始上传settings.py文件: ./statuspage/settings.py
|
||||||
|
2025-08-27 20:52:27.670 | INFO | __main__:run:516 - settings.py文件上传成功,原文件已备份到: ./statuspage/settings_backup_20250827_205227.py
|
||||||
|
2025-08-27 20:52:27.671 | INFO | __main__:on_upload_settings_result:1840 - 上传settings.py结果: True - settings.py文件上传成功,原文件已备份到: ./statuspage/settings_backup_20250827_205227.py
|
||||||
|
2025-08-27 20:52:32.483 | INFO | __main__:run:537 - 开始收集静态文件: ./statuspage
|
||||||
|
2025-08-27 20:52:32.493 | INFO | __main__:run:548 - 检查Django安装状态...
|
||||||
|
2025-08-27 20:52:33.288 | INFO | __main__:run:569 - 静态文件收集成功
|
||||||
|
2025-08-27 20:52:33.289 | INFO | __main__:on_collect_static_result:1853 - 收集静态文件结果: True - 静态文件收集成功:
|
||||||
|
|
||||||
|
127 static files copied to '/home/xiaji/static'.
|
||||||
|
|
||||||
|
2025-08-27 21:06:55.636 | INFO | __main__:<module>:2546 - 应用程序启动
|
||||||
|
2025-08-27 21:06:55.679 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 21:06:55.680 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 21:06:55.681 | INFO | __main__:load_gunicorn_config:2451 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 21:08:14.982 | INFO | __main__:<module>:2546 - 应用程序启动
|
||||||
|
2025-08-27 21:08:15.012 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 21:08:15.013 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 21:08:15.016 | INFO | __main__:load_gunicorn_config:2451 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 21:08:16.792 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 21:08:16.884 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 21:08:51.818 | INFO | __main__:run:1919 - 开始安装Gunicorn
|
||||||
|
2025-08-27 21:08:57.805 | INFO | __main__:show_gunicorn_password_dialog:2324 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:08:57.863 | INFO | __main__:run:1937 - Gunicorn未安装,开始安装gunicorn
|
||||||
|
2025-08-27 21:08:58.321 | ERROR | __main__:run:1942 - Gunicorn安装失败: [sudo] password for xiaji: error: externally-managed-environment
|
||||||
|
|
||||||
|
× This environment is externally managed
|
||||||
|
╰─> To install Python packages system-wide, try apt install
|
||||||
|
python3-xyz, where xyz is the package you are trying to
|
||||||
|
install.
|
||||||
|
|
||||||
|
If you wish to install a non-Debian-packaged Python package,
|
||||||
|
create a virtual environment using python3 -m venv path/to/venv.
|
||||||
|
Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
|
||||||
|
sure you have python3-full installed.
|
||||||
|
|
||||||
|
If you wish to install a non-Debian packaged Python application,
|
||||||
|
it may be easiest to use pipx install xyz, which will manage a
|
||||||
|
virtual environment for you. Make sure you have pipx installed.
|
||||||
|
|
||||||
|
See /usr/share/doc/python3.12/README.venv for more information.
|
||||||
|
|
||||||
|
note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
|
||||||
|
hint: See PEP 668 for the detailed specification.
|
||||||
|
|
||||||
|
2025-08-27 21:08:58.327 | INFO | __main__:on_gunicorn_install_result:2383 - Gunicorn安装结果: False - Gunicorn安装失败: [sudo] password for xiaji: error: externally-managed-environment
|
||||||
|
|
||||||
|
× This environment is externally managed
|
||||||
|
╰─> To install Python packages system-wide, try apt install
|
||||||
|
python3-xyz, where xyz is the package you are trying to
|
||||||
|
install.
|
||||||
|
|
||||||
|
If you wish to install a non-Debian-packaged Python package,
|
||||||
|
create a virtual environment using python3 -m venv path/to/venv.
|
||||||
|
Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
|
||||||
|
sure you have python3-full installed.
|
||||||
|
|
||||||
|
If you wish to install a non-Debian packaged Python application,
|
||||||
|
it may be easiest to use pipx install xyz, which will manage a
|
||||||
|
virtual environment for you. Make sure you have pipx installed.
|
||||||
|
|
||||||
|
See /usr/share/doc/python3.12/README.venv for more information.
|
||||||
|
|
||||||
|
note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
|
||||||
|
hint: See PEP 668 for the detailed specification.
|
||||||
|
|
||||||
|
2025-08-27 21:09:29.032 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 21:09:34.847 | INFO | __main__:show_service_password_dialog:2346 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:09:34.902 | ERROR | __main__:run:2103 - Gunicorn服务status操作失败: [sudo] password for xiaji: Unit gunicorn.service could not be found.
|
||||||
|
|
||||||
|
2025-08-27 21:09:34.903 | INFO | __main__:on_manage_service_result:2428 - Gunicorn服务管理结果: False - Gunicorn服务status操作失败: [sudo] password for xiaji: Unit gunicorn.service could not be found.
|
||||||
|
|
||||||
|
2025-08-27 21:09:59.573 | INFO | __main__:<module>:2546 - 应用程序启动
|
||||||
|
2025-08-27 21:09:59.616 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 21:09:59.618 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 21:09:59.619 | INFO | __main__:load_gunicorn_config:2451 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 21:10:01.671 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 21:10:01.769 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 21:10:08.156 | INFO | __main__:run:1919 - 开始安装Gunicorn
|
||||||
|
2025-08-27 21:10:12.554 | INFO | __main__:show_gunicorn_password_dialog:2324 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:10:12.616 | INFO | __main__:run:1937 - Gunicorn未安装,开始安装gunicorn
|
||||||
|
2025-08-27 21:10:28.248 | INFO | __main__:run:1951 - Gunicorn安装成功,版本: gunicorn (version 23.0.0)
|
||||||
|
2025-08-27 21:10:28.251 | INFO | __main__:on_gunicorn_install_result:2383 - Gunicorn安装结果: True - Gunicorn安装成功,版本: gunicorn (version 23.0.0)
|
||||||
|
2025-08-27 21:10:42.627 | INFO | __main__:run:1974 - 开始测试Gunicorn运行,项目目录: /home/xiaji/
|
||||||
|
2025-08-27 21:10:52.760 | INFO | __main__:run:1985 - Gunicorn测试运行成功
|
||||||
|
2025-08-27 21:10:52.765 | INFO | __main__:on_gunicorn_test_result:2396 - Gunicorn测试结果: True - Gunicorn测试运行成功
|
||||||
|
项目: statuspage
|
||||||
|
目录: /home/xiaji/
|
||||||
|
绑定: 0.0.0.0:8000
|
||||||
|
2025-08-27 21:10:56.336 | INFO | __main__:run:1974 - 开始测试Gunicorn运行,项目目录: /home/xiaji/
|
||||||
|
2025-08-27 21:11:06.468 | INFO | __main__:run:1985 - Gunicorn测试运行成功
|
||||||
|
2025-08-27 21:11:06.469 | INFO | __main__:on_gunicorn_test_result:2396 - Gunicorn测试结果: True - Gunicorn测试运行成功
|
||||||
|
项目: statuspage
|
||||||
|
目录: /home/xiaji/
|
||||||
|
绑定: 0.0.0.0:8000
|
||||||
|
2025-08-27 21:11:13.512 | INFO | __main__:run:1974 - 开始测试Gunicorn运行,项目目录: /home/xiaji/
|
||||||
|
2025-08-27 21:11:23.641 | INFO | __main__:run:1985 - Gunicorn测试运行成功
|
||||||
|
2025-08-27 21:11:23.642 | INFO | __main__:on_gunicorn_test_result:2396 - Gunicorn测试结果: True - Gunicorn测试运行成功
|
||||||
|
项目: statuspage
|
||||||
|
目录: /home/xiaji/
|
||||||
|
绑定: 0.0.0.0:8000
|
||||||
|
2025-08-27 21:12:46.221 | INFO | __main__:find_and_remember_settings_path:1865 - 正在查找settings.py文件位置...
|
||||||
|
2025-08-27 21:12:46.267 | INFO | __main__:find_and_remember_settings_path:1873 - 找到并记住settings.py文件: ./statuspage/settings.py
|
||||||
|
2025-08-27 21:12:46.269 | INFO | __main__:run:443 - 开始下载settings.py文件: ./statuspage/settings.py
|
||||||
|
2025-08-27 21:12:46.366 | INFO | __main__:run:466 - settings.py文件下载成功
|
||||||
|
2025-08-27 21:12:46.374 | INFO | __main__:on_download_settings_result:1819 - settings.py已保存到本地: settings_backup_20250827_211246.py
|
||||||
|
2025-08-27 21:12:46.374 | INFO | __main__:on_download_settings_result:1827 - 下载settings.py结果: True - settings.py文件下载成功
|
||||||
|
2025-08-27 21:16:10.875 | INFO | __main__:run:2014 - 开始上传Gunicorn systemd服务文件
|
||||||
|
2025-08-27 21:16:15.314 | INFO | __main__:show_service_password_dialog:2346 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:16:15.532 | INFO | __main__:run:2050 - Gunicorn systemd服务文件上传成功
|
||||||
|
2025-08-27 21:16:15.533 | INFO | __main__:on_upload_service_result:2409 - 上传服务文件结果: True - Gunicorn systemd服务文件上传成功
|
||||||
|
2025-08-27 21:16:22.515 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: enable
|
||||||
|
2025-08-27 21:16:26.948 | INFO | __main__:show_service_password_dialog:2346 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:16:27.303 | INFO | __main__:run:2099 - Gunicorn服务enable操作成功
|
||||||
|
2025-08-27 21:16:27.304 | INFO | __main__:on_manage_service_result:2428 - Gunicorn服务管理结果: True - Gunicorn服务enable操作成功
|
||||||
|
2025-08-27 21:16:28.462 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: start
|
||||||
|
2025-08-27 21:16:32.810 | INFO | __main__:show_service_password_dialog:2346 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:16:32.922 | INFO | __main__:run:2099 - Gunicorn服务start操作成功
|
||||||
|
2025-08-27 21:16:32.923 | INFO | __main__:on_manage_service_result:2428 - Gunicorn服务管理结果: True - Gunicorn服务start操作成功
|
||||||
|
2025-08-27 21:16:34.423 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 21:16:38.963 | INFO | __main__:show_service_password_dialog:2346 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:16:38.994 | ERROR | __main__:run:2103 - Gunicorn服务status操作失败: [sudo] password for xiaji:
|
||||||
|
2025-08-27 21:16:38.995 | INFO | __main__:on_manage_service_result:2428 - Gunicorn服务管理结果: False - Gunicorn服务status操作失败: [sudo] password for xiaji:
|
||||||
|
2025-08-27 21:17:15.645 | INFO | __main__:<module>:2547 - 应用程序启动
|
||||||
|
2025-08-27 21:17:15.687 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 21:17:15.689 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 21:17:15.690 | INFO | __main__:load_gunicorn_config:2452 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 21:17:17.514 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 21:17:17.614 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 21:17:20.576 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 21:17:25.390 | INFO | __main__:show_service_password_dialog:2347 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:17:25.419 | INFO | __main__:on_manage_service_result:2429 - Gunicorn服务管理结果: False - Gunicorn服务status操作失败:
|
||||||
|
2025-08-27 21:17:25.419 | ERROR | __main__:run:2104 - Gunicorn服务status操作失败:
|
||||||
|
2025-08-27 21:17:54.474 | INFO | __main__:<module>:2549 - 应用程序启动
|
||||||
|
2025-08-27 21:17:54.512 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 21:17:54.513 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 21:17:54.514 | INFO | __main__:load_gunicorn_config:2454 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 21:17:56.817 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 21:17:56.914 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 21:17:58.962 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 21:18:41.193 | INFO | __main__:run:1974 - 开始测试Gunicorn运行,项目目录: /home/xiaji/
|
||||||
|
2025-08-27 21:18:51.322 | INFO | __main__:run:1985 - Gunicorn测试运行成功
|
||||||
|
2025-08-27 21:18:51.324 | INFO | __main__:on_gunicorn_test_result:2399 - Gunicorn测试结果: True - Gunicorn测试运行成功
|
||||||
|
项目: statuspage
|
||||||
|
目录: /home/xiaji/
|
||||||
|
绑定: 0.0.0.0:8000
|
||||||
|
2025-08-27 21:18:58.906 | INFO | __main__:run:671 - 开始设置时区为北京时区并重启服务器
|
||||||
|
2025-08-27 21:19:02.375 | INFO | __main__:show_password_dialog:1358 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:19:02.442 | INFO | __main__:run:681 - 设置时区为Asia/Shanghai...
|
||||||
|
2025-08-27 21:19:02.587 | INFO | __main__:run:694 - 当前时区: Asia/Shanghai
|
||||||
|
2025-08-27 21:19:02.587 | INFO | __main__:run:702 - 开始重启服务器...
|
||||||
|
2025-08-27 21:19:02.654 | INFO | __main__:run:713 - 时区已设置为北京时区,服务器正在重启中...
|
||||||
|
2025-08-27 21:19:04.155 | INFO | __main__:on_set_timezone_and_restart_result:1384 - 设置时区和重启服务器结果: True - 时区已设置为北京时区,服务器正在重启中...
|
||||||
|
2025-08-27 21:19:49.291 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 21:19:49.434 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 21:21:05.121 | INFO | __main__:<module>:2557 - 应用程序启动
|
||||||
|
2025-08-27 21:21:05.158 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 21:21:05.159 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 21:21:05.160 | INFO | __main__:load_gunicorn_config:2462 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 21:21:15.903 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 21:21:15.991 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 21:21:37.089 | INFO | __main__:<module>:2557 - 应用程序启动
|
||||||
|
2025-08-27 21:21:37.123 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 21:21:37.123 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 21:21:37.125 | INFO | __main__:load_gunicorn_config:2462 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 21:21:39.243 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 21:21:39.332 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 21:21:51.029 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 21:22:02.555 | INFO | __main__:run:1974 - 开始测试Gunicorn运行,项目目录: /home/xiaji/
|
||||||
|
2025-08-27 21:22:12.692 | INFO | __main__:run:1985 - Gunicorn测试运行成功
|
||||||
|
2025-08-27 21:22:12.694 | INFO | __main__:on_gunicorn_test_result:2406 - Gunicorn测试结果: True - Gunicorn测试运行成功
|
||||||
|
项目: statuspage
|
||||||
|
目录: /home/xiaji/
|
||||||
|
绑定: 0.0.0.0:8000
|
||||||
|
2025-08-27 21:37:09.634 | INFO | __main__:<module>:2577 - 应用程序启动
|
||||||
|
2025-08-27 21:37:09.672 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 21:37:09.673 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 21:37:09.675 | INFO | __main__:load_gunicorn_config:2462 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 21:38:00.187 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 21:38:00.283 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 21:38:04.230 | INFO | __main__:on_tab_changed:2570 - 切换到Gunicorn标签,自动检测服务状态
|
||||||
|
2025-08-27 21:38:04.736 | INFO | __main__:check_service_status:2470 - 自动检测Gunicorn服务状态
|
||||||
|
2025-08-27 21:38:04.741 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 21:41:20.289 | INFO | __main__:<module>:2576 - 应用程序启动
|
||||||
|
2025-08-27 21:41:20.322 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 21:41:20.323 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 21:41:20.325 | INFO | __main__:load_gunicorn_config:2461 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 21:41:57.023 | INFO | __main__:<module>:2576 - 应用程序启动
|
||||||
|
2025-08-27 21:41:57.057 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 21:41:57.058 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 21:41:57.061 | INFO | __main__:load_gunicorn_config:2461 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 21:41:59.413 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 21:41:59.498 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 21:42:01.010 | INFO | __main__:on_tab_changed:2569 - 切换到Gunicorn标签,自动检测服务状态
|
||||||
|
2025-08-27 21:42:01.512 | INFO | __main__:check_service_status:2469 - 自动检测Gunicorn服务状态
|
||||||
|
2025-08-27 21:42:01.750 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 21:42:06.555 | INFO | __main__:show_service_password_dialog:2354 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:42:06.613 | ERROR | __main__:run:2104 - Gunicorn服务status操作失败: [sudo] password for xiaji:
|
||||||
|
2025-08-27 21:42:06.614 | INFO | __main__:on_manage_service_result:2438 - Gunicorn服务管理结果: False - Gunicorn服务status操作失败: [sudo] password for xiaji:
|
||||||
|
2025-08-27 21:42:39.942 | INFO | __main__:<module>:2581 - 应用程序启动
|
||||||
|
2025-08-27 21:42:39.982 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 21:42:39.983 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 21:42:39.984 | INFO | __main__:load_gunicorn_config:2466 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 21:42:52.012 | INFO | __main__:<module>:2581 - 应用程序启动
|
||||||
|
2025-08-27 21:42:52.062 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 21:42:52.063 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 21:42:52.064 | INFO | __main__:load_gunicorn_config:2466 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 21:42:53.954 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 21:42:54.039 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 21:42:55.018 | INFO | __main__:on_tab_changed:2574 - 切换到Gunicorn标签,自动检测服务状态
|
||||||
|
2025-08-27 21:42:55.511 | INFO | __main__:check_service_status:2474 - 自动检测Gunicorn服务状态
|
||||||
|
2025-08-27 21:42:55.729 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 21:43:00.740 | INFO | __main__:show_service_password_dialog:2359 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:43:00.793 | ERROR | __main__:run:2109 - Gunicorn服务status操作失败: [sudo] password for xiaji:
|
||||||
|
2025-08-27 21:43:00.795 | INFO | __main__:on_manage_service_result:2443 - Gunicorn服务管理结果: False - Gunicorn服务status操作失败: [sudo] password for xiaji:
|
||||||
|
2025-08-27 21:43:04.162 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: daemon-reload
|
||||||
|
2025-08-27 21:43:08.473 | INFO | __main__:show_service_password_dialog:2359 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:43:08.512 | ERROR | __main__:run:2109 - Gunicorn服务daemon-reload操作失败: [sudo] password for xiaji: Too many arguments.
|
||||||
|
|
||||||
|
2025-08-27 21:43:08.513 | INFO | __main__:on_manage_service_result:2443 - Gunicorn服务管理结果: False - Gunicorn服务daemon-reload操作失败: [sudo] password for xiaji: Too many arguments.
|
||||||
|
|
||||||
|
2025-08-27 21:43:10.549 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 21:43:13.633 | INFO | __main__:show_service_password_dialog:2359 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:43:13.700 | ERROR | __main__:run:2109 - Gunicorn服务status操作失败: [sudo] password for xiaji:
|
||||||
|
2025-08-27 21:43:13.702 | INFO | __main__:on_manage_service_result:2443 - Gunicorn服务管理结果: False - Gunicorn服务status操作失败: [sudo] password for xiaji:
|
||||||
|
2025-08-27 21:44:29.302 | INFO | __main__:<module>:2581 - 应用程序启动
|
||||||
|
2025-08-27 21:44:29.339 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 21:44:29.340 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 21:44:29.341 | INFO | __main__:load_gunicorn_config:2466 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 21:44:31.199 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 21:44:31.286 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 21:44:32.714 | INFO | __main__:on_tab_changed:2574 - 切换到Gunicorn标签,自动检测服务状态
|
||||||
|
2025-08-27 21:44:33.215 | INFO | __main__:check_service_status:2474 - 自动检测Gunicorn服务状态
|
||||||
|
2025-08-27 21:44:33.462 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 21:44:39.041 | INFO | __main__:show_service_password_dialog:2359 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:44:39.115 | ERROR | __main__:run:2109 - Gunicorn服务status操作失败: sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
|
||||||
|
sudo: a password is required
|
||||||
|
|
||||||
|
2025-08-27 21:44:39.117 | INFO | __main__:on_manage_service_result:2443 - Gunicorn服务管理结果: False - Gunicorn服务status操作失败: sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
|
||||||
|
sudo: a password is required
|
||||||
|
|
||||||
|
2025-08-27 21:44:43.001 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 21:44:47.532 | INFO | __main__:show_service_password_dialog:2359 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:44:47.556 | ERROR | __main__:run:2109 - Gunicorn服务status操作失败: sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
|
||||||
|
sudo: a password is required
|
||||||
|
|
||||||
|
2025-08-27 21:44:47.557 | INFO | __main__:on_manage_service_result:2443 - Gunicorn服务管理结果: False - Gunicorn服务status操作失败: sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
|
||||||
|
sudo: a password is required
|
||||||
|
|
||||||
|
2025-08-27 21:45:22.587 | INFO | __main__:<module>:2581 - 应用程序启动
|
||||||
|
2025-08-27 21:45:22.620 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 21:45:22.621 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 21:45:22.623 | INFO | __main__:load_gunicorn_config:2466 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 21:45:24.555 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 21:45:24.646 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 21:45:25.676 | INFO | __main__:on_tab_changed:2574 - 切换到Gunicorn标签,自动检测服务状态
|
||||||
|
2025-08-27 21:45:26.170 | INFO | __main__:check_service_status:2474 - 自动检测Gunicorn服务状态
|
||||||
|
2025-08-27 21:45:26.470 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 21:45:32.466 | INFO | __main__:show_service_password_dialog:2359 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:45:32.543 | ERROR | __main__:run:2109 - Gunicorn服务status操作失败: [sudo] password for xiaji:
|
||||||
|
2025-08-27 21:45:32.552 | INFO | __main__:on_manage_service_result:2443 - Gunicorn服务管理结果: False - Gunicorn服务status操作失败: [sudo] password for xiaji:
|
||||||
|
2025-08-27 21:45:35.574 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 21:45:36.964 | INFO | __main__:show_service_password_dialog:2371 - 用户取消了密码输入
|
||||||
|
2025-08-27 21:47:15.297 | INFO | __main__:<module>:2574 - 应用程序启动
|
||||||
|
2025-08-27 21:47:15.354 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 21:47:15.355 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 21:47:15.357 | INFO | __main__:load_gunicorn_config:2459 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 21:47:52.100 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 21:47:52.193 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 21:47:53.480 | INFO | __main__:on_tab_changed:2567 - 切换到Gunicorn标签,自动检测服务状态
|
||||||
|
2025-08-27 21:47:53.980 | INFO | __main__:check_service_status:2467 - 自动检测Gunicorn服务状态
|
||||||
|
2025-08-27 21:47:54.223 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 21:47:59.494 | INFO | __main__:show_service_password_dialog:2352 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:47:59.596 | ERROR | __main__:run:2102 - Gunicorn服务status操作失败: [sudo] password for xiaji:
|
||||||
|
2025-08-27 21:47:59.601 | INFO | __main__:on_manage_service_result:2436 - Gunicorn服务管理结果: False - Gunicorn服务status操作失败: [sudo] password for xiaji:
|
||||||
|
2025-08-27 21:48:02.598 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 21:48:06.136 | INFO | __main__:show_service_password_dialog:2352 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:48:06.260 | ERROR | __main__:run:2102 - Gunicorn服务status操作失败: [sudo] password for xiaji:
|
||||||
|
2025-08-27 21:48:06.261 | INFO | __main__:on_manage_service_result:2436 - Gunicorn服务管理结果: False - Gunicorn服务status操作失败: [sudo] password for xiaji:
|
||||||
|
2025-08-27 21:48:20.021 | INFO | __main__:<module>:2576 - 应用程序启动
|
||||||
|
2025-08-27 21:48:20.057 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 21:48:20.058 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 21:48:20.059 | INFO | __main__:load_gunicorn_config:2461 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 21:48:33.185 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 21:48:33.272 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 21:48:34.629 | INFO | __main__:on_tab_changed:2569 - 切换到Gunicorn标签,自动检测服务状态
|
||||||
|
2025-08-27 21:48:35.123 | INFO | __main__:check_service_status:2469 - 自动检测Gunicorn服务状态
|
||||||
|
2025-08-27 21:48:35.368 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 21:48:39.149 | INFO | __main__:show_service_password_dialog:2354 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:48:39.229 | ERROR | __main__:run:2104 - Gunicorn服务status操作失败: [sudo] password for xiaji:
|
||||||
|
2025-08-27 21:48:39.230 | INFO | __main__:on_manage_service_result:2438 - Gunicorn服务管理结果: False - Gunicorn服务status操作失败: [sudo] password for xiaji:
|
||||||
|
2025-08-27 21:48:40.738 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 21:48:45.799 | INFO | __main__:show_service_password_dialog:2354 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:48:45.891 | ERROR | __main__:run:2104 - Gunicorn服务status操作失败: [sudo] password for xiaji:
|
||||||
|
2025-08-27 21:48:45.894 | INFO | __main__:on_manage_service_result:2438 - Gunicorn服务管理结果: False - Gunicorn服务status操作失败: [sudo] password for xiaji:
|
||||||
|
2025-08-27 21:48:52.321 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 21:48:57.015 | INFO | __main__:show_service_password_dialog:2354 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:48:57.085 | ERROR | __main__:run:2104 - Gunicorn服务status操作失败: [sudo] password for xiaji:
|
||||||
|
2025-08-27 21:48:57.086 | INFO | __main__:on_manage_service_result:2438 - Gunicorn服务管理结果: False - Gunicorn服务status操作失败: [sudo] password for xiaji:
|
||||||
|
2025-08-27 21:49:12.442 | INFO | __main__:<module>:2576 - 应用程序启动
|
||||||
|
2025-08-27 21:49:12.488 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 21:49:12.489 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 21:49:12.490 | INFO | __main__:load_gunicorn_config:2461 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 21:49:18.363 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 21:49:18.456 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 21:49:21.130 | INFO | __main__:on_tab_changed:2569 - 切换到Gunicorn标签,自动检测服务状态
|
||||||
|
2025-08-27 21:49:21.635 | INFO | __main__:check_service_status:2469 - 自动检测Gunicorn服务状态
|
||||||
|
2025-08-27 21:49:21.641 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 21:49:26.161 | INFO | __main__:show_service_password_dialog:2354 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:50:03.244 | INFO | __main__:<module>:2597 - 应用程序启动
|
||||||
|
2025-08-27 21:50:03.279 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 21:50:03.280 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 21:50:03.281 | INFO | __main__:load_gunicorn_config:2482 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 21:50:25.577 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 21:50:25.662 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 21:50:25.772 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 21:50:25.865 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 21:50:27.575 | INFO | __main__:on_tab_changed:2590 - 切换到Gunicorn标签,自动检测服务状态
|
||||||
|
2025-08-27 21:50:28.082 | INFO | __main__:check_service_status:2490 - 自动检测Gunicorn服务状态
|
||||||
|
2025-08-27 21:50:28.304 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 21:50:33.275 | INFO | __main__:show_service_password_dialog:2375 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:50:33.468 | ERROR | __main__:run:2125 - Gunicorn服务status操作失败:
|
||||||
|
2025-08-27 21:50:33.472 | INFO | __main__:on_manage_service_result:2459 - Gunicorn服务管理结果: False - Gunicorn服务status操作失败:
|
||||||
|
2025-08-27 21:50:53.983 | INFO | __main__:<module>:2587 - 应用程序启动
|
||||||
|
2025-08-27 21:50:54.023 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 21:50:54.023 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 21:50:54.025 | INFO | __main__:load_gunicorn_config:2472 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 21:51:22.091 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 21:51:22.181 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 21:51:23.177 | INFO | __main__:on_tab_changed:2580 - 切换到Gunicorn标签,自动检测服务状态
|
||||||
|
2025-08-27 21:51:23.670 | INFO | __main__:check_service_status:2480 - 自动检测Gunicorn服务状态
|
||||||
|
2025-08-27 21:51:23.914 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 21:51:28.274 | INFO | __main__:show_service_password_dialog:2365 - 用户已输入sudo密码
|
||||||
|
2025-08-27 21:52:21.096 | INFO | __main__:<module>:2589 - 应用程序启动
|
||||||
|
2025-08-27 21:52:21.141 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 21:52:21.142 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 21:52:21.143 | INFO | __main__:load_gunicorn_config:2474 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 22:07:09.891 | INFO | __main__:<module>:2589 - 应用程序启动
|
||||||
|
2025-08-27 22:07:09.921 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 22:07:09.924 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 22:07:09.925 | INFO | __main__:load_gunicorn_config:2474 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 22:07:12.485 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 22:07:12.573 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 22:07:14.086 | INFO | __main__:on_tab_changed:2582 - 切换到Gunicorn标签,自动检测服务状态
|
||||||
|
2025-08-27 22:07:14.582 | INFO | __main__:check_service_status:2482 - 自动检测Gunicorn服务状态
|
||||||
|
2025-08-27 22:07:14.810 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 22:07:44.991 | INFO | __main__:<module>:2589 - 应用程序启动
|
||||||
|
2025-08-27 22:07:45.035 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 22:07:45.037 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 22:07:45.039 | INFO | __main__:load_gunicorn_config:2474 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 22:07:46.612 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 22:07:46.698 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 22:07:47.830 | INFO | __main__:on_tab_changed:2582 - 切换到Gunicorn标签,自动检测服务状态
|
||||||
|
2025-08-27 22:07:48.330 | INFO | __main__:check_service_status:2482 - 自动检测Gunicorn服务状态
|
||||||
|
2025-08-27 22:07:48.546 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 22:09:24.972 | INFO | __main__:<module>:2587 - 应用程序启动
|
||||||
|
2025-08-27 22:09:25.010 | INFO | __main__:load_git_config:1256 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 22:09:25.011 | INFO | __main__:load_django_config:1898 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 22:09:25.012 | INFO | __main__:load_gunicorn_config:2472 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 22:09:26.577 | INFO | __main__:run:68 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 22:09:26.668 | INFO | __main__:run:74 - 服务器连接成功
|
||||||
|
2025-08-27 22:09:32.521 | INFO | __main__:on_tab_changed:2580 - 切换到Gunicorn标签,自动检测服务状态
|
||||||
|
2025-08-27 22:09:33.021 | INFO | __main__:check_service_status:2480 - 自动检测Gunicorn服务状态
|
||||||
|
2025-08-27 22:09:33.022 | INFO | __main__:manage_service:2313 - 开始管理Gunicorn服务,操作: status
|
||||||
|
2025-08-27 22:09:33.250 | INFO | __main__:manage_service:2333 - ManageGunicornServiceThread已启动,操作: status
|
||||||
|
2025-08-27 22:09:33.250 | INFO | __main__:run:2074 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 22:09:40.208 | INFO | __main__:show_service_password_dialog:2365 - 用户已输入sudo密码
|
||||||
|
2025-08-27 22:13:56.872 | INFO | __main__:<module>:2600 - 应用程序启动
|
||||||
|
2025-08-27 22:13:56.910 | INFO | __main__:load_git_config:1257 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 22:13:56.911 | INFO | __main__:load_django_config:1899 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 22:13:56.913 | INFO | __main__:load_gunicorn_config:2485 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 22:13:58.882 | INFO | __main__:run:69 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 22:13:58.970 | INFO | __main__:run:75 - 服务器连接成功
|
||||||
|
2025-08-27 22:14:01.498 | INFO | __main__:on_tab_changed:2593 - 切换到Gunicorn标签,自动检测服务状态
|
||||||
|
2025-08-27 22:14:02.001 | INFO | __main__:check_service_status:2493 - 自动检测Gunicorn服务状态
|
||||||
|
2025-08-27 22:14:02.002 | INFO | __main__:manage_service:2326 - 开始管理Gunicorn服务,操作: status
|
||||||
|
2025-08-27 22:14:02.217 | INFO | __main__:manage_service:2346 - ManageGunicornServiceThread已启动,操作: status
|
||||||
|
2025-08-27 22:14:02.218 | INFO | __main__:run:2075 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 22:14:36.463 | INFO | __main__:show_service_password_dialog:2378 - 用户已输入sudo密码
|
||||||
|
2025-08-27 22:15:06.605 | ERROR | __main__:run:2098 - 命令执行超时: sudo -S systemctl status gunicorn
|
||||||
|
2025-08-27 22:15:06.607 | ERROR | __main__:run:2129 - Gunicorn服务status操作失败: 命令执行超时(30秒): sudo -S systemctl status gunicorn
|
||||||
|
2025-08-27 22:15:06.615 | INFO | __main__:on_manage_service_result:2462 - Gunicorn服务管理结果: False - Gunicorn服务status操作失败: 命令执行超时(30秒): sudo -S systemctl status gunicorn
|
||||||
|
2025-08-27 22:24:36.179 | INFO | __main__:<module>:2608 - 应用程序启动
|
||||||
|
2025-08-27 22:24:36.224 | INFO | __main__:load_git_config:1257 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 22:24:36.224 | INFO | __main__:load_django_config:1899 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 22:24:36.227 | INFO | __main__:load_gunicorn_config:2493 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 22:24:49.405 | INFO | __main__:run:69 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 22:24:49.500 | INFO | __main__:run:75 - 服务器连接成功
|
||||||
|
2025-08-27 22:24:50.639 | INFO | __main__:on_tab_changed:2601 - 切换到Gunicorn标签,自动检测服务状态
|
||||||
|
2025-08-27 22:24:51.149 | INFO | __main__:check_service_status:2501 - 自动检测Gunicorn服务状态
|
||||||
|
2025-08-27 22:24:51.150 | INFO | __main__:manage_service:2334 - 开始管理Gunicorn服务,操作: status
|
||||||
|
2025-08-27 22:24:51.388 | INFO | __main__:manage_service:2354 - ManageGunicornServiceThread已启动,操作: status
|
||||||
|
2025-08-27 22:24:51.389 | INFO | __main__:run:2075 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 22:24:55.839 | INFO | __main__:show_service_password_dialog:2386 - 用户已输入sudo密码
|
||||||
|
2025-08-27 22:25:25.941 | ERROR | __main__:run:2104 - 命令执行超时: sudo -S systemctl status gunicorn
|
||||||
|
2025-08-27 22:25:25.942 | ERROR | __main__:run:2137 - Gunicorn服务status操作失败: 命令执行超时(30秒): sudo -S systemctl status gunicorn
|
||||||
|
2025-08-27 22:25:25.944 | INFO | __main__:on_manage_service_result:2470 - Gunicorn服务管理结果: False - Gunicorn服务status操作失败: 命令执行超时(30秒): sudo -S systemctl status gunicorn
|
||||||
|
2025-08-27 22:28:02.231 | INFO | __main__:load_git_config:1257 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 22:28:02.232 | INFO | __main__:load_django_config:1899 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 22:28:02.233 | INFO | __main__:load_gunicorn_config:2507 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 22:28:03.873 | INFO | __main__:run:69 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 22:28:03.963 | INFO | __main__:run:75 - 服务器连接成功
|
||||||
|
2025-08-27 22:28:05.153 | INFO | __main__:on_tab_changed:2615 - 切换到Gunicorn标签,自动检测服务状态
|
||||||
|
2025-08-27 22:28:05.652 | INFO | __main__:check_service_status:2515 - 自动检测Gunicorn服务状态
|
||||||
|
2025-08-27 22:28:05.653 | INFO | __main__:manage_service:2348 - 开始管理Gunicorn服务,操作: status
|
||||||
|
2025-08-27 22:28:05.901 | INFO | __main__:manage_service:2368 - ManageGunicornServiceThread已启动,操作: status
|
||||||
|
2025-08-27 22:28:05.903 | INFO | __main__:run:2075 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 22:28:08.849 | INFO | __main__:show_service_password_dialog:2400 - 用户已输入sudo密码
|
||||||
67
app.log
Normal file
67
app.log
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
2025-08-27 22:29:13.339 | INFO | __main__:<module>:2691 - 应用程序启动
|
||||||
|
2025-08-27 22:29:13.376 | INFO | __main__:load_git_config:1257 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-27 22:29:13.377 | INFO | __main__:load_django_config:1899 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-27 22:29:13.379 | INFO | __main__:load_gunicorn_config:2576 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-27 22:29:15.654 | INFO | __main__:on_tab_changed:2684 - 切换到Gunicorn标签,自动检测服务状态
|
||||||
|
2025-08-27 22:29:16.159 | WARNING | __main__:check_service_status:2587 - 未连接服务器,跳过Gunicorn服务状态检测
|
||||||
|
2025-08-27 22:29:20.590 | INFO | __main__:run:69 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-27 22:29:20.678 | INFO | __main__:run:75 - 服务器连接成功
|
||||||
|
2025-08-27 22:29:21.205 | INFO | __main__:on_tab_changed:2684 - 切换到Gunicorn标签,自动检测服务状态
|
||||||
|
2025-08-27 22:29:21.708 | INFO | __main__:check_service_status:2584 - 自动检测Gunicorn服务状态
|
||||||
|
2025-08-27 22:29:21.708 | INFO | __main__:manage_service:2417 - 开始管理Gunicorn服务,操作: status
|
||||||
|
2025-08-27 22:29:21.947 | INFO | __main__:manage_service:2437 - ManageGunicornServiceThread已启动,操作: status
|
||||||
|
2025-08-27 22:29:21.954 | INFO | __main__:run:2075 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 22:29:26.166 | INFO | __main__:show_service_password_dialog:2469 - 用户已输入sudo密码
|
||||||
|
2025-08-27 22:29:26.185 | DEBUG | __main__:run:2087 - 准备执行命令: sudo -S systemctl status gunicorn
|
||||||
|
2025-08-27 22:29:26.787 | DEBUG | __main__:run:2101 - 正在传递sudo密码...
|
||||||
|
2025-08-27 22:29:26.788 | DEBUG | __main__:run:2104 - 密码传递完成,等待命令执行...
|
||||||
|
2025-08-27 22:29:56.835 | ERROR | __main__:run:2119 - 命令执行超时: sudo -S systemctl status gunicorn
|
||||||
|
2025-08-27 22:30:37.721 | INFO | __main__:on_tab_changed:2684 - 切换到Gunicorn标签,自动检测服务状态
|
||||||
|
2025-08-27 22:30:38.215 | INFO | __main__:check_service_status:2584 - 自动检测Gunicorn服务状态
|
||||||
|
2025-08-27 22:30:38.216 | INFO | __main__:manage_service:2417 - 开始管理Gunicorn服务,操作: status
|
||||||
|
2025-08-27 22:30:38.218 | INFO | __main__:manage_service:2437 - ManageGunicornServiceThread已启动,操作: status
|
||||||
|
2025-08-27 22:30:38.220 | INFO | __main__:run:2075 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-27 22:30:41.127 | INFO | __main__:show_service_password_dialog:2469 - 用户已输入sudo密码
|
||||||
|
2025-08-27 22:30:41.134 | DEBUG | __main__:run:2087 - 准备执行命令: sudo -S systemctl status gunicorn
|
||||||
|
2025-08-27 22:30:41.727 | DEBUG | __main__:run:2101 - 正在传递sudo密码...
|
||||||
|
2025-08-27 22:30:41.727 | DEBUG | __main__:run:2104 - 密码传递完成,等待命令执行...
|
||||||
|
2025-08-27 22:31:11.761 | ERROR | __main__:run:2119 - 命令执行超时: sudo -S systemctl status gunicorn
|
||||||
|
2025-08-28 20:04:06.090 | INFO | __main__:<module>:2691 - 应用程序启动
|
||||||
|
2025-08-28 20:04:06.159 | INFO | __main__:load_git_config:1257 - 已加载服务器 测试服务器(192.168.3.157) 的git配置
|
||||||
|
2025-08-28 20:04:06.160 | INFO | __main__:load_django_config:1899 - 已加载服务器 测试服务器(192.168.3.157) 的Django配置
|
||||||
|
2025-08-28 20:04:06.161 | INFO | __main__:load_gunicorn_config:2576 - 已加载服务器 测试服务器(192.168.3.157) 的Gunicorn配置
|
||||||
|
2025-08-28 20:04:07.908 | INFO | __main__:run:69 - 尝试连接服务器: 192.168.3.157:22
|
||||||
|
2025-08-28 20:04:08.017 | INFO | __main__:run:75 - 服务器连接成功
|
||||||
|
2025-08-28 20:04:11.660 | INFO | __main__:on_tab_changed:2684 - 切换到Gunicorn标签,自动检测服务状态
|
||||||
|
2025-08-28 20:04:12.159 | INFO | __main__:check_service_status:2584 - 自动检测Gunicorn服务状态
|
||||||
|
2025-08-28 20:04:12.159 | INFO | __main__:manage_service:2417 - 开始管理Gunicorn服务,操作: status
|
||||||
|
2025-08-28 20:04:12.161 | INFO | __main__:manage_service:2437 - ManageGunicornServiceThread已启动,操作: status
|
||||||
|
2025-08-28 20:04:12.162 | INFO | __main__:run:2075 - 开始执行Gunicorn服务操作: status
|
||||||
|
2025-08-28 20:04:15.634 | INFO | __main__:show_service_password_dialog:2469 - 用户已输入sudo密码
|
||||||
|
2025-08-28 20:04:15.686 | DEBUG | __main__:run:2087 - 准备执行命令: sudo -S systemctl status gunicorn
|
||||||
|
2025-08-28 20:04:16.326 | DEBUG | __main__:run:2101 - 正在传递sudo密码...
|
||||||
|
2025-08-28 20:04:16.327 | DEBUG | __main__:run:2104 - 密码传递完成,等待命令执行...
|
||||||
|
2025-08-28 20:28:50.493 | INFO | __main__:<module>:114 - 应用程序启动
|
||||||
|
2025-08-28 20:32:04.868 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157
|
||||||
|
2025-08-28 20:32:06.089 | INFO | __main__:on_tab_changed:107 - 切换到Gunicorn标签,自动检测服务状态
|
||||||
|
2025-08-28 20:32:06.620 | ERROR | gunicorn_tab:on_manage_service_result:270 - 服务操作失败: sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
|
||||||
|
sudo: a password is required
|
||||||
|
|
||||||
|
2025-08-28 20:32:06.620 | ERROR | threads:run:808 - 服务状态查询失败: sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
|
||||||
|
sudo: a password is required
|
||||||
|
|
||||||
|
2025-08-28 20:32:29.596 | INFO | __main__:on_tab_changed:107 - 切换到Gunicorn标签,自动检测服务状态
|
||||||
|
2025-08-28 20:32:30.115 | ERROR | threads:run:808 - 服务状态查询失败: sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
|
||||||
|
sudo: a password is required
|
||||||
|
|
||||||
|
2025-08-28 20:32:30.115 | ERROR | gunicorn_tab:on_manage_service_result:270 - 服务操作失败: sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
|
||||||
|
sudo: a password is required
|
||||||
|
|
||||||
|
2025-08-28 20:35:01.275 | ERROR | threads:run:808 - 服务状态查询失败: sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
|
||||||
|
sudo: a password is required
|
||||||
|
|
||||||
|
2025-08-28 20:35:01.275 | ERROR | gunicorn_tab:on_manage_service_result:270 - 服务操作失败: sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
|
||||||
|
sudo: a password is required
|
||||||
|
|
||||||
|
2025-08-28 20:37:01.109 | INFO | __main__:<module>:114 - 应用程序启动
|
||||||
|
2025-08-28 20:41:24.800 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157
|
||||||
25
config.json
Normal file
25
config.json
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"alias": "测试服务器(192.168.3.157)",
|
||||||
|
"host": "192.168.3.157",
|
||||||
|
"port": 22,
|
||||||
|
"username": "xiaji",
|
||||||
|
"password": "xiaji",
|
||||||
|
"project_name": "statuspage",
|
||||||
|
"git_url": "http://192.168.3.241:3000/xiaji/webstatus",
|
||||||
|
"remote_directory": "/home/xiaji/",
|
||||||
|
"django_path": "/home/xiaji/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": "生产服务器",
|
||||||
|
"host": "192.168.1.200",
|
||||||
|
"port": 22,
|
||||||
|
"username": "admin",
|
||||||
|
"password": "your_password",
|
||||||
|
"project_name": "production_app",
|
||||||
|
"git_url": "https://github.com/example/production_app.git",
|
||||||
|
"remote_directory": "/home/admin/production_app"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
277
django_tab.py
Normal file
277
django_tab.py
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
import os
|
||||||
|
from loguru import logger
|
||||||
|
from PySide6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit,
|
||||||
|
QPushButton, QComboBox, QMessageBox, QTextEdit,
|
||||||
|
QGroupBox, QGridLayout, QProgressBar)
|
||||||
|
from PySide6.QtCore import Qt
|
||||||
|
|
||||||
|
from threads import (DjangoInstallThread, DjangoTestThread, DownloadSettingsThread,
|
||||||
|
UploadSettingsThread, CollectStaticThread, CheckDjangoStatusThread)
|
||||||
|
|
||||||
|
|
||||||
|
class DjangoTab(QWidget):
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.parent = parent
|
||||||
|
self.init_ui()
|
||||||
|
|
||||||
|
def init_ui(self):
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
|
||||||
|
# Django项目配置组
|
||||||
|
config_group = QGroupBox("Django项目配置")
|
||||||
|
config_layout = QGridLayout()
|
||||||
|
|
||||||
|
config_layout.addWidget(QLabel("Django项目路径:"), 0, 0)
|
||||||
|
self.django_path_input = QLineEdit()
|
||||||
|
self.django_path_input.setPlaceholderText("/home/user/django_project")
|
||||||
|
config_layout.addWidget(self.django_path_input, 0, 1)
|
||||||
|
|
||||||
|
self.load_django_path_btn = QPushButton("加载路径")
|
||||||
|
self.load_django_path_btn.clicked.connect(self.load_django_path)
|
||||||
|
config_layout.addWidget(self.load_django_path_btn, 0, 2)
|
||||||
|
|
||||||
|
config_group.setLayout(config_layout)
|
||||||
|
layout.addWidget(config_group)
|
||||||
|
|
||||||
|
# Django操作组
|
||||||
|
django_group = QGroupBox("Django操作")
|
||||||
|
django_layout = QGridLayout()
|
||||||
|
|
||||||
|
self.install_django_btn = QPushButton("安装Django")
|
||||||
|
self.install_django_btn.clicked.connect(self.install_django)
|
||||||
|
django_layout.addWidget(self.install_django_btn, 0, 0)
|
||||||
|
|
||||||
|
self.test_django_btn = QPushButton("测试启动")
|
||||||
|
self.test_django_btn.clicked.connect(self.test_django)
|
||||||
|
django_layout.addWidget(self.test_django_btn, 0, 1)
|
||||||
|
|
||||||
|
self.download_settings_btn = QPushButton("下载settings.py")
|
||||||
|
self.download_settings_btn.clicked.connect(self.download_settings)
|
||||||
|
django_layout.addWidget(self.download_settings_btn, 1, 0)
|
||||||
|
|
||||||
|
self.upload_settings_btn = QPushButton("上传settings.py")
|
||||||
|
self.upload_settings_btn.clicked.connect(self.upload_settings)
|
||||||
|
django_layout.addWidget(self.upload_settings_btn, 1, 1)
|
||||||
|
|
||||||
|
self.collect_static_btn = QPushButton("收集静态文件")
|
||||||
|
self.collect_static_btn.clicked.connect(self.collect_static)
|
||||||
|
django_layout.addWidget(self.collect_static_btn, 2, 0)
|
||||||
|
|
||||||
|
self.check_status_btn = QPushButton("检查Django状态")
|
||||||
|
self.check_status_btn.clicked.connect(self.check_django_status)
|
||||||
|
django_layout.addWidget(self.check_status_btn, 2, 1)
|
||||||
|
|
||||||
|
django_group.setLayout(django_layout)
|
||||||
|
layout.addWidget(django_group)
|
||||||
|
|
||||||
|
# Settings.py编辑器
|
||||||
|
settings_group = QGroupBox("Settings.py编辑器")
|
||||||
|
settings_layout = QVBoxLayout()
|
||||||
|
|
||||||
|
self.settings_editor = QTextEdit()
|
||||||
|
self.settings_editor.setPlaceholderText("settings.py内容将在这里显示...")
|
||||||
|
settings_layout.addWidget(self.settings_editor)
|
||||||
|
|
||||||
|
settings_group.setLayout(settings_layout)
|
||||||
|
layout.addWidget(settings_group)
|
||||||
|
|
||||||
|
# 操作输出
|
||||||
|
output_group = QGroupBox("操作输出")
|
||||||
|
output_layout = QVBoxLayout()
|
||||||
|
|
||||||
|
self.output_text = QTextEdit()
|
||||||
|
self.output_text.setReadOnly(True)
|
||||||
|
self.output_text.setPlaceholderText("操作结果将在这里显示...")
|
||||||
|
output_layout.addWidget(self.output_text)
|
||||||
|
|
||||||
|
# 进度条
|
||||||
|
self.progress_bar = QProgressBar()
|
||||||
|
self.progress_bar.setVisible(False)
|
||||||
|
output_layout.addWidget(self.progress_bar)
|
||||||
|
|
||||||
|
output_group.setLayout(output_layout)
|
||||||
|
layout.addWidget(output_group)
|
||||||
|
|
||||||
|
layout.addStretch()
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
# 加载Django路径
|
||||||
|
self.load_django_path()
|
||||||
|
|
||||||
|
def load_django_path(self):
|
||||||
|
if self.parent and hasattr(self.parent, 'server_connection_tab'):
|
||||||
|
django_path = self.parent.server_connection_tab.django_path_input.text()
|
||||||
|
self.django_path_input.setText(django_path)
|
||||||
|
|
||||||
|
def check_ssh_connection(self):
|
||||||
|
if not self.parent or not self.parent.ssh_client:
|
||||||
|
QMessageBox.warning(self, "警告", "请先连接服务器")
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def install_django(self):
|
||||||
|
if not self.check_ssh_connection():
|
||||||
|
return
|
||||||
|
|
||||||
|
self.output_text.append("正在安装Django...")
|
||||||
|
self.install_django_btn.setEnabled(False)
|
||||||
|
self.progress_bar.setVisible(True)
|
||||||
|
self.progress_bar.setValue(0)
|
||||||
|
|
||||||
|
self.django_install_thread = DjangoInstallThread(self.parent.ssh_client)
|
||||||
|
self.django_install_thread.progress_updated.connect(self.update_progress)
|
||||||
|
self.django_install_thread.result_ready.connect(self.on_install_django_result)
|
||||||
|
self.django_install_thread.start()
|
||||||
|
|
||||||
|
def update_progress(self, value):
|
||||||
|
self.progress_bar.setValue(value)
|
||||||
|
|
||||||
|
def on_install_django_result(self, success, message):
|
||||||
|
self.install_django_btn.setEnabled(True)
|
||||||
|
self.progress_bar.setVisible(False)
|
||||||
|
if success:
|
||||||
|
self.output_text.append(f"Django安装成功: {message}")
|
||||||
|
logger.info(f"Django安装成功: {message}")
|
||||||
|
else:
|
||||||
|
self.output_text.append(f"Django安装失败: {message}")
|
||||||
|
logger.error(f"Django安装失败: {message}")
|
||||||
|
|
||||||
|
def test_django(self):
|
||||||
|
if not self.check_ssh_connection():
|
||||||
|
return
|
||||||
|
|
||||||
|
django_path = self.django_path_input.text().strip()
|
||||||
|
if not django_path:
|
||||||
|
QMessageBox.warning(self, "警告", "请输入Django项目路径")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.output_text.append(f"正在测试启动Django项目 {django_path}...")
|
||||||
|
self.test_django_btn.setEnabled(False)
|
||||||
|
self.progress_bar.setVisible(True)
|
||||||
|
self.progress_bar.setValue(0)
|
||||||
|
|
||||||
|
self.django_test_thread = DjangoTestThread(self.parent.ssh_client, django_path)
|
||||||
|
self.django_test_thread.progress_updated.connect(self.update_progress)
|
||||||
|
self.django_test_thread.result_ready.connect(self.on_test_django_result)
|
||||||
|
self.django_test_thread.start()
|
||||||
|
|
||||||
|
def on_test_django_result(self, success, message):
|
||||||
|
self.test_django_btn.setEnabled(True)
|
||||||
|
self.progress_bar.setVisible(False)
|
||||||
|
if success:
|
||||||
|
self.output_text.append(f"Django测试启动成功: {message}")
|
||||||
|
logger.info(f"Django测试启动成功: {message}")
|
||||||
|
else:
|
||||||
|
self.output_text.append(f"Django测试启动失败: {message}")
|
||||||
|
logger.error(f"Django测试启动失败: {message}")
|
||||||
|
|
||||||
|
def download_settings(self):
|
||||||
|
if not self.check_ssh_connection():
|
||||||
|
return
|
||||||
|
|
||||||
|
django_path = self.django_path_input.text().strip()
|
||||||
|
if not django_path:
|
||||||
|
QMessageBox.warning(self, "警告", "请输入Django项目路径")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.output_text.append(f"正在下载settings.py从 {django_path}...")
|
||||||
|
self.download_settings_btn.setEnabled(False)
|
||||||
|
|
||||||
|
self.download_thread = DownloadSettingsThread(self.parent.ssh_client, django_path)
|
||||||
|
self.download_thread.result_ready.connect(self.on_download_settings_result)
|
||||||
|
self.download_thread.start()
|
||||||
|
|
||||||
|
def on_download_settings_result(self, success, message):
|
||||||
|
self.download_settings_btn.setEnabled(True)
|
||||||
|
if success:
|
||||||
|
self.settings_editor.setText(message)
|
||||||
|
self.output_text.append("settings.py下载成功")
|
||||||
|
logger.info("settings.py下载成功")
|
||||||
|
else:
|
||||||
|
self.output_text.append(f"settings.py下载失败: {message}")
|
||||||
|
logger.error(f"settings.py下载失败: {message}")
|
||||||
|
|
||||||
|
def upload_settings(self):
|
||||||
|
if not self.check_ssh_connection():
|
||||||
|
return
|
||||||
|
|
||||||
|
django_path = self.django_path_input.text().strip()
|
||||||
|
settings_content = self.settings_editor.toPlainText()
|
||||||
|
|
||||||
|
if not django_path or not settings_content:
|
||||||
|
QMessageBox.warning(self, "警告", "请输入Django项目路径并编辑settings.py内容")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.output_text.append(f"正在上传settings.py到 {django_path}...")
|
||||||
|
self.upload_settings_btn.setEnabled(False)
|
||||||
|
|
||||||
|
self.upload_thread = UploadSettingsThread(self.parent.ssh_client, django_path, settings_content)
|
||||||
|
self.upload_thread.result_ready.connect(self.on_upload_settings_result)
|
||||||
|
self.upload_thread.start()
|
||||||
|
|
||||||
|
def on_upload_settings_result(self, success, message):
|
||||||
|
self.upload_settings_btn.setEnabled(True)
|
||||||
|
if success:
|
||||||
|
self.output_text.append("settings.py上传成功")
|
||||||
|
logger.info("settings.py上传成功")
|
||||||
|
else:
|
||||||
|
self.output_text.append(f"settings.py上传失败: {message}")
|
||||||
|
logger.error(f"settings.py上传失败: {message}")
|
||||||
|
|
||||||
|
def collect_static(self):
|
||||||
|
if not self.check_ssh_connection():
|
||||||
|
return
|
||||||
|
|
||||||
|
django_path = self.django_path_input.text().strip()
|
||||||
|
if not django_path:
|
||||||
|
QMessageBox.warning(self, "警告", "请输入Django项目路径")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.output_text.append(f"正在收集 {django_path} 的静态文件...")
|
||||||
|
self.collect_static_btn.setEnabled(False)
|
||||||
|
self.progress_bar.setVisible(True)
|
||||||
|
self.progress_bar.setValue(0)
|
||||||
|
|
||||||
|
self.collect_thread = CollectStaticThread(self.parent.ssh_client, django_path)
|
||||||
|
self.collect_thread.progress_updated.connect(self.update_progress)
|
||||||
|
self.collect_thread.result_ready.connect(self.on_collect_static_result)
|
||||||
|
self.collect_thread.start()
|
||||||
|
|
||||||
|
def on_collect_static_result(self, success, message):
|
||||||
|
self.collect_static_btn.setEnabled(True)
|
||||||
|
self.progress_bar.setVisible(False)
|
||||||
|
if success:
|
||||||
|
self.output_text.append(f"静态文件收集成功: {message}")
|
||||||
|
logger.info(f"静态文件收集成功: {message}")
|
||||||
|
else:
|
||||||
|
self.output_text.append(f"静态文件收集失败: {message}")
|
||||||
|
logger.error(f"静态文件收集失败: {message}")
|
||||||
|
|
||||||
|
def check_django_status(self):
|
||||||
|
if not self.check_ssh_connection():
|
||||||
|
return
|
||||||
|
|
||||||
|
django_path = self.django_path_input.text().strip()
|
||||||
|
if not django_path:
|
||||||
|
QMessageBox.warning(self, "警告", "请输入Django项目路径")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.output_text.append(f"正在检查 {django_path} 的Django状态...")
|
||||||
|
self.check_status_btn.setEnabled(False)
|
||||||
|
|
||||||
|
self.check_status_thread = CheckDjangoStatusThread(self.parent.ssh_client, django_path)
|
||||||
|
self.check_status_thread.result_ready.connect(self.on_check_django_status_result)
|
||||||
|
self.check_status_thread.start()
|
||||||
|
|
||||||
|
def on_check_django_status_result(self, success, message):
|
||||||
|
self.check_status_btn.setEnabled(True)
|
||||||
|
if success:
|
||||||
|
self.output_text.append(f"Django状态检查结果:\n{message}")
|
||||||
|
logger.info("Django状态检查成功")
|
||||||
|
else:
|
||||||
|
self.output_text.append(f"Django状态检查失败: {message}")
|
||||||
|
logger.error(f"Django状态检查失败: {message}")
|
||||||
|
|
||||||
|
def on_server_changed(self):
|
||||||
|
self.load_django_path()
|
||||||
298
gunicorn_tab.py
Normal file
298
gunicorn_tab.py
Normal file
@@ -0,0 +1,298 @@
|
|||||||
|
import os
|
||||||
|
from loguru import logger
|
||||||
|
from PySide6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit,
|
||||||
|
QPushButton, QComboBox, QMessageBox, QTextEdit,
|
||||||
|
QGroupBox, QGridLayout, QProgressBar)
|
||||||
|
from PySide6.QtCore import Qt
|
||||||
|
|
||||||
|
from threads import (GunicornInstallThread, GunicornTestThread,
|
||||||
|
UploadGunicornServiceThread, ManageGunicornServiceThread)
|
||||||
|
|
||||||
|
|
||||||
|
class GunicornTab(QWidget):
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.parent = parent
|
||||||
|
self.init_ui()
|
||||||
|
|
||||||
|
def init_ui(self):
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
|
||||||
|
# Gunicorn配置组
|
||||||
|
config_group = QGroupBox("Gunicorn配置")
|
||||||
|
config_layout = QGridLayout()
|
||||||
|
|
||||||
|
config_layout.addWidget(QLabel("Django项目路径:"), 0, 0)
|
||||||
|
self.django_path_input = QLineEdit()
|
||||||
|
self.django_path_input.setPlaceholderText("/home/user/django_project")
|
||||||
|
config_layout.addWidget(self.django_path_input, 0, 1)
|
||||||
|
|
||||||
|
config_layout.addWidget(QLabel("服务名称:"), 1, 0)
|
||||||
|
self.service_name_input = QLineEdit("django_gunicorn")
|
||||||
|
config_layout.addWidget(self.service_name_input, 1, 1)
|
||||||
|
|
||||||
|
config_layout.addWidget(QLabel("端口:"), 2, 0)
|
||||||
|
self.port_input = QLineEdit("8000")
|
||||||
|
config_layout.addWidget(self.port_input, 2, 1)
|
||||||
|
|
||||||
|
config_layout.addWidget(QLabel("工作进程数:"), 3, 0)
|
||||||
|
self.workers_input = QLineEdit("3")
|
||||||
|
config_layout.addWidget(self.workers_input, 3, 1)
|
||||||
|
|
||||||
|
self.load_config_btn = QPushButton("加载配置")
|
||||||
|
self.load_config_btn.clicked.connect(self.load_gunicorn_config)
|
||||||
|
config_layout.addWidget(self.load_config_btn, 4, 1)
|
||||||
|
|
||||||
|
config_group.setLayout(config_layout)
|
||||||
|
layout.addWidget(config_group)
|
||||||
|
|
||||||
|
# Gunicorn操作组
|
||||||
|
gunicorn_group = QGroupBox("Gunicorn操作")
|
||||||
|
gunicorn_layout = QGridLayout()
|
||||||
|
|
||||||
|
self.install_gunicorn_btn = QPushButton("安装Gunicorn")
|
||||||
|
self.install_gunicorn_btn.clicked.connect(self.install_gunicorn)
|
||||||
|
gunicorn_layout.addWidget(self.install_gunicorn_btn, 0, 0)
|
||||||
|
|
||||||
|
self.test_gunicorn_btn = QPushButton("测试Gunicorn")
|
||||||
|
self.test_gunicorn_btn.clicked.connect(self.test_gunicorn)
|
||||||
|
gunicorn_layout.addWidget(self.test_gunicorn_btn, 0, 1)
|
||||||
|
|
||||||
|
self.upload_service_btn = QPushButton("上传服务文件")
|
||||||
|
self.upload_service_btn.clicked.connect(self.upload_service_file)
|
||||||
|
gunicorn_layout.addWidget(self.upload_service_btn, 1, 0)
|
||||||
|
|
||||||
|
self.start_service_btn = QPushButton("启动服务")
|
||||||
|
self.start_service_btn.clicked.connect(lambda: self.manage_service("start"))
|
||||||
|
gunicorn_layout.addWidget(self.start_service_btn, 1, 1)
|
||||||
|
|
||||||
|
self.stop_service_btn = QPushButton("停止服务")
|
||||||
|
self.stop_service_btn.clicked.connect(lambda: self.manage_service("stop"))
|
||||||
|
gunicorn_layout.addWidget(self.stop_service_btn, 2, 0)
|
||||||
|
|
||||||
|
self.restart_service_btn = QPushButton("重启服务")
|
||||||
|
self.restart_service_btn.clicked.connect(lambda: self.manage_service("restart"))
|
||||||
|
gunicorn_layout.addWidget(self.restart_service_btn, 2, 1)
|
||||||
|
|
||||||
|
self.status_service_btn = QPushButton("查看服务状态")
|
||||||
|
self.status_service_btn.clicked.connect(lambda: self.manage_service("status"))
|
||||||
|
gunicorn_layout.addWidget(self.status_service_btn, 3, 0)
|
||||||
|
|
||||||
|
self.enable_service_btn = QPushButton("启用开机自启")
|
||||||
|
self.enable_service_btn.clicked.connect(lambda: self.manage_service("enable"))
|
||||||
|
gunicorn_layout.addWidget(self.enable_service_btn, 3, 1)
|
||||||
|
|
||||||
|
gunicorn_group.setLayout(gunicorn_layout)
|
||||||
|
layout.addWidget(gunicorn_group)
|
||||||
|
|
||||||
|
# 服务文件编辑器
|
||||||
|
service_group = QGroupBox("Gunicorn服务文件")
|
||||||
|
service_layout = QVBoxLayout()
|
||||||
|
|
||||||
|
self.service_editor = QTextEdit()
|
||||||
|
self.service_editor.setPlaceholderText("Gunicorn服务文件内容将在这里显示...")
|
||||||
|
service_layout.addWidget(self.service_editor)
|
||||||
|
|
||||||
|
service_group.setLayout(service_layout)
|
||||||
|
layout.addWidget(service_group)
|
||||||
|
|
||||||
|
# 操作输出
|
||||||
|
output_group = QGroupBox("操作输出")
|
||||||
|
output_layout = QVBoxLayout()
|
||||||
|
|
||||||
|
self.output_text = QTextEdit()
|
||||||
|
self.output_text.setReadOnly(True)
|
||||||
|
self.output_text.setPlaceholderText("操作结果将在这里显示...")
|
||||||
|
output_layout.addWidget(self.output_text)
|
||||||
|
|
||||||
|
# 进度条
|
||||||
|
self.progress_bar = QProgressBar()
|
||||||
|
self.progress_bar.setVisible(False)
|
||||||
|
output_layout.addWidget(self.progress_bar)
|
||||||
|
|
||||||
|
output_group.setLayout(output_layout)
|
||||||
|
layout.addWidget(output_group)
|
||||||
|
|
||||||
|
layout.addStretch()
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
# 加载Gunicorn配置
|
||||||
|
self.load_gunicorn_config()
|
||||||
|
|
||||||
|
def load_gunicorn_config(self):
|
||||||
|
if self.parent and hasattr(self.parent, 'server_connection_tab'):
|
||||||
|
django_path = self.parent.server_connection_tab.django_path_input.text()
|
||||||
|
self.django_path_input.setText(django_path)
|
||||||
|
|
||||||
|
# 生成默认的服务文件内容
|
||||||
|
service_name = self.service_name_input.text()
|
||||||
|
port = self.port_input.text()
|
||||||
|
workers = self.workers_input.text()
|
||||||
|
|
||||||
|
service_content = self.generate_service_file(service_name, django_path, port, workers)
|
||||||
|
self.service_editor.setText(service_content)
|
||||||
|
|
||||||
|
def generate_service_file(self, service_name, django_path, port, workers):
|
||||||
|
return f"""[Unit]
|
||||||
|
Description={service_name} daemon
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
User=www-data
|
||||||
|
Group=www-data
|
||||||
|
WorkingDirectory={django_path}
|
||||||
|
ExecStart=/usr/local/bin/gunicorn --workers {workers} --bind 0.0.0.0:{port} {os.path.basename(django_path)}.wsgi:application
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
"""
|
||||||
|
|
||||||
|
def check_ssh_connection(self):
|
||||||
|
if not self.parent or not self.parent.ssh_client:
|
||||||
|
QMessageBox.warning(self, "警告", "请先连接服务器")
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def install_gunicorn(self):
|
||||||
|
if not self.check_ssh_connection():
|
||||||
|
return
|
||||||
|
|
||||||
|
self.output_text.append("正在安装Gunicorn...")
|
||||||
|
self.install_gunicorn_btn.setEnabled(False)
|
||||||
|
self.progress_bar.setVisible(True)
|
||||||
|
self.progress_bar.setValue(0)
|
||||||
|
|
||||||
|
# 获取密码
|
||||||
|
password = None
|
||||||
|
if self.parent and hasattr(self.parent, 'server_connection_tab'):
|
||||||
|
password = self.parent.server_connection_tab.password_input.text()
|
||||||
|
|
||||||
|
self.gunicorn_install_thread = GunicornInstallThread(self.parent.ssh_client, password)
|
||||||
|
self.gunicorn_install_thread.progress_updated.connect(self.update_progress)
|
||||||
|
self.gunicorn_install_thread.result_ready.connect(self.on_install_gunicorn_result)
|
||||||
|
self.gunicorn_install_thread.start()
|
||||||
|
|
||||||
|
def update_progress(self, value):
|
||||||
|
self.progress_bar.setValue(value)
|
||||||
|
|
||||||
|
def on_install_gunicorn_result(self, success, message):
|
||||||
|
self.install_gunicorn_btn.setEnabled(True)
|
||||||
|
self.progress_bar.setVisible(False)
|
||||||
|
if success:
|
||||||
|
self.output_text.append(f"Gunicorn安装成功: {message}")
|
||||||
|
logger.info(f"Gunicorn安装成功: {message}")
|
||||||
|
else:
|
||||||
|
self.output_text.append(f"Gunicorn安装失败: {message}")
|
||||||
|
logger.error(f"Gunicorn安装失败: {message}")
|
||||||
|
|
||||||
|
def test_gunicorn(self):
|
||||||
|
if not self.check_ssh_connection():
|
||||||
|
return
|
||||||
|
|
||||||
|
django_path = self.django_path_input.text().strip()
|
||||||
|
if not django_path:
|
||||||
|
QMessageBox.warning(self, "警告", "请输入Django项目路径")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.output_text.append(f"正在测试Gunicorn {django_path}...")
|
||||||
|
self.test_gunicorn_btn.setEnabled(False)
|
||||||
|
self.progress_bar.setVisible(True)
|
||||||
|
self.progress_bar.setValue(0)
|
||||||
|
|
||||||
|
self.gunicorn_test_thread = GunicornTestThread(self.parent.ssh_client, django_path)
|
||||||
|
self.gunicorn_test_thread.progress_updated.connect(self.update_progress)
|
||||||
|
self.gunicorn_test_thread.result_ready.connect(self.on_test_gunicorn_result)
|
||||||
|
self.gunicorn_test_thread.start()
|
||||||
|
|
||||||
|
def on_test_gunicorn_result(self, success, message):
|
||||||
|
self.test_gunicorn_btn.setEnabled(True)
|
||||||
|
self.progress_bar.setVisible(False)
|
||||||
|
if success:
|
||||||
|
self.output_text.append(f"Gunicorn测试成功: {message}")
|
||||||
|
logger.info(f"Gunicorn测试成功: {message}")
|
||||||
|
else:
|
||||||
|
self.output_text.append(f"Gunicorn测试失败: {message}")
|
||||||
|
logger.error(f"Gunicorn测试失败: {message}")
|
||||||
|
|
||||||
|
def upload_service_file(self):
|
||||||
|
if not self.check_ssh_connection():
|
||||||
|
return
|
||||||
|
|
||||||
|
service_name = self.service_name_input.text().strip()
|
||||||
|
service_content = self.service_editor.toPlainText()
|
||||||
|
|
||||||
|
if not service_name or not service_content:
|
||||||
|
QMessageBox.warning(self, "警告", "请输入服务名称并编辑服务文件内容")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.output_text.append(f"正在上传服务文件 {service_name}...")
|
||||||
|
self.upload_service_btn.setEnabled(False)
|
||||||
|
|
||||||
|
# 获取密码
|
||||||
|
password = None
|
||||||
|
if self.parent and hasattr(self.parent, 'server_connection_tab'):
|
||||||
|
password = self.parent.server_connection_tab.password_input.text()
|
||||||
|
|
||||||
|
self.upload_thread = UploadGunicornServiceThread(self.parent.ssh_client, service_name, service_content, password)
|
||||||
|
self.upload_thread.result_ready.connect(self.on_upload_service_result)
|
||||||
|
self.upload_thread.start()
|
||||||
|
|
||||||
|
def on_upload_service_result(self, success, message):
|
||||||
|
self.upload_service_btn.setEnabled(True)
|
||||||
|
if success:
|
||||||
|
self.output_text.append(f"服务文件上传成功: {message}")
|
||||||
|
logger.info(f"服务文件上传成功: {message}")
|
||||||
|
else:
|
||||||
|
self.output_text.append(f"服务文件上传失败: {message}")
|
||||||
|
logger.error(f"服务文件上传失败: {message}")
|
||||||
|
|
||||||
|
def manage_service(self, action):
|
||||||
|
if not self.check_ssh_connection():
|
||||||
|
return
|
||||||
|
|
||||||
|
service_name = self.service_name_input.text().strip()
|
||||||
|
if not service_name:
|
||||||
|
QMessageBox.warning(self, "警告", "请输入服务名称")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.output_text.append(f"正在执行服务 {action} 操作...")
|
||||||
|
|
||||||
|
# 禁用所有服务管理按钮
|
||||||
|
buttons = [self.start_service_btn, self.stop_service_btn, self.restart_service_btn,
|
||||||
|
self.status_service_btn, self.enable_service_btn]
|
||||||
|
for btn in buttons:
|
||||||
|
btn.setEnabled(False)
|
||||||
|
|
||||||
|
# 获取密码
|
||||||
|
password = None
|
||||||
|
if self.parent and hasattr(self.parent, 'server_connection_tab'):
|
||||||
|
password = self.parent.server_connection_tab.password_input.text()
|
||||||
|
|
||||||
|
self.manage_thread = ManageGunicornServiceThread(self.parent.ssh_client, service_name, action, password)
|
||||||
|
self.manage_thread.result_ready.connect(lambda s, m: self.on_manage_service_result(s, m, buttons))
|
||||||
|
self.manage_thread.start()
|
||||||
|
|
||||||
|
def on_manage_service_result(self, success, message, buttons):
|
||||||
|
# 重新启用所有服务管理按钮
|
||||||
|
for btn in buttons:
|
||||||
|
btn.setEnabled(True)
|
||||||
|
|
||||||
|
if success:
|
||||||
|
self.output_text.append(f"服务操作成功: {message}")
|
||||||
|
logger.info(f"服务操作成功: {message}")
|
||||||
|
else:
|
||||||
|
self.output_text.append(f"服务操作失败: {message}")
|
||||||
|
logger.error(f"服务操作失败: {message}")
|
||||||
|
|
||||||
|
def on_server_changed(self):
|
||||||
|
self.load_gunicorn_config()
|
||||||
|
|
||||||
|
def check_service_status(self):
|
||||||
|
if not self.check_ssh_connection():
|
||||||
|
return
|
||||||
|
|
||||||
|
service_name = self.service_name_input.text().strip()
|
||||||
|
if not service_name:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.manage_service("status")
|
||||||
119
main.py
Normal file
119
main.py
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
import sys
|
||||||
|
import os
|
||||||
|
from loguru import logger
|
||||||
|
from PySide6.QtWidgets import QApplication, QMainWindow, QTabWidget
|
||||||
|
from PySide6.QtCore import QTimer
|
||||||
|
|
||||||
|
from server_connection_tab import ServerConnectionTab
|
||||||
|
from remote_command_tab import RemoteCommandTab
|
||||||
|
from django_tab import DjangoTab
|
||||||
|
from gunicorn_tab import GunicornTab
|
||||||
|
|
||||||
|
|
||||||
|
class MainWindow(QMainWindow):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.setWindowTitle("服务器管理工具")
|
||||||
|
self.setGeometry(100, 100, 800, 600)
|
||||||
|
|
||||||
|
# 创建标签页
|
||||||
|
self.tab_widget = QTabWidget()
|
||||||
|
|
||||||
|
# 服务器连接标签
|
||||||
|
self.server_tab = ServerConnectionTab()
|
||||||
|
self.tab_widget.addTab(self.server_tab, "服务器连接")
|
||||||
|
|
||||||
|
# 远程命令标签
|
||||||
|
self.remote_tab = RemoteCommandTab(self.server_tab)
|
||||||
|
self.tab_widget.addTab(self.remote_tab, "远程命令")
|
||||||
|
|
||||||
|
# Django标签
|
||||||
|
self.django_tab = DjangoTab(self.server_tab)
|
||||||
|
self.tab_widget.addTab(self.django_tab, "Django")
|
||||||
|
|
||||||
|
# Gunicorn标签
|
||||||
|
self.gunicorn_tab = GunicornTab(self.server_tab)
|
||||||
|
self.tab_widget.addTab(self.gunicorn_tab, "Gunicorn")
|
||||||
|
|
||||||
|
self.setCentralWidget(self.tab_widget)
|
||||||
|
|
||||||
|
# 连接标签切换事件
|
||||||
|
self.tab_widget.currentChanged.connect(self.on_tab_changed)
|
||||||
|
|
||||||
|
# 设置样式
|
||||||
|
self.setStyleSheet("""
|
||||||
|
QMainWindow {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
}
|
||||||
|
QTabWidget::pane {
|
||||||
|
border: 1px solid #c4c4c3;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
QTabBar::tab {
|
||||||
|
background: #e1e1e1;
|
||||||
|
border: 1px solid #c4c4c3;
|
||||||
|
padding: 8px 16px;
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
QTabBar::tab:selected {
|
||||||
|
background: white;
|
||||||
|
border-bottom-color: white;
|
||||||
|
}
|
||||||
|
QPushButton {
|
||||||
|
background-color: #0078d4;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
QPushButton:hover {
|
||||||
|
background-color: #106ebe;
|
||||||
|
}
|
||||||
|
QPushButton:pressed {
|
||||||
|
background-color: #005a9e;
|
||||||
|
}
|
||||||
|
QPushButton:disabled {
|
||||||
|
background-color: #cccccc;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
QLineEdit {
|
||||||
|
border: 1px solid #c4c4c3;
|
||||||
|
padding: 6px;
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
QTextEdit {
|
||||||
|
border: 1px solid #c4c4c3;
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
font-family: 'Consolas', 'Monaco', monospace;
|
||||||
|
}
|
||||||
|
QProgressBar {
|
||||||
|
border: 1px solid #c4c4c3;
|
||||||
|
border-radius: 3px;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
}
|
||||||
|
QProgressBar::chunk {
|
||||||
|
background-color: #0078d4;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
|
||||||
|
def on_tab_changed(self, index):
|
||||||
|
"""标签切换事件处理"""
|
||||||
|
tab_text = self.tab_widget.tabText(index)
|
||||||
|
if tab_text == "Gunicorn":
|
||||||
|
# 切换到Gunicorn标签时自动检测服务状态
|
||||||
|
logger.info("切换到Gunicorn标签,自动检测服务状态")
|
||||||
|
# 延迟执行以确保UI完全加载
|
||||||
|
QTimer.singleShot(500, self.gunicorn_tab.check_service_status)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
logger.add("app.log", rotation="1 day", retention="7 days")
|
||||||
|
logger.info("应用程序启动")
|
||||||
|
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
window = MainWindow()
|
||||||
|
window.show()
|
||||||
|
sys.exit(app.exec())
|
||||||
291
remote_command_tab.py
Normal file
291
remote_command_tab.py
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
import os
|
||||||
|
from loguru import logger
|
||||||
|
from PySide6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit,
|
||||||
|
QPushButton, QComboBox, QMessageBox, QTextEdit,
|
||||||
|
QGroupBox, QGridLayout)
|
||||||
|
from PySide6.QtCore import Qt
|
||||||
|
|
||||||
|
from threads import (GitInstallThread, GitCloneThread, ListDirectoryThread,
|
||||||
|
DeleteDirectoryThread, SetTimezoneAndRestartThread,
|
||||||
|
CheckFirewallThread, OpenPortThread)
|
||||||
|
|
||||||
|
|
||||||
|
class RemoteCommandTab(QWidget):
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.parent = parent
|
||||||
|
self.init_ui()
|
||||||
|
|
||||||
|
def init_ui(self):
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
|
||||||
|
# Git管理组
|
||||||
|
git_group = QGroupBox("Git代码管理")
|
||||||
|
git_layout = QGridLayout()
|
||||||
|
|
||||||
|
git_layout.addWidget(QLabel("Git仓库URL:"), 0, 0)
|
||||||
|
self.git_url_input = QLineEdit()
|
||||||
|
self.git_url_input.setPlaceholderText("https://github.com/username/repo.git")
|
||||||
|
git_layout.addWidget(self.git_url_input, 0, 1)
|
||||||
|
|
||||||
|
git_layout.addWidget(QLabel("项目路径:"), 1, 0)
|
||||||
|
self.project_path_input = QLineEdit()
|
||||||
|
self.project_path_input.setPlaceholderText("/home/user/project")
|
||||||
|
git_layout.addWidget(self.project_path_input, 1, 1)
|
||||||
|
|
||||||
|
git_layout.addWidget(QLabel("删除目录:"), 2, 0)
|
||||||
|
self.delete_dir_input = QLineEdit()
|
||||||
|
self.delete_dir_input.setPlaceholderText("/home/user/old_project")
|
||||||
|
git_layout.addWidget(self.delete_dir_input, 2, 1)
|
||||||
|
|
||||||
|
self.install_git_btn = QPushButton("安装Git")
|
||||||
|
self.install_git_btn.clicked.connect(self.install_git)
|
||||||
|
git_layout.addWidget(self.install_git_btn, 0, 2)
|
||||||
|
|
||||||
|
self.clone_btn = QPushButton("拉取代码")
|
||||||
|
self.clone_btn.clicked.connect(self.clone_git)
|
||||||
|
git_layout.addWidget(self.clone_btn, 1, 2)
|
||||||
|
|
||||||
|
self.list_dir_btn = QPushButton("列出目录")
|
||||||
|
self.list_dir_btn.clicked.connect(self.list_directory)
|
||||||
|
git_layout.addWidget(self.list_dir_btn, 2, 2)
|
||||||
|
|
||||||
|
self.delete_dir_btn = QPushButton("删除目录")
|
||||||
|
self.delete_dir_btn.clicked.connect(self.delete_directory)
|
||||||
|
git_layout.addWidget(self.delete_dir_btn, 3, 2)
|
||||||
|
|
||||||
|
self.set_timezone_btn = QPushButton("设置时区并重启")
|
||||||
|
self.set_timezone_btn.clicked.connect(self.set_timezone_and_restart)
|
||||||
|
git_layout.addWidget(self.set_timezone_btn, 3, 0, 1, 2)
|
||||||
|
|
||||||
|
git_group.setLayout(git_layout)
|
||||||
|
layout.addWidget(git_group)
|
||||||
|
|
||||||
|
# 防火墙管理组
|
||||||
|
firewall_group = QGroupBox("防火墙管理")
|
||||||
|
firewall_layout = QGridLayout()
|
||||||
|
|
||||||
|
self.check_firewall_btn = QPushButton("检查防火墙")
|
||||||
|
self.check_firewall_btn.clicked.connect(self.check_firewall)
|
||||||
|
firewall_layout.addWidget(self.check_firewall_btn, 0, 0)
|
||||||
|
|
||||||
|
firewall_layout.addWidget(QLabel("端口:"), 0, 1)
|
||||||
|
self.port_input = QLineEdit("8000")
|
||||||
|
firewall_layout.addWidget(self.port_input, 0, 2)
|
||||||
|
|
||||||
|
self.open_port_btn = QPushButton("开放端口")
|
||||||
|
self.open_port_btn.clicked.connect(self.open_port)
|
||||||
|
firewall_layout.addWidget(self.open_port_btn, 0, 3)
|
||||||
|
|
||||||
|
firewall_group.setLayout(firewall_layout)
|
||||||
|
layout.addWidget(firewall_group)
|
||||||
|
|
||||||
|
# Settings.py编辑器
|
||||||
|
settings_group = QGroupBox("Settings.py编辑器")
|
||||||
|
settings_layout = QVBoxLayout()
|
||||||
|
|
||||||
|
self.settings_editor = QTextEdit()
|
||||||
|
self.settings_editor.setPlaceholderText("settings.py内容将在这里显示...")
|
||||||
|
settings_layout.addWidget(self.settings_editor)
|
||||||
|
|
||||||
|
settings_group.setLayout(settings_layout)
|
||||||
|
layout.addWidget(settings_group)
|
||||||
|
|
||||||
|
# 操作输出
|
||||||
|
output_group = QGroupBox("操作输出")
|
||||||
|
output_layout = QVBoxLayout()
|
||||||
|
|
||||||
|
self.output_text = QTextEdit()
|
||||||
|
self.output_text.setReadOnly(True)
|
||||||
|
self.output_text.setPlaceholderText("操作结果将在这里显示...")
|
||||||
|
output_layout.addWidget(self.output_text)
|
||||||
|
|
||||||
|
output_group.setLayout(output_layout)
|
||||||
|
layout.addWidget(output_group)
|
||||||
|
|
||||||
|
layout.addStretch()
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
# 加载Git配置
|
||||||
|
self.load_git_config()
|
||||||
|
|
||||||
|
def load_git_config(self):
|
||||||
|
if self.parent and hasattr(self.parent, 'server_connection_tab'):
|
||||||
|
git_url = self.parent.server_connection_tab.git_url_input.text()
|
||||||
|
remote_dir = self.parent.server_connection_tab.remote_dir_input.text()
|
||||||
|
self.git_url_input.setText(git_url)
|
||||||
|
self.project_path_input.setText(remote_dir)
|
||||||
|
|
||||||
|
def install_git(self):
|
||||||
|
if not self.check_ssh_connection():
|
||||||
|
return
|
||||||
|
|
||||||
|
self.output_text.append("正在安装Git...")
|
||||||
|
self.install_git_btn.setEnabled(False)
|
||||||
|
|
||||||
|
self.git_install_thread = GitInstallThread(self.parent.ssh_client)
|
||||||
|
self.git_install_thread.result_ready.connect(self.on_git_install_result)
|
||||||
|
self.git_install_thread.start()
|
||||||
|
|
||||||
|
def on_git_install_result(self, success, message):
|
||||||
|
self.install_git_btn.setEnabled(True)
|
||||||
|
if success:
|
||||||
|
self.output_text.append(f"Git安装成功: {message}")
|
||||||
|
logger.info(f"Git安装成功: {message}")
|
||||||
|
else:
|
||||||
|
self.output_text.append(f"Git安装失败: {message}")
|
||||||
|
logger.error(f"Git安装失败: {message}")
|
||||||
|
|
||||||
|
def clone_git(self):
|
||||||
|
if not self.check_ssh_connection():
|
||||||
|
return
|
||||||
|
|
||||||
|
git_url = self.git_url_input.text().strip()
|
||||||
|
project_path = self.project_path_input.text().strip()
|
||||||
|
|
||||||
|
if not git_url or not project_path:
|
||||||
|
QMessageBox.warning(self, "警告", "请填写Git仓库URL和项目路径")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.output_text.append(f"正在克隆 {git_url} 到 {project_path}...")
|
||||||
|
self.clone_btn.setEnabled(False)
|
||||||
|
|
||||||
|
self.git_clone_thread = GitCloneThread(self.parent.ssh_client, git_url, project_path)
|
||||||
|
self.git_clone_thread.result_ready.connect(self.on_git_clone_result)
|
||||||
|
self.git_clone_thread.start()
|
||||||
|
|
||||||
|
def on_git_clone_result(self, success, message):
|
||||||
|
self.clone_btn.setEnabled(True)
|
||||||
|
if success:
|
||||||
|
self.output_text.append(f"Git克隆成功: {message}")
|
||||||
|
logger.info(f"Git克隆成功: {message}")
|
||||||
|
else:
|
||||||
|
self.output_text.append(f"Git克隆失败: {message}")
|
||||||
|
logger.error(f"Git克隆失败: {message}")
|
||||||
|
|
||||||
|
def list_directory(self):
|
||||||
|
if not self.check_ssh_connection():
|
||||||
|
return
|
||||||
|
|
||||||
|
path = self.project_path_input.text().strip()
|
||||||
|
if not path:
|
||||||
|
QMessageBox.warning(self, "警告", "请输入要列出的目录路径")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.output_text.append(f"正在列出目录 {path}...")
|
||||||
|
self.list_dir_btn.setEnabled(False)
|
||||||
|
|
||||||
|
self.list_dir_thread = ListDirectoryThread(self.parent.ssh_client, path)
|
||||||
|
self.list_dir_thread.result_ready.connect(self.on_list_directory_result)
|
||||||
|
self.list_dir_thread.start()
|
||||||
|
|
||||||
|
def on_list_directory_result(self, success, message):
|
||||||
|
self.list_dir_btn.setEnabled(True)
|
||||||
|
if success:
|
||||||
|
self.output_text.append(f"目录列表:\n{message}")
|
||||||
|
logger.info(f"目录列表成功")
|
||||||
|
else:
|
||||||
|
self.output_text.append(f"列出目录失败: {message}")
|
||||||
|
logger.error(f"列出目录失败: {message}")
|
||||||
|
|
||||||
|
def delete_directory(self):
|
||||||
|
if not self.check_ssh_connection():
|
||||||
|
return
|
||||||
|
|
||||||
|
path = self.delete_dir_input.text().strip()
|
||||||
|
if not path:
|
||||||
|
QMessageBox.warning(self, "警告", "请输入要删除的目录路径")
|
||||||
|
return
|
||||||
|
|
||||||
|
reply = QMessageBox.question(self, "确认删除",
|
||||||
|
f"确定要删除目录 {path} 吗?此操作不可撤销!",
|
||||||
|
QMessageBox.Yes | QMessageBox.No)
|
||||||
|
if reply == QMessageBox.No:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.output_text.append(f"正在删除目录 {path}...")
|
||||||
|
self.delete_dir_btn.setEnabled(False)
|
||||||
|
|
||||||
|
self.delete_dir_thread = DeleteDirectoryThread(self.parent.ssh_client, path)
|
||||||
|
self.delete_dir_thread.result_ready.connect(self.on_delete_directory_result)
|
||||||
|
self.delete_dir_thread.start()
|
||||||
|
|
||||||
|
def on_delete_directory_result(self, success, message):
|
||||||
|
self.delete_dir_btn.setEnabled(True)
|
||||||
|
if success:
|
||||||
|
self.output_text.append(f"目录删除成功: {message}")
|
||||||
|
logger.info(f"目录删除成功: {message}")
|
||||||
|
else:
|
||||||
|
self.output_text.append(f"目录删除失败: {message}")
|
||||||
|
logger.error(f"目录删除失败: {message}")
|
||||||
|
|
||||||
|
def set_timezone_and_restart(self):
|
||||||
|
if not self.check_ssh_connection():
|
||||||
|
return
|
||||||
|
|
||||||
|
self.output_text.append("正在设置时区为Asia/Shanghai并重启服务器...")
|
||||||
|
self.set_timezone_btn.setEnabled(False)
|
||||||
|
|
||||||
|
self.timezone_thread = SetTimezoneAndRestartThread(self.parent.ssh_client)
|
||||||
|
self.timezone_thread.result_ready.connect(self.on_set_timezone_and_restart_result)
|
||||||
|
self.timezone_thread.start()
|
||||||
|
|
||||||
|
def on_set_timezone_and_restart_result(self, success, message):
|
||||||
|
self.set_timezone_btn.setEnabled(True)
|
||||||
|
if success:
|
||||||
|
self.output_text.append(f"时区设置成功: {message}")
|
||||||
|
logger.info(f"时区设置成功: {message}")
|
||||||
|
else:
|
||||||
|
self.output_text.append(f"时区设置失败: {message}")
|
||||||
|
logger.error(f"时区设置失败: {message}")
|
||||||
|
|
||||||
|
def check_firewall(self):
|
||||||
|
if not self.check_ssh_connection():
|
||||||
|
return
|
||||||
|
|
||||||
|
self.output_text.append("正在检查防火墙状态...")
|
||||||
|
self.check_firewall_btn.setEnabled(False)
|
||||||
|
|
||||||
|
self.firewall_thread = CheckFirewallThread(self.parent.ssh_client)
|
||||||
|
self.firewall_thread.result_ready.connect(self.on_check_firewall_result)
|
||||||
|
self.firewall_thread.start()
|
||||||
|
|
||||||
|
def on_check_firewall_result(self, success, message):
|
||||||
|
self.check_firewall_btn.setEnabled(True)
|
||||||
|
if success:
|
||||||
|
self.output_text.append(f"防火墙状态:\n{message}")
|
||||||
|
logger.info(f"防火墙状态检查成功")
|
||||||
|
else:
|
||||||
|
self.output_text.append(f"防火墙状态检查失败: {message}")
|
||||||
|
logger.error(f"防火墙状态检查失败: {message}")
|
||||||
|
|
||||||
|
def open_port(self):
|
||||||
|
if not self.check_ssh_connection():
|
||||||
|
return
|
||||||
|
|
||||||
|
port = self.port_input.text().strip()
|
||||||
|
if not port:
|
||||||
|
QMessageBox.warning(self, "警告", "请输入要开放的端口号")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.output_text.append(f"正在开放端口 {port}...")
|
||||||
|
self.open_port_btn.setEnabled(False)
|
||||||
|
|
||||||
|
self.open_port_thread = OpenPortThread(self.parent.ssh_client, port)
|
||||||
|
self.open_port_thread.result_ready.connect(self.on_open_port_result)
|
||||||
|
self.open_port_thread.start()
|
||||||
|
|
||||||
|
def on_open_port_result(self, success, message):
|
||||||
|
self.open_port_btn.setEnabled(True)
|
||||||
|
if success:
|
||||||
|
self.output_text.append(f"端口开放成功: {message}")
|
||||||
|
logger.info(f"端口开放成功: {message}")
|
||||||
|
else:
|
||||||
|
self.output_text.append(f"端口开放失败: {message}")
|
||||||
|
logger.error(f"端口开放失败: {message}")
|
||||||
|
|
||||||
|
def check_ssh_connection(self):
|
||||||
|
if not self.parent or not self.parent.ssh_client:
|
||||||
|
QMessageBox.warning(self, "警告", "请先连接服务器")
|
||||||
|
return False
|
||||||
|
return True
|
||||||
3
requirements.txt
Normal file
3
requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
PySide6>=6.5.0
|
||||||
|
paramiko>=2.11.0
|
||||||
|
loguru>=0.7.0
|
||||||
225
server_connection_tab.py
Normal file
225
server_connection_tab.py
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
from loguru import logger
|
||||||
|
from PySide6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit,
|
||||||
|
QPushButton, QComboBox, QMessageBox)
|
||||||
|
from PySide6.QtCore import Qt
|
||||||
|
import paramiko
|
||||||
|
|
||||||
|
from threads import SSHConnectionThread
|
||||||
|
|
||||||
|
|
||||||
|
class ServerConnectionTab(QWidget):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.ssh_client = None
|
||||||
|
self.config = self.load_config()
|
||||||
|
self.init_ui()
|
||||||
|
|
||||||
|
def load_config(self):
|
||||||
|
config_file = "config.json"
|
||||||
|
if os.path.exists(config_file):
|
||||||
|
try:
|
||||||
|
with open(config_file, 'r', encoding='utf-8') as f:
|
||||||
|
return json.load(f)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"读取配置文件失败: {e}")
|
||||||
|
return {"servers": []}
|
||||||
|
return {"servers": []}
|
||||||
|
|
||||||
|
def save_config(self):
|
||||||
|
try:
|
||||||
|
with open("config.json", 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(self.config, f, ensure_ascii=False, indent=2)
|
||||||
|
logger.info("配置文件保存成功")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"保存配置文件失败: {e}")
|
||||||
|
QMessageBox.critical(self, "错误", f"保存配置文件失败: {e}")
|
||||||
|
|
||||||
|
def init_ui(self):
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
|
||||||
|
# 服务器选择
|
||||||
|
server_layout = QHBoxLayout()
|
||||||
|
server_layout.addWidget(QLabel("服务器别名:"))
|
||||||
|
self.server_combo = QComboBox()
|
||||||
|
self.server_combo.currentTextChanged.connect(self.on_server_selected)
|
||||||
|
server_layout.addWidget(self.server_combo)
|
||||||
|
layout.addLayout(server_layout)
|
||||||
|
|
||||||
|
# 服务器信息输入
|
||||||
|
form_layout = QVBoxLayout()
|
||||||
|
|
||||||
|
# IP地址
|
||||||
|
ip_layout = QHBoxLayout()
|
||||||
|
ip_layout.addWidget(QLabel("IP地址:"))
|
||||||
|
self.ip_input = QLineEdit()
|
||||||
|
ip_layout.addWidget(self.ip_input)
|
||||||
|
form_layout.addLayout(ip_layout)
|
||||||
|
|
||||||
|
# 端口
|
||||||
|
port_layout = QHBoxLayout()
|
||||||
|
port_layout.addWidget(QLabel("端口:"))
|
||||||
|
self.port_input = QLineEdit("22")
|
||||||
|
port_layout.addWidget(self.port_input)
|
||||||
|
form_layout.addLayout(port_layout)
|
||||||
|
|
||||||
|
# 用户名
|
||||||
|
username_layout = QHBoxLayout()
|
||||||
|
username_layout.addWidget(QLabel("用户名:"))
|
||||||
|
self.username_input = QLineEdit()
|
||||||
|
username_layout.addWidget(self.username_input)
|
||||||
|
form_layout.addLayout(username_layout)
|
||||||
|
|
||||||
|
# 密码
|
||||||
|
password_layout = QHBoxLayout()
|
||||||
|
password_layout.addWidget(QLabel("密码:"))
|
||||||
|
self.password_input = QLineEdit()
|
||||||
|
self.password_input.setEchoMode(QLineEdit.Password)
|
||||||
|
password_layout.addWidget(self.password_input)
|
||||||
|
form_layout.addLayout(password_layout)
|
||||||
|
|
||||||
|
# 项目名称
|
||||||
|
project_layout = QHBoxLayout()
|
||||||
|
project_layout.addWidget(QLabel("项目名称:"))
|
||||||
|
self.project_input = QLineEdit()
|
||||||
|
project_layout.addWidget(self.project_input)
|
||||||
|
form_layout.addLayout(project_layout)
|
||||||
|
|
||||||
|
# Git仓库URL
|
||||||
|
git_url_layout = QHBoxLayout()
|
||||||
|
git_url_layout.addWidget(QLabel("Git仓库URL:"))
|
||||||
|
self.git_url_input = QLineEdit()
|
||||||
|
self.git_url_input.setPlaceholderText("https://github.com/username/repo.git")
|
||||||
|
git_url_layout.addWidget(self.git_url_input)
|
||||||
|
form_layout.addLayout(git_url_layout)
|
||||||
|
|
||||||
|
# 远程目录
|
||||||
|
remote_dir_layout = QHBoxLayout()
|
||||||
|
remote_dir_layout.addWidget(QLabel("远程目录:"))
|
||||||
|
self.remote_dir_input = QLineEdit()
|
||||||
|
self.remote_dir_input.setPlaceholderText("/home/user/project")
|
||||||
|
remote_dir_layout.addWidget(self.remote_dir_input)
|
||||||
|
form_layout.addLayout(remote_dir_layout)
|
||||||
|
|
||||||
|
# Django项目路径
|
||||||
|
django_path_layout = QHBoxLayout()
|
||||||
|
django_path_layout.addWidget(QLabel("Django项目路径:"))
|
||||||
|
self.django_path_input = QLineEdit()
|
||||||
|
self.django_path_input.setPlaceholderText("/home/user/django_project")
|
||||||
|
django_path_layout.addWidget(self.django_path_input)
|
||||||
|
form_layout.addLayout(django_path_layout)
|
||||||
|
|
||||||
|
layout.addLayout(form_layout)
|
||||||
|
|
||||||
|
# 按钮
|
||||||
|
button_layout = QHBoxLayout()
|
||||||
|
self.save_button = QPushButton("保存配置")
|
||||||
|
self.save_button.clicked.connect(self.save_server_config)
|
||||||
|
self.connect_button = QPushButton("连接服务器")
|
||||||
|
self.connect_button.clicked.connect(self.connect_server)
|
||||||
|
button_layout.addWidget(self.save_button)
|
||||||
|
button_layout.addWidget(self.connect_button)
|
||||||
|
layout.addLayout(button_layout)
|
||||||
|
|
||||||
|
# 连接状态
|
||||||
|
self.status_label = QLabel("未连接")
|
||||||
|
self.status_label.setAlignment(Qt.AlignCenter)
|
||||||
|
layout.addWidget(self.status_label)
|
||||||
|
|
||||||
|
layout.addStretch()
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
# 加载服务器列表
|
||||||
|
self.load_server_list()
|
||||||
|
|
||||||
|
def load_server_list(self):
|
||||||
|
self.server_combo.clear()
|
||||||
|
servers = self.config.get("servers", [])
|
||||||
|
for server in servers:
|
||||||
|
self.server_combo.addItem(server.get("alias", ""))
|
||||||
|
|
||||||
|
def on_server_selected(self, alias):
|
||||||
|
if not alias:
|
||||||
|
return
|
||||||
|
|
||||||
|
servers = self.config.get("servers", [])
|
||||||
|
for server in servers:
|
||||||
|
if server.get("alias") == alias:
|
||||||
|
self.ip_input.setText(server.get("host", ""))
|
||||||
|
self.port_input.setText(str(server.get("port", 22)))
|
||||||
|
self.username_input.setText(server.get("username", ""))
|
||||||
|
self.password_input.setText(server.get("password", ""))
|
||||||
|
self.project_input.setText(server.get("project_name", ""))
|
||||||
|
self.git_url_input.setText(server.get("git_url", ""))
|
||||||
|
self.remote_dir_input.setText(server.get("remote_directory", ""))
|
||||||
|
self.django_path_input.setText(server.get("django_path", ""))
|
||||||
|
break
|
||||||
|
|
||||||
|
def save_server_config(self):
|
||||||
|
alias = self.server_combo.currentText()
|
||||||
|
if not alias:
|
||||||
|
alias = f"服务器_{len(self.config.get('servers', [])) + 1}"
|
||||||
|
self.server_combo.addItem(alias)
|
||||||
|
|
||||||
|
server_config = {
|
||||||
|
"alias": alias,
|
||||||
|
"host": self.ip_input.text(),
|
||||||
|
"port": int(self.port_input.text()) if self.port_input.text() else 22,
|
||||||
|
"username": self.username_input.text(),
|
||||||
|
"password": self.password_input.text(),
|
||||||
|
"project_name": self.project_input.text(),
|
||||||
|
"git_url": self.git_url_input.text(),
|
||||||
|
"remote_directory": self.remote_dir_input.text(),
|
||||||
|
"django_path": self.django_path_input.text()
|
||||||
|
}
|
||||||
|
|
||||||
|
servers = self.config.get("servers", [])
|
||||||
|
# 更新或添加服务器配置
|
||||||
|
found = False
|
||||||
|
for i, server in enumerate(servers):
|
||||||
|
if server.get("alias") == alias:
|
||||||
|
servers[i] = server_config
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not found:
|
||||||
|
servers.append(server_config)
|
||||||
|
|
||||||
|
self.config["servers"] = servers
|
||||||
|
self.save_config()
|
||||||
|
QMessageBox.information(self, "成功", "配置已保存")
|
||||||
|
|
||||||
|
def connect_server(self):
|
||||||
|
host = self.ip_input.text()
|
||||||
|
port = int(self.port_input.text()) if self.port_input.text() else 22
|
||||||
|
username = self.username_input.text()
|
||||||
|
password = self.password_input.text()
|
||||||
|
|
||||||
|
if not all([host, username, password]):
|
||||||
|
QMessageBox.warning(self, "警告", "请填写完整的连接信息")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.status_label.setText("正在连接...")
|
||||||
|
self.connect_button.setEnabled(False)
|
||||||
|
|
||||||
|
self.connection_thread = SSHConnectionThread(host, username, password, port)
|
||||||
|
self.connection_thread.connection_status.connect(self.on_connection_result)
|
||||||
|
self.connection_thread.start()
|
||||||
|
|
||||||
|
def on_connection_result(self, success, message):
|
||||||
|
self.connect_button.setEnabled(True)
|
||||||
|
if success:
|
||||||
|
self.status_label.setText(f"连接成功: {message}")
|
||||||
|
self.status_label.setStyleSheet("color: green;")
|
||||||
|
# 创建SSH客户端实例供其他标签使用
|
||||||
|
self.ssh_client = paramiko.SSHClient()
|
||||||
|
self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||||
|
self.ssh_client.connect(self.ip_input.text(),
|
||||||
|
port=int(self.port_input.text()),
|
||||||
|
username=self.username_input.text(),
|
||||||
|
password=self.password_input.text())
|
||||||
|
else:
|
||||||
|
self.status_label.setText(f"连接失败: {message}")
|
||||||
|
self.status_label.setStyleSheet("color: red;")
|
||||||
|
self.ssh_client = None
|
||||||
113
settings_backup_20250827_194227.py
Normal file
113
settings_backup_20250827_194227.py
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
|
||||||
|
# Quick-start development settings - unsuitable for production
|
||||||
|
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
|
||||||
|
|
||||||
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
|
SECRET_KEY = 'django-insecure-$w+8+hw%p$2xi_fi+7avahc&03-y@x05e^r02-x3nt5johmk6l'
|
||||||
|
|
||||||
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
|
DEBUG = True
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = []
|
||||||
|
|
||||||
|
|
||||||
|
# Application definition
|
||||||
|
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
'django.contrib.admin',
|
||||||
|
'django.contrib.auth',
|
||||||
|
'django.contrib.contenttypes',
|
||||||
|
'django.contrib.sessions',
|
||||||
|
'django.contrib.messages',
|
||||||
|
'django.contrib.staticfiles',
|
||||||
|
'status',
|
||||||
|
]
|
||||||
|
|
||||||
|
MIDDLEWARE = [
|
||||||
|
'django.middleware.security.SecurityMiddleware',
|
||||||
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
|
'django.middleware.locale.LocaleMiddleware',
|
||||||
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
|
]
|
||||||
|
|
||||||
|
ROOT_URLCONF = 'statuspage.urls'
|
||||||
|
|
||||||
|
TEMPLATES = [
|
||||||
|
{
|
||||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
'DIRS': [],
|
||||||
|
'APP_DIRS': True,
|
||||||
|
'OPTIONS': {
|
||||||
|
'context_processors': [
|
||||||
|
'django.template.context_processors.debug',
|
||||||
|
'django.template.context_processors.request',
|
||||||
|
'django.contrib.auth.context_processors.auth',
|
||||||
|
'django.contrib.messages.context_processors.messages',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
WSGI_APPLICATION = 'statuspage.wsgi.application'
|
||||||
|
|
||||||
|
|
||||||
|
# Database
|
||||||
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
'NAME': BASE_DIR / 'db.sqlite3',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Password validation
|
||||||
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
|
||||||
|
|
||||||
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Internationalization
|
||||||
|
# https://docs.djangoproject.com/en/4.2/topics/i18n/
|
||||||
|
|
||||||
|
LANGUAGE_CODE = 'zh-hans'
|
||||||
|
|
||||||
|
TIME_ZONE = 'Asia/Shanghai'
|
||||||
|
|
||||||
|
USE_I18N = True
|
||||||
|
|
||||||
|
USE_TZ = True
|
||||||
|
|
||||||
|
|
||||||
|
# Static files (CSS, JavaScript, Images)
|
||||||
|
# https://docs.djangoproject.com/en/4.2/howto/static-files/
|
||||||
|
|
||||||
|
STATIC_URL = 'static/'
|
||||||
|
|
||||||
|
# Default primary key field type
|
||||||
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
|
||||||
|
|
||||||
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||||
113
settings_backup_20250827_194650.py
Normal file
113
settings_backup_20250827_194650.py
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
|
||||||
|
# Quick-start development settings - unsuitable for production
|
||||||
|
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
|
||||||
|
|
||||||
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
|
SECRET_KEY = 'django-insecure-$w+8+hw%p$2xi_fi+7avahc&03-y@x05e^r02-x3nt5johmk6l'
|
||||||
|
|
||||||
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
|
DEBUG = True
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = []
|
||||||
|
|
||||||
|
|
||||||
|
# Application definition
|
||||||
|
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
'django.contrib.admin',
|
||||||
|
'django.contrib.auth',
|
||||||
|
'django.contrib.contenttypes',
|
||||||
|
'django.contrib.sessions',
|
||||||
|
'django.contrib.messages',
|
||||||
|
'django.contrib.staticfiles',
|
||||||
|
'status',
|
||||||
|
]
|
||||||
|
|
||||||
|
MIDDLEWARE = [
|
||||||
|
'django.middleware.security.SecurityMiddleware',
|
||||||
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
|
'django.middleware.locale.LocaleMiddleware',
|
||||||
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
|
]
|
||||||
|
|
||||||
|
ROOT_URLCONF = 'statuspage.urls'
|
||||||
|
|
||||||
|
TEMPLATES = [
|
||||||
|
{
|
||||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
'DIRS': [],
|
||||||
|
'APP_DIRS': True,
|
||||||
|
'OPTIONS': {
|
||||||
|
'context_processors': [
|
||||||
|
'django.template.context_processors.debug',
|
||||||
|
'django.template.context_processors.request',
|
||||||
|
'django.contrib.auth.context_processors.auth',
|
||||||
|
'django.contrib.messages.context_processors.messages',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
WSGI_APPLICATION = 'statuspage.wsgi.application'
|
||||||
|
|
||||||
|
|
||||||
|
# Database
|
||||||
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
'NAME': BASE_DIR / 'db.sqlite3',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Password validation
|
||||||
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
|
||||||
|
|
||||||
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Internationalization
|
||||||
|
# https://docs.djangoproject.com/en/4.2/topics/i18n/
|
||||||
|
|
||||||
|
LANGUAGE_CODE = 'zh-hans'
|
||||||
|
|
||||||
|
TIME_ZONE = 'Asia/Shanghai'
|
||||||
|
|
||||||
|
USE_I18N = True
|
||||||
|
|
||||||
|
USE_TZ = True
|
||||||
|
|
||||||
|
|
||||||
|
# Static files (CSS, JavaScript, Images)
|
||||||
|
# https://docs.djangoproject.com/en/4.2/howto/static-files/
|
||||||
|
|
||||||
|
STATIC_URL = 'static/'
|
||||||
|
|
||||||
|
# Default primary key field type
|
||||||
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
|
||||||
|
|
||||||
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||||
113
settings_backup_20250827_200524.py
Normal file
113
settings_backup_20250827_200524.py
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
|
||||||
|
# Quick-start development settings - unsuitable for production
|
||||||
|
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
|
||||||
|
|
||||||
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
|
SECRET_KEY = 'django-insecure-$w+8+hw%p$2xi_fi+7avahc&03-y@x05e^r02-x3nt5johmk6l'
|
||||||
|
|
||||||
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
|
DEBUG = True
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = []
|
||||||
|
|
||||||
|
|
||||||
|
# Application definition
|
||||||
|
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
'django.contrib.admin',
|
||||||
|
'django.contrib.auth',
|
||||||
|
'django.contrib.contenttypes',
|
||||||
|
'django.contrib.sessions',
|
||||||
|
'django.contrib.messages',
|
||||||
|
'django.contrib.staticfiles',
|
||||||
|
'status',
|
||||||
|
]
|
||||||
|
|
||||||
|
MIDDLEWARE = [
|
||||||
|
'django.middleware.security.SecurityMiddleware',
|
||||||
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
|
'django.middleware.locale.LocaleMiddleware',
|
||||||
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
|
]
|
||||||
|
|
||||||
|
ROOT_URLCONF = 'statuspage.urls'
|
||||||
|
|
||||||
|
TEMPLATES = [
|
||||||
|
{
|
||||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
'DIRS': [],
|
||||||
|
'APP_DIRS': True,
|
||||||
|
'OPTIONS': {
|
||||||
|
'context_processors': [
|
||||||
|
'django.template.context_processors.debug',
|
||||||
|
'django.template.context_processors.request',
|
||||||
|
'django.contrib.auth.context_processors.auth',
|
||||||
|
'django.contrib.messages.context_processors.messages',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
WSGI_APPLICATION = 'statuspage.wsgi.application'
|
||||||
|
|
||||||
|
|
||||||
|
# Database
|
||||||
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
'NAME': BASE_DIR / 'db.sqlite3',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Password validation
|
||||||
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
|
||||||
|
|
||||||
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Internationalization
|
||||||
|
# https://docs.djangoproject.com/en/4.2/topics/i18n/
|
||||||
|
|
||||||
|
LANGUAGE_CODE = 'zh-hans'
|
||||||
|
|
||||||
|
TIME_ZONE = 'Asia/Shanghai'
|
||||||
|
|
||||||
|
USE_I18N = True
|
||||||
|
|
||||||
|
USE_TZ = True
|
||||||
|
|
||||||
|
|
||||||
|
# Static files (CSS, JavaScript, Images)
|
||||||
|
# https://docs.djangoproject.com/en/4.2/howto/static-files/
|
||||||
|
|
||||||
|
STATIC_URL = 'static/'
|
||||||
|
|
||||||
|
# Default primary key field type
|
||||||
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
|
||||||
|
|
||||||
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||||
116
settings_backup_20250827_205200.py
Normal file
116
settings_backup_20250827_205200.py
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
|
||||||
|
# Quick-start development settings - unsuitable for production
|
||||||
|
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
|
||||||
|
|
||||||
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
|
SECRET_KEY = 'django-insecure-$w+8+hw%p$2xi_fi+7avahc&03-y@x05e^r02-x3nt5johmk6l'
|
||||||
|
|
||||||
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
|
DEBUG = False
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = ["192.168.3.157"]
|
||||||
|
|
||||||
|
|
||||||
|
# Application definition
|
||||||
|
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
'django.contrib.admin',
|
||||||
|
'django.contrib.auth',
|
||||||
|
'django.contrib.contenttypes',
|
||||||
|
'django.contrib.sessions',
|
||||||
|
'django.contrib.messages',
|
||||||
|
'django.contrib.staticfiles',
|
||||||
|
'status',
|
||||||
|
]
|
||||||
|
|
||||||
|
MIDDLEWARE = [
|
||||||
|
'django.middleware.security.SecurityMiddleware',
|
||||||
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
|
'django.middleware.locale.LocaleMiddleware',
|
||||||
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
|
]
|
||||||
|
|
||||||
|
ROOT_URLCONF = 'statuspage.urls'
|
||||||
|
|
||||||
|
TEMPLATES = [
|
||||||
|
{
|
||||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
'DIRS': [],
|
||||||
|
'APP_DIRS': True,
|
||||||
|
'OPTIONS': {
|
||||||
|
'context_processors': [
|
||||||
|
'django.template.context_processors.debug',
|
||||||
|
'django.template.context_processors.request',
|
||||||
|
'django.contrib.auth.context_processors.auth',
|
||||||
|
'django.contrib.messages.context_processors.messages',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
WSGI_APPLICATION = 'statuspage.wsgi.application'
|
||||||
|
|
||||||
|
|
||||||
|
# Database
|
||||||
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
'NAME': BASE_DIR / 'db.sqlite3',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Password validation
|
||||||
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
|
||||||
|
|
||||||
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Internationalization
|
||||||
|
# https://docs.djangoproject.com/en/4.2/topics/i18n/
|
||||||
|
|
||||||
|
LANGUAGE_CODE = 'zh-hans'
|
||||||
|
|
||||||
|
TIME_ZONE = 'Asia/Shanghai'
|
||||||
|
|
||||||
|
USE_I18N = True
|
||||||
|
|
||||||
|
USE_TZ = True
|
||||||
|
|
||||||
|
|
||||||
|
# Static files (CSS, JavaScript, Images)
|
||||||
|
# https://docs.djangoproject.com/en/4.2/howto/static-files/
|
||||||
|
|
||||||
|
STATIC_URL = 'static/'
|
||||||
|
|
||||||
|
# Default primary key field type
|
||||||
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
|
||||||
|
|
||||||
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||||
|
|
||||||
|
STATIC_ROOT = BASE_DIR / "home" / "xiaji" / "static"
|
||||||
|
MEDIA_ROOT = BASE_DIR / "home" / "xiaji" / "media"
|
||||||
116
settings_backup_20250827_211246.py
Normal file
116
settings_backup_20250827_211246.py
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
|
||||||
|
# Quick-start development settings - unsuitable for production
|
||||||
|
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
|
||||||
|
|
||||||
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
|
SECRET_KEY = 'django-insecure-$w+8+hw%p$2xi_fi+7avahc&03-y@x05e^r02-x3nt5johmk6l'
|
||||||
|
|
||||||
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
|
DEBUG = False
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = ["192.168.3.157"]
|
||||||
|
|
||||||
|
|
||||||
|
# Application definition
|
||||||
|
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
'django.contrib.admin',
|
||||||
|
'django.contrib.auth',
|
||||||
|
'django.contrib.contenttypes',
|
||||||
|
'django.contrib.sessions',
|
||||||
|
'django.contrib.messages',
|
||||||
|
'django.contrib.staticfiles',
|
||||||
|
'status',
|
||||||
|
]
|
||||||
|
|
||||||
|
MIDDLEWARE = [
|
||||||
|
'django.middleware.security.SecurityMiddleware',
|
||||||
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
|
'django.middleware.locale.LocaleMiddleware',
|
||||||
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
|
]
|
||||||
|
|
||||||
|
ROOT_URLCONF = 'statuspage.urls'
|
||||||
|
|
||||||
|
TEMPLATES = [
|
||||||
|
{
|
||||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
'DIRS': [],
|
||||||
|
'APP_DIRS': True,
|
||||||
|
'OPTIONS': {
|
||||||
|
'context_processors': [
|
||||||
|
'django.template.context_processors.debug',
|
||||||
|
'django.template.context_processors.request',
|
||||||
|
'django.contrib.auth.context_processors.auth',
|
||||||
|
'django.contrib.messages.context_processors.messages',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
WSGI_APPLICATION = 'statuspage.wsgi.application'
|
||||||
|
|
||||||
|
|
||||||
|
# Database
|
||||||
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
'NAME': BASE_DIR / 'db.sqlite3',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Password validation
|
||||||
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
|
||||||
|
|
||||||
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Internationalization
|
||||||
|
# https://docs.djangoproject.com/en/4.2/topics/i18n/
|
||||||
|
|
||||||
|
LANGUAGE_CODE = 'zh-hans'
|
||||||
|
|
||||||
|
TIME_ZONE = 'Asia/Shanghai'
|
||||||
|
|
||||||
|
USE_I18N = True
|
||||||
|
|
||||||
|
USE_TZ = True
|
||||||
|
|
||||||
|
|
||||||
|
# Static files (CSS, JavaScript, Images)
|
||||||
|
# https://docs.djangoproject.com/en/4.2/howto/static-files/
|
||||||
|
|
||||||
|
STATIC_URL = 'static/'
|
||||||
|
|
||||||
|
# Default primary key field type
|
||||||
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
|
||||||
|
|
||||||
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||||
|
|
||||||
|
STATIC_ROOT = BASE_DIR / "static"
|
||||||
|
MEDIA_ROOT = BASE_DIR / "media"
|
||||||
858
threads.py
Normal file
858
threads.py
Normal file
@@ -0,0 +1,858 @@
|
|||||||
|
import os
|
||||||
|
import time
|
||||||
|
from loguru import logger
|
||||||
|
from PySide6.QtCore import QThread, Signal
|
||||||
|
import paramiko
|
||||||
|
|
||||||
|
|
||||||
|
class PasswordDialog:
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
self.parent = parent
|
||||||
|
self.password = None
|
||||||
|
|
||||||
|
def get_password(self, prompt="请输入sudo密码:"):
|
||||||
|
# 这里简化实现,实际应该使用QInputDialog
|
||||||
|
if self.parent:
|
||||||
|
from PySide6.QtWidgets import QInputDialog
|
||||||
|
password, ok = QInputDialog.getText(self.parent, "sudo密码", prompt,
|
||||||
|
echo=QInputDialog.Password)
|
||||||
|
if ok:
|
||||||
|
self.password = password
|
||||||
|
return password
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class SSHConnectionThread(QThread):
|
||||||
|
connection_status = Signal(bool, str)
|
||||||
|
|
||||||
|
def __init__(self, host, username, password, port=22):
|
||||||
|
super().__init__()
|
||||||
|
self.host = host
|
||||||
|
self.username = username
|
||||||
|
self.password = password
|
||||||
|
self.port = port
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
ssh = paramiko.SSHClient()
|
||||||
|
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||||
|
ssh.connect(self.host, port=self.port, username=self.username, password=self.password, timeout=10)
|
||||||
|
|
||||||
|
# 测试连接
|
||||||
|
stdin, stdout, stderr = ssh.exec_command("echo 'Connection test'")
|
||||||
|
output = stdout.read().decode().strip()
|
||||||
|
|
||||||
|
if output == "Connection test":
|
||||||
|
self.connection_status.emit(True, f"成功连接到 {self.host}")
|
||||||
|
logger.info(f"SSH连接成功: {self.host}")
|
||||||
|
else:
|
||||||
|
self.connection_status.emit(False, "连接测试失败")
|
||||||
|
logger.error("SSH连接测试失败")
|
||||||
|
|
||||||
|
ssh.close()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
self.connection_status.emit(False, error_msg)
|
||||||
|
logger.error(f"SSH连接失败: {error_msg}")
|
||||||
|
|
||||||
|
|
||||||
|
class GitInstallThread(QThread):
|
||||||
|
result_ready = Signal(bool, str)
|
||||||
|
|
||||||
|
def __init__(self, ssh_client):
|
||||||
|
super().__init__()
|
||||||
|
self.ssh_client = ssh_client
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
# 检查Git是否已安装
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("git --version")
|
||||||
|
git_version = stdout.read().decode().strip()
|
||||||
|
|
||||||
|
if git_version:
|
||||||
|
self.result_ready.emit(True, f"Git已安装: {git_version}")
|
||||||
|
logger.info(f"Git已安装: {git_version}")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 安装Git
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("sudo apt update && sudo apt install -y git")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status == 0:
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("git --version")
|
||||||
|
git_version = stdout.read().decode().strip()
|
||||||
|
self.result_ready.emit(True, f"Git安装成功: {git_version}")
|
||||||
|
logger.info(f"Git安装成功: {git_version}")
|
||||||
|
else:
|
||||||
|
error = stderr.read().decode()
|
||||||
|
self.result_ready.emit(False, f"Git安装失败: {error}")
|
||||||
|
logger.error(f"Git安装失败: {error}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
self.result_ready.emit(False, error_msg)
|
||||||
|
logger.error(f"Git安装异常: {error_msg}")
|
||||||
|
|
||||||
|
|
||||||
|
class GitCloneThread(QThread):
|
||||||
|
result_ready = Signal(bool, str)
|
||||||
|
|
||||||
|
def __init__(self, ssh_client, git_url, project_path):
|
||||||
|
super().__init__()
|
||||||
|
self.ssh_client = ssh_client
|
||||||
|
self.git_url = git_url
|
||||||
|
self.project_path = project_path
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
# 检查目录是否存在
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"ls -la {self.project_path}")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status == 0:
|
||||||
|
self.result_ready.emit(False, f"目录 {self.project_path} 已存在")
|
||||||
|
logger.warning(f"目录已存在: {self.project_path}")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 创建父目录
|
||||||
|
parent_dir = os.path.dirname(self.project_path)
|
||||||
|
if parent_dir:
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"mkdir -p {parent_dir}")
|
||||||
|
|
||||||
|
# 克隆仓库
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"cd {parent_dir} && git clone {self.git_url} {os.path.basename(self.project_path)}")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status == 0:
|
||||||
|
self.result_ready.emit(True, f"Git克隆成功: {self.project_path}")
|
||||||
|
logger.info(f"Git克隆成功: {self.project_path}")
|
||||||
|
else:
|
||||||
|
error = stderr.read().decode()
|
||||||
|
self.result_ready.emit(False, f"Git克隆失败: {error}")
|
||||||
|
logger.error(f"Git克隆失败: {error}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
self.result_ready.emit(False, error_msg)
|
||||||
|
logger.error(f"Git克隆异常: {error_msg}")
|
||||||
|
|
||||||
|
|
||||||
|
class ListDirectoryThread(QThread):
|
||||||
|
result_ready = Signal(bool, str)
|
||||||
|
|
||||||
|
def __init__(self, ssh_client, path):
|
||||||
|
super().__init__()
|
||||||
|
self.ssh_client = ssh_client
|
||||||
|
self.path = path
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"ls -la {self.path}")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status == 0:
|
||||||
|
output = stdout.read().decode()
|
||||||
|
self.result_ready.emit(True, output)
|
||||||
|
logger.info(f"目录列表成功: {self.path}")
|
||||||
|
else:
|
||||||
|
error = stderr.read().decode()
|
||||||
|
self.result_ready.emit(False, error)
|
||||||
|
logger.error(f"目录列表失败: {error}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
self.result_ready.emit(False, error_msg)
|
||||||
|
logger.error(f"目录列表异常: {error_msg}")
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteDirectoryThread(QThread):
|
||||||
|
result_ready = Signal(bool, str)
|
||||||
|
|
||||||
|
def __init__(self, ssh_client, path):
|
||||||
|
super().__init__()
|
||||||
|
self.ssh_client = ssh_client
|
||||||
|
self.path = path
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"rm -rf {self.path}")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status == 0:
|
||||||
|
self.result_ready.emit(True, f"目录删除成功: {self.path}")
|
||||||
|
logger.info(f"目录删除成功: {self.path}")
|
||||||
|
else:
|
||||||
|
error = stderr.read().decode()
|
||||||
|
self.result_ready.emit(False, error)
|
||||||
|
logger.error(f"目录删除失败: {error}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
self.result_ready.emit(False, error_msg)
|
||||||
|
logger.error(f"目录删除异常: {error_msg}")
|
||||||
|
|
||||||
|
|
||||||
|
class SetTimezoneAndRestartThread(QThread):
|
||||||
|
result_ready = Signal(bool, str)
|
||||||
|
|
||||||
|
def __init__(self, ssh_client):
|
||||||
|
super().__init__()
|
||||||
|
self.ssh_client = ssh_client
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
# 设置时区
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("sudo timedatectl set-timezone Asia/Shanghai")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status != 0:
|
||||||
|
error = stderr.read().decode()
|
||||||
|
self.result_ready.emit(False, f"设置时区失败: {error}")
|
||||||
|
logger.error(f"设置时区失败: {error}")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 重启服务器
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("sudo reboot")
|
||||||
|
|
||||||
|
self.result_ready.emit(True, "时区设置成功,服务器正在重启")
|
||||||
|
logger.info("时区设置成功,服务器正在重启")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
self.result_ready.emit(False, error_msg)
|
||||||
|
logger.error(f"时区设置异常: {error_msg}")
|
||||||
|
|
||||||
|
|
||||||
|
class CheckFirewallThread(QThread):
|
||||||
|
result_ready = Signal(bool, str)
|
||||||
|
|
||||||
|
def __init__(self, ssh_client):
|
||||||
|
super().__init__()
|
||||||
|
self.ssh_client = ssh_client
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
# 检查UFW状态
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("sudo ufw status")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status == 0:
|
||||||
|
output = stdout.read().decode()
|
||||||
|
self.result_ready.emit(True, output)
|
||||||
|
logger.info("防火墙状态检查成功")
|
||||||
|
else:
|
||||||
|
error = stderr.read().decode()
|
||||||
|
self.result_ready.emit(False, error)
|
||||||
|
logger.error(f"防火墙状态检查失败: {error}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
self.result_ready.emit(False, error_msg)
|
||||||
|
logger.error(f"防火墙状态检查异常: {error_msg}")
|
||||||
|
|
||||||
|
|
||||||
|
class OpenPortThread(QThread):
|
||||||
|
result_ready = Signal(bool, str)
|
||||||
|
|
||||||
|
def __init__(self, ssh_client, port):
|
||||||
|
super().__init__()
|
||||||
|
self.ssh_client = ssh_client
|
||||||
|
self.port = port
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
# 开放端口
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"sudo ufw allow {self.port}")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status == 0:
|
||||||
|
# 重新加载防火墙
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("sudo ufw reload")
|
||||||
|
|
||||||
|
self.result_ready.emit(True, f"端口 {self.port} 开放成功")
|
||||||
|
logger.info(f"端口 {self.port} 开放成功")
|
||||||
|
else:
|
||||||
|
error = stderr.read().decode()
|
||||||
|
self.result_ready.emit(False, error)
|
||||||
|
logger.error(f"端口开放失败: {error}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
self.result_ready.emit(False, error_msg)
|
||||||
|
logger.error(f"端口开放异常: {error_msg}")
|
||||||
|
|
||||||
|
|
||||||
|
class DjangoInstallThread(QThread):
|
||||||
|
result_ready = Signal(bool, str)
|
||||||
|
progress_updated = Signal(int)
|
||||||
|
|
||||||
|
def __init__(self, ssh_client):
|
||||||
|
super().__init__()
|
||||||
|
self.ssh_client = ssh_client
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
self.progress_updated.emit(10)
|
||||||
|
|
||||||
|
# 检查Django是否已安装
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("python3 -m django --version")
|
||||||
|
django_version = stdout.read().decode().strip()
|
||||||
|
|
||||||
|
if django_version:
|
||||||
|
self.result_ready.emit(True, f"Django已安装: {django_version}")
|
||||||
|
logger.info(f"Django已安装: {django_version}")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.progress_updated.emit(30)
|
||||||
|
|
||||||
|
# 尝试使用pip安装
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("pip3 install django")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status == 0:
|
||||||
|
self.progress_updated.emit(90)
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("python3 -m django --version")
|
||||||
|
django_version = stdout.read().decode().strip()
|
||||||
|
self.result_ready.emit(True, f"Django安装成功: {django_version}")
|
||||||
|
logger.info(f"Django安装成功: {django_version}")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.progress_updated.emit(50)
|
||||||
|
|
||||||
|
# 如果pip安装失败,尝试使用apt安装
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("sudo apt update && sudo apt install -y python3-django")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status == 0:
|
||||||
|
self.progress_updated.emit(90)
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("python3 -m django --version")
|
||||||
|
django_version = stdout.read().decode().strip()
|
||||||
|
self.result_ready.emit(True, f"Django安装成功: {django_version}")
|
||||||
|
logger.info(f"Django安装成功: {django_version}")
|
||||||
|
else:
|
||||||
|
error = stderr.read().decode()
|
||||||
|
self.result_ready.emit(False, f"Django安装失败: {error}")
|
||||||
|
logger.error(f"Django安装失败: {error}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
self.result_ready.emit(False, error_msg)
|
||||||
|
logger.error(f"Django安装异常: {error_msg}")
|
||||||
|
|
||||||
|
|
||||||
|
class DjangoTestThread(QThread):
|
||||||
|
result_ready = Signal(bool, str)
|
||||||
|
progress_updated = Signal(int)
|
||||||
|
|
||||||
|
def __init__(self, ssh_client, django_path):
|
||||||
|
super().__init__()
|
||||||
|
self.ssh_client = ssh_client
|
||||||
|
self.django_path = django_path
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
self.progress_updated.emit(10)
|
||||||
|
|
||||||
|
# 检查Django项目是否存在
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"ls -la {self.django_path}/manage.py")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status != 0:
|
||||||
|
self.result_ready.emit(False, f"Django项目不存在: {self.django_path}")
|
||||||
|
logger.error(f"Django项目不存在: {self.django_path}")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.progress_updated.emit(30)
|
||||||
|
|
||||||
|
# 检查requirements.txt
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"ls -la {self.django_path}/requirements.txt")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status == 0:
|
||||||
|
self.progress_updated.emit(50)
|
||||||
|
# 安装依赖
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"cd {self.django_path} && pip3 install -r requirements.txt")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status != 0:
|
||||||
|
error = stderr.read().decode()
|
||||||
|
self.result_ready.emit(False, f"依赖安装失败: {error}")
|
||||||
|
logger.error(f"依赖安装失败: {error}")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.progress_updated.emit(70)
|
||||||
|
|
||||||
|
# 运行Django测试服务器
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"cd {self.django_path} && python3 manage.py runserver 0.0.0.0:8000 --noreload &")
|
||||||
|
time.sleep(3) # 等待服务器启动
|
||||||
|
|
||||||
|
# 检查服务器是否运行
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("ps aux | grep 'manage.py runserver'")
|
||||||
|
output = stdout.read().decode()
|
||||||
|
|
||||||
|
if "manage.py runserver" in output:
|
||||||
|
self.progress_updated.emit(100)
|
||||||
|
self.result_ready.emit(True, "Django测试服务器启动成功")
|
||||||
|
logger.info("Django测试服务器启动成功")
|
||||||
|
else:
|
||||||
|
self.result_ready.emit(False, "Django测试服务器启动失败")
|
||||||
|
logger.error("Django测试服务器启动失败")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
self.result_ready.emit(False, error_msg)
|
||||||
|
logger.error(f"Django测试异常: {error_msg}")
|
||||||
|
|
||||||
|
|
||||||
|
class DownloadSettingsThread(QThread):
|
||||||
|
result_ready = Signal(bool, str)
|
||||||
|
|
||||||
|
def __init__(self, ssh_client, django_path):
|
||||||
|
super().__init__()
|
||||||
|
self.ssh_client = ssh_client
|
||||||
|
self.django_path = django_path
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
# 查找settings.py文件
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"find {self.django_path} -name settings.py")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status != 0:
|
||||||
|
self.result_ready.emit(False, "未找到settings.py文件")
|
||||||
|
logger.error("未找到settings.py文件")
|
||||||
|
return
|
||||||
|
|
||||||
|
settings_path = stdout.read().decode().strip()
|
||||||
|
|
||||||
|
# 下载settings.py内容
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"cat {settings_path}")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status == 0:
|
||||||
|
settings_content = stdout.read().decode()
|
||||||
|
self.result_ready.emit(True, settings_content)
|
||||||
|
logger.info("settings.py下载成功")
|
||||||
|
else:
|
||||||
|
error = stderr.read().decode()
|
||||||
|
self.result_ready.emit(False, error)
|
||||||
|
logger.error(f"settings.py下载失败: {error}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
self.result_ready.emit(False, error_msg)
|
||||||
|
logger.error(f"settings.py下载异常: {error_msg}")
|
||||||
|
|
||||||
|
|
||||||
|
class UploadSettingsThread(QThread):
|
||||||
|
result_ready = Signal(bool, str)
|
||||||
|
|
||||||
|
def __init__(self, ssh_client, django_path, settings_content):
|
||||||
|
super().__init__()
|
||||||
|
self.ssh_client = ssh_client
|
||||||
|
self.django_path = django_path
|
||||||
|
self.settings_content = settings_content
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
# 查找settings.py文件
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"find {self.django_path} -name settings.py")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status != 0:
|
||||||
|
self.result_ready.emit(False, "未找到settings.py文件")
|
||||||
|
logger.error("未找到settings.py文件")
|
||||||
|
return
|
||||||
|
|
||||||
|
settings_path = stdout.read().decode().strip()
|
||||||
|
|
||||||
|
# 创建临时文件
|
||||||
|
temp_file = "/tmp/settings_upload.py"
|
||||||
|
sftp = self.ssh_client.open_sftp()
|
||||||
|
|
||||||
|
with sftp.file(temp_file, 'w') as f:
|
||||||
|
f.write(self.settings_content)
|
||||||
|
|
||||||
|
# 移动到目标位置
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"sudo mv {temp_file} {settings_path}")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status == 0:
|
||||||
|
self.result_ready.emit(True, "settings.py上传成功")
|
||||||
|
logger.info("settings.py上传成功")
|
||||||
|
else:
|
||||||
|
error = stderr.read().decode()
|
||||||
|
self.result_ready.emit(False, error)
|
||||||
|
logger.error(f"settings.py上传失败: {error}")
|
||||||
|
|
||||||
|
sftp.close()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
self.result_ready.emit(False, error_msg)
|
||||||
|
logger.error(f"settings.py上传异常: {error_msg}")
|
||||||
|
|
||||||
|
|
||||||
|
class CollectStaticThread(QThread):
|
||||||
|
result_ready = Signal(bool, str)
|
||||||
|
progress_updated = Signal(int)
|
||||||
|
|
||||||
|
def __init__(self, ssh_client, django_path):
|
||||||
|
super().__init__()
|
||||||
|
self.ssh_client = ssh_client
|
||||||
|
self.django_path = django_path
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
self.progress_updated.emit(10)
|
||||||
|
|
||||||
|
# 检查Django项目是否存在
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"ls -la {self.django_path}/manage.py")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status != 0:
|
||||||
|
self.result_ready.emit(False, f"Django项目不存在: {self.django_path}")
|
||||||
|
logger.error(f"Django项目不存在: {self.django_path}")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.progress_updated.emit(30)
|
||||||
|
|
||||||
|
# 收集静态文件
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"cd {self.django_path} && python3 manage.py collectstatic --noinput")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status == 0:
|
||||||
|
self.progress_updated.emit(100)
|
||||||
|
output = stdout.read().decode()
|
||||||
|
self.result_ready.emit(True, f"静态文件收集成功: {output}")
|
||||||
|
logger.info("静态文件收集成功")
|
||||||
|
else:
|
||||||
|
error = stderr.read().decode()
|
||||||
|
self.result_ready.emit(False, error)
|
||||||
|
logger.error(f"静态文件收集失败: {error}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
self.result_ready.emit(False, error_msg)
|
||||||
|
logger.error(f"静态文件收集异常: {error_msg}")
|
||||||
|
|
||||||
|
|
||||||
|
class CheckDjangoStatusThread(QThread):
|
||||||
|
result_ready = Signal(bool, str)
|
||||||
|
|
||||||
|
def __init__(self, ssh_client, django_path):
|
||||||
|
super().__init__()
|
||||||
|
self.ssh_client = ssh_client
|
||||||
|
self.django_path = django_path
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
status_info = []
|
||||||
|
|
||||||
|
# 检查Django项目是否存在
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"ls -la {self.django_path}/manage.py")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status != 0:
|
||||||
|
self.result_ready.emit(False, f"Django项目不存在: {self.django_path}")
|
||||||
|
logger.error(f"Django项目不存在: {self.django_path}")
|
||||||
|
return
|
||||||
|
|
||||||
|
status_info.append("✓ Django项目存在")
|
||||||
|
|
||||||
|
# 检查Django版本
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("python3 -m django --version")
|
||||||
|
django_version = stdout.read().decode().strip()
|
||||||
|
status_info.append(f"✓ Django版本: {django_version}")
|
||||||
|
|
||||||
|
# 检查requirements.txt
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"ls -la {self.django_path}/requirements.txt")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status == 0:
|
||||||
|
status_info.append("✓ requirements.txt存在")
|
||||||
|
else:
|
||||||
|
status_info.append("✗ requirements.txt不存在")
|
||||||
|
|
||||||
|
# 检查settings.py
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"find {self.django_path} -name settings.py")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status == 0:
|
||||||
|
status_info.append("✓ settings.py存在")
|
||||||
|
else:
|
||||||
|
status_info.append("✗ settings.py不存在")
|
||||||
|
|
||||||
|
# 检查静态文件目录
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"ls -la {self.django_path}/static")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status == 0:
|
||||||
|
status_info.append("✓ static目录存在")
|
||||||
|
else:
|
||||||
|
status_info.append("✗ static目录不存在")
|
||||||
|
|
||||||
|
status_text = "\n".join(status_info)
|
||||||
|
self.result_ready.emit(True, status_text)
|
||||||
|
logger.info("Django状态检查完成")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
self.result_ready.emit(False, error_msg)
|
||||||
|
logger.error(f"Django状态检查异常: {error_msg}")
|
||||||
|
|
||||||
|
|
||||||
|
class GunicornInstallThread(QThread):
|
||||||
|
result_ready = Signal(bool, str)
|
||||||
|
progress_updated = Signal(int)
|
||||||
|
|
||||||
|
def __init__(self, ssh_client, password=None):
|
||||||
|
super().__init__()
|
||||||
|
self.ssh_client = ssh_client
|
||||||
|
self.password = password
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
self.progress_updated.emit(10)
|
||||||
|
|
||||||
|
# 检查Gunicorn是否已安装
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("gunicorn --version")
|
||||||
|
gunicorn_version = stdout.read().decode().strip()
|
||||||
|
|
||||||
|
if gunicorn_version:
|
||||||
|
self.result_ready.emit(True, f"Gunicorn已安装: {gunicorn_version}")
|
||||||
|
logger.info(f"Gunicorn已安装: {gunicorn_version}")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.progress_updated.emit(30)
|
||||||
|
|
||||||
|
# 尝试使用pip安装
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("pip3 install gunicorn")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status == 0:
|
||||||
|
self.progress_updated.emit(90)
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("gunicorn --version")
|
||||||
|
gunicorn_version = stdout.read().decode().strip()
|
||||||
|
self.result_ready.emit(True, f"Gunicorn安装成功: {gunicorn_version}")
|
||||||
|
logger.info(f"Gunicorn安装成功: {gunicorn_version}")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.progress_updated.emit(50)
|
||||||
|
|
||||||
|
# 如果pip安装失败,尝试使用apt安装
|
||||||
|
if self.password:
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("sudo -S apt update && sudo -S apt install -y gunicorn")
|
||||||
|
stdin.write(f"{self.password}\n")
|
||||||
|
stdin.flush()
|
||||||
|
else:
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("sudo apt update && sudo apt install -y gunicorn")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status == 0:
|
||||||
|
self.progress_updated.emit(90)
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("gunicorn --version")
|
||||||
|
gunicorn_version = stdout.read().decode().strip()
|
||||||
|
self.result_ready.emit(True, f"Gunicorn安装成功: {gunicorn_version}")
|
||||||
|
logger.info(f"Gunicorn安装成功: {gunicorn_version}")
|
||||||
|
else:
|
||||||
|
error = stderr.read().decode()
|
||||||
|
self.result_ready.emit(False, f"Gunicorn安装失败: {error}")
|
||||||
|
logger.error(f"Gunicorn安装失败: {error}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
self.result_ready.emit(False, error_msg)
|
||||||
|
logger.error(f"Gunicorn安装异常: {error_msg}")
|
||||||
|
|
||||||
|
|
||||||
|
class GunicornTestThread(QThread):
|
||||||
|
result_ready = Signal(bool, str)
|
||||||
|
progress_updated = Signal(int)
|
||||||
|
|
||||||
|
def __init__(self, ssh_client, django_path):
|
||||||
|
super().__init__()
|
||||||
|
self.ssh_client = ssh_client
|
||||||
|
self.django_path = django_path
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
self.progress_updated.emit(10)
|
||||||
|
|
||||||
|
# 检查Django项目是否存在
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"ls -la {self.django_path}/manage.py")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status != 0:
|
||||||
|
self.result_ready.emit(False, f"Django项目不存在: {self.django_path}")
|
||||||
|
logger.error(f"Django项目不存在: {self.django_path}")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.progress_updated.emit(30)
|
||||||
|
|
||||||
|
# 检查wsgi.py文件
|
||||||
|
project_name = os.path.basename(self.django_path)
|
||||||
|
wsgi_path = f"{self.django_path}/{project_name}/wsgi.py"
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"ls -la {wsgi_path}")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status != 0:
|
||||||
|
self.result_ready.emit(False, f"wsgi.py文件不存在: {wsgi_path}")
|
||||||
|
logger.error(f"wsgi.py文件不存在: {wsgi_path}")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.progress_updated.emit(50)
|
||||||
|
|
||||||
|
# 测试Gunicorn启动
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"cd {self.django_path} && gunicorn --workers 2 --bind 0.0.0.0:8001 {project_name}.wsgi:application --timeout 10 &")
|
||||||
|
time.sleep(5) # 等待Gunicorn启动
|
||||||
|
|
||||||
|
# 检查Gunicorn是否运行
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("ps aux | grep gunicorn")
|
||||||
|
output = stdout.read().decode()
|
||||||
|
|
||||||
|
if "gunicorn" in output and "--bind 0.0.0.0:8001" in output:
|
||||||
|
# 停止测试进程
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("pkill -f 'gunicorn --bind 0.0.0.0:8001'")
|
||||||
|
|
||||||
|
self.progress_updated.emit(100)
|
||||||
|
self.result_ready.emit(True, "Gunicorn测试成功")
|
||||||
|
logger.info("Gunicorn测试成功")
|
||||||
|
else:
|
||||||
|
self.result_ready.emit(False, "Gunicorn测试失败")
|
||||||
|
logger.error("Gunicorn测试失败")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
self.result_ready.emit(False, error_msg)
|
||||||
|
logger.error(f"Gunicorn测试异常: {error_msg}")
|
||||||
|
|
||||||
|
|
||||||
|
class UploadGunicornServiceThread(QThread):
|
||||||
|
result_ready = Signal(bool, str)
|
||||||
|
|
||||||
|
def __init__(self, ssh_client, service_name, service_content, password=None):
|
||||||
|
super().__init__()
|
||||||
|
self.ssh_client = ssh_client
|
||||||
|
self.service_name = service_name
|
||||||
|
self.service_content = service_content
|
||||||
|
self.password = password
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
# 创建服务文件
|
||||||
|
service_file = f"/etc/systemd/system/{self.service_name}.service"
|
||||||
|
temp_file = f"/tmp/{self.service_name}.service"
|
||||||
|
|
||||||
|
sftp = self.ssh_client.open_sftp()
|
||||||
|
|
||||||
|
with sftp.file(temp_file, 'w') as f:
|
||||||
|
f.write(self.service_content)
|
||||||
|
|
||||||
|
# 移动到systemd目录
|
||||||
|
if self.password:
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"sudo -S mv {temp_file} {service_file}")
|
||||||
|
stdin.write(f"{self.password}\n")
|
||||||
|
stdin.flush()
|
||||||
|
else:
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"sudo mv {temp_file} {service_file}")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status != 0:
|
||||||
|
error = stderr.read().decode()
|
||||||
|
self.result_ready.emit(False, f"服务文件移动失败: {error}")
|
||||||
|
logger.error(f"服务文件移动失败: {error}")
|
||||||
|
sftp.close()
|
||||||
|
return
|
||||||
|
|
||||||
|
# 设置权限
|
||||||
|
if self.password:
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"sudo -S chmod 644 {service_file}")
|
||||||
|
stdin.write(f"{self.password}\n")
|
||||||
|
stdin.flush()
|
||||||
|
else:
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"sudo chmod 644 {service_file}")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status != 0:
|
||||||
|
error = stderr.read().decode()
|
||||||
|
self.result_ready.emit(False, f"权限设置失败: {error}")
|
||||||
|
logger.error(f"权限设置失败: {error}")
|
||||||
|
sftp.close()
|
||||||
|
return
|
||||||
|
|
||||||
|
# 重新加载systemd
|
||||||
|
if self.password:
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("sudo -S systemctl daemon-reload")
|
||||||
|
stdin.write(f"{self.password}\n")
|
||||||
|
stdin.flush()
|
||||||
|
else:
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command("sudo systemctl daemon-reload")
|
||||||
|
|
||||||
|
sftp.close()
|
||||||
|
|
||||||
|
self.result_ready.emit(True, f"服务文件上传成功: {service_file}")
|
||||||
|
logger.info(f"服务文件上传成功: {service_file}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
self.result_ready.emit(False, error_msg)
|
||||||
|
logger.error(f"服务文件上传异常: {error_msg}")
|
||||||
|
|
||||||
|
|
||||||
|
class ManageGunicornServiceThread(QThread):
|
||||||
|
result_ready = Signal(bool, str)
|
||||||
|
|
||||||
|
def __init__(self, ssh_client, service_name, action, password=None):
|
||||||
|
super().__init__()
|
||||||
|
self.ssh_client = ssh_client
|
||||||
|
self.service_name = service_name
|
||||||
|
self.action = action
|
||||||
|
self.password = password
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
# 构建systemd命令
|
||||||
|
cmd = f"systemctl {self.action} {self.service_name}"
|
||||||
|
|
||||||
|
if self.action == "status":
|
||||||
|
# 状态命令需要特殊处理
|
||||||
|
if self.password:
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"sudo -S {cmd}")
|
||||||
|
stdin.write(f"{self.password}\n")
|
||||||
|
stdin.flush()
|
||||||
|
else:
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"sudo {cmd}")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status == 0:
|
||||||
|
output = stdout.read().decode()
|
||||||
|
self.result_ready.emit(True, output)
|
||||||
|
logger.info(f"服务状态查询成功: {self.service_name}")
|
||||||
|
else:
|
||||||
|
error = stderr.read().decode()
|
||||||
|
self.result_ready.emit(False, error)
|
||||||
|
logger.error(f"服务状态查询失败: {error}")
|
||||||
|
else:
|
||||||
|
# 其他操作(start, stop, restart, enable, disable)
|
||||||
|
if self.password:
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"sudo -S {cmd}")
|
||||||
|
stdin.write(f"{self.password}\n")
|
||||||
|
stdin.flush()
|
||||||
|
else:
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(f"sudo {cmd}")
|
||||||
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
|
|
||||||
|
if exit_status == 0:
|
||||||
|
self.result_ready.emit(True, f"服务{self.action}成功: {self.service_name}")
|
||||||
|
logger.info(f"服务{self.action}成功: {self.service_name}")
|
||||||
|
else:
|
||||||
|
error = stderr.read().decode()
|
||||||
|
self.result_ready.emit(False, error)
|
||||||
|
logger.error(f"服务{self.action}失败: {error}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
self.result_ready.emit(False, error_msg)
|
||||||
|
logger.error(f"服务管理异常: {error_msg}")
|
||||||
Reference in New Issue
Block a user