This commit is contained in:
2025-09-12 10:12:35 +02:00
commit 4dbee4a106
4 changed files with 187 additions and 0 deletions

96
pty_monitor.py Normal file
View File

@@ -0,0 +1,96 @@
import sys
import os
import pty
import tty
import termios
import select
import re
import getpass
import datetime
import itertools
def get_log_filename():
"""Ermittelt einen Dateinamen basierend auf Username und TTY-Nummer."""
try:
username = getpass.getuser()
except Exception:
username = "user"
try:
tty_path = os.ttyname(sys.stdout.fileno())
tty_number = os.path.basename(tty_path)
filename = f"{username}-tty{tty_number}.log"
except OSError:
for i in itertools.count():
filename = f"{username}-tty{i}.log"
if not os.path.exists(filename):
break
return filename
def sanitize_output(data: bytes) -> bytes:
"""Entfernt Steuerzeichen und -sequenzen, um die Log-Datei lesbarer zu machen."""
data = re.sub(
rb'\x1b(\[[0-?]*[ -/]*[@-~]|\][^]*(\x07|\x1b\\))', b'', data)
data = data.replace(b'\r', b'')
data = data.replace(b'\b', b'')
data = data.replace(b'\a', b'')
return data
def run_interactive_shell():
log_filename = get_log_filename()
print(f"Sitzung wird in '{log_filename}' aufgezeichnet.")
file_existed = os.path.exists(log_filename)
original_termios = termios.tcgetattr(sys.stdin.fileno())
try:
# Öffne die Datei im 'append binary'-Modus ('ab')
with open(log_filename, 'ab') as log_file:
if file_existed:
# Füge einen Trenner für die neue Sitzung hinzu
timestamp = datetime.datetime.now().isoformat()
separator = f"\n\n--- NEUE SITZUNG GESTARTET AM {
timestamp} ---\n\n".encode('utf-8')
log_file.write(separator)
pid, master_fd = pty.fork()
if pid == 0:
os.execv("/bin/zsh", ["/bin/zsh"])
else:
tty.setraw(sys.stdin.fileno())
while True:
try:
readable, _, _ = select.select(
[sys.stdin, master_fd], [], [])
if sys.stdin in readable:
user_input = os.read(sys.stdin.fileno(), 1024)
if not user_input:
break
log_file.write(sanitize_output(user_input))
os.write(master_fd, user_input)
if master_fd in readable:
shell_output = os.read(master_fd, 1024)
if not shell_output:
break
log_file.write(sanitize_output(shell_output))
os.write(sys.stdout.fileno(), shell_output)
sys.stdout.flush()
except OSError:
break
finally:
termios.tcsetattr(sys.stdin.fileno(),
termios.TCSADRAIN, original_termios)
if __name__ == "__main__":
print("Starte PTY-Monitor. Gib 'exit' ein, um die Sitzung zu beenden.")
run_interactive_shell()
print(f"\nPTY-Monitor beendet.")