完成Django的标签的功能
This commit is contained in:
@@ -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()
|
||||
Reference in New Issue
Block a user