v1.8.6: fix sudo auto-password detection
- Strip ANSI escape sequences before matching sudo prompt - Normalize \r\n and \r to \n for reliable line splitting - Add 200ms delay before sending password (let PTY settle) - Increase buffer to 500 bytes for longer prompts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,12 +3,16 @@ Terminal tab — persistent interactive SSH shell via ShellSession + TerminalWid
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import queue
|
import queue
|
||||||
|
import re
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import customtkinter as ctk
|
import customtkinter as ctk
|
||||||
from core.ssh_client import ShellSession
|
from core.ssh_client import ShellSession
|
||||||
from core.i18n import t
|
from core.i18n import t
|
||||||
|
|
||||||
|
# Regex to strip ANSI escape sequences
|
||||||
|
_ANSI_RE = re.compile(r'\x1b\[[0-9;]*[a-zA-Z]|\x1b\].*?\x07|\x1b[()][AB012]|\x1b\[?\d*[a-zA-Z]')
|
||||||
|
|
||||||
|
|
||||||
class TerminalTab(ctk.CTkFrame):
|
class TerminalTab(ctk.CTkFrame):
|
||||||
def __init__(self, master, store, session_pool=None):
|
def __init__(self, master, store, session_pool=None):
|
||||||
@@ -161,14 +165,20 @@ class TerminalTab(ctk.CTkFrame):
|
|||||||
# Sudo auto-password: only check if not already sent
|
# Sudo auto-password: only check if not already sent
|
||||||
if not self._sudo_sent and self._session:
|
if not self._sudo_sent and self._session:
|
||||||
self._sudo_buffer += combined
|
self._sudo_buffer += combined
|
||||||
self._sudo_buffer = self._sudo_buffer[-300:]
|
self._sudo_buffer = self._sudo_buffer[-500:]
|
||||||
buf_str = self._sudo_buffer.decode("utf-8", errors="replace")
|
buf_str = self._sudo_buffer.decode("utf-8", errors="replace")
|
||||||
# Only match actual sudo password prompt — NOT log output
|
# Strip ANSI escapes and normalize line endings
|
||||||
last_line = buf_str.rstrip().rsplit("\n", 1)[-1].strip()
|
clean = _ANSI_RE.sub("", buf_str)
|
||||||
|
clean = clean.replace("\r\n", "\n").replace("\r", "\n")
|
||||||
|
last_line = clean.rstrip().rsplit("\n", 1)[-1].strip()
|
||||||
if "[sudo] password for" in last_line:
|
if "[sudo] password for" in last_line:
|
||||||
server = self.store.get_server(self._current_alias)
|
server = self.store.get_server(self._current_alias)
|
||||||
if server and server.get("password"):
|
if server and server.get("password"):
|
||||||
|
# Small delay — let the PTY settle before sending
|
||||||
|
def _send_sudo_pass():
|
||||||
|
if self._session and self._session.connected:
|
||||||
self._session.send(server["password"].encode() + b"\n")
|
self._session.send(server["password"].encode() + b"\n")
|
||||||
|
self.after(200, _send_sudo_pass)
|
||||||
self._sudo_sent = True
|
self._sudo_sent = True
|
||||||
self._sudo_buffer = b""
|
self._sudo_buffer = b""
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user