multiSSH3 5.43__py3-none-any.whl → 5.44__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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: multiSSH3
3
- Version: 5.43
3
+ Version: 5.44
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=bv60tQeVuc9mX2LL20sQbrst_dPEluel6Yg141kYxK8,135462
2
+ multiSSH3-5.44.dist-info/METADATA,sha256=1NZdIrRezS68gFKzFM2pcJBW_OCYYdNF87NDQ7nHelY,18001
3
+ multiSSH3-5.44.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
4
+ multiSSH3-5.44.dist-info/entry_points.txt,sha256=xi2rWWNfmHx6gS8Mmx0rZL2KZz6XWBYP3DWBpWAnnZ0,143
5
+ multiSSH3-5.44.dist-info/top_level.txt,sha256=tUwttxlnpLkZorSsroIprNo41lYSxjd2ASuL8-EJIJw,10
6
+ multiSSH3-5.44.dist-info/RECORD,,
multiSSH3.py CHANGED
@@ -45,10 +45,18 @@ except AttributeError:
45
45
  # If neither is available, use a dummy decorator
46
46
  def cache_decorator(func):
47
47
  return func
48
- version = '5.43'
48
+ version = '5.44'
49
49
  VERSION = version
50
50
 
51
- CONFIG_FILE = '/etc/multiSSH3.config.json'
51
+ CONFIG_FILE_CHAIN = ['./multiSSH3.config.json',
52
+ '~/multiSSH3.config.json',
53
+ '~/.multiSSH3.config.json',
54
+ '~/.config/multiSSH3/multiSSH3.config.json',
55
+ '/etc/multiSSH3.d/multiSSH3.config.json',
56
+ '/etc/multiSSH3.config.json'] # The first one has the highest priority
57
+
58
+
59
+ # TODO: Add terminal TUI with history support
52
60
 
53
61
  # ------------ Pre Helper Functions ----------------
54
62
  def eprint(*args, **kwargs):
@@ -224,44 +232,42 @@ def load_config_file(config_file):
224
232
  return {}
225
233
  return config
226
234
 
227
- __configs_from_file = load_config_file(CONFIG_FILE)
228
-
229
- __build_in_default_config = {
230
- 'AUTHOR': 'Yufei Pan',
231
- 'AUTHOR_EMAIL': 'pan@zopyr.us',
232
- 'DEFAULT_HOSTS': 'all',
233
- 'DEFAULT_USERNAME': None,
234
- 'DEFAULT_PASSWORD': '',
235
- 'DEFAULT_IDENTITY_FILE': None,
236
- 'DEDAULT_SSH_KEY_SEARCH_PATH': '~/.ssh/',
237
- 'DEFAULT_USE_KEY': False,
238
- 'DEFAULT_EXTRA_ARGS': None,
239
- 'DEFAULT_ONE_ON_ONE': False,
240
- 'DEFAULT_SCP': False,
241
- 'DEFAULT_FILE_SYNC': False,
242
- 'DEFAULT_TIMEOUT': 50,
243
- 'DEFAULT_CLI_TIMEOUT': 0,
244
- 'DEFAULT_REPEAT': 1,
245
- 'DEFAULT_INTERVAL': 0,
246
- 'DEFAULT_IPMI': False,
247
- 'DEFAULT_IPMI_INTERFACE_IP_PREFIX': '',
248
- 'DEFAULT_INTERFACE_IP_PREFIX': None,
249
- 'DEFAULT_NO_WATCH': False,
250
- 'DEFAULT_CURSES_MINIMUM_CHAR_LEN': 40,
251
- 'DEFAULT_CURSES_MINIMUM_LINE_LEN': 1,
252
- 'DEFAULT_SINGLE_WINDOW': False,
253
- 'DEFAULT_ERROR_ONLY': False,
254
- 'DEFAULT_NO_OUTPUT': False,
255
- 'DEFAULT_NO_ENV': False,
256
- 'DEFAULT_ENV_FILE': '/etc/profile.d/hosts.sh',
257
- 'DEFAULT_MAX_CONNECTIONS': 4 * os.cpu_count(),
258
- 'DEFAULT_JSON_MODE': False,
259
- 'DEFAULT_PRINT_SUCCESS_HOSTS': False,
260
- 'DEFAULT_GREPPABLE_MODE': False,
261
- 'DEFAULT_SKIP_UNREACHABLE': True,
262
- 'DEFAULT_SKIP_HOSTS': '',
263
- 'SSH_STRICT_HOST_KEY_CHECKING': False,
264
- 'ERROR_MESSAGES_TO_IGNORE': [
235
+ if True:
236
+ AUTHOR = 'Yufei Pan'
237
+ AUTHOR_EMAIL = 'pan@zopyr.us'
238
+ DEFAULT_HOSTS = 'all'
239
+ DEFAULT_USERNAME = None
240
+ DEFAULT_PASSWORD = ''
241
+ DEFAULT_IDENTITY_FILE = None
242
+ DEDAULT_SSH_KEY_SEARCH_PATH = '~/.ssh/'
243
+ DEFAULT_USE_KEY = False
244
+ DEFAULT_EXTRA_ARGS = None
245
+ DEFAULT_ONE_ON_ONE = False
246
+ DEFAULT_SCP = False
247
+ DEFAULT_FILE_SYNC = False
248
+ DEFAULT_TIMEOUT = 50
249
+ DEFAULT_CLI_TIMEOUT = 0
250
+ DEFAULT_REPEAT = 1
251
+ DEFAULT_INTERVAL = 0
252
+ DEFAULT_IPMI = False
253
+ DEFAULT_IPMI_INTERFACE_IP_PREFIX = ''
254
+ DEFAULT_INTERFACE_IP_PREFIX = None
255
+ DEFAULT_NO_WATCH = False
256
+ DEFAULT_CURSES_MINIMUM_CHAR_LEN = 40
257
+ DEFAULT_CURSES_MINIMUM_LINE_LEN = 1
258
+ DEFAULT_SINGLE_WINDOW = False
259
+ DEFAULT_ERROR_ONLY = False
260
+ DEFAULT_NO_OUTPUT = False
261
+ DEFAULT_NO_ENV = False
262
+ DEFAULT_ENV_FILE = '/etc/profile.d/hosts.sh'
263
+ DEFAULT_MAX_CONNECTIONS = 4 * os.cpu_count()
264
+ DEFAULT_JSON_MODE = False
265
+ DEFAULT_PRINT_SUCCESS_HOSTS = False
266
+ DEFAULT_GREPPABLE_MODE = False
267
+ DEFAULT_SKIP_UNREACHABLE = True
268
+ DEFAULT_SKIP_HOSTS = ''
269
+ SSH_STRICT_HOST_KEY_CHECKING = False
270
+ ERROR_MESSAGES_TO_IGNORE = [
265
271
  'Pseudo-terminal will not be allocated because stdin is not a terminal',
266
272
  'Connection to .* closed',
267
273
  'Warning: Permanently added',
@@ -269,80 +275,34 @@ __build_in_default_config = {
269
275
  'disabling multiplexing',
270
276
  'Killed by signal',
271
277
  'Connection reset by peer',
272
- ],
273
- '_DEFAULT_CALLED': True,
274
- '_DEFAULT_RETURN_UNFINISHED': False,
275
- '_DEFAULT_UPDATE_UNREACHABLE_HOSTS': True,
276
- '_DEFAULT_NO_START': False,
277
- '_etc_hosts': {},
278
- '_sshpassPath': None,
279
- '_sshPath': None,
280
- '_scpPath': None,
281
- '_ipmitoolPath': None,
282
- '_rsyncPath': None,
283
- '_shellPath': None,
284
- '__ERROR_MESSAGES_TO_IGNORE_REGEX':None,
285
- '__DEBUG_MODE': False,
286
- }
278
+ ]
279
+ _DEFAULT_CALLED = True
280
+ _DEFAULT_RETURN_UNFINISHED = False
281
+ _DEFAULT_UPDATE_UNREACHABLE_HOSTS = True
282
+ _DEFAULT_NO_START = False
283
+ _etc_hosts = {}
284
+ _sshpassPath = None
285
+ _sshPath = None
286
+ _scpPath = None
287
+ _ipmitoolPath = None
288
+ _rsyncPath = None
289
+ _shellPath = None
290
+ __ERROR_MESSAGES_TO_IGNORE_REGEX =None
291
+ __DEBUG_MODE = False
287
292
 
288
293
  # Load Config Based Default Global variables
289
294
  if True:
290
- AUTHOR = __configs_from_file.get('AUTHOR', __build_in_default_config['AUTHOR'])
291
- AUTHOR_EMAIL = __configs_from_file.get('AUTHOR_EMAIL', __build_in_default_config['AUTHOR_EMAIL'])
292
-
293
- DEFAULT_HOSTS = __configs_from_file.get('DEFAULT_HOSTS', __build_in_default_config['DEFAULT_HOSTS'])
294
- DEFAULT_ENV_FILE = __configs_from_file.get('DEFAULT_ENV_FILE', __build_in_default_config['DEFAULT_ENV_FILE'])
295
- DEFAULT_USERNAME = __configs_from_file.get('DEFAULT_USERNAME', __build_in_default_config['DEFAULT_USERNAME'])
296
- DEFAULT_PASSWORD = __configs_from_file.get('DEFAULT_PASSWORD', __build_in_default_config['DEFAULT_PASSWORD'])
297
- DEFAULT_IDENTITY_FILE = __configs_from_file.get('DEFAULT_IDENTITY_FILE', __build_in_default_config['DEFAULT_IDENTITY_FILE'])
298
- DEDAULT_SSH_KEY_SEARCH_PATH = __configs_from_file.get('DEDAULT_SSH_KEY_SEARCH_PATH', __build_in_default_config['DEDAULT_SSH_KEY_SEARCH_PATH'])
299
- DEFAULT_USE_KEY = __configs_from_file.get('DEFAULT_USE_KEY', __build_in_default_config['DEFAULT_USE_KEY'])
300
- DEFAULT_EXTRA_ARGS = __configs_from_file.get('DEFAULT_EXTRA_ARGS', __build_in_default_config['DEFAULT_EXTRA_ARGS'])
301
- DEFAULT_ONE_ON_ONE = __configs_from_file.get('DEFAULT_ONE_ON_ONE', __build_in_default_config['DEFAULT_ONE_ON_ONE'])
302
- DEFAULT_SCP = __configs_from_file.get('DEFAULT_SCP', __build_in_default_config['DEFAULT_SCP'])
303
- DEFAULT_FILE_SYNC = __configs_from_file.get('DEFAULT_FILE_SYNC', __build_in_default_config['DEFAULT_FILE_SYNC'])
304
- DEFAULT_TIMEOUT = __configs_from_file.get('DEFAULT_TIMEOUT', __build_in_default_config['DEFAULT_TIMEOUT'])
305
- DEFAULT_CLI_TIMEOUT = __configs_from_file.get('DEFAULT_CLI_TIMEOUT', __build_in_default_config['DEFAULT_CLI_TIMEOUT'])
306
- DEFAULT_REPEAT = __configs_from_file.get('DEFAULT_REPEAT', __build_in_default_config['DEFAULT_REPEAT'])
307
- DEFAULT_INTERVAL = __configs_from_file.get('DEFAULT_INTERVAL', __build_in_default_config['DEFAULT_INTERVAL'])
308
- DEFAULT_IPMI = __configs_from_file.get('DEFAULT_IPMI', __build_in_default_config['DEFAULT_IPMI'])
309
- DEFAULT_IPMI_INTERFACE_IP_PREFIX = __configs_from_file.get('DEFAULT_IPMI_INTERFACE_IP_PREFIX', __build_in_default_config['DEFAULT_IPMI_INTERFACE_IP_PREFIX'])
310
- DEFAULT_INTERFACE_IP_PREFIX = __configs_from_file.get('DEFAULT_INTERFACE_IP_PREFIX', __build_in_default_config['DEFAULT_INTERFACE_IP_PREFIX'])
311
- DEFAULT_NO_WATCH = __configs_from_file.get('DEFAULT_NO_WATCH', __build_in_default_config['DEFAULT_NO_WATCH'])
312
- DEFAULT_CURSES_MINIMUM_CHAR_LEN = __configs_from_file.get('DEFAULT_CURSES_MINIMUM_CHAR_LEN', __build_in_default_config['DEFAULT_CURSES_MINIMUM_CHAR_LEN'])
313
- DEFAULT_CURSES_MINIMUM_LINE_LEN = __configs_from_file.get('DEFAULT_CURSES_MINIMUM_LINE_LEN', __build_in_default_config['DEFAULT_CURSES_MINIMUM_LINE_LEN'])
314
- DEFAULT_SINGLE_WINDOW = __configs_from_file.get('DEFAULT_SINGLE_WINDOW', __build_in_default_config['DEFAULT_SINGLE_WINDOW'])
315
- DEFAULT_ERROR_ONLY = __configs_from_file.get('DEFAULT_ERROR_ONLY', __build_in_default_config['DEFAULT_ERROR_ONLY'])
316
- DEFAULT_NO_OUTPUT = __configs_from_file.get('DEFAULT_NO_OUTPUT', __build_in_default_config['DEFAULT_NO_OUTPUT'])
317
- DEFAULT_NO_ENV = __configs_from_file.get('DEFAULT_NO_ENV', __build_in_default_config['DEFAULT_NO_ENV'])
318
- DEFAULT_MAX_CONNECTIONS = __configs_from_file.get('DEFAULT_MAX_CONNECTIONS', __build_in_default_config['DEFAULT_MAX_CONNECTIONS'])
319
- if not DEFAULT_MAX_CONNECTIONS:
320
- DEFAULT_MAX_CONNECTIONS = 4 * os.cpu_count()
321
- DEFAULT_JSON_MODE = __configs_from_file.get('DEFAULT_JSON_MODE', __build_in_default_config['DEFAULT_JSON_MODE'])
322
- DEFAULT_PRINT_SUCCESS_HOSTS = __configs_from_file.get('DEFAULT_PRINT_SUCCESS_HOSTS', __build_in_default_config['DEFAULT_PRINT_SUCCESS_HOSTS'])
323
- DEFAULT_GREPPABLE_MODE = __configs_from_file.get('DEFAULT_GREPPABLE_MODE', __build_in_default_config['DEFAULT_GREPPABLE_MODE'])
324
- DEFAULT_SKIP_UNREACHABLE = __configs_from_file.get('DEFAULT_SKIP_UNREACHABLE', __build_in_default_config['DEFAULT_SKIP_UNREACHABLE'])
325
- DEFAULT_SKIP_HOSTS = __configs_from_file.get('DEFAULT_SKIP_HOSTS', __build_in_default_config['DEFAULT_SKIP_HOSTS'])
326
-
327
- SSH_STRICT_HOST_KEY_CHECKING = __configs_from_file.get('SSH_STRICT_HOST_KEY_CHECKING', __build_in_default_config['SSH_STRICT_HOST_KEY_CHECKING'])
328
-
329
- ERROR_MESSAGES_TO_IGNORE = __configs_from_file.get('ERROR_MESSAGES_TO_IGNORE', __build_in_default_config['ERROR_MESSAGES_TO_IGNORE'])
330
-
331
- _DEFAULT_CALLED = __configs_from_file.get('_DEFAULT_CALLED', __build_in_default_config['_DEFAULT_CALLED'])
332
- _DEFAULT_RETURN_UNFINISHED = __configs_from_file.get('_DEFAULT_RETURN_UNFINISHED', __build_in_default_config['_DEFAULT_RETURN_UNFINISHED'])
333
- _DEFAULT_UPDATE_UNREACHABLE_HOSTS = __configs_from_file.get('_DEFAULT_UPDATE_UNREACHABLE_HOSTS', __build_in_default_config['_DEFAULT_UPDATE_UNREACHABLE_HOSTS'])
334
- _DEFAULT_NO_START = __configs_from_file.get('_DEFAULT_NO_START', __build_in_default_config['_DEFAULT_NO_START'])
335
-
295
+ __configs_from_file = {}
296
+ for config_file in reversed(CONFIG_FILE_CHAIN.copy()):
297
+ __configs_from_file.update(load_config_file(os.path.expanduser(config_file)))
298
+ globals().update(__configs_from_file)
336
299
  # form the regex from the list
337
- __ERROR_MESSAGES_TO_IGNORE_REGEX = __configs_from_file.get('__ERROR_MESSAGES_TO_IGNORE_REGEX', __build_in_default_config['__ERROR_MESSAGES_TO_IGNORE_REGEX'])
338
300
  if __ERROR_MESSAGES_TO_IGNORE_REGEX:
339
- eprint('Using __ERROR_MESSAGES_TO_IGNORE_REGEX from config file, ignoring ERROR_MESSAGES_TO_IGNORE')
340
- __ERROR_MESSAGES_TO_IGNORE_REGEX = re.compile(__configs_from_file['__ERROR_MESSAGES_TO_IGNORE_REGEX'])
301
+ eprint('Using __ERROR_MESSAGES_TO_IGNORE_REGEX, ignoring ERROR_MESSAGES_TO_IGNORE')
302
+ __ERROR_MESSAGES_TO_IGNORE_REGEX = re.compile(__ERROR_MESSAGES_TO_IGNORE_REGEX)
341
303
  else:
342
304
  __ERROR_MESSAGES_TO_IGNORE_REGEX = re.compile('|'.join(ERROR_MESSAGES_TO_IGNORE))
343
305
 
344
- __DEBUG_MODE = __configs_from_file.get('__DEBUG_MODE', __build_in_default_config['__DEBUG_MODE'])
345
-
346
306
  # Load mssh Functional Global Variables
347
307
  if True:
348
308
  __global_suppress_printout = False
@@ -355,7 +315,6 @@ if True:
355
315
  __ipmiiInterfaceIPPrefix = DEFAULT_IPMI_INTERFACE_IP_PREFIX
356
316
  __keyPressesIn = [[]]
357
317
  _emo = False
358
- _etc_hosts = __configs_from_file.get('_etc_hosts', __build_in_default_config['_etc_hosts'])
359
318
  __curses_global_color_pairs = {(-1,-1):1}
360
319
  __curses_current_color_pair_index = 2 # Start from 1, as 0 is the default color pair
361
320
  __curses_color_table = {}
@@ -394,12 +353,11 @@ if __curses_available:
394
353
  _binPaths = {}
395
354
  def check_path(program_name):
396
355
  global __configs_from_file
397
- global __build_in_default_config
398
356
  global _binPaths
399
357
  config_key = f'_{program_name}Path'
400
358
  program_path = (
401
359
  __configs_from_file.get(config_key) or
402
- __build_in_default_config.get(config_key) or
360
+ globals().get(config_key) or
403
361
  shutil.which(program_name)
404
362
  )
405
363
  if program_path:
@@ -2715,14 +2673,45 @@ def generate_default_config(args):
2715
2673
  'ERROR_MESSAGES_TO_IGNORE': ERROR_MESSAGES_TO_IGNORE,
2716
2674
  }
2717
2675
 
2718
- def write_default_config(args,CONFIG_FILE,backup = True):
2719
- if backup and os.path.exists(CONFIG_FILE):
2720
- os.rename(CONFIG_FILE,CONFIG_FILE+'.bak')
2676
+ def write_default_config(args,CONFIG_FILE = None):
2721
2677
  default_config = generate_default_config(args)
2722
2678
  # apply the updated defualt_config to __configs_from_file and write that to file
2723
2679
  __configs_from_file.update(default_config)
2724
- with open(CONFIG_FILE,'w') as f:
2725
- json.dump(__configs_from_file,f,indent=4)
2680
+ if not CONFIG_FILE:
2681
+ print(json.dumps(__configs_from_file, indent=4))
2682
+ return
2683
+ backup = True
2684
+ if os.path.exists(CONFIG_FILE):
2685
+ eprint(f"Warning: {CONFIG_FILE!r} already exists, what to do? (o/b/n)")
2686
+ eprint(f"o: Overwrite the file")
2687
+ eprint(f"b: Rename the current config file at {CONFIG_FILE!r}.bak forcefully and write the new config file (default)")
2688
+ eprint(f"n: Do nothing")
2689
+ inStr = input_with_timeout_and_countdown(10)
2690
+ if (not inStr) or inStr.lower().strip().startswith('b'):
2691
+ backup = True
2692
+ elif inStr.lower().strip().startswith('o'):
2693
+ backup = False
2694
+ else:
2695
+ eprint("Aborted")
2696
+ sys.exit(1)
2697
+ try:
2698
+ if backup and os.path.exists(CONFIG_FILE):
2699
+ os.rename(CONFIG_FILE,CONFIG_FILE+'.bak')
2700
+ except Exception as e:
2701
+ eprint(f"Error: Unable to backup the config file: {e!r}")
2702
+ eprint(f"Do you want to continue writing the new config file to {CONFIG_FILE!r}? (y/n)")
2703
+ inStr = input_with_timeout_and_countdown(10)
2704
+ if not inStr or not inStr.lower().strip().startswith('y'):
2705
+ eprint("Aborted")
2706
+ sys.exit(1)
2707
+ try:
2708
+ with open(CONFIG_FILE,'w') as f:
2709
+ json.dump(__configs_from_file,f,indent=4)
2710
+ eprint(f"Config file written to {CONFIG_FILE!r}")
2711
+ except Exception as e:
2712
+ eprint(f"Error: Unable to write to the config file: {e!r}")
2713
+ eprint(f'Printing the config file to stdout:')
2714
+ print(json.dumps(__configs_from_file, indent=4))
2726
2715
 
2727
2716
  # ------------ Wrapper Block ----------------
2728
2717
  def main():
@@ -2734,11 +2723,12 @@ def main():
2734
2723
  global _binPaths
2735
2724
  global _env_file
2736
2725
  global __DEBUG_MODE
2726
+ global __configs_from_file
2737
2727
  _emo = False
2738
2728
  # We handle the signal
2739
2729
  signal.signal(signal.SIGINT, signal_handler)
2740
2730
  # We parse the arguments
2741
- parser = argparse.ArgumentParser(description=f'Run a command on multiple hosts, Use #HOST# or #HOSTNAME# to replace the host name in the command. Config file: {CONFIG_FILE}')
2731
+ parser = argparse.ArgumentParser(description=f'Run a command on multiple hosts, Use #HOST# or #HOSTNAME# to replace the host name in the command. Config file chain: {CONFIG_FILE_CHAIN!r}')
2742
2732
  parser.add_argument('hosts', metavar='hosts', type=str, nargs='?', help=f'Hosts to run the command on, use "," to seperate hosts. (default: {DEFAULT_HOSTS})',default=DEFAULT_HOSTS)
2743
2733
  parser.add_argument('commands', metavar='commands', type=str, nargs='*',default=None,help='the command to run on the hosts / the destination of the files #HOST# or #HOSTNAME# will be replaced with the host name.')
2744
2734
  parser.add_argument('-u','--username', type=str,help=f'The general username to use to connect to the hosts. Will get overwrote by individual username@host if specified. (default: {DEFAULT_USERNAME})',default=DEFAULT_USERNAME)
@@ -2775,7 +2765,9 @@ def main():
2775
2765
  group.add_argument("-nsu","--no_skip_unreachable",dest = 'skip_unreachable', action='store_false', help=f"Do not skip unreachable hosts. Note: Timedout Hosts are considered unreachable. Note: multiple command sequence will still auto skip unreachable hosts. (default: {not DEFAULT_SKIP_UNREACHABLE})", default=not DEFAULT_SKIP_UNREACHABLE)
2776
2766
 
2777
2767
  parser.add_argument("-sh","--skip_hosts", type=str, help=f"Skip the hosts in the list. (default: {DEFAULT_SKIP_HOSTS if DEFAULT_SKIP_HOSTS else 'None'})", default=DEFAULT_SKIP_HOSTS)
2778
- parser.add_argument('--store_config_file', action='store_true', help=f'Store / generate the default config file from command line argument and current config at {CONFIG_FILE}')
2768
+ parser.add_argument('--generate_config_file', action='store_true', help=f'Store / generate the default config file from command line argument and current config at --config_file / stdout')
2769
+ parser.add_argument('--config_file', type=str,nargs='?', help=f'Additional config file to use, will pioritize over config chains. When using with store_config_file, will store the resulting config file at this location. Use without a path will use multiSSH3.config.json',const='multiSSH3.config.json',default=None)
2770
+ parser.add_argument('--store_config_file',type = str,nargs='?',help=f'Store the default config file from command line argument and current config. Same as --store_config_file --config_file=<path>',const='multiSSH3.config.json')
2779
2771
  parser.add_argument('--debug', action='store_true', help='Print debug information')
2780
2772
  parser.add_argument('-ci','--copy_id', action='store_true', help='Copy the ssh id to the hosts')
2781
2773
  parser.add_argument("-V","--version", action='version', version=f'%(prog)s {version} with [ {", ".join(_binPaths.keys())} ] by {AUTHOR} ({AUTHOR_EMAIL})')
@@ -2796,33 +2788,26 @@ def main():
2796
2788
  eprint(f"Warning: Unknown arguments, treating all as commands: {unknown!r}")
2797
2789
  args.commands += unknown
2798
2790
 
2799
-
2800
-
2801
- if args.store_config_file:
2802
- try:
2803
- if os.path.exists(CONFIG_FILE):
2804
- eprint(f"Warning: {CONFIG_FILE!r} already exists, what to do? (o/b/n)")
2805
- eprint(f"o: Overwrite the file")
2806
- eprint(f"b: Rename the current config file at {CONFIG_FILE!r}.bak forcefully and write the new config file (default)")
2807
- eprint(f"n: Do nothing")
2808
- inStr = input_with_timeout_and_countdown(10)
2809
- if (not inStr) or inStr.lower().strip().startswith('b'):
2810
- write_default_config(args,CONFIG_FILE,backup = True)
2811
- eprint(f"Config file written to {CONFIG_FILE!r}")
2812
- elif inStr.lower().strip().startswith('o'):
2813
- write_default_config(args,CONFIG_FILE,backup = False)
2814
- eprint(f"Config file written to {CONFIG_FILE!r}")
2815
- else:
2816
- write_default_config(args,CONFIG_FILE,backup = True)
2817
- eprint(f"Config file written to {CONFIG_FILE!r}")
2818
- except Exception as e:
2819
- eprint(f"Error while writing config file: {e!r}")
2820
- import traceback
2821
- eprint(traceback.format_exc())
2822
- if not args.commands:
2823
- with open(CONFIG_FILE,'r') as f:
2791
+ if args.generate_config_file or args.store_config_file:
2792
+ if args.store_config_file:
2793
+ configFileToWriteTo = args.store_config_file
2794
+ if args.config_file:
2795
+ if os.path.exists(args.config_file):
2796
+ __configs_from_file.update(load_config_file(os.path.expanduser(args.config_file)))
2797
+ else:
2798
+ eprint(f"Warning: Pre store config file {args.config_file!r} not found.")
2799
+ else:
2800
+ configFileToWriteTo = args.config_file
2801
+ write_default_config(args,configFileToWriteTo)
2802
+ if not args.commands and configFileToWriteTo:
2803
+ with open(configFileToWriteTo,'r') as f:
2824
2804
  eprint(f"Config file content: \n{f.read()}")
2825
2805
  sys.exit(0)
2806
+ if args.config_file:
2807
+ if os.path.exists(args.config_file):
2808
+ __configs_from_file.update(load_config_file(os.path.expanduser(args.config_file)))
2809
+ else:
2810
+ eprint(f"Warning: Config file {args.config_file!r} not found, ignoring it.")
2826
2811
 
2827
2812
  _env_file = args.env_file
2828
2813
  __DEBUG_MODE = args.debug
@@ -1,6 +0,0 @@
1
- multiSSH3.py,sha256=XcI427f_uDAZzhRVSrnGa2CLQbEIcRfNHuRxGm-hC-c,138864
2
- multiSSH3-5.43.dist-info/METADATA,sha256=aRmafYNhFOtGQDjkn4biNypqy01CJ1Y35eMwok4udYk,18001
3
- multiSSH3-5.43.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
4
- multiSSH3-5.43.dist-info/entry_points.txt,sha256=xi2rWWNfmHx6gS8Mmx0rZL2KZz6XWBYP3DWBpWAnnZ0,143
5
- multiSSH3-5.43.dist-info/top_level.txt,sha256=tUwttxlnpLkZorSsroIprNo41lYSxjd2ASuL8-EJIJw,10
6
- multiSSH3-5.43.dist-info/RECORD,,