Files
tty_logger/pty_monitor.py
2025-09-12 10:12:35 +02:00

97 lines
3.1 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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