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.
- {multiSSH3-5.43.dist-info → multiSSH3-5.44.dist-info}/METADATA +1 -1
- multiSSH3-5.44.dist-info/RECORD +6 -0
- multiSSH3.py +126 -141
- multiSSH3-5.43.dist-info/RECORD +0 -6
- {multiSSH3-5.43.dist-info → multiSSH3-5.44.dist-info}/WHEEL +0 -0
- {multiSSH3-5.43.dist-info → multiSSH3-5.44.dist-info}/entry_points.txt +0 -0
- {multiSSH3-5.43.dist-info → multiSSH3-5.44.dist-info}/top_level.txt +0 -0
|
@@ -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.
|
|
48
|
+
version = '5.44'
|
|
49
49
|
VERSION = version
|
|
50
50
|
|
|
51
|
-
|
|
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
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
'
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
'
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
'
|
|
261
|
-
|
|
262
|
-
|
|
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
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
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
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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
|
|
340
|
-
__ERROR_MESSAGES_TO_IGNORE_REGEX = re.compile(
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
2725
|
-
json.
|
|
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: {
|
|
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('--
|
|
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
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
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
|
multiSSH3-5.43.dist-info/RECORD
DELETED
|
@@ -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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|