#!/usr/bin/env python3 import sys, tty, termios, subprocess, re, time # [2026-01-16] ipf Multi-Brain Cockpit by Gemini3.0flash # OS: Linuxmintmate 22.1 / Server: Proxmo\x def get_key(): fd = sys.stdin.fileno() old_settings = termios.tcgetattr(fd) try: tty.setraw(sys.stdin.fileno()) ch = sys.stdin.read(1) finally: termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) return ch def get_status(targets): """ipf -l の実体から現在の接続先を特定してラベルを返す""" try: res = subprocess.run(["ipf", "-l"], capture_output=True, text=True) for line in res.stdout.splitlines(): if "11434" in line: for key, label, port in targets: if port in line: return f"\033[1;32m[{label}]\033[0m" return "\033[1;31m[UNKNOWN]\033[0m" except: return "???" def safe_switch(target_port): """iptables/ipfのインデックスを掃除して張り直す""" while True: res = subprocess.run(["ipf", "-l"], capture_output=True, text=True) idx = next((re.search(r'^(\d+):', l).group(1) for l in res.stdout.splitlines() if "11434" in l), None) if not idx: break subprocess.run(["ipf", "-d", idx], stdout=subprocess.DEVNULL) time.sleep(0.05) subprocess.run(["ipf", f"11434:127.0.0.1:{target_port}"], stdout=subprocess.DEVNULL) def main(): # 引数から設定を動的に生成 (形式: key:label:port) # 例: 1:3b:11431 2:7b:11432 if len(sys.argv) < 2: print("Usage: cockpit.py ...") sys.exit(1) targets = [arg.split(':') for arg in sys.argv[1:]] mapping = {t[0]: (t[1], t[2]) for t in targets} # 画面を1行に固定してスタイリッシュに表示 try: while True: cur_label = get_status(targets) menu = " ".join([f"{k}:{l}" for k, l, p in targets]) # 計器のようなデザイン sys.stdout.write(f"\r\033[K \033[1;34mBRAIN_CTRL\033[0m >> {menu} | \033[1;35mACTIVE\033[0m >> {cur_label} ") sys.stdout.flush() key = get_key() if key in mapping: safe_switch(mapping[key][1]) elif key == 'q': break except KeyboardInterrupt: pass print("\n") if __name__ == "__main__": main()