multiSSH3 5.96__py3-none-any.whl → 5.97__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of multiSSH3 might be problematic. Click here for more details.

multiSSH3.py CHANGED
@@ -84,7 +84,7 @@ except Exception:
84
84
  print('Warning: functools.lru_cache is not available, multiSSH3 will run slower without cache.',file=sys.stderr)
85
85
  def cache_decorator(func):
86
86
  return func
87
- version = '5.96'
87
+ version = '5.97'
88
88
  VERSION = version
89
89
  __version__ = version
90
90
  COMMIT_DATE = '2025-10-21'
@@ -420,6 +420,11 @@ __thread_start_delay = 0
420
420
  _encoding = DEFAULT_ENCODING
421
421
  __returnZero = DEFAULT_RETURN_ZERO
422
422
  __running_threads = set()
423
+ __control_master_string = '''Host *
424
+ ControlMaster auto
425
+ ControlPath /run/user/%i/ssh_sockets_%C
426
+ ControlPersist 3600
427
+ '''
423
428
  if __resource_lib_available:
424
429
  # Get the current limits
425
430
  _, __system_nofile_limit = resource.getrlimit(resource.RLIMIT_NOFILE)
@@ -1388,14 +1393,14 @@ def compact_hostnames(Hostnames,verify = True):
1388
1393
  # hostSet = frozenset(Hostnames)
1389
1394
  # else:
1390
1395
  # hostSet = Hostnames
1391
- hostSet = frozenset(
1396
+ hostSet = frozenset(expand_hostnames(
1392
1397
  hostname.strip()
1393
1398
  for hostnames_str in Hostnames
1394
1399
  for hostname in hostnames_str.split(',')
1395
- )
1400
+ ))
1396
1401
  compact_hosts = __compact_hostnames(hostSet)
1397
1402
  if verify:
1398
- if set(expand_hostnames(compact_hosts)) != set(expand_hostnames(hostSet)):
1403
+ if frozenset(expand_hostnames(compact_hosts)) != hostSet:
1399
1404
  if not __global_suppress_printout:
1400
1405
  eprint(f"Error compacting hostnames: {hostSet} -> {compact_hosts}")
1401
1406
  compact_hosts = hostSet
@@ -2918,7 +2923,7 @@ def pre_merge_hosts(hosts):
2918
2923
  # Create merged hosts
2919
2924
  merged_hosts = []
2920
2925
  for group in output_groups.values():
2921
- group[0].name = ','.join(host.name for host in group)
2926
+ group[0].name = ','.join(compact_hostnames(host.name for host in group))
2922
2927
  merged_hosts.append(group[0])
2923
2928
  return merged_hosts
2924
2929
 
@@ -2931,6 +2936,7 @@ def get_host_raw_output(hosts, terminal_width):
2931
2936
  max_length = 20
2932
2937
  hosts = pre_merge_hosts(hosts)
2933
2938
  for host in hosts:
2939
+ max_length = max(max_length, len(max(host.name.split(','), key=len)) + 3)
2934
2940
  hostPrintOut = ["│█ EXECUTED COMMAND:"]
2935
2941
  for line in host.command.splitlines():
2936
2942
  hostPrintOut.extend(text_wrapper.wrap(line))
@@ -3800,6 +3806,7 @@ def get_parser():
3800
3806
  parser.add_argument('-e','--encoding', type=str, help=f'The encoding to use for the output. (default: {DEFAULT_ENCODING})', default=DEFAULT_ENCODING)
3801
3807
  parser.add_argument('-dt','--diff_display_threshold', type=float, help=f'The threshold of lines to display the diff when files differ. {{0-1}} Set to 0 to always display the diff. Set to 1 to disable diff. (Only merge same) (default: {DEFAULT_DIFF_DISPLAY_THRESHOLD})', default=DEFAULT_DIFF_DISPLAY_THRESHOLD)
3802
3808
  parser.add_argument('--force_truecolor', action='store_true', help=f'Force truecolor output even when not in a truecolor terminal. (default: {FORCE_TRUECOLOR})', default=FORCE_TRUECOLOR)
3809
+ parser.add_argument('--add_control_master_config', action='store_true', help='Add ControlMaster configuration to ~/.ssh/config to speed up multiple connections to the same host.')
3803
3810
  parser.add_argument("-V","--version", action='version', version=f'%(prog)s {version} @ {COMMIT_DATE} with [ {", ".join(_binPaths.keys())} ] by {AUTHOR} ({AUTHOR_EMAIL})')
3804
3811
  return parser
3805
3812
 
@@ -3859,7 +3866,7 @@ def process_config_file(args):
3859
3866
  else:
3860
3867
  configFileToWriteTo = args.config_file
3861
3868
  write_default_config(args,configFileToWriteTo)
3862
- if not args.commands:
3869
+ if not args.commands and not args.file:
3863
3870
  if configFileToWriteTo:
3864
3871
  with open(configFileToWriteTo,'r') as f:
3865
3872
  eprint(f"Config file content: \n{f.read()}")
@@ -3901,6 +3908,35 @@ def process_keys(args):
3901
3908
  eprint(f"Warning: Identity file {args.key!r} not found. Passing to ssh anyway. Proceed with caution.")
3902
3909
  return args
3903
3910
 
3911
+ def process_control_master_config(args):
3912
+ global __control_master_string
3913
+ if args.add_control_master_config:
3914
+ try:
3915
+ if not os.path.exists(os.path.expanduser('~/.ssh')):
3916
+ os.makedirs(os.path.expanduser('~/.ssh'),mode=0o700)
3917
+ ssh_config_file = os.path.expanduser('~/.ssh/config')
3918
+ if not os.path.exists(ssh_config_file):
3919
+ with open(ssh_config_file,'w') as f:
3920
+ f.write(__control_master_string)
3921
+ os.chmod(ssh_config_file,0o644)
3922
+ else:
3923
+ with open(ssh_config_file,'r') as f:
3924
+ ssh_config_content = f.readlines()
3925
+ if set(map(str.strip,ssh_config_content)).issuperset(set(map(str.strip,__control_master_string.splitlines()))):
3926
+ eprint("ControlMaster configuration already exists in ~/.ssh/config, skipping adding:")
3927
+ eprint(__control_master_string)
3928
+ else:
3929
+ with open(ssh_config_file,'a') as f:
3930
+ f.write('\n# Added by multiSSH3.py to speed up subsequent connections\n')
3931
+ f.write(__control_master_string)
3932
+ eprint("ControlMaster configuration added to ~/.ssh/config.")
3933
+ except Exception as e:
3934
+ eprint(f"Error adding ControlMaster configuration: {e}")
3935
+ import traceback
3936
+ traceback.print_exc()
3937
+ if not args.commands and not args.file:
3938
+ _exit_with_code(0, "Done configuring ControlMaster.")
3939
+ return args
3904
3940
 
3905
3941
  def set_global_with_args(args):
3906
3942
  global _emo
@@ -3937,6 +3973,7 @@ def main():
3937
3973
  args = process_config_file(args)
3938
3974
  args = process_commands(args)
3939
3975
  args = process_keys(args)
3976
+ args = process_control_master_config(args)
3940
3977
  set_global_with_args(args)
3941
3978
 
3942
3979
  if args.use_script_timeout:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: multiSSH3
3
- Version: 5.96
3
+ Version: 5.97
4
4
  Summary: Run commands on multiple hosts via SSH
5
5
  Home-page: https://github.com/yufei-pan/multiSSH3
6
6
  Author: Yufei Pan
@@ -0,0 +1,6 @@
1
+ multiSSH3.py,sha256=AXZqfsQ3c0O0qIGUedwGChpLnkxPX_pDtDEtBj_L7Rk,181554
2
+ multissh3-5.97.dist-info/METADATA,sha256=26GBKHydWcT4nR5HO3St3ubhaH6zp2-_ajR6RvOX6rI,18093
3
+ multissh3-5.97.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
4
+ multissh3-5.97.dist-info/entry_points.txt,sha256=xi2rWWNfmHx6gS8Mmx0rZL2KZz6XWBYP3DWBpWAnnZ0,143
5
+ multissh3-5.97.dist-info/top_level.txt,sha256=tUwttxlnpLkZorSsroIprNo41lYSxjd2ASuL8-EJIJw,10
6
+ multissh3-5.97.dist-info/RECORD,,
@@ -1,6 +0,0 @@
1
- multiSSH3.py,sha256=xmpPdker87cPs5mcocUo3MdI4SjMsCh4u3MnwJbcGo8,179830
2
- multissh3-5.96.dist-info/METADATA,sha256=QuuF4JIB_Fv_WcFiYrChIFVt8eCioYYbFJLHri8CTVA,18093
3
- multissh3-5.96.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
4
- multissh3-5.96.dist-info/entry_points.txt,sha256=xi2rWWNfmHx6gS8Mmx0rZL2KZz6XWBYP3DWBpWAnnZ0,143
5
- multissh3-5.96.dist-info/top_level.txt,sha256=tUwttxlnpLkZorSsroIprNo41lYSxjd2ASuL8-EJIJw,10
6
- multissh3-5.96.dist-info/RECORD,,