最初一个版本,已经初步实现各种功能

主页连接
远程命令
django
Gunicorn操作
This commit is contained in:
2025-08-28 20:44:35 +08:00
commit d559a85feb
22 changed files with 3841 additions and 0 deletions

89
README.md Normal file
View 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
## 界面预览
程序采用现代化的界面设计,包含:\- 美观的标签页布局
- 直观的表单输入
- 实时状态反馈
- 进度条显示
- 彩色状态指示

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View 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

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@@ -0,0 +1,3 @@
PySide6>=6.5.0
paramiko>=2.11.0
loguru>=0.7.0

225
server_connection_tab.py Normal file
View 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

View 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'

View 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'

View 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'

View 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"

View 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
View 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}")