完善nginx标签。使用unix套接字。增加远程命令的运行和显示。
This commit is contained in:
@@ -79,27 +79,33 @@ class RemoteCommandThread(QThread):
|
||||
command_with_sudo = self.command.replace("sudo", "sudo -S")
|
||||
stdin, stdout, stderr = self.ssh_client.exec_command(command_with_sudo)
|
||||
|
||||
# 检查是否需要密码
|
||||
password_prompt = False
|
||||
for line in stderr:
|
||||
self.output_signal.emit(line)
|
||||
if "password for" in line.lower() or "密码" in line:
|
||||
password_prompt = True
|
||||
break
|
||||
|
||||
# 如果需要密码,请求用户输入
|
||||
if password_prompt:
|
||||
self.waiting_for_password = True
|
||||
self.password_request_signal.emit()
|
||||
# 如果预先设置了密码,直接发送
|
||||
if self.password:
|
||||
logger.info("使用预先设置的密码")
|
||||
stdin.write(self.password + "\n")
|
||||
stdin.flush()
|
||||
else:
|
||||
# 检查是否需要密码
|
||||
password_prompt = False
|
||||
for line in stderr:
|
||||
self.output_signal.emit(line)
|
||||
if "password for" in line.lower() or "密码" in line:
|
||||
password_prompt = True
|
||||
break
|
||||
|
||||
# 等待密码输入
|
||||
while self.waiting_for_password:
|
||||
self.msleep(100)
|
||||
|
||||
# 发送密码
|
||||
if self.password:
|
||||
stdin.write(self.password + "\n")
|
||||
stdin.flush()
|
||||
# 如果需要密码,请求用户输入
|
||||
if password_prompt:
|
||||
self.waiting_for_password = True
|
||||
self.password_request_signal.emit()
|
||||
|
||||
# 等待密码输入
|
||||
while self.waiting_for_password:
|
||||
self.msleep(100)
|
||||
|
||||
# 发送密码
|
||||
if self.password:
|
||||
stdin.write(self.password + "\n")
|
||||
stdin.flush()
|
||||
else:
|
||||
stdin, stdout, stderr = self.ssh_client.exec_command(self.command)
|
||||
|
||||
@@ -194,26 +200,24 @@ class RemoteCommandsTab(QWidget):
|
||||
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)
|
||||
# 自定义命令执行区域
|
||||
custom_command_layout = QVBoxLayout()
|
||||
custom_command_layout.addWidget(QLabel("自定义命令:"))
|
||||
|
||||
# 服务器重启
|
||||
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)
|
||||
# 命令输入框
|
||||
self.custom_command_input = QTextEdit()
|
||||
self.custom_command_input.setMaximumHeight(100)
|
||||
custom_command_layout.addWidget(self.custom_command_input)
|
||||
|
||||
# 配置sudo免密按钮
|
||||
self.sudo_nopasswd_button = QPushButton("配置sudo免密")
|
||||
self.sudo_nopasswd_button.clicked.connect(self.configure_sudo_nopasswd)
|
||||
system_layout.addWidget(self.sudo_nopasswd_button)
|
||||
# 执行按钮
|
||||
execute_button_layout = QHBoxLayout()
|
||||
self.execute_command_button = QPushButton("执行命令")
|
||||
self.execute_command_button.clicked.connect(self.execute_custom_command)
|
||||
execute_button_layout.addWidget(self.execute_command_button)
|
||||
execute_button_layout.addStretch()
|
||||
custom_command_layout.addLayout(execute_button_layout)
|
||||
|
||||
system_layout.addLayout(custom_command_layout)
|
||||
|
||||
system_group.setLayout(system_layout)
|
||||
main_layout.addWidget(system_group)
|
||||
@@ -519,92 +523,57 @@ class RemoteCommandsTab(QWidget):
|
||||
logger.error(f"刷新目录列表失败: {message}")
|
||||
QMessageBox.warning(self, "错误", f"刷新目录列表失败: {message}")
|
||||
|
||||
def set_timezone(self):
|
||||
logger.info("设置时区为北京时区")
|
||||
def execute_custom_command(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:
|
||||
command = self.custom_command_input.toPlainText().strip()
|
||||
if not command:
|
||||
QMessageBox.warning(self, "警告", "请输入要执行的命令")
|
||||
return
|
||||
|
||||
self.output_text.clear()
|
||||
self.status_label.setText("正在设置时区...")
|
||||
self.status_label.setText("正在执行命令...")
|
||||
|
||||
# 如果命令以sudo开头,预先请求密码
|
||||
if command.startswith("sudo "):
|
||||
logger.info("检测到sudo命令,预先请求密码")
|
||||
# 创建密码输入对话框
|
||||
dialog = PasswordDialog(self)
|
||||
if dialog.exec() == QDialog.Accepted:
|
||||
password = dialog.get_password()
|
||||
if not password:
|
||||
QMessageBox.warning(self, "警告", "未输入密码,取消执行命令")
|
||||
return
|
||||
else:
|
||||
QMessageBox.warning(self, "警告", "已取消输入密码")
|
||||
return
|
||||
|
||||
# 创建并启动线程执行命令
|
||||
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.finished_signal.connect(self.on_custom_command_finished)
|
||||
self.command_thread.password_request_signal.connect(self.request_password)
|
||||
|
||||
# 如果是sudo命令且已获取密码,预先设置密码
|
||||
if command.startswith("sudo ") and password:
|
||||
self.command_thread.set_password(password)
|
||||
self.output_text.append("密码已设置\n")
|
||||
|
||||
self.command_thread.start()
|
||||
|
||||
def on_timezone_set(self, success, message):
|
||||
def on_custom_command_finished(self, success, message):
|
||||
if success:
|
||||
self.status_label.setText("时区设置成功")
|
||||
self.status_label.setText("命令执行成功")
|
||||
self.status_label.setStyleSheet("color: green;")
|
||||
QMessageBox.information(self, "成功", "服务器时区已设置为北京时区")
|
||||
|
||||
# 显示当前时区
|
||||
self.show_current_timezone()
|
||||
self.output_text.append(f"\n=== 命令执行成功 ===\n{message}")
|
||||
else:
|
||||
self.status_label.setText("时区设置失败")
|
||||
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}")
|
||||
self.output_text.append(f"\n=== 命令执行失败 ===\n{message}")
|
||||
|
||||
def delete_directory(self):
|
||||
logger.info("删除目录")
|
||||
@@ -640,42 +609,7 @@ class RemoteCommandsTab(QWidget):
|
||||
self.command_thread.finished_signal.connect(self.on_command_finished)
|
||||
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连接是否有效"""
|
||||
|
||||
Reference in New Issue
Block a user