diff --git a/__pycache__/django_tab.cpython-38.pyc b/__pycache__/django_tab.cpython-38.pyc index d59d2e6..ebcc56b 100644 Binary files a/__pycache__/django_tab.cpython-38.pyc and b/__pycache__/django_tab.cpython-38.pyc differ diff --git a/__pycache__/gunicorn_tab.cpython-38.pyc b/__pycache__/gunicorn_tab.cpython-38.pyc index eb54d6f..4bbe000 100644 Binary files a/__pycache__/gunicorn_tab.cpython-38.pyc and b/__pycache__/gunicorn_tab.cpython-38.pyc differ diff --git a/__pycache__/remote_command_tab.cpython-38.pyc b/__pycache__/remote_command_tab.cpython-38.pyc index 7082b5b..b670998 100644 Binary files a/__pycache__/remote_command_tab.cpython-38.pyc and b/__pycache__/remote_command_tab.cpython-38.pyc differ diff --git a/__pycache__/server_connection_tab.cpython-38.pyc b/__pycache__/server_connection_tab.cpython-38.pyc index 813705a..56d9d9f 100644 Binary files a/__pycache__/server_connection_tab.cpython-38.pyc and b/__pycache__/server_connection_tab.cpython-38.pyc differ diff --git a/__pycache__/threads.cpython-38.pyc b/__pycache__/threads.cpython-38.pyc index 28382de..fbde459 100644 Binary files a/__pycache__/threads.cpython-38.pyc and b/__pycache__/threads.cpython-38.pyc differ diff --git a/app.log b/app.log index eb7d455..aaa2968 100644 --- a/app.log +++ b/app.log @@ -65,3 +65,346 @@ sudo: a password is required 2025-08-28 20:37:01.109 | INFO | __main__::114 - 应用程序启动 2025-08-28 20:41:24.800 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 20:51:01.943 | INFO | __main__::114 - 应用程序启动 +2025-08-28 20:51:04.428 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 20:51:05.201 | INFO | __main__:on_tab_changed:107 - 切换到Gunicorn标签,自动检测服务状态 +2025-08-28 20:51:05.730 | ERROR | threads:run:836 - 服务状态查询失败: 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:51:05.734 | ERROR | gunicorn_tab:on_manage_service_result:285 - 服务操作失败: 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:52:55.800 | INFO | __main__::114 - 应用程序启动 +2025-08-28 20:52:58.689 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 20:52:59.622 | INFO | __main__:on_tab_changed:107 - 切换到Gunicorn标签,自动检测服务状态 +2025-08-28 20:53:05.630 | ERROR | threads:run:836 - 服务状态查询失败: [sudo] password for xiaji: Unit django_gunicorn.service could not be found. + +2025-08-28 20:53:05.631 | ERROR | gunicorn_tab:on_manage_service_result:338 - 服务操作失败: [sudo] password for xiaji: Unit django_gunicorn.service could not be found. + +2025-08-28 20:54:39.385 | INFO | __main__::114 - 应用程序启动 +2025-08-28 20:54:45.328 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 20:54:46.326 | INFO | __main__:on_tab_changed:107 - 切换到Gunicorn标签,自动检测服务状态 +2025-08-28 20:54:53.497 | INFO | threads:run:862 - 执行服务管理命令: systemctl status django_gunicorn +2025-08-28 20:54:53.505 | ERROR | threads:run:871 - 服务文件不存在: /etc/systemd/system/django_gunicorn.service, 错误: ls: cannot access '/etc/systemd/system/django_gunicorn.service': No such file or directory + +2025-08-28 20:54:53.507 | ERROR | gunicorn_tab:on_manage_service_result:338 - 服务操作失败: 服务文件不存在: django_gunicorn.service +2025-08-28 21:00:17.337 | INFO | remote_command_tab:on_list_directory_result:186 - 目录列表成功 +2025-08-28 21:00:17.337 | INFO | threads:run:157 - 目录列表成功: /home/xiaji/ +2025-08-28 21:00:56.560 | ERROR | threads:run:559 - Django项目不存在: /home/xiaji/statuspage +2025-08-28 21:00:56.560 | ERROR | django_tab:on_check_django_status_result:274 - Django状态检查失败: Django项目不存在: /home/xiaji/statuspage +2025-08-28 21:01:14.969 | INFO | threads:run:157 - 目录列表成功: /home/xiaji/ +2025-08-28 21:01:14.969 | INFO | remote_command_tab:on_list_directory_result:186 - 目录列表成功 +2025-08-28 21:01:28.149 | ERROR | threads:run:559 - Django项目不存在: /home/xiaji/statuspage/ +2025-08-28 21:01:28.149 | ERROR | django_tab:on_check_django_status_result:274 - Django状态检查失败: Django项目不存在: /home/xiaji/statuspage/ +2025-08-28 21:01:32.368 | ERROR | threads:run:363 - Django项目不存在: /home/xiaji/statuspage/ +2025-08-28 21:01:32.370 | ERROR | django_tab:on_test_django_result:167 - Django测试启动失败: Django项目不存在: /home/xiaji/statuspage/ +2025-08-28 21:01:36.279 | INFO | threads:run:304 - Django已安装: 5.2.5 +2025-08-28 21:01:36.280 | INFO | django_tab:on_install_django_result:135 - Django安装成功: Django已安装: 5.2.5 +2025-08-28 21:01:39.699 | ERROR | threads:run:363 - Django项目不存在: /home/xiaji/statuspage/ +2025-08-28 21:01:39.700 | ERROR | django_tab:on_test_django_result:167 - Django测试启动失败: Django项目不存在: /home/xiaji/statuspage/ +2025-08-28 21:02:37.594 | INFO | server_connection_tab:save_config:34 - 配置文件保存成功 +2025-08-28 21:02:47.403 | INFO | __main__::114 - 应用程序启动 +2025-08-28 21:03:06.423 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 21:03:13.531 | INFO | __main__::114 - 应用程序启动 +2025-08-28 21:03:18.362 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 21:06:04.148 | INFO | __main__::114 - 应用程序启动 +2025-08-28 21:06:04.183 | ERROR | remote_command_tab:load_git_config:113 - 加载git配置失败: [Errno 2] No such file or directory: 'C:\\Users\\xiaji\\Documents\\个人文件夹\\夏骥\\config.json' +2025-08-28 21:06:32.121 | INFO | __main__::114 - 应用程序启动 +2025-08-28 21:06:32.155 | ERROR | remote_command_tab:load_git_config:113 - 加载git配置失败: 'gbk' codec can't decode byte 0xa8 in position 56: illegal multibyte sequence +2025-08-28 21:06:47.698 | INFO | __main__::114 - 应用程序启动 +2025-08-28 21:06:47.729 | INFO | remote_command_tab:load_git_config:109 - 从配置文件加载git配置: git_url=http://192.168.3.241:3000/xiaji/webstatus, project_path=/home/xiaji/ +2025-08-28 21:06:52.075 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 21:08:17.090 | INFO | __main__::114 - 应用程序启动 +2025-08-28 21:08:17.130 | INFO | remote_command_tab:load_git_config:109 - 从配置文件加载git配置: git_url=http://192.168.3.241:3000/xiaji/webstatus, project_path=/home/xiaji/ +2025-08-28 21:08:17.131 | INFO | django_tab:load_django_path:117 - 从配置文件加载django路径: /home/xiaji/statuspage +2025-08-28 21:12:20.285 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 21:12:28.603 | ERROR | django_tab:on_test_django_result:184 - Django测试启动失败: Django项目不存在: /home/xiaji/statuspage +2025-08-28 21:12:28.603 | ERROR | threads:run:363 - Django项目不存在: /home/xiaji/statuspage +2025-08-28 21:13:22.162 | INFO | __main__::114 - 应用程序启动 +2025-08-28 21:13:22.202 | INFO | remote_command_tab:load_git_config:109 - 从配置文件加载git配置: git_url=http://192.168.3.241:3000/xiaji/webstatus, project_path=/home/xiaji/ +2025-08-28 21:13:22.203 | INFO | django_tab:load_django_path:117 - 从配置文件加载django路径: /home/xiaji/statuspage +2025-08-28 21:13:27.903 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 21:13:39.808 | ERROR | threads:run:363 - Django项目不存在: /home/xiaji/statuspage +2025-08-28 21:13:39.809 | ERROR | django_tab:on_test_django_result:184 - Django测试启动失败: Django项目不存在: /home/xiaji/statuspage +2025-08-28 21:13:48.684 | INFO | threads:run:157 - 目录列表成功: /home/xiaji/ +2025-08-28 21:13:48.688 | INFO | remote_command_tab:on_list_directory_result:199 - 目录列表成功 +2025-08-28 21:16:20.769 | INFO | __main__::114 - 应用程序启动 +2025-08-28 21:16:20.810 | INFO | remote_command_tab:load_git_config:109 - 从配置文件加载git配置: git_url=http://192.168.3.241:3000/xiaji/webstatus, project_path=/home/xiaji/ +2025-08-28 21:16:20.811 | INFO | django_tab:load_django_path:117 - 从配置文件加载django路径: /home/xiaji/statuspage +2025-08-28 21:16:22.780 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 21:16:25.519 | ERROR | threads:run:363 - Django项目不存在: /home/xiaji/statuspage +2025-08-28 21:16:25.519 | ERROR | django_tab:on_test_django_result:184 - Django测试启动失败: Django项目不存在: /home/xiaji/statuspage +2025-08-28 21:16:29.049 | INFO | threads:run:157 - 目录列表成功: /home/xiaji/ +2025-08-28 21:16:29.051 | INFO | remote_command_tab:on_list_directory_result:199 - 目录列表成功: +total 176 +drwxr-x--- 9 xiaji xiaji 4096 Aug 27 20:52 . +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 3 xiaji xiaji 4096 Aug 27 20:51 home +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 3 xiaji xiaji 4096 Aug 27 20:52 static +drwxrwxr-x 5 xiaji xiaji 4096 Aug 26 22:18 status +drwxrwxr-x 3 xiaji xiaji 4096 Aug 28 04:20 statuspage +-rw-r--r-- 1 xiaji xiaji 0 Aug 27 20:03 .sudo_as_admin_successful + +2025-08-28 21:17:03.711 | INFO | __main__::114 - 应用程序启动 +2025-08-28 21:17:03.777 | INFO | remote_command_tab:load_git_config:109 - 从配置文件加载git配置: git_url=http://192.168.3.241:3000/xiaji/webstatus, project_path=/home/xiaji/ +2025-08-28 21:17:03.782 | INFO | django_tab:load_django_path:117 - 从配置文件加载django路径: /home/xiaji/statuspage +2025-08-28 21:17:09.386 | INFO | server_connection_tab:save_config:34 - 配置文件保存成功 +2025-08-28 21:17:11.652 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 21:17:16.174 | INFO | django_tab:load_django_path:117 - 从配置文件加载django路径: /home/xiaji/ +2025-08-28 21:17:18.319 | ERROR | django_tab:on_test_django_result:184 - 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-28 21:17:18.319 | ERROR | threads:run:381 - 依赖安装失败: 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-28 21:17:50.278 | INFO | __main__::114 - 应用程序启动 +2025-08-28 21:17:50.317 | INFO | remote_command_tab:load_git_config:109 - 从配置文件加载git配置: git_url=http://192.168.3.241:3000/xiaji/webstatus, project_path=/home/xiaji/ +2025-08-28 21:17:50.319 | INFO | django_tab:load_django_path:117 - 从配置文件加载django路径: /home/xiaji/ +2025-08-28 21:18:00.995 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 21:18:02.871 | INFO | threads:run:304 - Django已安装: 5.2.5 +2025-08-28 21:18:02.873 | INFO | django_tab:on_install_django_result:152 - Django安装成功: Django已安装: 5.2.5 +2025-08-28 21:19:24.402 | ERROR | threads:run:381 - 依赖安装失败: +2025-08-28 21:19:36.038 | INFO | __main__::114 - 应用程序启动 +2025-08-28 21:19:36.077 | INFO | remote_command_tab:load_git_config:109 - 从配置文件加载git配置: git_url=http://192.168.3.241:3000/xiaji/webstatus, project_path=/home/xiaji/ +2025-08-28 21:19:36.079 | INFO | django_tab:load_django_path:117 - 从配置文件加载django路径: /home/xiaji/ +2025-08-28 21:19:39.142 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 21:21:54.132 | INFO | server_connection_tab:save_config:34 - 配置文件保存成功 +2025-08-28 21:23:22.197 | INFO | __main__::114 - 应用程序启动 +2025-08-28 21:23:22.228 | INFO | remote_command_tab:load_git_config:109 - 从配置文件加载git配置: git_url=http://192.168.3.241:3000/xiaji/webstatus, project_path=/home/xiaji/ +2025-08-28 21:23:22.229 | INFO | django_tab:load_django_path:117 - 从配置文件加载django路径: /home/xiaji/ +2025-08-28 21:23:24.309 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 21:26:27.449 | INFO | __main__::114 - 应用程序启动 +2025-08-28 21:26:27.484 | INFO | remote_command_tab:load_git_config:109 - 从配置文件加载git配置: git_url=http://192.168.3.241:3000/xiaji/webstatus, project_path=/home/xiaji/ +2025-08-28 21:26:27.485 | INFO | django_tab:load_django_path:117 - 从配置文件加载django路径: /home/xiaji/ +2025-08-28 21:26:29.358 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 21:26:39.130 | INFO | threads:run:397 - Django测试服务器启动成功 +2025-08-28 21:26:39.131 | INFO | django_tab:on_test_django_result:181 - Django测试启动成功: Django测试服务器启动成功 +2025-08-28 21:26:52.767 | INFO | threads:run:598 - Django状态检查完成 +2025-08-28 21:26:52.786 | INFO | django_tab:on_check_django_status_result:288 - Django状态检查成功 +2025-08-28 21:26:56.002 | INFO | __main__:on_tab_changed:107 - 切换到Gunicorn标签,自动检测服务状态 +2025-08-28 21:27:03.503 | INFO | threads:run:867 - 执行服务管理命令: systemctl status django_gunicorn +2025-08-28 21:27:03.511 | ERROR | threads:run:876 - 服务文件不存在: /etc/systemd/system/django_gunicorn.service, 错误: ls: cannot access '/etc/systemd/system/django_gunicorn.service': No such file or directory + +2025-08-28 21:27:03.512 | ERROR | gunicorn_tab:on_manage_service_result:338 - 服务操作失败: 服务文件不存在: django_gunicorn.service +2025-08-28 21:27:54.858 | INFO | __main__:on_tab_changed:107 - 切换到Gunicorn标签,自动检测服务状态 +2025-08-28 21:28:00.516 | INFO | threads:run:867 - 执行服务管理命令: systemctl status django_gunicorn +2025-08-28 21:28:00.525 | ERROR | threads:run:876 - 服务文件不存在: /etc/systemd/system/django_gunicorn.service, 错误: ls: cannot access '/etc/systemd/system/django_gunicorn.service': No such file or directory + +2025-08-28 21:28:00.527 | ERROR | gunicorn_tab:on_manage_service_result:338 - 服务操作失败: 服务文件不存在: django_gunicorn.service +2025-08-28 21:28:02.915 | ERROR | threads:run:702 - wsgi.py文件不存在: /home/xiaji///wsgi.py +2025-08-28 21:28:02.916 | ERROR | gunicorn_tab:on_test_gunicorn_result:265 - Gunicorn测试失败: wsgi.py文件不存在: /home/xiaji///wsgi.py +2025-08-28 21:45:10.338 | INFO | __main__::114 - 应用程序启动 +2025-08-28 21:45:10.373 | INFO | remote_command_tab:load_git_config:109 - 从配置文件加载git配置: git_url=http://192.168.3.241:3000/xiaji/webstatus, project_path=/home/xiaji/ +2025-08-28 21:45:10.374 | INFO | django_tab:load_django_path:117 - 从配置文件加载django路径: /home/xiaji/ +2025-08-28 21:45:12.542 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 21:45:14.597 | INFO | __main__:on_tab_changed:107 - 切换到Gunicorn标签,自动检测服务状态 +2025-08-28 21:45:18.259 | INFO | threads:run:875 - 执行服务管理命令: systemctl status gunicorn_django +2025-08-28 21:45:18.269 | ERROR | threads:run:884 - 服务文件不存在: /etc/systemd/system/gunicorn_django.service, 错误: ls: cannot access '/etc/systemd/system/gunicorn_django.service': No such file or directory + +2025-08-28 21:45:18.270 | ERROR | gunicorn_tab:on_manage_service_result:386 - 服务操作失败: 服务文件不存在: gunicorn_django.service +2025-08-28 21:45:26.168 | INFO | __main__:on_tab_changed:107 - 切换到Gunicorn标签,自动检测服务状态 +2025-08-28 21:45:30.745 | INFO | threads:run:875 - 执行服务管理命令: systemctl status gunicorn_django +2025-08-28 21:45:30.754 | ERROR | threads:run:884 - 服务文件不存在: /etc/systemd/system/gunicorn_django.service, 错误: ls: cannot access '/etc/systemd/system/gunicorn_django.service': No such file or directory + +2025-08-28 21:45:30.755 | ERROR | gunicorn_tab:on_manage_service_result:386 - 服务操作失败: 服务文件不存在: gunicorn_django.service +2025-08-28 22:01:41.803 | INFO | __main__::114 - 应用程序启动 +2025-08-28 22:01:41.845 | INFO | remote_command_tab:load_git_config:109 - 从配置文件加载git配置: git_url=http://192.168.3.241:3000/xiaji/webstatus, project_path=/home/xiaji/ +2025-08-28 22:01:41.846 | INFO | django_tab:load_django_path:117 - 从配置文件加载django路径: /home/xiaji/ +2025-08-28 22:01:43.842 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 22:01:44.537 | INFO | __main__:on_tab_changed:107 - 切换到Gunicorn标签,自动检测服务状态 +2025-08-28 22:01:48.082 | INFO | threads:run:875 - 执行服务管理命令: systemctl status gunicorn_django +2025-08-28 22:01:48.090 | ERROR | threads:run:884 - 服务文件不存在: /etc/systemd/system/gunicorn_django.service, 错误: ls: cannot access '/etc/systemd/system/gunicorn_django.service': No such file or directory + +2025-08-28 22:01:48.091 | ERROR | gunicorn_tab:on_manage_service_result:386 - 服务操作失败: 服务文件不存在: gunicorn_django.service +2025-08-28 22:01:55.720 | INFO | __main__:on_tab_changed:107 - 切换到Gunicorn标签,自动检测服务状态 +2025-08-28 22:01:59.324 | INFO | threads:run:875 - 执行服务管理命令: systemctl status gunicorn_django +2025-08-28 22:01:59.333 | ERROR | threads:run:884 - 服务文件不存在: /etc/systemd/system/gunicorn_django.service, 错误: ls: cannot access '/etc/systemd/system/gunicorn_django.service': No such file or directory + +2025-08-28 22:01:59.334 | ERROR | gunicorn_tab:on_manage_service_result:386 - 服务操作失败: 服务文件不存在: gunicorn_django.service +2025-08-28 22:04:31.027 | INFO | __main__::114 - 应用程序启动 +2025-08-28 22:04:31.062 | INFO | remote_command_tab:load_git_config:109 - 从配置文件加载git配置: git_url=http://192.168.3.241:3000/xiaji/webstatus, project_path=/home/xiaji/ +2025-08-28 22:04:31.063 | INFO | django_tab:load_django_path:117 - 从配置文件加载django路径: /home/xiaji/ +2025-08-28 22:05:26.599 | INFO | __main__::114 - 应用程序启动 +2025-08-28 22:05:26.631 | INFO | remote_command_tab:load_git_config:109 - 从配置文件加载git配置: git_url=http://192.168.3.241:3000/xiaji/webstatus, project_path=/home/xiaji/ +2025-08-28 22:05:26.632 | INFO | django_tab:load_django_path:117 - 从配置文件加载django路径: /home/xiaji/ +2025-08-28 22:05:28.618 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 22:05:29.755 | INFO | __main__:on_tab_changed:107 - 切换到Gunicorn标签,自动检测服务状态 +2025-08-28 22:05:34.219 | INFO | threads:run:875 - 执行服务管理命令: systemctl status gunicorn_django +2025-08-28 22:05:34.227 | ERROR | threads:run:884 - 服务文件不存在: /etc/systemd/system/gunicorn_django.service, 错误: ls: cannot access '/etc/systemd/system/gunicorn_django.service': No such file or directory + +2025-08-28 22:05:34.229 | ERROR | gunicorn_tab:on_manage_service_result:424 - 服务操作失败: 服务文件不存在: gunicorn_django.service +2025-08-28 22:06:09.440 | INFO | threads:run:756 - 准备上传服务文件: /etc/systemd/system/gunicorn_django.service +2025-08-28 22:06:09.454 | INFO | threads:run:763 - 临时服务文件创建成功: /tmp/gunicorn_django.service +2025-08-28 22:06:09.477 | INFO | threads:run:781 - 服务文件移动成功: /etc/systemd/system/gunicorn_django.service +2025-08-28 22:06:09.538 | INFO | threads:run:799 - 服务文件权限设置成功: /etc/systemd/system/gunicorn_django.service +2025-08-28 22:06:09.590 | INFO | threads:run:807 - 服务文件验证成功: -rw-r--r-- 1 xiaji xiaji 705 Aug 28 22:06 /etc/systemd/system/gunicorn_django.service +2025-08-28 22:06:09.888 | INFO | threads:run:831 - systemd重新加载成功 +2025-08-28 22:06:10.453 | INFO | threads:run:839 - 服务被systemd识别: gunicorn_django.service disabled enabled +2025-08-28 22:06:10.454 | INFO | threads:run:847 - 服务文件上传成功: /etc/systemd/system/gunicorn_django.service +2025-08-28 22:06:10.456 | INFO | gunicorn_tab:on_upload_service_result:373 - 服务文件上传成功: 服务文件上传成功: /etc/systemd/system/gunicorn_django.service +2025-08-28 22:06:20.044 | INFO | threads:run:875 - 执行服务管理命令: systemctl restart gunicorn_django +2025-08-28 22:06:20.059 | INFO | threads:run:889 - 服务文件存在: -rw-r--r-- 1 xiaji xiaji 705 Aug 28 22:06 /etc/systemd/system/gunicorn_django.service +2025-08-28 22:06:20.139 | INFO | threads:run:920 - 服务restart成功: gunicorn_django +2025-08-28 22:06:20.140 | INFO | gunicorn_tab:on_manage_service_result:421 - 服务操作成功: 服务restart成功: gunicorn_django +2025-08-28 22:07:59.648 | INFO | __main__::109 - 应用程序启动 +2025-08-28 22:07:59.692 | INFO | remote_command_tab:load_git_config:109 - 从配置文件加载git配置: git_url=http://192.168.3.241:3000/xiaji/webstatus, project_path=/home/xiaji/ +2025-08-28 22:07:59.697 | INFO | django_tab:load_django_path:117 - 从配置文件加载django路径: /home/xiaji/ +2025-08-28 22:08:02.096 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 22:10:45.949 | INFO | __main__::109 - 应用程序启动 +2025-08-28 22:10:45.986 | INFO | remote_command_tab:load_git_config:109 - 从配置文件加载git配置: git_url=http://192.168.3.241:3000/xiaji/webstatus, project_path=/home/xiaji/ +2025-08-28 22:10:45.987 | INFO | django_tab:load_django_path:115 - 从当前服务器配置加载django路径: /home/xiaji/ +2025-08-28 22:10:45.987 | INFO | django_tab:__init__:22 - Django标签已连接到服务器切换信号 +2025-08-28 22:10:53.292 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 22:13:07.349 | INFO | __main__::109 - 应用程序启动 +2025-08-28 22:13:07.387 | INFO | remote_command_tab:load_git_config:109 - 从配置文件加载git配置: git_url=http://192.168.3.241:3000/xiaji/webstatus, project_path=/home/xiaji/ +2025-08-28 22:13:07.388 | INFO | django_tab:load_django_path:115 - 从当前服务器配置加载django路径: /home/xiaji/ +2025-08-28 22:13:07.390 | INFO | django_tab:__init__:22 - Django标签已连接到服务器切换信号 +2025-08-28 22:13:07.391 | INFO | gunicorn_tab:__init__:50 - Gunicorn标签已连接到服务器切换信号 +2025-08-28 22:13:09.561 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 22:13:22.767 | INFO | threads:run:756 - 准备上传服务文件: /etc/systemd/system/gunicorn_django.service +2025-08-28 22:13:22.782 | INFO | threads:run:763 - 临时服务文件创建成功: /tmp/gunicorn_django.service +2025-08-28 22:13:22.803 | INFO | threads:run:781 - 服务文件移动成功: /etc/systemd/system/gunicorn_django.service +2025-08-28 22:13:22.865 | INFO | threads:run:799 - 服务文件权限设置成功: /etc/systemd/system/gunicorn_django.service +2025-08-28 22:13:22.917 | INFO | threads:run:807 - 服务文件验证成功: -rw-r--r-- 1 xiaji xiaji 778 Aug 28 22:13 /etc/systemd/system/gunicorn_django.service +2025-08-28 22:13:23.219 | INFO | threads:run:831 - systemd重新加载成功 +2025-08-28 22:13:23.845 | INFO | threads:run:839 - 服务被systemd识别: gunicorn_django.service disabled enabled +2025-08-28 22:13:23.846 | INFO | threads:run:847 - 服务文件上传成功: /etc/systemd/system/gunicorn_django.service +2025-08-28 22:13:23.847 | INFO | gunicorn_tab:on_upload_service_result:377 - 服务文件上传成功: 服务文件上传成功: /etc/systemd/system/gunicorn_django.service +2025-08-28 22:13:28.149 | INFO | threads:run:875 - 执行服务管理命令: systemctl restart gunicorn_django +2025-08-28 22:13:28.158 | INFO | threads:run:889 - 服务文件存在: -rw-r--r-- 1 xiaji xiaji 778 Aug 28 22:13 /etc/systemd/system/gunicorn_django.service +2025-08-28 22:13:28.228 | INFO | threads:run:920 - 服务restart成功: gunicorn_django +2025-08-28 22:13:28.230 | INFO | gunicorn_tab:on_manage_service_result:425 - 服务操作成功: 服务restart成功: gunicorn_django +2025-08-28 22:15:05.213 | INFO | __main__::109 - 应用程序启动 +2025-08-28 22:15:05.248 | INFO | remote_command_tab:load_git_config:109 - 从配置文件加载git配置: git_url=http://192.168.3.241:3000/xiaji/webstatus, project_path=/home/xiaji/ +2025-08-28 22:15:05.249 | INFO | django_tab:load_django_path:115 - 从当前服务器配置加载django路径: /home/xiaji/ +2025-08-28 22:15:05.249 | INFO | django_tab:__init__:22 - Django标签已连接到服务器切换信号 +2025-08-28 22:15:05.250 | INFO | gunicorn_tab:__init__:50 - Gunicorn标签已连接到服务器切换信号 +2025-08-28 22:15:08.328 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 22:18:00.966 | INFO | __main__::109 - 应用程序启动 +2025-08-28 22:18:01.005 | INFO | remote_command_tab:load_git_config:109 - 从配置文件加载git配置: git_url=http://192.168.3.241:3000/xiaji/webstatus, project_path=/home/xiaji/ +2025-08-28 22:18:01.007 | INFO | django_tab:load_django_path:115 - 从当前服务器配置加载django路径: /home/xiaji/ +2025-08-28 22:18:01.007 | INFO | django_tab:__init__:22 - Django标签已连接到服务器切换信号 +2025-08-28 22:18:01.008 | INFO | gunicorn_tab:load_gunicorn_config:175 - 从当前服务器配置加载Gunicorn配置: django_path=/home/xiaji/, project_name=statuspage +2025-08-28 22:18:01.009 | INFO | gunicorn_tab:__init__:50 - Gunicorn标签已连接到服务器切换信号 +2025-08-28 22:18:03.033 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 22:18:10.456 | INFO | threads:run:707 - 找到wsgi.py文件: /home/xiaji/statuspage/wsgi.py +/home/xiaji/.local/lib/python3.12/site-packages/django/core/handlers/wsgi.py +/home/xiaji/.local/lib/python3.12/site-packages/django/core/wsgi.py +/home/xiaji/.local/lib/python3.12/site-packages/asgiref/wsgi.py +2025-08-28 22:18:15.531 | ERROR | threads:run:732 - Gunicorn测试失败 +2025-08-28 22:18:15.531 | ERROR | gunicorn_tab:on_test_gunicorn_result:367 - Gunicorn测试失败: Gunicorn测试失败 +2025-08-28 22:18:21.513 | INFO | threads:run:707 - 找到wsgi.py文件: /home/xiaji/statuspage/wsgi.py +/home/xiaji/.local/lib/python3.12/site-packages/django/core/handlers/wsgi.py +/home/xiaji/.local/lib/python3.12/site-packages/django/core/wsgi.py +/home/xiaji/.local/lib/python3.12/site-packages/asgiref/wsgi.py +2025-08-28 22:18:26.582 | ERROR | threads:run:732 - Gunicorn测试失败 +2025-08-28 22:18:26.585 | ERROR | gunicorn_tab:on_test_gunicorn_result:367 - Gunicorn测试失败: Gunicorn测试失败 +2025-08-28 22:20:04.518 | INFO | __main__::109 - 应用程序启动 +2025-08-28 22:20:04.553 | INFO | remote_command_tab:load_git_config:109 - 从配置文件加载git配置: git_url=http://192.168.3.241:3000/xiaji/webstatus, project_path=/home/xiaji/ +2025-08-28 22:20:04.556 | INFO | django_tab:load_django_path:115 - 从当前服务器配置加载django路径: /home/xiaji/statuspage +2025-08-28 22:20:04.556 | INFO | django_tab:__init__:22 - Django标签已连接到服务器切换信号 +2025-08-28 22:20:04.558 | INFO | gunicorn_tab:load_gunicorn_config:175 - 从当前服务器配置加载Gunicorn配置: django_path=/home/xiaji/statuspage, project_name=statuspage +2025-08-28 22:20:04.559 | INFO | gunicorn_tab:__init__:50 - Gunicorn标签已连接到服务器切换信号 +2025-08-28 22:20:12.042 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 22:20:15.094 | ERROR | threads:run:689 - Django项目不存在: /home/xiaji/statuspage +2025-08-28 22:20:15.095 | ERROR | gunicorn_tab:on_test_gunicorn_result:367 - Gunicorn测试失败: Django项目不存在: /home/xiaji/statuspage +2025-08-28 22:20:24.016 | INFO | threads:run:707 - 找到wsgi.py文件: /home/xiaji/statuspage/wsgi.py +/home/xiaji/.local/lib/python3.12/site-packages/django/core/handlers/wsgi.py +/home/xiaji/.local/lib/python3.12/site-packages/django/core/wsgi.py +/home/xiaji/.local/lib/python3.12/site-packages/asgiref/wsgi.py +2025-08-28 22:20:59.164 | INFO | __main__::109 - 应用程序启动 +2025-08-28 22:20:59.201 | INFO | remote_command_tab:load_git_config:109 - 从配置文件加载git配置: git_url=http://192.168.3.241:3000/xiaji/webstatus, project_path=/home/xiaji/ +2025-08-28 22:20:59.203 | INFO | django_tab:load_django_path:115 - 从当前服务器配置加载django路径: /home/xiaji/statuspage +2025-08-28 22:20:59.203 | INFO | django_tab:__init__:22 - Django标签已连接到服务器切换信号 +2025-08-28 22:20:59.204 | INFO | gunicorn_tab:load_gunicorn_config:175 - 从当前服务器配置加载Gunicorn配置: django_path=/home/xiaji/statuspage, project_name=statuspage +2025-08-28 22:20:59.204 | INFO | gunicorn_tab:__init__:50 - Gunicorn标签已连接到服务器切换信号 +2025-08-28 22:21:00.318 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 22:21:07.110 | ERROR | threads:run:689 - Django项目不存在: /home/xiaji/statuspage +2025-08-28 22:21:07.112 | ERROR | gunicorn_tab:on_test_gunicorn_result:367 - Gunicorn测试失败: Django项目不存在: /home/xiaji/statuspage +2025-08-28 22:24:30.595 | INFO | __main__::109 - 应用程序启动 +2025-08-28 22:24:30.635 | INFO | remote_command_tab:load_git_config:109 - 从配置文件加载git配置: git_url=http://192.168.3.241:3000/xiaji/webstatus, project_path=/home/xiaji/ +2025-08-28 22:24:30.636 | INFO | django_tab:load_django_path:115 - 从当前服务器配置加载django路径: /home/xiaji/statuspage +2025-08-28 22:24:30.636 | INFO | django_tab:__init__:22 - Django标签已连接到服务器切换信号 +2025-08-28 22:24:30.637 | INFO | gunicorn_tab:load_gunicorn_config:175 - 从当前服务器配置加载Gunicorn配置: django_path=/home/xiaji/statuspage, project_name=statuspage +2025-08-28 22:24:30.638 | INFO | gunicorn_tab:__init__:50 - Gunicorn标签已连接到服务器切换信号 +2025-08-28 22:24:32.673 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 22:26:19.189 | INFO | __main__::109 - 应用程序启动 +2025-08-28 22:26:19.228 | INFO | remote_command_tab:load_git_config:109 - 从配置文件加载git配置: git_url=http://192.168.3.241:3000/xiaji/webstatus, project_path=/home/xiaji/ +2025-08-28 22:26:19.229 | INFO | django_tab:load_django_path:115 - 从当前服务器配置加载django路径: /home/xiaji/statuspage +2025-08-28 22:26:19.229 | INFO | django_tab:__init__:22 - Django标签已连接到服务器切换信号 +2025-08-28 22:26:19.231 | INFO | gunicorn_tab:load_gunicorn_config:175 - 从当前服务器配置加载Gunicorn配置: django_path=/home/xiaji/statuspage, project_name=statuspage +2025-08-28 22:26:19.231 | INFO | gunicorn_tab:__init__:50 - Gunicorn标签已连接到服务器切换信号 +2025-08-28 22:26:25.092 | INFO | threads:run:47 - SSH连接成功: 192.168.3.157 +2025-08-28 22:26:31.515 | INFO | threads:run:707 - 找到wsgi.py文件: /home/xiaji/statuspage/wsgi.py +/home/xiaji/.local/lib/python3.12/site-packages/django/core/handlers/wsgi.py +/home/xiaji/.local/lib/python3.12/site-packages/django/core/wsgi.py +/home/xiaji/.local/lib/python3.12/site-packages/asgiref/wsgi.py +2025-08-28 22:26:36.591 | ERROR | threads:run:732 - Gunicorn测试失败 +2025-08-28 22:26:36.592 | ERROR | gunicorn_tab:on_test_gunicorn_result:367 - Gunicorn测试失败: Gunicorn测试失败 +2025-08-28 22:27:18.620 | INFO | threads:run:756 - 准备上传服务文件: /etc/systemd/system/gunicorn_django.service +2025-08-28 22:27:18.634 | INFO | threads:run:763 - 临时服务文件创建成功: /tmp/gunicorn_django.service +2025-08-28 22:27:18.654 | INFO | threads:run:781 - 服务文件移动成功: /etc/systemd/system/gunicorn_django.service +2025-08-28 22:27:18.717 | INFO | threads:run:799 - 服务文件权限设置成功: /etc/systemd/system/gunicorn_django.service +2025-08-28 22:27:18.768 | INFO | threads:run:807 - 服务文件验证成功: -rw-r--r-- 1 xiaji xiaji 703 Aug 28 22:27 /etc/systemd/system/gunicorn_django.service +2025-08-28 22:27:19.090 | INFO | threads:run:831 - systemd重新加载成功 +2025-08-28 22:27:19.712 | INFO | threads:run:839 - 服务被systemd识别: gunicorn_django.service disabled enabled +2025-08-28 22:27:19.714 | INFO | threads:run:847 - 服务文件上传成功: /etc/systemd/system/gunicorn_django.service +2025-08-28 22:27:19.715 | INFO | gunicorn_tab:on_upload_service_result:408 - 服务文件上传成功: 服务文件上传成功: /etc/systemd/system/gunicorn_django.service +2025-08-28 22:27:24.287 | INFO | threads:run:875 - 执行服务管理命令: systemctl restart gunicorn_django +2025-08-28 22:27:24.295 | INFO | threads:run:889 - 服务文件存在: -rw-r--r-- 1 xiaji xiaji 703 Aug 28 22:27 /etc/systemd/system/gunicorn_django.service +2025-08-28 22:27:24.366 | INFO | threads:run:920 - 服务restart成功: gunicorn_django +2025-08-28 22:27:24.367 | INFO | gunicorn_tab:on_manage_service_result:456 - 服务操作成功: 服务restart成功: gunicorn_django +2025-08-28 22:27:28.045 | INFO | threads:run:875 - 执行服务管理命令: systemctl enable gunicorn_django +2025-08-28 22:27:28.054 | INFO | threads:run:889 - 服务文件存在: -rw-r--r-- 1 xiaji xiaji 703 Aug 28 22:27 /etc/systemd/system/gunicorn_django.service +2025-08-28 22:27:28.368 | INFO | threads:run:920 - 服务enable成功: gunicorn_django +2025-08-28 22:27:28.371 | INFO | gunicorn_tab:on_manage_service_result:456 - 服务操作成功: 服务enable成功: gunicorn_django +2025-08-28 22:27:32.509 | INFO | threads:run:875 - 执行服务管理命令: systemctl status gunicorn_django +2025-08-28 22:27:32.518 | INFO | threads:run:889 - 服务文件存在: -rw-r--r-- 1 xiaji xiaji 703 Aug 28 22:27 /etc/systemd/system/gunicorn_django.service +2025-08-28 22:27:32.587 | ERROR | threads:run:907 - 服务状态查询失败: [sudo] password for xiaji: +2025-08-28 22:27:32.588 | ERROR | gunicorn_tab:on_manage_service_result:459 - 服务操作失败: [sudo] password for xiaji: +2025-08-28 22:27:52.590 | INFO | threads:run:875 - 执行服务管理命令: systemctl status gunicorn_django +2025-08-28 22:27:52.599 | INFO | threads:run:889 - 服务文件存在: -rw-r--r-- 1 xiaji xiaji 703 Aug 28 22:27 /etc/systemd/system/gunicorn_django.service +2025-08-28 22:27:52.670 | ERROR | threads:run:907 - 服务状态查询失败: [sudo] password for xiaji: +2025-08-28 22:27:52.671 | ERROR | gunicorn_tab:on_manage_service_result:459 - 服务操作失败: [sudo] password for xiaji: diff --git a/config.json b/config.json index 30ac249..6f34109 100644 --- a/config.json +++ b/config.json @@ -9,7 +9,7 @@ "project_name": "statuspage", "git_url": "http://192.168.3.241:3000/xiaji/webstatus", "remote_directory": "/home/xiaji/", - "django_path": "/home/xiaji/" + "django_path": "/home/xiaji/statuspage" }, { "alias": "生产服务器", diff --git a/django_tab.py b/django_tab.py index 60bd23d..2c1487d 100644 --- a/django_tab.py +++ b/django_tab.py @@ -1,4 +1,5 @@ import os +import json from loguru import logger from PySide6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton, QComboBox, QMessageBox, QTextEdit, @@ -15,6 +16,10 @@ class DjangoTab(QWidget): self.parent = parent self.init_ui() + # 连接服务器切换信号 + if self.parent and hasattr(self.parent, 'server_changed'): + self.parent.server_changed.connect(self.on_server_changed) + logger.info("Django标签已连接到服务器切换信号") def init_ui(self): layout = QVBoxLayout() @@ -100,9 +105,31 @@ class DjangoTab(QWidget): 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) + """从当前服务器配置加载Django路径""" + try: + if self.parent and hasattr(self.parent, 'get_current_config'): + config = self.parent.get_current_config() + if config: + django_path = config.get('django_path', '') + self.django_path_input.setText(django_path) + logger.info(f"从当前服务器配置加载django路径: {django_path}") + else: + logger.warning("未找到当前服务器配置") + else: + # 兼容旧的加载方式 + config_path = os.path.join(os.path.dirname(__file__), 'config.json') + with open(config_path, 'r', encoding='utf-8') as f: + config = json.load(f) + + if config and 'servers' in config and len(config['servers']) > 0: + server_config = config['servers'][0] + django_path = server_config.get('django_path', '') + self.django_path_input.setText(django_path) + logger.info(f"从配置文件加载django路径: {django_path}") + except Exception as e: + logger.error(f"加载django路径失败: {str(e)}") + # 不显示警告,避免影响用户体验 + QMessageBox.warning(self, "警告", f"加载django路径失败: {str(e)}") def check_ssh_connection(self): if not self.parent or not self.parent.ssh_client: diff --git a/gunicorn_tab.py b/gunicorn_tab.py index a90423c..1cc5e6f 100644 --- a/gunicorn_tab.py +++ b/gunicorn_tab.py @@ -2,19 +2,52 @@ import os from loguru import logger from PySide6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton, QComboBox, QMessageBox, QTextEdit, - QGroupBox, QGridLayout, QProgressBar) + QGroupBox, QGridLayout, QProgressBar, QDialog, + QDialogButtonBox) from PySide6.QtCore import Qt from threads import (GunicornInstallThread, GunicornTestThread, UploadGunicornServiceThread, ManageGunicornServiceThread) +class PasswordDialog(QDialog): + def __init__(self, parent=None): + super().__init__(parent) + self.setWindowTitle("输入密码") + self.setMinimumWidth(300) + + layout = QVBoxLayout() + + # 密码输入 + password_layout = QHBoxLayout() + password_layout.addWidget(QLabel("密码:")) + self.password_input = QLineEdit() + self.password_input.setEchoMode(QLineEdit.Password) + password_layout.addWidget(self.password_input) + layout.addLayout(password_layout) + + # 按钮 + button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) + button_box.accepted.connect(self.accept) + button_box.rejected.connect(self.reject) + layout.addWidget(button_box) + + self.setLayout(layout) + + def get_password(self): + return self.password_input.text() + + class GunicornTab(QWidget): def __init__(self, parent=None): super().__init__(parent) self.parent = parent self.init_ui() + # 连接服务器切换信号 + if self.parent and hasattr(self.parent, 'server_changed'): + self.parent.server_changed.connect(self.on_server_changed) + logger.info("Gunicorn标签已连接到服务器切换信号") def init_ui(self): layout = QVBoxLayout() @@ -120,32 +153,130 @@ class GunicornTab(QWidget): 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) + """加载Gunicorn配置,使用config.json中的值""" + try: + if self.parent and hasattr(self.parent, 'get_current_config'): + config = self.parent.get_current_config() + if config: + django_path = config.get('django_path', '') + project_name = config.get('project_name', 'myproject') + username = config.get('username', 'www-data') + + # 设置Django项目路径 + self.django_path_input.setText(django_path) + + # 设置服务名称为项目名 + self.service_name_input.setText(project_name) + + # 生成服务文件内容 + service_content = self.generate_service_file_from_config(config) + self.service_editor.setText(service_content) + + logger.info(f"从当前服务器配置加载Gunicorn配置: django_path={django_path}, project_name={project_name}") + else: + logger.warning("未找到当前服务器配置") + else: + # 兼容旧的加载方式 + config_path = os.path.join(os.path.dirname(__file__), 'config.json') + with open(config_path, 'r', encoding='utf-8') as f: + config = json.load(f) + + if config and 'servers' in config and len(config['servers']) > 0: + server_config = config['servers'][0] + django_path = server_config.get('remote_directory', '') + project_name = server_config.get('project_name', 'myproject') + username = server_config.get('username', 'www-data') + + # 设置Django项目路径 + self.django_path_input.setText(django_path) + + # 设置服务名称为项目名 + self.service_name_input.setText(project_name) + + # 生成服务文件内容 + service_content = self.generate_service_file_from_config(server_config) + self.service_editor.setText(service_content) + + logger.info(f"从配置文件加载Gunicorn配置: django_path={django_path}, project_name={project_name}") + except Exception as e: + logger.error(f"加载Gunicorn配置失败: {str(e)}") + # 不显示警告,避免影响用户体验 - def generate_service_file(self, service_name, django_path, port, workers): + def generate_service_file_from_config(self, config): + """根据config.json配置生成服务文件内容""" + username = config.get('username', 'www-data') + project_name = config.get('project_name', 'myproject') + django_path = config.get('remote_directory', '/home/user') + + # 构建完整的项目路径 + project_path = f"{django_path.rstrip('/')}/{project_name}" + return f"""[Unit] -Description={service_name} daemon +Description=Gunicorn daemon for {project_name} 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 +User={username} +Group={username} +WorkingDirectory={project_path} +# 所有Gunicorn参数直接在这里配置 +ExecStart=/usr/local/bin/gunicorn \\ + --bind 127.0.0.1:8000 \\ + --workers $(nproc --all * 2 + 1) \\ + --worker-class sync \\ + --timeout 60 \\ + --name {project_name} \\ + --access-logfile {project_path}/logs/gunicorn_access.log \\ + --error-logfile {project_path}/logs/gunicorn_error.log \\ + --log-level info \\ + {project_name}.wsgi:application +Restart=on-failure +RestartSec=5s +PrivateTmp=true [Install] -WantedBy=multi-user.target -""" +WantedBy=multi-user.target""" + + def generate_service_file(self, service_name, django_path, port, workers): + """保持向后兼容的方法""" + # 获取config.json中的配置信息 + config = None + if self.parent and hasattr(self.parent, 'server_connection_tab'): + config = self.parent.server_connection_tab.get_current_config() + + if config: + return self.generate_service_file_from_config(config) + else: + # 如果没有config,使用默认值 + username = 'www-data' + project_name = service_name + project_path = f"{django_path.rstrip('/')}/{project_name}" + + return f"""[Unit] +Description=Gunicorn daemon for {project_name} +After=network.target + +[Service] +User={username} +Group={username} +WorkingDirectory={project_path} +# 所有Gunicorn参数直接在这里配置 +ExecStart=/usr/local/bin/gunicorn \\ + --bind 127.0.0.1:{port} \\ + --workers $(nproc --all * 2 + 1) \\ + --worker-class sync \\ + --timeout 60 \\ + --name {project_name} \\ + --access-logfile {project_path}/logs/gunicorn_access.log \\ + --error-logfile {project_path}/logs/gunicorn_error.log \\ + --log-level info \\ + {project_name}.wsgi:application +Restart=on-failure +RestartSec=5s +PrivateTmp=true + +[Install] +WantedBy=multi-user.target""" def check_ssh_connection(self): if not self.parent or not self.parent.ssh_client: @@ -153,6 +284,25 @@ WantedBy=multi-user.target return False return True + def get_password(self): + # 获取密码 + password = None + if self.parent and hasattr(self.parent, 'server_connection_tab'): + password = self.parent.server_connection_tab.password_input.text() + + # 如果密码为空,弹出密码输入对话框 + if not password: + dialog = PasswordDialog(self) + if dialog.exec_() == QDialog.Accepted: + password = dialog.get_password() + # 保存密码到服务器连接标签页 + if self.parent and hasattr(self.parent, 'server_connection_tab'): + self.parent.server_connection_tab.password_input.setText(password) + else: + return None + + return password + def install_gunicorn(self): if not self.check_ssh_connection(): return @@ -163,9 +313,11 @@ WantedBy=multi-user.target 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() + password = self.get_password() + if password is None: + self.install_gunicorn_btn.setEnabled(True) + self.progress_bar.setVisible(False) + return self.gunicorn_install_thread = GunicornInstallThread(self.parent.ssh_client, password) self.gunicorn_install_thread.progress_updated.connect(self.update_progress) @@ -218,20 +370,32 @@ WantedBy=multi-user.target if not self.check_ssh_connection(): return - service_name = self.service_name_input.text().strip() + # 获取config.json中的配置信息 + config = None + if self.parent and hasattr(self.parent, 'server_connection_tab'): + config = self.parent.server_connection_tab.get_current_config() + + if config: + project_name = config.get('project_name', 'django') + else: + project_name = 'django' + + # 使用gunicorn_[project_name].service格式作为服务名称 + service_name = f"gunicorn_{project_name}" service_content = self.service_editor.toPlainText() if not service_name or not service_content: - QMessageBox.warning(self, "警告", "请输入服务名称并编辑服务文件内容") + 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() + password = self.get_password() + if password is None: + self.upload_service_btn.setEnabled(True) + return self.upload_thread = UploadGunicornServiceThread(self.parent.ssh_client, service_name, service_content, password) self.upload_thread.result_ready.connect(self.on_upload_service_result) @@ -250,10 +414,18 @@ WantedBy=multi-user.target if not self.check_ssh_connection(): return - service_name = self.service_name_input.text().strip() - if not service_name: - QMessageBox.warning(self, "警告", "请输入服务名称") - return + # 获取config.json中的配置信息 + config = None + if self.parent and hasattr(self.parent, 'server_connection_tab'): + config = self.parent.server_connection_tab.get_current_config() + + if config: + project_name = config.get('project_name', 'django') + else: + project_name = 'django' + + # 使用gunicorn_[project_name].service格式作为服务名称 + service_name = f"gunicorn_{project_name}" self.output_text.append(f"正在执行服务 {action} 操作...") @@ -264,9 +436,11 @@ WantedBy=multi-user.target btn.setEnabled(False) # 获取密码 - password = None - if self.parent and hasattr(self.parent, 'server_connection_tab'): - password = self.parent.server_connection_tab.password_input.text() + password = self.get_password() + if password is None: + for btn in buttons: + btn.setEnabled(True) + return 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)) @@ -291,8 +465,17 @@ WantedBy=multi-user.target if not self.check_ssh_connection(): return - service_name = self.service_name_input.text().strip() - if not service_name: - return + # 获取config.json中的配置信息 + config = None + if self.parent and hasattr(self.parent, 'server_connection_tab'): + config = self.parent.server_connection_tab.get_current_config() + + if config: + project_name = config.get('project_name', 'django') + else: + project_name = 'django' + + # 使用gunicorn_[project_name].service格式作为服务名称 + service_name = f"gunicorn_{project_name}" self.manage_service("status") \ No newline at end of file diff --git a/main.py b/main.py index 7f5599a..b36d3a2 100644 --- a/main.py +++ b/main.py @@ -101,12 +101,7 @@ class MainWindow(QMainWindow): 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) + pass if __name__ == "__main__": diff --git a/remote_command_tab.py b/remote_command_tab.py index 9aee48b..5708cf1 100644 --- a/remote_command_tab.py +++ b/remote_command_tab.py @@ -1,4 +1,5 @@ import os +import json from loguru import logger from PySide6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton, QComboBox, QMessageBox, QTextEdit, @@ -6,7 +7,7 @@ from PySide6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineE from PySide6.QtCore import Qt from threads import (GitInstallThread, GitCloneThread, ListDirectoryThread, - DeleteDirectoryThread, SetTimezoneAndRestartThread, + SetTimezoneAndRestartThread, CheckFirewallThread, OpenPortThread) @@ -33,11 +34,6 @@ class RemoteCommandTab(QWidget): 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) @@ -50,10 +46,6 @@ class RemoteCommandTab(QWidget): 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) @@ -80,17 +72,6 @@ class RemoteCommandTab(QWidget): 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() @@ -106,15 +87,31 @@ class RemoteCommandTab(QWidget): layout.addStretch() self.setLayout(layout) - # 加载Git配置 + # 从配置文件加载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) + try: + # 从config.json文件读取配置 + config_path = os.path.join(os.path.dirname(__file__), 'config.json') + with open(config_path, 'r', encoding='utf-8') as f: + config = json.load(f) + + # 获取第一个服务器的配置 + if config and 'servers' in config and len(config['servers']) > 0: + server_config = config['servers'][0] + git_url = server_config.get('git_url', '') + project_path = server_config.get('remote_directory', '') + + self.git_url_input.setText(git_url) + self.project_path_input.setText(project_path) + + logger.info(f"从配置文件加载git配置: git_url={git_url}, project_path={project_path}") + else: + logger.warning("配置文件中未找到服务器配置") + except Exception as e: + logger.error(f"加载git配置失败: {str(e)}") + QMessageBox.warning(self, "警告", f"加载git配置失败: {str(e)}") def install_git(self): if not self.check_ssh_connection(): @@ -147,6 +144,22 @@ class RemoteCommandTab(QWidget): QMessageBox.warning(self, "警告", "请填写Git仓库URL和项目路径") return + # 从config.json获取django_path作为克隆目标路径 + try: + config_path = os.path.join(os.path.dirname(__file__), 'config.json') + with open(config_path, 'r', encoding='utf-8') as f: + config = json.load(f) + + if config and 'servers' in config and len(config['servers']) > 0: + server_config = config['servers'][0] + django_path = server_config.get('django_path', '') + + if django_path: + project_path = django_path + logger.info(f"使用django_path作为克隆目标路径: {django_path}") + except Exception as e: + logger.error(f"获取django_path失败: {str(e)}") + self.output_text.append(f"正在克隆 {git_url} 到 {project_path}...") self.clone_btn.setEnabled(False) @@ -183,42 +196,11 @@ class RemoteCommandTab(QWidget): self.list_dir_btn.setEnabled(True) if success: self.output_text.append(f"目录列表:\n{message}") - logger.info(f"目录列表成功") + logger.info(f"目录列表成功:\n{message}") 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 diff --git a/server_connection_tab.py b/server_connection_tab.py index 36ab8d5..97bc6ef 100644 --- a/server_connection_tab.py +++ b/server_connection_tab.py @@ -3,13 +3,16 @@ import os from loguru import logger from PySide6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton, QComboBox, QMessageBox) -from PySide6.QtCore import Qt +from PySide6.QtCore import Qt, Signal # 添加Signal导入 import paramiko from threads import SSHConnectionThread class ServerConnectionTab(QWidget): + # 添加服务器切换信号 + server_changed = Signal(dict) + def __init__(self): super().__init__() self.ssh_client = None @@ -154,6 +157,9 @@ class ServerConnectionTab(QWidget): 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", "")) + + # 发送服务器切换信号 + self.server_changed.emit(server) break def save_server_config(self): @@ -222,4 +228,20 @@ class ServerConnectionTab(QWidget): else: self.status_label.setText(f"连接失败: {message}") self.status_label.setStyleSheet("color: red;") - self.ssh_client = None \ No newline at end of file + self.ssh_client = None + + def get_current_config(self): + """获取当前选中的服务器配置""" + try: + alias = self.server_combo.currentText() + if not alias: + return None + + servers = self.config.get("servers", []) + for server in servers: + if server.get("alias") == alias: + return server + return None + except Exception as e: + logger.error(f"获取当前服务器配置失败: {e}") + return None \ No newline at end of file diff --git a/threads.py b/threads.py index 7507623..7e694e0 100644 --- a/threads.py +++ b/threads.py @@ -307,7 +307,7 @@ class DjangoInstallThread(QThread): self.progress_updated.emit(30) # 尝试使用pip安装 - stdin, stdout, stderr = self.ssh_client.exec_command("pip3 install django") + stdin, stdout, stderr = self.ssh_client.exec_command("pip3 install --break-system-packages django") exit_status = stdout.channel.recv_exit_status() if exit_status == 0: @@ -372,7 +372,7 @@ class DjangoTestThread(QThread): 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") + stdin, stdout, stderr = self.ssh_client.exec_command(f"cd {self.django_path} && pip3 install --break-system-packages -r requirements.txt") exit_status = stdout.channel.recv_exit_status() if exit_status != 0: @@ -384,7 +384,7 @@ class DjangoTestThread(QThread): 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 &") + stdin, stdout, stderr = self.ssh_client.exec_command(f"cd {self.django_path} && timeout 10 python3 manage.py runserver 0.0.0.0:8000 --noreload &") time.sleep(3) # 等待服务器启动 # 检查服务器是否运行 @@ -692,15 +692,23 @@ class GunicornTestThread(QThread): 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" + project_name = os.path.basename(self.django_path.rstrip('/')) + wsgi_path = f"{self.django_path.rstrip('/')}/{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 + # 尝试在Django项目根目录下查找wsgi.py文件 + stdin, stdout, stderr = self.ssh_client.exec_command(f"find {self.django_path} -name wsgi.py") + exit_status = stdout.channel.recv_exit_status() + + if exit_status == 0: + wsgi_path = stdout.read().decode().strip() + logger.info(f"找到wsgi.py文件: {wsgi_path}") + else: + self.result_ready.emit(False, f"wsgi.py文件不存在: {wsgi_path}") + logger.error(f"wsgi.py文件不存在: {wsgi_path}") + return self.progress_updated.emit(50) @@ -745,11 +753,15 @@ class UploadGunicornServiceThread(QThread): service_file = f"/etc/systemd/system/{self.service_name}.service" temp_file = f"/tmp/{self.service_name}.service" + logger.info(f"准备上传服务文件: {service_file}") + sftp = self.ssh_client.open_sftp() with sftp.file(temp_file, 'w') as f: f.write(self.service_content) + logger.info(f"临时服务文件创建成功: {temp_file}") + # 移动到systemd目录 if self.password: stdin, stdout, stderr = self.ssh_client.exec_command(f"sudo -S mv {temp_file} {service_file}") @@ -761,11 +773,13 @@ class UploadGunicornServiceThread(QThread): if exit_status != 0: error = stderr.read().decode() - self.result_ready.emit(False, f"服务文件移动失败: {error}") logger.error(f"服务文件移动失败: {error}") + self.result_ready.emit(False, f"服务文件移动失败: {error}") sftp.close() return + logger.info(f"服务文件移动成功: {service_file}") + # 设置权限 if self.password: stdin, stdout, stderr = self.ssh_client.exec_command(f"sudo -S chmod 644 {service_file}") @@ -777,8 +791,24 @@ class UploadGunicornServiceThread(QThread): if exit_status != 0: error = stderr.read().decode() - self.result_ready.emit(False, f"权限设置失败: {error}") logger.error(f"权限设置失败: {error}") + self.result_ready.emit(False, f"权限设置失败: {error}") + sftp.close() + return + + logger.info(f"服务文件权限设置成功: {service_file}") + + # 验证服务文件是否存在 + stdin, stdout, stderr = self.ssh_client.exec_command(f"ls -la {service_file}") + exit_status = stdout.channel.recv_exit_status() + + if exit_status == 0: + file_info = stdout.read().decode().strip() + logger.info(f"服务文件验证成功: {file_info}") + else: + error = stderr.read().decode() + logger.error(f"服务文件验证失败: {error}") + self.result_ready.emit(False, f"服务文件验证失败: {error}") sftp.close() return @@ -789,6 +819,27 @@ class UploadGunicornServiceThread(QThread): stdin.flush() else: stdin, stdout, stderr = self.ssh_client.exec_command("sudo systemctl daemon-reload") + exit_status = stdout.channel.recv_exit_status() + + if exit_status != 0: + error = stderr.read().decode() + logger.error(f"systemd重新加载失败: {error}") + self.result_ready.emit(False, f"systemd重新加载失败: {error}") + sftp.close() + return + + logger.info(f"systemd重新加载成功") + + # 验证服务是否被systemd识别 + stdin, stdout, stderr = self.ssh_client.exec_command(f"systemctl list-unit-files | grep {self.service_name}") + exit_status = stdout.channel.recv_exit_status() + + if exit_status == 0: + service_info = stdout.read().decode().strip() + logger.info(f"服务被systemd识别: {service_info}") + else: + error = stderr.read().decode() + logger.warning(f"服务未被systemd识别: {error}") sftp.close() @@ -797,8 +848,8 @@ class UploadGunicornServiceThread(QThread): except Exception as e: error_msg = str(e) - self.result_ready.emit(False, error_msg) logger.error(f"服务文件上传异常: {error_msg}") + self.result_ready.emit(False, error_msg) class ManageGunicornServiceThread(QThread): @@ -814,7 +865,28 @@ class ManageGunicornServiceThread(QThread): def run(self): try: # 构建systemd命令 - cmd = f"systemctl {self.action} {self.service_name}" + # 注意:systemd命令中不需要.service后缀 + service_name_for_systemd = self.service_name + if service_name_for_systemd.endswith('.service'): + service_name_for_systemd = service_name_for_systemd[:-8] # 移除.service后缀 + + cmd = f"systemctl {self.action} {service_name_for_systemd}" + + logger.info(f"执行服务管理命令: {cmd}") + + # 首先检查服务文件是否存在 + service_file = f"/etc/systemd/system/{self.service_name}.service" + stdin, stdout, stderr = self.ssh_client.exec_command(f"ls -la {service_file}") + exit_status = stdout.channel.recv_exit_status() + + if exit_status != 0: + error = stderr.read().decode() + logger.error(f"服务文件不存在: {service_file}, 错误: {error}") + self.result_ready.emit(False, f"服务文件不存在: {self.service_name}.service") + return + + file_info = stdout.read().decode().strip() + logger.info(f"服务文件存在: {file_info}") if self.action == "status": # 状态命令需要特殊处理 @@ -828,12 +900,12 @@ class ManageGunicornServiceThread(QThread): if exit_status == 0: output = stdout.read().decode() + logger.info(f"服务状态查询成功: {service_name_for_systemd}") 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}") + self.result_ready.emit(False, error) else: # 其他操作(start, stop, restart, enable, disable) if self.password: @@ -845,14 +917,14 @@ class ManageGunicornServiceThread(QThread): 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}") + logger.info(f"服务{self.action}成功: {service_name_for_systemd}") + self.result_ready.emit(True, f"服务{self.action}成功: {service_name_for_systemd}") else: error = stderr.read().decode() - self.result_ready.emit(False, error) logger.error(f"服务{self.action}失败: {error}") + self.result_ready.emit(False, error) except Exception as e: error_msg = str(e) - self.result_ready.emit(False, error_msg) - logger.error(f"服务管理异常: {error_msg}") \ No newline at end of file + logger.error(f"服务管理异常: {error_msg}") + self.result_ready.emit(False, error_msg) \ No newline at end of file