完成Django的标签的功能

This commit is contained in:
2025-08-31 13:08:06 +08:00
parent 9854a00542
commit d20ddfed59
10 changed files with 1993 additions and 4 deletions

View File

@@ -52,6 +52,18 @@ class RemoteCommandThread(QThread):
try:
logger.info(f"执行远程命令: {self.command}")
# 检查SSH连接是否仍然有效
try:
# 尝试执行一个简单的命令来检查连接
transport = self.ssh_client.get_transport() if self.ssh_client else None
if not transport or not transport.is_active():
raise Exception("SSH连接已断开")
except Exception as e:
logger.error(f"SSH连接检查失败: {str(e)}")
self.output_signal.emit(f"错误: SSH连接已断开请重新连接服务器")
self.finished_signal.emit(False, f"SSH连接已断开请重新连接服务器")
return
# 如果命令包含sudo修改为使用-S选项从标准输入读取密码
if "sudo" in self.command:
command_with_sudo = self.command.replace("sudo", "sudo -S")
@@ -106,8 +118,15 @@ class RemoteCommandThread(QThread):
except Exception as e:
logger.error(f"执行命令时发生错误: {str(e)}")
self.output_signal.emit(f"错误: {str(e)}")
self.finished_signal.emit(False, f"执行命令时发生错误: {str(e)}")
error_msg = str(e)
# 检查是否是Socket关闭错误
if "Socket is closed" in error_msg or "SSH session not active" in error_msg:
self.output_signal.emit(f"错误: SSH连接已断开请重新连接服务器")
self.finished_signal.emit(False, "SSH连接已断开请重新连接服务器")
else:
self.output_signal.emit(f"错误: {error_msg}")
self.finished_signal.emit(False, f"执行命令时发生错误: {error_msg}")
class RemoteCommandsTab(QWidget):
def __init__(self):
@@ -161,6 +180,34 @@ class RemoteCommandsTab(QWidget):
git_group.setLayout(git_layout)
main_layout.addWidget(git_group)
# 系统管理组
system_group = QGroupBox("系统管理")
system_layout = QVBoxLayout()
# 时区设置
timezone_layout = QHBoxLayout()
self.set_timezone_button = QPushButton("设置时区为北京时区")
self.set_timezone_button.clicked.connect(self.set_timezone)
timezone_layout.addWidget(self.set_timezone_button)
timezone_layout.addStretch()
system_layout.addLayout(timezone_layout)
# 服务器重启
reboot_layout = QHBoxLayout()
self.reboot_button = QPushButton("重启服务器")
self.reboot_button.clicked.connect(self.reboot_server)
reboot_layout.addWidget(self.reboot_button)
reboot_layout.addStretch()
system_layout.addLayout(reboot_layout)
# 配置sudo免密按钮
self.sudo_nopasswd_button = QPushButton("配置sudo免密")
self.sudo_nopasswd_button.clicked.connect(self.configure_sudo_nopasswd)
system_layout.addWidget(self.sudo_nopasswd_button)
system_group.setLayout(system_layout)
main_layout.addWidget(system_group)
# 目录管理组
dir_group = QGroupBox("目录管理")
dir_layout = QVBoxLayout()
@@ -326,7 +373,17 @@ class RemoteCommandsTab(QWidget):
else:
self.status_label.setText(message)
self.status_label.setStyleSheet("color: red;")
QMessageBox.warning(self, "错误", message)
# 检查是否是SSH连接断开错误
if "SSH连接已断开" in message:
reply = QMessageBox.question(self, "SSH连接已断开",
f"{message}\n\n是否现在重新连接服务器?",
QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
if reply == QMessageBox.Yes:
self.reconnect_ssh()
else:
QMessageBox.warning(self, "错误", message)
def refresh_directory(self):
logger.info("刷新目录列表")
@@ -354,16 +411,107 @@ class RemoteCommandsTab(QWidget):
def append_dir_output(self, text):
self.dir_list_text.append(text)
# 将目录信息输出到日志文件
logger.info(f"目录列表信息: {text.strip()}")
def on_dir_refresh_finished(self, success, message):
if success:
self.status_label.setText("目录列表已刷新")
self.status_label.setStyleSheet("color: green;")
logger.info("目录列表刷新成功")
else:
self.status_label.setText("刷新目录列表失败")
self.status_label.setStyleSheet("color: red;")
logger.error(f"刷新目录列表失败: {message}")
QMessageBox.warning(self, "错误", f"刷新目录列表失败: {message}")
def set_timezone(self):
logger.info("设置时区为北京时区")
if not self.ssh_client:
QMessageBox.warning(self, "警告", "请先连接到服务器")
return
# 确认操作
reply = QMessageBox.question(self, "确认设置时区",
"确定要将服务器时区设置为北京时区吗?",
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.No:
return
self.output_text.clear()
self.status_label.setText("正在设置时区...")
# 创建并启动线程执行命令
command = "sudo timedatectl set-timezone Asia/Shanghai"
self.command_thread = RemoteCommandThread(self.ssh_client, command)
self.command_thread.output_signal.connect(self.append_output)
self.command_thread.finished_signal.connect(self.on_timezone_set)
self.command_thread.password_request_signal.connect(self.request_password)
self.command_thread.start()
def on_timezone_set(self, success, message):
if success:
self.status_label.setText("时区设置成功")
self.status_label.setStyleSheet("color: green;")
QMessageBox.information(self, "成功", "服务器时区已设置为北京时区")
# 显示当前时区
self.show_current_timezone()
else:
self.status_label.setText("时区设置失败")
self.status_label.setStyleSheet("color: red;")
QMessageBox.warning(self, "错误", f"设置时区失败: {message}")
def show_current_timezone(self):
logger.info("显示当前时区")
if not self.ssh_client:
return
command = "timedatectl status"
self.command_thread = RemoteCommandThread(self.ssh_client, command)
self.command_thread.output_signal.connect(self.append_output)
self.command_thread.finished_signal.connect(lambda success, message: None)
self.command_thread.start()
def reboot_server(self):
logger.info("重启服务器")
if not self.ssh_client:
QMessageBox.warning(self, "警告", "请先连接到服务器")
return
# 确认操作
reply = QMessageBox.question(self, "确认重启",
"确定要重启服务器吗?\n此操作将导致服务器临时不可用!",
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.No:
return
self.output_text.clear()
self.status_label.setText("正在重启服务器...")
# 创建并启动线程执行命令
command = "sudo reboot"
self.command_thread = RemoteCommandThread(self.ssh_client, command)
self.command_thread.output_signal.connect(self.append_output)
self.command_thread.finished_signal.connect(self.on_reboot_initiated)
self.command_thread.password_request_signal.connect(self.request_password)
self.command_thread.start()
def on_reboot_initiated(self, success, message):
if success:
self.status_label.setText("服务器重启命令已发送")
self.status_label.setStyleSheet("color: green;")
QMessageBox.information(self, "重启已启动", "服务器重启命令已发送,服务器将在几秒后重启。\n请等待服务器重启完成后重新连接。")
else:
self.status_label.setText("服务器重启失败")
self.status_label.setStyleSheet("color: red;")
QMessageBox.warning(self, "错误", f"服务器重启失败: {message}")
def delete_directory(self):
logger.info("删除目录")
@@ -396,4 +544,86 @@ class RemoteCommandsTab(QWidget):
self.command_thread = RemoteCommandThread(self.ssh_client, command)
self.command_thread.output_signal.connect(self.append_output)
self.command_thread.finished_signal.connect(self.on_command_finished)
self.command_thread.start()
self.command_thread.start()
def configure_sudo_nopasswd(self):
logger.info("配置sudo免密")
if not self.ssh_client:
QMessageBox.warning(self, "警告", "请先连接到服务器")
return
# 确认操作
reply = QMessageBox.question(self, "确认配置sudo免密",
"确定要配置sudo免密吗\n此操作将允许当前用户无需密码执行sudo命令请谨慎操作",
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.No:
return
self.output_text.clear()
self.status_label.setText("正在配置sudo免密...")
# 创建并启动线程执行命令
# 首先获取当前用户名然后配置sudo免密
command = "whoami && echo '\n' | sudo -S visudo -c && (echo '\n' | sudo -S visudo -f /etc/sudoers.d/nopasswd && echo '$(whoami) ALL=(ALL) NOPASSWD: ALL' | sudo -S tee /etc/sudoers.d/nopasswd && sudo -S chmod 440 /etc/sudoers.d/nopasswd)"
self.command_thread = RemoteCommandThread(self.ssh_client, command)
self.command_thread.output_signal.connect(self.append_output)
self.command_thread.finished_signal.connect(self.on_sudo_nopasswd_configured)
self.command_thread.password_request_signal.connect(self.request_password)
self.command_thread.start()
def on_sudo_nopasswd_configured(self, success, message):
if success:
self.status_label.setText("sudo免密配置成功")
self.status_label.setStyleSheet("color: green;")
QMessageBox.information(self, "成功", "sudo免密配置成功\n当前用户现在可以无需密码执行sudo命令。")
else:
self.status_label.setText("sudo免密配置失败")
self.status_label.setStyleSheet("color: red;")
QMessageBox.warning(self, "错误", f"sudo免密配置失败: {message}")
def check_ssh_connection(self):
"""检查SSH连接是否有效"""
if not self.ssh_client:
return False
try:
transport = self.ssh_client.get_transport()
return transport and transport.is_active()
except Exception as e:
logger.error(f"检查SSH连接时发生错误: {str(e)}")
return False
def reconnect_ssh(self):
"""重新连接SSH服务器"""
logger.info("尝试重新连接SSH服务器")
# 关闭现有连接
if self.ssh_client:
try:
self.ssh_client.close()
except:
pass
self.ssh_client = None
# 切换到服务器连接标签页
main_window = self.parent().parent()
if hasattr(main_window, 'tabs'):
main_window.tabs.setCurrentIndex(0) # 切换到服务器连接标签页
# 显示提示信息
self.status_label.setText("请重新连接服务器")
self.status_label.setStyleSheet("color: orange;")
self.output_text.append("\n=== SSH连接已断开 ===\n")
self.output_text.append("请切换到\"服务器连接\"标签页重新连接服务器\n")
# 显示重新连接的对话框
reply = QMessageBox.question(self, "SSH连接已断开",
"SSH连接已断开是否现在重新连接",
QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
if reply == QMessageBox.Yes:
# 模拟点击连接按钮
server_connection_tab = main_window.server_connection_tab
server_connection_tab.connect_to_server()