68 lines
2.4 KiB
Python
68 lines
2.4 KiB
Python
#!/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 <key:label:port> ...")
|
|
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()
|