From 4d6a14f4e2a387197f559ac713a34dd055578bf7 Mon Sep 17 00:00:00 2001 From: Guillaume Raffy Date: Thu, 25 Jun 2026 12:35:24 +0200 Subject: [PATCH] made cssh also work with ssh config host ids eg ```sh cssh monitoring.tunnel ``` fixes [https://bugzilla.ipr.univ-rennes.fr/show_bug.cgi?id=4405] --- home/bin/cssh | 110 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 107 insertions(+), 3 deletions(-) diff --git a/home/bin/cssh b/home/bin/cssh index fac22d5..dbe2615 100755 --- a/home/bin/cssh +++ b/home/bin/cssh @@ -1,11 +1,13 @@ #!/usr/bin/env python3 import logging -from typing import Optional, List +from typing import Optional, List, Dict import argparse import re import subprocess import abc import atexit +from pathlib import Path +import os class RgbColor(): @@ -354,16 +356,118 @@ def get_host_real_fqdn(host_id: HostId) -> HostId: assert is_valid_host_fqdn(host_real_fqdn), f'invalid host name: {host_real_fqdn}' return host_real_fqdn +class SshHostConfig(): + ''' + Host flique-macpro6.tunnel + hostname flique-macpro6.ipr.univ-rennes1.fr + user francois + ProxyCommand ssh graffy@tunnel1.ipr.univ-rennes1.fr nc %h %p 2> /dev/null + + Host physix-frontal.ipr.univ-rennes1.fr + hostname physix-frontal.ipr.univ-rennes1.fr + user graffy + IdentityFile ~/.ssh/homekey + + Host gpgpu + hostname physix58.ipr.univ-rennes1.fr + ProxyCommand ssh -i ~/.ssh/homekey graffy@physix.ipr.univ-rennes1.fr nc %h %p 2> /dev/null + IdentityFile ~/.ssh/homekey + + Host gpu-p100 + hostname physix90.ipr.univ-rennes1.fr + ProxyCommand ssh -i ~/.ssh/homekey graffy@physix.ipr.univ-rennes1.fr nc %h %p 2> /dev/null + IdentityFile ~/.ssh/homekey + + Host cloud.tunnel + hostname cloud.ipr.univ-rennes.fr + ProxyCommand ssh graffy@tunnel1.ipr.univ-rennes.fr nc %h %p 2> /dev/null + + Host adminpod-1.tunnel + hostname adminpod-1.ipr.univ-rennes.fr + ProxyCommand ssh graffy@tunnel1.ipr.univ-rennes1.fr nc %h %p 2> /dev/null + + Host mazinger.tunnel + hostname mazinger.ipr.univ-rennes.fr + ProxyCommand ssh graffy@tunnel1.ipr.univ-rennes1.fr nc %h %p 2> /dev/null + + # git.ipr.univ-rennes.fr + Host vmipr-p1 git + hostname vmipr-p1.univ-rennes.fr + User graffy + IdentityFile ~/.ssh/id_ed25519 + ''' + names: List[SshHostConfigId] # eg ['vmipr-p1', 'git'] + attrs: Dict[SshHostConfigAttr, str] # eg {'hostname': 'vmipr-p1.univ-rennes.fr', 'User': 'graffy', 'IdentityFile': '~/.ssh/id_ed25519'} + + def __init__(self): + self.names = [] + self.attrs = {} + + +class SshConfig(): + + host_configs = List[SshHostConfig] + + def __init__(self): + self.host_configs = [] + + def get_host_name(self, host_config_id) -> Optional[str]: + host_name = None + for host_conf in self.host_configs: + if host_config_id in host_conf.names: + host_name = host_conf.attrs['hostname'] + break + return host_name + + +def parse_ssh_config(ssh_config_file_path) -> SshConfig: + ssh_config = SshConfig() + with open(ssh_config_file_path, 'rt', encoding='utf8') as f: + for line in f.readlines(): + logging.debug('line = %s', line) + + # skip comments + if re.match(r'^\s*#.*$', line): + continue + + match = re.match(r'^\s*(?P[^\s]+)\s+(?P.*)$', line) + if match: + # Host vmipr-p1 git + # hostname vmipr-p1.univ-rennes.fr + # User graffy + # IdentityFile ~/.ssh/id_ed25519 + attr_name = match['attr_name'].lower() + attr_value = match['attr_value'] + logging.debug('attr_name = %s', attr_name) + + if attr_name == 'host': + host_config_ids = attr_value.split(' ') + ssh_config.host_configs.append(SshHostConfig()) + ssh_config.host_configs[-1].names = host_config_ids + else: + ssh_config.host_configs[-1].attrs[attr_name] = attr_value + continue + return ssh_config + def main(): - logging.basicConfig(level=logging.INFO) + logging.basicConfig(level=logging.DEBUG) arg_parser = argparse.ArgumentParser('cssh (colored ssh) opens a terminal window with a background color that depends on the fully qualified domain name of the target machine') arg_parser.add_argument('ssh_target', help='eg root@alambix50.ipr.univ-rennes.fr') args = arg_parser.parse_args() logging.debug(args) ssh_target = SshTarget(args.ssh_target) # eg 'root@alambix50.ipr.univ-rennes.fr' - ssh_target.host_id = get_host_real_fqdn(ssh_target.host_id) + ssh_config_file_path: Path = Path(os.getenv('HOME')) / '.ssh' / 'config' + host_real_name = ssh_target.host_id + if ssh_config_file_path.exists(): + ssh_config = parse_ssh_config(ssh_config_file_path) + hn = ssh_config.get_host_name(ssh_target.host_id) + if hn: + host_real_name = hn + + logging.debug('host_real_name = %s', host_real_name) + ssh_target.host_id = get_host_real_fqdn(host_real_name) logging.debug('ssh_target.host_id = %s', ssh_target.host_id) # AS_ROOT='false' # if [ "$(echo $@ | grep '^root@' > /dev/null)" ]