Gunicorn测试完成,里程碑是服务注册成功,服务器自启动的时候也能正常运行

This commit is contained in:
2025-08-31 19:55:23 +08:00
parent d20ddfed59
commit 7bd1764103
8 changed files with 4367 additions and 978 deletions

Binary file not shown.

4177
app.log

File diff suppressed because it is too large Load Diff

964
gunicorn_tab.py Normal file
View File

@@ -0,0 +1,964 @@
import os
import sys
import datetime
from PySide6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QPushButton,
QLabel, QTextEdit, QFileDialog, QMessageBox,
QLineEdit, QDialog, QDialogButtonBox)
from PySide6.QtCore import QThread, Signal
from loguru import logger
class PasswordDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("输入密码")
self.setMinimumWidth(300)
layout = QVBoxLayout()
# 提示标签
label = QLabel("请输入sudo密码:")
layout.addWidget(label)
# 密码输入框
self.password_input = QLineEdit()
self.password_input.setEchoMode(QLineEdit.Password)
layout.addWidget(self.password_input)
# 按钮
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 GunicornInstallThread(QThread):
"""安装Gunicorn的线程"""
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是否已安装
logger.info("检查Gunicorn是否已安装")
stdin, stdout, stderr = self.ssh_client.exec_command("gunicorn --version")
exit_status = stdout.channel.recv_exit_status()
gunicorn_version = stdout.read().decode().strip()
version_error = stderr.read().decode()
logger.info(f"Gunicorn版本检查状态: {exit_status}")
logger.info(f"Gunicorn版本信息: {gunicorn_version}")
if version_error:
logger.error(f"Gunicorn版本检查错误: {version_error}")
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安装
logger.info("开始使用pip安装Gunicorn")
stdin, stdout, stderr = self.ssh_client.exec_command("pip3 install gunicorn")
exit_status = stdout.channel.recv_exit_status()
install_output = stdout.read().decode()
install_error = stderr.read().decode()
logger.info(f"Gunicorn pip安装命令执行状态: {exit_status}")
logger.info(f"Gunicorn pip安装输出: {install_output}")
if install_error:
logger.error(f"Gunicorn pip安装错误: {install_error}")
if exit_status == 0:
self.progress_updated.emit(90)
# 验证安装
logger.info("验证Gunicorn安装")
stdin, stdout, stderr = self.ssh_client.exec_command("gunicorn --version")
version_exit_status = stdout.channel.recv_exit_status()
gunicorn_version = stdout.read().decode().strip()
version_error = stderr.read().decode()
logger.info(f"Gunicorn版本检查状态: {version_exit_status}")
logger.info(f"Gunicorn版本信息: {gunicorn_version}")
if version_error:
logger.error(f"Gunicorn版本检查错误: {version_error}")
if gunicorn_version:
self.result_ready.emit(True, f"Gunicorn安装成功: {gunicorn_version}")
logger.info(f"Gunicorn安装成功: {gunicorn_version}")
else:
self.result_ready.emit(False, "Gunicorn安装后无法获取版本信息")
logger.error("Gunicorn安装后无法获取版本信息")
return
self.progress_updated.emit(50)
# 如果pip安装失败尝试使用apt安装
logger.info("pip安装失败尝试使用apt安装Gunicorn")
if self.password:
logger.info("使用密码进行sudo apt安装")
# 使用bash -c将命令组合在一起确保密码对所有sudo命令有效
stdin, stdout, stderr = self.ssh_client.exec_command(f"bash -c 'echo \"{self.password}\" | sudo -S apt update && echo \"{self.password}\" | sudo -S apt install -y gunicorn'")
else:
logger.info("无密码进行sudo apt安装")
stdin, stdout, stderr = self.ssh_client.exec_command("sudo apt update && sudo apt install -y gunicorn")
exit_status = stdout.channel.recv_exit_status()
apt_output = stdout.read().decode()
apt_error = stderr.read().decode()
logger.info(f"Gunicorn apt安装命令执行状态: {exit_status}")
logger.info(f"Gunicorn apt安装输出: {apt_output}")
if apt_error:
logger.error(f"Gunicorn apt安装错误: {apt_error}")
if exit_status == 0:
self.progress_updated.emit(90)
# 验证安装
logger.info("验证apt安装的Gunicorn")
stdin, stdout, stderr = self.ssh_client.exec_command("gunicorn --version")
version_exit_status = stdout.channel.recv_exit_status()
gunicorn_version = stdout.read().decode().strip()
version_error = stderr.read().decode()
logger.info(f"Gunicorn版本检查状态: {version_exit_status}")
logger.info(f"Gunicorn版本信息: {gunicorn_version}")
if version_error:
logger.error(f"Gunicorn版本检查错误: {version_error}")
if gunicorn_version:
self.result_ready.emit(True, f"Gunicorn安装成功: {gunicorn_version}")
logger.info(f"Gunicorn安装成功: {gunicorn_version}")
else:
self.result_ready.emit(False, "Gunicorn安装后无法获取版本信息")
logger.error("Gunicorn安装后无法获取版本信息")
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):
"""测试Gunicorn的线程"""
result_ready = Signal(bool, str)
def __init__(self, ssh_client, project_name, django_path, password):
super().__init__()
self.ssh_client = ssh_client
self.project_name = project_name
self.django_path = django_path
self.password = password
def run(self):
try:
logger.info(f"开始测试Gunicorn使用的Django路径: {self.django_path}, 项目名: {self.project_name}")
# 首先检查项目目录结构
logger.info("检查项目目录结构...")
list_command = f"ls -la {self.django_path}{self.project_name}"
stdin, stdout, stderr = self.ssh_client.exec_command(list_command)
dir_content = stdout.read().decode()
dir_error = stderr.read().decode()
logger.info(f"项目目录内容: {dir_content}")
if dir_error:
logger.error(f"列出目录内容错误: {dir_error}")
# 检查是否存在manage.py文件这通常位于Django项目的根目录
manage_check = f"find {self.django_path} -name manage.py"
stdin, stdout, stderr = self.ssh_client.exec_command(manage_check)
manage_files = stdout.read().decode()
manage_error = stderr.read().decode()
logger.info(f"找到的manage.py文件: {manage_files}")
if manage_error:
logger.error(f"查找manage.py文件错误: {manage_error}")
# 如果找到manage.py文件检查其所在目录
if manage_files.strip():
manage_path = manage_files.strip().split('\n')[0]
manage_dir = manage_path.rsplit('/', 1)[0] # 获取manage.py所在的目录
logger.info(f"manage.py所在目录: {manage_dir}")
# 检查该目录下的内容
list_manage_dir = f"ls -la {manage_dir}"
stdin, stdout, stderr = self.ssh_client.exec_command(list_manage_dir)
manage_dir_content = stdout.read().decode()
manage_dir_error = stderr.read().decode()
logger.info(f"manage.py所在目录内容: {manage_dir_content}")
if manage_dir_error:
logger.error(f"列出manage.py所在目录内容错误: {manage_dir_error}")
# 检查是否存在wsgi.py文件
wsgi_check = f"find {self.django_path} -name wsgi.py"
stdin, stdout, stderr = self.ssh_client.exec_command(wsgi_check)
wsgi_files = stdout.read().decode()
wsgi_error = stderr.read().decode()
logger.info(f"找到的wsgi.py文件: {wsgi_files}")
if wsgi_error:
logger.error(f"查找wsgi.py文件错误: {wsgi_error}")
# 检查settings.py文件特别是INSTALLED_APPS配置
settings_check = f"find {self.django_path} -name settings.py"
stdin, stdout, stderr = self.ssh_client.exec_command(settings_check)
settings_files = stdout.read().decode()
settings_error = stderr.read().decode()
logger.info(f"找到的settings.py文件: {settings_files}")
if settings_error:
logger.error(f"查找settings.py文件错误: {settings_error}")
# 如果找到settings.py文件检查其内容
if settings_files.strip():
settings_path = settings_files.strip().split('\n')[0]
cat_settings = f"cat {settings_path}"
stdin, stdout, stderr = self.ssh_client.exec_command(cat_settings)
settings_content = stdout.read().decode()
settings_content_error = stderr.read().decode()
logger.info(f"settings.py文件内容: {settings_content[:500]}...") # 只显示前500个字符避免日志过长
if settings_content_error:
logger.error(f"读取settings.py文件错误: {settings_content_error}")
# 测试运行Gunicorn
# 尝试使用不同的路径来运行Gunicorn
# 首先尝试使用manage.py所在的目录作为工作目录
if manage_files.strip():
manage_path = manage_files.strip().split('\n')[0]
manage_dir = manage_path.rsplit('/', 1)[0] # 获取manage.py所在的目录
logger.info(f"尝试使用manage.py所在目录作为工作目录: {manage_dir}")
# 检查manage_dir中是否有与项目同名的子目录
project_subdir = f"{manage_dir}/{self.project_name}"
check_subdir = f"ls -la {project_subdir}"
stdin, stdout, stderr = self.ssh_client.exec_command(check_subdir)
subdir_content = stdout.read().decode()
subdir_error = stderr.read().decode()
if not subdir_error and "wsgi.py" in subdir_content:
logger.info(f"找到项目子目录尝试使用该目录运行Gunicorn: {project_subdir}")
command = f"cd {manage_dir} && bash -c 'echo \"{self.password}\" | sudo -S gunicorn --pythonpath {manage_dir} {self.project_name}.wsgi:application --bind 0.0.0.0:8000' &"
else:
logger.info(f"未找到项目子目录尝试使用Django路径运行Gunicorn")
# 使用Django路径作为工作目录但项目模块在子目录中
command = f"cd {self.django_path} && bash -c 'echo \"{self.password}\" | sudo -S gunicorn --pythonpath {self.django_path} {self.project_name}.wsgi:application --bind 0.0.0.0:8000' &"
else:
logger.info(f"未找到manage.py文件尝试使用原始路径运行Gunicorn")
# 使用Django路径作为工作目录但项目模块在子目录中
command = f"cd {self.django_path} && bash -c 'echo \"{self.password}\" | sudo -S gunicorn --pythonpath {self.django_path} {self.project_name}.wsgi:application --bind 0.0.0.0:8000' &"
logger.info(f"执行Gunicorn测试命令: {command}")
stdin, stdout, stderr = self.ssh_client.exec_command(command)
# 记录Gunicorn启动命令的输出和错误
start_output = stdout.read().decode()
start_error = stderr.read().decode()
logger.info(f"Gunicorn启动输出: {start_output}")
if start_error:
logger.error(f"Gunicorn启动错误: {start_error}")
# 等待一段时间让Gunicorn启动
logger.info("等待Gunicorn启动...")
self.msleep(3000)
# 检查Gunicorn进程是否在运行
logger.info("检查Gunicorn进程状态...")
stdin, stdout, stderr = self.ssh_client.exec_command("ps aux | grep gunicorn")
processes = stdout.read().decode()
logger.info(f"Gunicorn进程检查结果: {processes}")
if self.project_name in processes:
self.result_ready.emit(True, "Gunicorn测试运行成功")
logger.info("Gunicorn测试运行成功")
# 停止Gunicorn进程
logger.info("停止Gunicorn进程...")
stdin, stdout, stderr = self.ssh_client.exec_command("pkill -f gunicorn")
stop_result = stdout.read().decode()
stop_error = stderr.read().decode()
logger.info(f"停止Gunicorn进程结果: {stop_result}")
if stop_error:
logger.error(f"停止Gunicorn进程错误: {stop_error}")
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 GunicornServiceUploadThread(QThread):
"""上传Gunicorn服务文件的线程"""
result_ready = Signal(bool, str)
def __init__(self, ssh_client, service_content, service_name, password):
super().__init__()
self.ssh_client = ssh_client
self.service_content = service_content
self.service_name = service_name
self.password = password
def run(self):
try:
# 创建临时文件
temp_file = f"/tmp/{self.service_name}"
sftp = self.ssh_client.open_sftp()
with sftp.file(temp_file, 'w') as f:
f.write(self.service_content)
# 移动到目标位置
stdin, stdout, stderr = self.ssh_client.exec_command(f"bash -c 'echo \"{self.password}\" | sudo -S mv {temp_file} /etc/systemd/system/{self.service_name}'")
exit_status = stdout.channel.recv_exit_status()
if exit_status == 0:
self.result_ready.emit(True, f"Gunicorn服务文件上传成功: {self.service_name}")
logger.info(f"Gunicorn服务文件上传成功: {self.service_name}")
else:
error = stderr.read().decode()
self.result_ready.emit(False, f"Gunicorn服务文件上传失败: {error}")
logger.error(f"Gunicorn服务文件上传失败: {error}")
sftp.close()
except Exception as e:
error_msg = str(e)
self.result_ready.emit(False, error_msg)
logger.error(f"Gunicorn服务文件上传异常: {error_msg}")
class GunicornServiceControlThread(QThread):
"""控制Gunicorn服务的线程"""
result_ready = Signal(bool, str)
def __init__(self, ssh_client, service_name, password, action):
super().__init__()
self.ssh_client = ssh_client
self.service_name = service_name
self.password = password
self.action = action # "daemon-reload", "start", "enable"
def run(self):
try:
if self.action == "daemon-reload":
command = f"bash -c 'echo \"{self.password}\" | sudo -S systemctl daemon-reload'"
success_msg = "系统服务配置重新加载成功"
error_msg = "系统服务配置重新加载失败"
elif self.action == "start":
command = f"bash -c 'echo \"{self.password}\" | sudo -S systemctl start {self.service_name}'"
success_msg = f"Gunicorn服务启动成功: {self.service_name}"
error_msg = f"Gunicorn服务启动失败: {self.service_name}"
elif self.action == "enable":
command = f"bash -c 'echo \"{self.password}\" | sudo -S systemctl enable {self.service_name}'"
success_msg = f"Gunicorn服务设置开机自启动成功: {self.service_name}"
error_msg = f"Gunicorn服务设置开机自启动失败: {self.service_name}"
elif self.action == "restart":
command = f"bash -c 'echo \"{self.password}\" | sudo -S systemctl restart {self.service_name}'"
success_msg = f"Gunicorn服务重启成功: {self.service_name}"
error_msg = f"Gunicorn服务重启失败: {self.service_name}"
elif self.action == "status":
command = f"bash -c 'echo \"{self.password}\" | sudo -S systemctl status {self.service_name}'"
success_msg = f"Gunicorn服务状态查询成功: {self.service_name}"
error_msg = f"Gunicorn服务状态查询失败: {self.service_name}"
else:
self.result_ready.emit(False, "未知的操作")
logger.error("未知的Gunicorn服务操作")
return
stdin, stdout, stderr = self.ssh_client.exec_command(command)
exit_status = stdout.channel.recv_exit_status()
# 对于status操作即使exit_status不为0我们也需要获取输出
output = stdout.read().decode()
error = stderr.read().decode()
if self.action == "status":
# 对于status操作我们将输出作为结果返回无论exit_status如何
if output:
self.result_ready.emit(True, f"{success_msg}\n{output}")
logger.info(f"{success_msg}\n{output}")
else:
self.result_ready.emit(False, f"{error_msg}: {error}")
logger.error(f"{error_msg}: {error}")
elif exit_status == 0:
self.result_ready.emit(True, success_msg)
logger.info(success_msg)
else:
self.result_ready.emit(False, f"{error_msg}: {error}")
logger.error(f"{error_msg}: {error}")
except Exception as e:
error_msg = str(e)
self.result_ready.emit(False, error_msg)
logger.error(f"Gunicorn服务控制异常: {error_msg}")
class ServerControlThread(QThread):
"""控制服务器设置的线程"""
result_ready = Signal(bool, str)
def __init__(self, ssh_client, password):
super().__init__()
self.ssh_client = ssh_client
self.password = password
def run(self):
try:
# 设置时区,使用-S选项从标准输入读取密码
logger.info("开始设置服务器时区为Asia/Shanghai")
stdin, stdout, stderr = self.ssh_client.exec_command(f"bash -c 'echo \"{self.password}\" | sudo -S 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
# 重启服务器,使用-S选项从标准输入读取密码
logger.info("开始重启服务器")
stdin, stdout, stderr = self.ssh_client.exec_command(f"bash -c 'echo \"{self.password}\" | sudo -S 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 GunicornCommandThread(QThread):
"""执行Gunicorn命令的线程"""
result_ready = Signal(bool, str)
def __init__(self, ssh_client, command, password, django_path="", project_name=""):
super().__init__()
self.ssh_client = ssh_client
self.command = command
self.password = password
self.django_path = django_path
self.project_name = project_name
def run(self):
try:
logger.info(f"开始执行Gunicorn命令: {self.command}")
# 如果有django_path则切换到该目录执行命令
if self.django_path:
# 检查命令中是否已经包含--pythonpath参数
if "--pythonpath" not in self.command:
# 如果没有--pythonpath参数则添加
if "gunicorn" in self.command:
# 在gunicorn命令后添加--pythonpath参数
modified_command = self.command.replace("gunicorn", f"gunicorn --pythonpath {self.django_path}", 1)
logger.info(f"添加--pythonpath参数后的命令: {modified_command}")
self.command = modified_command
# 切换到django_path目录执行命令
full_command = f"cd {self.django_path} && bash -c 'echo \"{self.password}\" | sudo -S {self.command}'"
logger.info(f"在目录 {self.django_path} 中执行命令: {full_command}")
else:
# 如果没有django_path则直接执行命令
full_command = f"bash -c 'echo \"{self.password}\" | sudo -S {self.command}'"
logger.info(f"直接执行命令: {full_command}")
# 执行命令
stdin, stdout, stderr = self.ssh_client.exec_command(full_command)
exit_status = stdout.channel.recv_exit_status()
output = stdout.read().decode()
error = stderr.read().decode()
if exit_status == 0:
self.result_ready.emit(True, f"命令执行成功\n{output}")
logger.info(f"Gunicorn命令执行成功: {output}")
else:
self.result_ready.emit(False, f"命令执行失败\n{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 GunicornTab(QWidget):
def __init__(self):
super().__init__()
self.ssh_client = None
self.username = ""
self.project_name = ""
self.django_path = ""
self.init_ui()
def init_ui(self):
layout = QVBoxLayout()
# Gunicorn管理区域
manage_layout = QHBoxLayout()
# 安装Gunicorn按钮
self.install_gunicorn_btn = QPushButton("安装Gunicorn")
self.install_gunicorn_btn.clicked.connect(self.install_gunicorn)
manage_layout.addWidget(self.install_gunicorn_btn)
# 测试运行按钮
self.test_gunicorn_btn = QPushButton("测试运行")
self.test_gunicorn_btn.clicked.connect(self.test_gunicorn)
manage_layout.addWidget(self.test_gunicorn_btn)
layout.addLayout(manage_layout)
# 服务文件编辑区域
service_layout = QVBoxLayout()
service_layout.addWidget(QLabel("Gunicorn服务文件编辑器:"))
# 服务文件编辑文本框
self.service_editor = QTextEdit()
self.service_editor.setReadOnly(False)
service_layout.addWidget(self.service_editor)
# 服务文件操作按钮
service_btn_layout = QHBoxLayout()
# 上传服务文件按钮
self.upload_service_btn = QPushButton("上传服务文件")
self.upload_service_btn.clicked.connect(self.upload_service)
service_btn_layout.addWidget(self.upload_service_btn)
# 查看服务状态按钮
self.check_status_btn = QPushButton("查看服务状态")
self.check_status_btn.clicked.connect(self.check_service_status)
service_btn_layout.addWidget(self.check_status_btn)
service_layout.addLayout(service_btn_layout)
layout.addLayout(service_layout)
# Gunicorn命令编辑区域
command_layout = QVBoxLayout()
command_layout.addWidget(QLabel("Gunicorn命令编辑器:"))
# 命令编辑文本框
self.command_editor = QTextEdit()
self.command_editor.setReadOnly(False)
self.command_editor.setPlainText("gunicorn --workers 3 --bind 0.0.0.0:8000 myproject.wsgi:application")
command_layout.addWidget(self.command_editor)
# 命令执行按钮
command_btn_layout = QHBoxLayout()
# 运行命令按钮
self.run_command_btn = QPushButton("运行以上命令")
self.run_command_btn.clicked.connect(self.run_gunicorn_command)
command_btn_layout.addWidget(self.run_command_btn)
command_layout.addLayout(command_btn_layout)
layout.addLayout(command_layout)
# 服务器控制区域
server_control_layout = QHBoxLayout()
# 设置时区并重启按钮
self.set_timezone_btn = QPushButton("设置时区并重启")
self.set_timezone_btn.clicked.connect(self.set_timezone_and_reboot)
server_control_layout.addWidget(self.set_timezone_btn)
layout.addLayout(server_control_layout)
# 输出区域
self.output_text = QTextEdit()
self.output_text.setReadOnly(True)
layout.addWidget(self.output_text)
self.setLayout(layout)
# 初始化服务文件内容
self.init_service_content()
def init_service_content(self):
"""初始化服务文件内容"""
default_content = "[Unit]\n"
default_content += "Description=Gunicorn daemon for myproject\n"
default_content += "After=network.target\n\n"
default_content += "[Service]\n"
default_content += "User=【用户名】\n"
default_content += "Group=【用户名】\n"
default_content += "WorkingDirectory=【Django路径】\n"
default_content += "# 所有Gunicorn参数直接在这里配置\n"
default_content += "ExecStart=/usr/bin/gunicorn \\ \n"
default_content += " --pythonpath 【Django路径】 \\ \n"
default_content += " --bind 127.0.0.1:8000 \\ \n"
default_content += " --workers $(nproc) \\ \n"
default_content += " --worker-class sync \\ \n"
default_content += " --timeout 60 \\ \n"
default_content += " --name 【项目名】 \\ \n"
default_content += " --access-logfile 【Django路径】/logs/gunicorn_access.log \\ \n"
default_content += " --error-logfile 【Django路径】/logs/gunicorn_error.log \\ \n"
default_content += " --log-level info \\ \n"
default_content += " 【项目名】.wsgi:application\n"
default_content += "Restart=on-failure\n"
default_content += "RestartSec=5s\n"
default_content += "PrivateTmp=true\n\n"
default_content += "[Install]\n"
default_content += "WantedBy=multi-user.target"
self.service_editor.setPlainText(default_content)
def set_ssh_client(self, ssh_client):
"""设置SSH客户端"""
self.ssh_client = ssh_client
logger.info("Gunicorn标签页已设置SSH客户端")
def set_username(self, username):
"""设置用户名"""
self.username = username
logger.info(f"Gunicorn标签页已设置用户名: {username}")
def set_project_info(self, project_name, django_path):
"""设置项目信息"""
self.project_name = project_name
self.django_path = django_path
logger.info(f"Gunicorn标签页已设置项目信息: {project_name}, {django_path}")
# 更新服务文件内容
self.update_service_content()
# 更新命令编辑器中的项目名称
self.update_command_editor()
def update_service_content(self):
"""更新服务文件内容"""
content = self.service_editor.toPlainText()
# 替换占位符
content = content.replace("【用户名】", self.username)
content = content.replace("【项目名】", self.project_name)
content = content.replace("【Django路径】", self.django_path.rstrip('/'))
self.service_editor.setPlainText(content)
def update_command_editor(self):
"""更新命令编辑器中的项目名称"""
command_text = self.command_editor.toPlainText()
# 替换项目名称
command_text = command_text.replace("myproject.wsgi:application", f"{self.project_name}.wsgi:application")
self.command_editor.setPlainText(command_text)
logger.info(f"Gunicorn命令编辑器已更新项目名称: {self.project_name}")
def append_output(self, text):
"""添加输出到文本框"""
self.output_text.append(text)
def install_gunicorn(self):
"""安装Gunicorn"""
if not self.ssh_client:
self.append_output("错误: 未连接到服务器")
return
# 请求用户输入sudo密码
dialog = PasswordDialog(self)
if dialog.exec_() == QDialog.Accepted:
password = dialog.get_password()
self.append_output("正在安装Gunicorn...")
# 创建并启动Gunicorn安装线程
self.install_thread = GunicornInstallThread(self.ssh_client, password)
self.install_thread.result_ready.connect(self.on_install_result)
self.install_thread.progress_updated.connect(self.on_install_progress)
self.install_thread.start()
else:
self.append_output("用户取消了密码输入")
def on_install_progress(self, progress):
"""处理安装进度更新"""
self.append_output(f"安装进度: {progress}%")
logger.info(f"Gunicorn安装进度: {progress}%")
def on_install_result(self, success, message):
"""处理安装结果"""
if success:
self.append_output(f"安装成功: {message}")
logger.info(f"Gunicorn安装成功: {message}")
QMessageBox.information(self, "成功", message)
else:
self.append_output(f"安装失败: {message}")
logger.error(f"Gunicorn安装失败: {message}")
QMessageBox.warning(self, "错误", f"Gunicorn安装失败: {message}")
def test_gunicorn(self):
"""测试运行Gunicorn"""
if not self.ssh_client:
self.append_output("错误: 未连接到服务器")
return
if not self.project_name or not self.django_path:
self.append_output("错误: 未设置项目信息")
return
# 请求用户输入sudo密码
dialog = PasswordDialog(self)
if dialog.exec_() == QDialog.Accepted:
password = dialog.get_password()
self.append_output("正在测试运行Gunicorn...")
# 创建并启动Gunicorn测试线程
self.test_thread = GunicornTestThread(self.ssh_client, self.project_name, self.django_path, password)
self.test_thread.result_ready.connect(self.on_test_result)
self.test_thread.start()
else:
self.append_output("用户取消了密码输入")
def on_test_result(self, success, message):
"""处理测试结果"""
if success:
self.append_output(f"测试成功: {message}")
logger.info(f"Gunicorn测试成功: {message}")
QMessageBox.information(self, "成功", message)
else:
self.append_output(f"测试失败: {message}")
logger.error(f"Gunicorn测试失败: {message}")
QMessageBox.warning(self, "错误", f"Gunicorn测试失败: {message}")
def upload_service(self):
"""上传服务文件"""
if not self.ssh_client:
self.append_output("错误: 未连接到服务器")
return
if not self.project_name:
self.append_output("错误: 未设置项目名")
return
service_content = self.service_editor.toPlainText()
service_name = f"gunicorn_{self.project_name}.service"
# 请求用户输入sudo密码
dialog = PasswordDialog(self)
if dialog.exec_() == QDialog.Accepted:
password = dialog.get_password()
self.append_output(f"正在上传服务文件: {service_name}...")
# 创建并启动服务文件上传线程
self.upload_thread = GunicornServiceUploadThread(self.ssh_client, service_content, service_name, password)
self.upload_thread.result_ready.connect(self.on_upload_result)
self.upload_thread.start()
else:
self.append_output("用户取消了密码输入")
def on_upload_result(self, success, message):
"""处理上传结果"""
if success:
self.append_output(f"上传成功: {message}")
logger.info(f"Gunicorn服务文件上传成功: {message}")
QMessageBox.information(self, "成功", message)
else:
self.append_output(f"上传失败: {message}")
logger.error(f"Gunicorn服务文件上传失败: {message}")
QMessageBox.warning(self, "错误", f"Gunicorn服务文件上传失败: {message}")
def reload_daemon(self):
"""重新加载系统服务配置"""
if not self.ssh_client:
self.append_output("错误: 未连接到服务器")
return
# 请求用户输入sudo密码
dialog = PasswordDialog(self)
if dialog.exec_() == QDialog.Accepted:
password = dialog.get_password()
self.append_output("正在重新加载系统服务配置...")
# 创建并启动服务控制线程
self.control_thread = GunicornServiceControlThread(self.ssh_client, "", password, "daemon-reload")
self.control_thread.result_ready.connect(self.on_control_result)
self.control_thread.start()
else:
self.append_output("用户取消了密码输入")
def start_service(self):
"""启动Gunicorn服务"""
if not self.ssh_client:
self.append_output("错误: 未连接到服务器")
return
if not self.project_name:
self.append_output("错误: 未设置项目名")
return
service_name = f"gunicorn_{self.project_name}"
# 请求用户输入sudo密码
dialog = PasswordDialog(self)
if dialog.exec_() == QDialog.Accepted:
password = dialog.get_password()
self.append_output(f"正在启动Gunicorn服务: {service_name}...")
# 创建并启动服务控制线程
self.control_thread = GunicornServiceControlThread(self.ssh_client, service_name, password, "start")
self.control_thread.result_ready.connect(self.on_control_result)
self.control_thread.start()
else:
self.append_output("用户取消了密码输入")
def enable_service(self):
"""设置开机自启动"""
if not self.ssh_client:
self.append_output("错误: 未连接到服务器")
return
if not self.project_name:
self.append_output("错误: 未设置项目名")
return
service_name = f"gunicorn_{self.project_name}"
# 请求用户输入sudo密码
dialog = PasswordDialog(self)
if dialog.exec_() == QDialog.Accepted:
password = dialog.get_password()
self.append_output(f"正在设置Gunicorn服务开机自启动: {service_name}...")
# 创建并启动服务控制线程
self.control_thread = GunicornServiceControlThread(self.ssh_client, service_name, password, "enable")
self.control_thread.result_ready.connect(self.on_control_result)
self.control_thread.start()
else:
self.append_output("用户取消了密码输入")
def restart_service(self):
"""重启Gunicorn服务"""
if not self.ssh_client:
self.append_output("错误: 未连接到服务器")
return
if not self.project_name:
self.append_output("错误: 未设置项目名")
return
service_name = f"gunicorn_{self.project_name}"
# 请求用户输入sudo密码
dialog = PasswordDialog(self)
if dialog.exec_() == QDialog.Accepted:
password = dialog.get_password()
self.append_output(f"正在重启Gunicorn服务: {service_name}...")
# 创建并启动服务控制线程
self.control_thread = GunicornServiceControlThread(self.ssh_client, service_name, password, "restart")
self.control_thread.result_ready.connect(self.on_control_result)
self.control_thread.start()
else:
self.append_output("用户取消了密码输入")
def check_service_status(self):
"""查看Gunicorn服务状态"""
if not self.ssh_client:
self.append_output("错误: 未连接到服务器")
return
if not self.project_name:
self.append_output("错误: 未设置项目名")
return
service_name = f"gunicorn_{self.project_name}"
# 请求用户输入sudo密码
dialog = PasswordDialog(self)
if dialog.exec_() == QDialog.Accepted:
password = dialog.get_password()
self.append_output(f"正在查看Gunicorn服务状态: {service_name}...")
# 创建并启动服务控制线程
self.control_thread = GunicornServiceControlThread(self.ssh_client, service_name, password, "status")
self.control_thread.result_ready.connect(self.on_control_result)
self.control_thread.start()
else:
self.append_output("用户取消了密码输入")
def on_control_result(self, success, message):
"""处理控制结果"""
if success:
self.append_output(f"操作成功: {message}")
logger.info(f"Gunicorn服务控制成功: {message}")
QMessageBox.information(self, "成功", message)
else:
self.append_output(f"操作失败: {message}")
logger.error(f"Gunicorn服务控制失败: {message}")
QMessageBox.warning(self, "错误", f"Gunicorn服务控制失败: {message}")
def set_timezone_and_reboot(self):
"""设置时区并重启服务器"""
if not self.ssh_client:
self.append_output("错误: 未连接到服务器")
return
# 请求用户输入sudo密码
dialog = PasswordDialog(self)
if dialog.exec_() == QDialog.Accepted:
password = dialog.get_password()
self.append_output("正在设置时区并重启服务器...")
# 创建并启动服务器控制线程
self.server_control_thread = ServerControlThread(self.ssh_client, password)
self.server_control_thread.result_ready.connect(self.on_server_control_result)
self.server_control_thread.start()
else:
self.append_output("用户取消了密码输入")
def on_server_control_result(self, success, message):
"""处理服务器控制结果"""
if success:
self.append_output(f"操作成功: {message}")
logger.info(f"服务器控制成功: {message}")
QMessageBox.information(self, "成功", message)
else:
self.append_output(f"操作失败: {message}")
logger.error(f"服务器控制失败: {message}")
QMessageBox.warning(self, "错误", f"服务器控制失败: {message}")
def run_gunicorn_command(self):
"""运行Gunicorn命令"""
if not self.ssh_client:
self.append_output("错误: 未连接到服务器")
return
command = self.command_editor.toPlainText().strip()
if not command:
self.append_output("错误: 命令不能为空")
return
# 请求用户输入sudo密码
dialog = PasswordDialog(self)
if dialog.exec_() == QDialog.Accepted:
password = dialog.get_password()
self.append_output(f"正在执行命令: {command}...")
# 创建并启动命令执行线程传递django_path和project_name参数
self.command_thread = GunicornCommandThread(self.ssh_client, command, password, self.django_path, self.project_name)
self.command_thread.result_ready.connect(self.on_command_result)
self.command_thread.start()
else:
self.append_output("用户取消了密码输入")
def on_command_result(self, success, message):
"""处理命令执行结果"""
if success:
self.append_output(f"命令执行成功: {message}")
logger.info(f"Gunicorn命令执行成功: {message}")
QMessageBox.information(self, "成功", message)
else:
self.append_output(f"命令执行失败: {message}")
logger.error(f"Gunicorn命令执行失败: {message}")
QMessageBox.warning(self, "错误", f"Gunicorn命令执行失败: {message}")

95
main.py
View File

@@ -1,11 +1,13 @@
import sys import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QTabWidget import os
from PySide6.QtWidgets import QApplication, QMainWindow, QTabWidget, QStatusBar
from PySide6.QtCore import QSize from PySide6.QtCore import QSize
from loguru import logger from loguru import logger
from server_connection_tab import ServerConnectionTab from server_connection_tab import ServerConnectionTab
from remote_commands_tab import RemoteCommandsTab from remote_commands_tab import RemoteCommandsTab
from django_tab import DjangoTab from django_tab import DjangoTab
from gunicorn_tab import GunicornTab
class MainWindow(QMainWindow): class MainWindow(QMainWindow):
def __init__(self): def __init__(self):
@@ -19,6 +21,15 @@ class MainWindow(QMainWindow):
self.tabs = QTabWidget() self.tabs = QTabWidget()
self.setCentralWidget(self.tabs) self.setCentralWidget(self.tabs)
# 创建状态栏
self.status_bar = QStatusBar()
self.setStatusBar(self.status_bar)
# 显示当前工作目录路径
current_dir = os.getcwd()
self.status_bar.showMessage(f"当前目录: {current_dir}")
logger.info(f"设置状态栏显示当前目录: {current_dir}")
# 添加服务器连接标签页 # 添加服务器连接标签页
self.server_connection_tab = ServerConnectionTab() self.server_connection_tab = ServerConnectionTab()
self.tabs.addTab(self.server_connection_tab, "服务器连接") self.tabs.addTab(self.server_connection_tab, "服务器连接")
@@ -31,6 +42,10 @@ class MainWindow(QMainWindow):
self.django_tab = DjangoTab() self.django_tab = DjangoTab()
self.tabs.addTab(self.django_tab, "Django") self.tabs.addTab(self.django_tab, "Django")
# 添加Gunicorn管理标签页
self.gunicorn_tab = GunicornTab()
self.tabs.addTab(self.gunicorn_tab, "Gunicorn")
# 连接标签页切换信号 # 连接标签页切换信号
self.tabs.currentChanged.connect(self.on_tab_changed) self.tabs.currentChanged.connect(self.on_tab_changed)
@@ -39,8 +54,14 @@ class MainWindow(QMainWindow):
def on_tab_changed(self, index): def on_tab_changed(self, index):
logger.info(f"标签页切换到: {index}") logger.info(f"标签页切换到: {index}")
# 更新状态栏显示当前目录信息
if index == 0: # 服务器连接标签页
current_dir = os.getcwd()
self.status_bar.showMessage(f"当前目录: {current_dir}")
logger.info(f"状态栏更新为本地目录: {current_dir}")
# 当切换到远程命令标签页时传递SSH客户端和服务器配置 # 当切换到远程命令标签页时传递SSH客户端和服务器配置
if index == 1: # 远程命令标签页 elif index == 1: # 远程命令标签页
ssh_client = self.server_connection_tab.get_ssh_client() ssh_client = self.server_connection_tab.get_ssh_client()
self.remote_commands_tab.set_ssh_client(ssh_client) self.remote_commands_tab.set_ssh_client(ssh_client)
@@ -51,10 +72,32 @@ class MainWindow(QMainWindow):
git_url = server_config.get("git_url", "") git_url = server_config.get("git_url", "")
remote_dir = server_config.get("remote_dir", "") remote_dir = server_config.get("remote_dir", "")
self.remote_commands_tab.set_server_config(git_url, remote_dir) self.remote_commands_tab.set_server_config(git_url, remote_dir)
# 调用set_server_info方法更新服务器信息
self.remote_commands_tab.set_server_info(server_config)
# 尝试获取远程服务器当前目录并更新状态栏
try:
if hasattr(self.remote_commands_tab, 'current_dir_display') and self.remote_commands_tab.current_dir_display.text():
current_dir = self.remote_commands_tab.current_dir_display.text()
self.status_bar.showMessage(f"远程服务器 {current_alias}: {current_dir}")
logger.info(f"状态栏更新为远程服务器目录: {current_alias}: {current_dir}")
else:
# 更新状态栏显示远程服务器信息
self.status_bar.showMessage(f"远程服务器: {current_alias} | 远程目录: {remote_dir}")
logger.info(f"状态栏更新为远程服务器: {current_alias}, 目录: {remote_dir}")
except Exception as e:
logger.error(f"获取远程目录信息失败: {str(e)}")
# 更新状态栏显示远程服务器信息
self.status_bar.showMessage(f"远程服务器: {current_alias} | 远程目录: {remote_dir}")
logger.info(f"状态栏更新为远程服务器: {current_alias}, 目录: {remote_dir}")
else: else:
# 如果没有配置远程目录,初始化为默认目录 # 如果没有配置远程目录,初始化为默认目录
self.remote_commands_tab.current_dir_display.setText("~") self.remote_commands_tab.current_dir_display.setText("~")
self.remote_commands_tab.refresh_directory() self.remote_commands_tab.refresh_directory()
# 更新状态栏显示远程服务器信息
self.status_bar.showMessage(f"远程服务器: {current_alias} | 远程目录: ~")
logger.info(f"状态栏更新为远程服务器: {current_alias}, 目录: ~")
# 当切换到Django标签页时传递SSH客户端和用户名 # 当切换到Django标签页时传递SSH客户端和用户名
elif index == 2: # Django标签页 elif index == 2: # Django标签页
@@ -67,6 +110,54 @@ class MainWindow(QMainWindow):
server_config = self.server_connection_tab.config_data[current_alias] server_config = self.server_connection_tab.config_data[current_alias]
username = server_config.get("username", "") username = server_config.get("username", "")
self.django_tab.set_username(username) self.django_tab.set_username(username)
# 更新状态栏显示Django项目信息
project_name = server_config.get("project", "")
remote_dir = server_config.get("remote_dir", "")
self.status_bar.showMessage(f"远程服务器: {current_alias} | Django项目: {project_name} | 项目目录: {remote_dir}")
logger.info(f"状态栏更新为Django项目: {project_name}, 目录: {remote_dir}")
# 当切换到Gunicorn标签页时传递SSH客户端、用户名和项目信息
elif index == 3: # Gunicorn标签页
ssh_client = self.server_connection_tab.get_ssh_client()
self.gunicorn_tab.set_ssh_client(ssh_client)
# 获取当前选中的服务器配置中的用户名和项目信息
current_alias = self.server_connection_tab.alias_combo.currentText()
if current_alias and current_alias in self.server_connection_tab.config_data:
server_config = self.server_connection_tab.config_data[current_alias]
username = server_config.get("username", "")
project_name = server_config.get("project", "")
# 获取Django路径根据用户说明路径应该是/home/[user]/[project_path]/[project_name]
# 其中user是config.json中的usernameproject_path是git_url中的webstatusproject_name是project的值
remote_dir = server_config.get("remote_dir", "")
git_url = server_config.get("git_url", "")
project_name = server_config.get("project", "")
# 从git_url中提取project_pathwebstatus
project_path = ""
if git_url:
# git_url格式为http://192.168.3.241:3000/xiaji/webstatus.git
# 提取最后一个/和.git之间的部分作为project_path
import os
git_name = os.path.basename(git_url) # 获取webstatus.git
if git_name.endswith(".git"):
project_path = git_name[:-4] # 去掉.git后缀得到webstatus
# 构建Django路径/home/[user]/[project_path]/ (statuspage的父目录)
if remote_dir and project_path:
django_path = f"{remote_dir}/{project_path}/"
else:
django_path = f"{remote_dir}/" if remote_dir else ""
logger.info(f"构建的Django路径: {django_path}, 项目名: {project_name}")
self.gunicorn_tab.set_username(username)
self.gunicorn_tab.set_project_info(project_name, django_path)
# 更新状态栏显示Gunicorn服务信息
self.status_bar.showMessage(f"远程服务器: {current_alias} | Gunicorn服务: gunicorn_{project_name} | 服务目录: {django_path}")
logger.info(f"状态栏更新为Gunicorn服务: gunicorn_{project_name}, 目录: {django_path}")
if __name__ == "__main__": if __name__ == "__main__":
logger.add("app.log", rotation="10 MB") logger.add("app.log", rotation="10 MB")

View File

@@ -64,6 +64,16 @@ class RemoteCommandThread(QThread):
self.finished_signal.emit(False, f"SSH连接已断开请重新连接服务器") self.finished_signal.emit(False, f"SSH连接已断开请重新连接服务器")
return return
# 在执行命令前,先输出当前目录
try:
pwd_stdin, pwd_stdout, pwd_stderr = self.ssh_client.exec_command("pwd")
pwd_output = pwd_stdout.read().decode().strip()
if pwd_output:
self.output_signal.emit(f"当前目录: {pwd_output}")
logger.info(f"当前目录: {pwd_output}")
except Exception as e:
logger.error(f"获取当前目录失败: {str(e)}")
# 如果命令包含sudo修改为使用-S选项从标准输入读取密码 # 如果命令包含sudo修改为使用-S选项从标准输入读取密码
if "sudo" in self.command: if "sudo" in self.command:
command_with_sudo = self.command.replace("sudo", "sudo -S") command_with_sudo = self.command.replace("sudo", "sudo -S")
@@ -219,7 +229,7 @@ class RemoteCommandsTab(QWidget):
# 允许用户输入当前目录路径 # 允许用户输入当前目录路径
# self.current_dir_display.setReadOnly(True) # self.current_dir_display.setReadOnly(True)
# 添加回车键刷新目录功能 # 添加回车键刷新目录功能
self.current_dir_display.returnPressed.connect(self.refresh_directory) self.current_dir_display.returnPressed.connect(self.on_current_dir_entered)
current_dir_layout.addWidget(self.current_dir_display) current_dir_layout.addWidget(self.current_dir_display)
# 刷新目录按钮 # 刷新目录按钮
@@ -275,6 +285,26 @@ class RemoteCommandsTab(QWidget):
self.setLayout(main_layout) self.setLayout(main_layout)
logger.info("远程命令标签页UI初始化完成") logger.info("远程命令标签页UI初始化完成")
def set_server_info(self, server_info):
"""设置服务器信息"""
logger.info(f"设置服务器信息: {server_info}")
self.server_info = server_info
# 更新主窗口状态栏显示当前目录
try:
main_window = self.parent().parent()
if hasattr(main_window, 'status_bar') and self.ssh_client:
current_dir = self.current_dir_display.text().strip()
server_host = self.server_info.get('host', '未知')
if current_dir:
main_window.status_bar.showMessage(f"远程服务器 {server_host}: {current_dir}")
logger.info(f"主窗口状态栏更新为远程服务器目录: {server_host}: {current_dir}")
else:
main_window.status_bar.showMessage(f"远程服务器: {server_host}")
logger.info(f"主窗口状态栏更新为远程服务器: {server_host}")
except Exception as e:
logger.error(f"更新主窗口状态栏失败: {str(e)}")
def set_ssh_client(self, ssh_client): def set_ssh_client(self, ssh_client):
logger.info("设置SSH客户端") logger.info("设置SSH客户端")
self.ssh_client = ssh_client self.ssh_client = ssh_client
@@ -282,9 +312,33 @@ class RemoteCommandsTab(QWidget):
if self.ssh_client: if self.ssh_client:
self.status_label.setText("已连接到服务器") self.status_label.setText("已连接到服务器")
self.status_label.setStyleSheet("color: green;") self.status_label.setStyleSheet("color: green;")
# 更新主窗口状态栏显示当前目录
try:
main_window = self.parent().parent()
if hasattr(main_window, 'status_bar'):
current_dir = self.current_dir_display.text().strip()
server_host = self.server_info.get('host', '未知') if hasattr(self, 'server_info') else '未知'
if current_dir:
main_window.status_bar.showMessage(f"远程服务器 {server_host}: {current_dir}")
logger.info(f"主窗口状态栏更新为远程服务器目录: {server_host}: {current_dir}")
else:
main_window.status_bar.showMessage(f"远程服务器: {server_host}")
logger.info(f"主窗口状态栏更新为远程服务器: {server_host}")
except Exception as e:
logger.error(f"更新主窗口状态栏失败: {str(e)}")
else: else:
self.status_label.setText("未连接到服务器") self.status_label.setText("未连接到服务器")
self.status_label.setStyleSheet("color: red;") self.status_label.setStyleSheet("color: red;")
# 更新主窗口状态栏显示未连接状态
try:
main_window = self.parent().parent()
if hasattr(main_window, 'status_bar'):
main_window.status_bar.showMessage("未连接到远程服务器")
logger.info("主窗口状态栏更新为未连接状态")
except Exception as e:
logger.error(f"更新主窗口状态栏失败: {str(e)}")
def set_server_config(self, git_url, remote_dir): def set_server_config(self, git_url, remote_dir):
logger.info(f"设置服务器配置: git_url={git_url}, remote_dir={remote_dir}") logger.info(f"设置服务器配置: git_url={git_url}, remote_dir={remote_dir}")
@@ -295,6 +349,16 @@ class RemoteCommandsTab(QWidget):
if remote_dir: if remote_dir:
self.current_dir_display.setText(remote_dir) self.current_dir_display.setText(remote_dir)
self.refresh_directory() self.refresh_directory()
# 更新主窗口状态栏显示当前目录
try:
main_window = self.parent().parent()
if hasattr(main_window, 'status_bar'):
server_host = self.server_info['host'] if hasattr(self, 'server_info') and 'host' in self.server_info else '未知'
main_window.status_bar.showMessage(f"远程服务器 {server_host}: {remote_dir}")
logger.info(f"主窗口状态栏更新为远程服务器目录: {server_host}: {remote_dir}")
except Exception as e:
logger.error(f"更新主窗口状态栏失败: {str(e)}")
def install_git(self): def install_git(self):
logger.info("安装Git") logger.info("安装Git")
@@ -385,6 +449,25 @@ class RemoteCommandsTab(QWidget):
else: else:
QMessageBox.warning(self, "错误", message) QMessageBox.warning(self, "错误", message)
def on_current_dir_entered(self):
"""处理用户输入目录路径并按回车键的情况"""
logger.info("用户输入目录路径并按回车键")
# 更新主窗口状态栏显示当前目录
try:
main_window = self.parent().parent()
if hasattr(main_window, 'status_bar'):
current_dir = self.current_dir_display.text().strip()
server_host = self.server_info['host'] if hasattr(self, 'server_info') and 'host' in self.server_info else '未知'
if current_dir:
main_window.status_bar.showMessage(f"远程服务器 {server_host}: {current_dir}")
logger.info(f"主窗口状态栏更新为远程服务器目录: {server_host}: {current_dir}")
except Exception as e:
logger.error(f"更新主窗口状态栏失败: {str(e)}")
# 刷新目录列表
self.refresh_directory()
def refresh_directory(self): def refresh_directory(self):
logger.info("刷新目录列表") logger.info("刷新目录列表")
@@ -419,6 +502,17 @@ class RemoteCommandsTab(QWidget):
self.status_label.setText("目录列表已刷新") self.status_label.setText("目录列表已刷新")
self.status_label.setStyleSheet("color: green;") self.status_label.setStyleSheet("color: green;")
logger.info("目录列表刷新成功") logger.info("目录列表刷新成功")
# 更新主窗口状态栏显示当前目录
try:
main_window = self.parent().parent()
if hasattr(main_window, 'status_bar'):
current_dir = self.current_dir_display.text()
server_host = self.server_info['host'] if hasattr(self, 'server_info') and 'host' in self.server_info else '未知'
main_window.status_bar.showMessage(f"远程服务器 {server_host}: {current_dir}")
logger.info(f"主窗口状态栏更新为远程服务器目录: {server_host}: {current_dir}")
except Exception as e:
logger.error(f"更新主窗口状态栏失败: {str(e)}")
else: else:
self.status_label.setText("刷新目录列表失败") self.status_label.setText("刷新目录列表失败")
self.status_label.setStyleSheet("color: red;") self.status_label.setStyleSheet("color: red;")

View File

@@ -210,6 +210,19 @@ class ServerConnectionTab(QWidget):
self.status_label.setStyleSheet("color: green;") self.status_label.setStyleSheet("color: green;")
QMessageBox.information(self, "成功", f"成功连接到服务器: {ip}") QMessageBox.information(self, "成功", f"成功连接到服务器: {ip}")
# 更新状态栏显示服务器信息
try:
main_window = self.parent().parent()
if hasattr(main_window, 'remote_commands_tab'):
server_config = {
'host': ip,
'remote_dir': self.remote_dir_input.text()
}
main_window.remote_commands_tab.set_server_info(server_config)
logger.info(f"连接服务器后更新状态栏: {ip}")
except Exception as e:
logger.error(f"连接服务器后更新状态栏失败: {str(e)}")
except Exception as e: except Exception as e:
logger.error(f"连接服务器失败: {str(e)}") logger.error(f"连接服务器失败: {str(e)}")
self.status_label.setText("连接失败") self.status_label.setText("连接失败")