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.")