multiSSH3 5.68__py3-none-any.whl → 5.69__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 +40 -36
- {multissh3-5.68.dist-info → multissh3-5.69.dist-info}/METADATA +1 -1
- multissh3-5.69.dist-info/RECORD +6 -0
- {multissh3-5.68.dist-info → multissh3-5.69.dist-info}/WHEEL +1 -1
- multissh3-5.68.dist-info/RECORD +0 -6
- {multissh3-5.68.dist-info → multissh3-5.69.dist-info}/entry_points.txt +0 -0
- {multissh3-5.68.dist-info → multissh3-5.69.dist-info}/top_level.txt +0 -0
multiSSH3.py
CHANGED
|
@@ -54,7 +54,7 @@ except AttributeError:
|
|
|
54
54
|
# If neither is available, use a dummy decorator
|
|
55
55
|
def cache_decorator(func):
|
|
56
56
|
return func
|
|
57
|
-
version = '5.
|
|
57
|
+
version = '5.69'
|
|
58
58
|
VERSION = version
|
|
59
59
|
__version__ = version
|
|
60
60
|
COMMIT_DATE = '2025-05-09'
|
|
@@ -349,7 +349,7 @@ __failedHosts = set()
|
|
|
349
349
|
__wildCharacters = ['*','?','x']
|
|
350
350
|
_no_env = DEFAULT_NO_ENV
|
|
351
351
|
_env_file = DEFAULT_ENV_FILE
|
|
352
|
-
__globalUnavailableHosts =
|
|
352
|
+
__globalUnavailableHosts = dict()
|
|
353
353
|
__ipmiiInterfaceIPPrefix = DEFAULT_IPMI_INTERFACE_IP_PREFIX
|
|
354
354
|
__keyPressesIn = [[]]
|
|
355
355
|
_emo = False
|
|
@@ -2235,7 +2235,7 @@ def generate_output(hosts, usejson = False, greppable = False):
|
|
|
2235
2235
|
hostPrintOut = f" Command:\n {host['command']}\n"
|
|
2236
2236
|
hostPrintOut += " stdout:\n "+'\n '.join(host['stdout'])
|
|
2237
2237
|
if host['stderr']:
|
|
2238
|
-
if host['stderr'][0].strip().startswith('ssh: connect to host '):
|
|
2238
|
+
if host['stderr'][0].strip().startswith('ssh: connect to host ') and host['stderr'][0].strip().endswith('Connection refused'):
|
|
2239
2239
|
host['stderr'][0] = 'SSH not reachable!'
|
|
2240
2240
|
elif host['stderr'][-1].strip().endswith('Connection timed out'):
|
|
2241
2241
|
host['stderr'][-1] = 'SSH connection timed out!'
|
|
@@ -2287,7 +2287,7 @@ def print_output(hosts,usejson = False,quiet = False,greppable = False):
|
|
|
2287
2287
|
|
|
2288
2288
|
#%% ------------ Run / Process Hosts Block ----------------
|
|
2289
2289
|
def processRunOnHosts(timeout, password, max_connections, hosts, returnUnfinished, no_watch, json, called, greppable,
|
|
2290
|
-
unavailableHosts,willUpdateUnreachableHosts,curses_min_char_len = DEFAULT_CURSES_MINIMUM_CHAR_LEN,
|
|
2290
|
+
unavailableHosts:dict,willUpdateUnreachableHosts,curses_min_char_len = DEFAULT_CURSES_MINIMUM_CHAR_LEN,
|
|
2291
2291
|
curses_min_line_len = DEFAULT_CURSES_MINIMUM_LINE_LEN,single_window = DEFAULT_SINGLE_WINDOW,
|
|
2292
2292
|
unavailable_host_expiry = DEFAULT_UNAVAILABLE_HOST_EXPIRY):
|
|
2293
2293
|
global __globalUnavailableHosts
|
|
@@ -2317,45 +2317,47 @@ def processRunOnHosts(timeout, password, max_connections, hosts, returnUnfinishe
|
|
|
2317
2317
|
thread.join(timeout=3)
|
|
2318
2318
|
# update the unavailable hosts and global unavailable hosts
|
|
2319
2319
|
if willUpdateUnreachableHosts:
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2320
|
+
availableHosts = set()
|
|
2321
|
+
for host in hosts:
|
|
2322
|
+
if host.stderr and ('No route to host' in host.stderr[0].strip() or 'Connection timed out' in host.stderr[0].strip() or (host.stderr[-1].strip().startswith('Timeout!') and host.returncode == 124)):
|
|
2323
|
+
unavailableHosts[host.name] = int(time.monotonic())
|
|
2324
|
+
__globalUnavailableHosts[host.name] = int(time.monotonic())
|
|
2325
|
+
else:
|
|
2326
|
+
availableHosts.add(host.name)
|
|
2327
|
+
if host.name in unavailableHosts:
|
|
2328
|
+
del unavailableHosts[host.name]
|
|
2329
|
+
if host.name in __globalUnavailableHosts:
|
|
2330
|
+
del __globalUnavailableHosts[host.name]
|
|
2324
2331
|
if __DEBUG_MODE:
|
|
2325
2332
|
print(f'Unreachable hosts: {unavailableHosts}')
|
|
2326
|
-
__globalUnavailableHosts.update(unavailableHosts)
|
|
2327
|
-
|
|
2328
|
-
# os.environ['__multiSSH3_UNAVAILABLE_HOSTS'] = ','.join(unavailableHosts)
|
|
2329
|
-
# create a temporary file to store the unavailable hosts
|
|
2330
2333
|
try:
|
|
2331
2334
|
# check for the old content, only update if the new content is different
|
|
2332
|
-
if not os.path.exists(os.path.join(tempfile.gettempdir(),'
|
|
2333
|
-
with open(os.path.join(tempfile.gettempdir(),'
|
|
2334
|
-
f.
|
|
2335
|
+
if not os.path.exists(os.path.join(tempfile.gettempdir(),f'__{getpass.getuser()}_multiSSH3_UNAVAILABLE_HOSTS.csv')):
|
|
2336
|
+
with open(os.path.join(tempfile.gettempdir(),f'__{getpass.getuser()}_multiSSH3_UNAVAILABLE_HOSTS.csv'),'w') as f:
|
|
2337
|
+
f.writelines(f'{host},{expTime}' for host,expTime in unavailableHosts.values())
|
|
2335
2338
|
else:
|
|
2336
2339
|
oldDic = {}
|
|
2337
2340
|
try:
|
|
2338
|
-
with open(os.path.join(tempfile.gettempdir(),'
|
|
2341
|
+
with open(os.path.join(tempfile.gettempdir(),f'__{getpass.getuser()}_multiSSH3_UNAVAILABLE_HOSTS.csv'),'r') as f:
|
|
2339
2342
|
for line in f:
|
|
2340
2343
|
line = line.strip()
|
|
2341
2344
|
if line and ',' in line and len(line.split(',')) >= 2 and line.split(',')[0] and line.split(',')[1].isdigit():
|
|
2342
|
-
|
|
2345
|
+
hostname = line.split(',')[0]
|
|
2346
|
+
expireTime = int(line.split(',')[1])
|
|
2347
|
+
if expireTime < time.monotonic() and hostname not in availableHosts:
|
|
2348
|
+
oldDic[hostname] = expireTime
|
|
2343
2349
|
except:
|
|
2344
2350
|
pass
|
|
2345
|
-
for key in list(oldDic.keys()):
|
|
2346
|
-
if key in reachableHosts or time.monotonic() < oldDic[key] or time.monotonic() - oldDic[key] > unavailable_host_expiry:
|
|
2347
|
-
del oldDic[key]
|
|
2348
2351
|
# add new entries
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
oldDic[host] = int(time.monotonic ())
|
|
2352
|
-
with open(os.path.join(tempfile.gettempdir(),'__multiSSH3_UNAVAILABLE_HOSTS.csv.new'),'w') as f:
|
|
2352
|
+
oldDic.update(unavailableHosts)
|
|
2353
|
+
with open(os.path.join(tempfile.gettempdir(),getpass.getuser()+'__multiSSH3_UNAVAILABLE_HOSTS.csv.new'),'w') as f:
|
|
2353
2354
|
for key, value in oldDic.items():
|
|
2354
2355
|
f.write(f'{key},{value}\n')
|
|
2355
|
-
os.replace(os.path.join(tempfile.gettempdir(),'__multiSSH3_UNAVAILABLE_HOSTS.csv.new'),os.path.join(tempfile.gettempdir(),'
|
|
2356
|
-
|
|
2356
|
+
os.replace(os.path.join(tempfile.gettempdir(),getpass.getuser()+'__multiSSH3_UNAVAILABLE_HOSTS.csv.new'),os.path.join(tempfile.gettempdir(),f'__{getpass.getuser()}_multiSSH3_UNAVAILABLE_HOSTS.csv'))
|
|
2357
2357
|
except Exception as e:
|
|
2358
2358
|
eprint(f'Error writing to temporary file: {e!r}')
|
|
2359
|
+
import traceback
|
|
2360
|
+
eprint(traceback.format_exc())
|
|
2359
2361
|
|
|
2360
2362
|
# print the output, if the output of multiple hosts are the same, we aggragate them
|
|
2361
2363
|
if not called:
|
|
@@ -2566,27 +2568,29 @@ def run_command_on_hosts(hosts = DEFAULT_HOSTS,commands = None,oneonone = DEFAUL
|
|
|
2566
2568
|
record_command_history(locals())
|
|
2567
2569
|
if error_only:
|
|
2568
2570
|
__global_suppress_printout = True
|
|
2569
|
-
if os.path.exists(os.path.join(tempfile.gettempdir(),'
|
|
2571
|
+
if os.path.exists(os.path.join(tempfile.gettempdir(),f'__{getpass.getuser()}_multiSSH3_UNAVAILABLE_HOSTS.csv')):
|
|
2570
2572
|
if unavailable_host_expiry <= 0:
|
|
2571
2573
|
unavailable_host_expiry = 10
|
|
2572
2574
|
try:
|
|
2573
2575
|
readed = False
|
|
2574
|
-
if 0 < time.time() - os.path.getmtime(os.path.join(tempfile.gettempdir(),'
|
|
2576
|
+
if 0 < time.time() - os.path.getmtime(os.path.join(tempfile.gettempdir(),f'__{getpass.getuser()}_multiSSH3_UNAVAILABLE_HOSTS.csv')) < unavailable_host_expiry:
|
|
2575
2577
|
|
|
2576
|
-
with open(os.path.join(tempfile.gettempdir(),'
|
|
2578
|
+
with open(os.path.join(tempfile.gettempdir(),f'__{getpass.getuser()}_multiSSH3_UNAVAILABLE_HOSTS.csv'),'r') as f:
|
|
2577
2579
|
for line in f:
|
|
2578
2580
|
line = line.strip()
|
|
2579
2581
|
if line and ',' in line and len(line.split(',')) >= 2 and line.split(',')[0] and line.split(',')[1].isdigit():
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
+
hostname = line.split(',')[0]
|
|
2583
|
+
expireTime = int(line.split(',')[1])
|
|
2584
|
+
if expireTime < time.monotonic() and expireTime + unavailable_host_expiry > time.monotonic():
|
|
2585
|
+
__globalUnavailableHosts[hostname] = expireTime
|
|
2582
2586
|
readed = True
|
|
2583
2587
|
if readed and not __global_suppress_printout:
|
|
2584
|
-
eprint(f"Read unavailable hosts from the file {os.path.join(tempfile.gettempdir(),'
|
|
2588
|
+
eprint(f"Read unavailable hosts from the file {os.path.join(tempfile.gettempdir(),f'__{getpass.getuser()}_multiSSH3_UNAVAILABLE_HOSTS.csv')}")
|
|
2585
2589
|
except Exception as e:
|
|
2586
|
-
eprint(f"Warning: Unable to read the unavailable hosts from the file {os.path.join(tempfile.gettempdir(),'
|
|
2590
|
+
eprint(f"Warning: Unable to read the unavailable hosts from the file {os.path.join(tempfile.gettempdir(),f'__{getpass.getuser()}_multiSSH3_UNAVAILABLE_HOSTS.csv')!r}")
|
|
2587
2591
|
eprint(str(e))
|
|
2588
2592
|
elif '__multiSSH3_UNAVAILABLE_HOSTS' in readEnvFromFile():
|
|
2589
|
-
__globalUnavailableHosts.update(readEnvFromFile()['__multiSSH3_UNAVAILABLE_HOSTS'].split(','))
|
|
2593
|
+
__globalUnavailableHosts.update({host: int(time.monotonic()) for host in readEnvFromFile()['__multiSSH3_UNAVAILABLE_HOSTS'].split(',') if host})
|
|
2590
2594
|
if not max_connections:
|
|
2591
2595
|
max_connections = 4 * os.cpu_count()
|
|
2592
2596
|
elif max_connections == 0:
|
|
@@ -2619,7 +2623,7 @@ def run_command_on_hosts(hosts = DEFAULT_HOSTS,commands = None,oneonone = DEFAUL
|
|
|
2619
2623
|
if skipUnreachable:
|
|
2620
2624
|
unavailableHosts = __globalUnavailableHosts
|
|
2621
2625
|
else:
|
|
2622
|
-
unavailableHosts =
|
|
2626
|
+
unavailableHosts = dict()
|
|
2623
2627
|
# set global input to empty
|
|
2624
2628
|
__keyPressesIn = [[]]
|
|
2625
2629
|
__global_suppress_printout = True
|
|
@@ -2628,7 +2632,7 @@ def run_command_on_hosts(hosts = DEFAULT_HOSTS,commands = None,oneonone = DEFAUL
|
|
|
2628
2632
|
if skipUnreachable:
|
|
2629
2633
|
unavailableHosts = __globalUnavailableHosts
|
|
2630
2634
|
else:
|
|
2631
|
-
unavailableHosts =
|
|
2635
|
+
unavailableHosts = dict()
|
|
2632
2636
|
skipUnreachable = True
|
|
2633
2637
|
if quiet:
|
|
2634
2638
|
__global_suppress_printout = True
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
multiSSH3.py,sha256=Fh69JiPpBe27zs05RmXa8z1CQmaNXh7hVIZl_RN2iGY,144513
|
|
2
|
+
multissh3-5.69.dist-info/METADATA,sha256=2PFFZiQ4Jck3s1L0DjzHtNerxXPGaxe3maZ8_UOonhU,18093
|
|
3
|
+
multissh3-5.69.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
|
|
4
|
+
multissh3-5.69.dist-info/entry_points.txt,sha256=xi2rWWNfmHx6gS8Mmx0rZL2KZz6XWBYP3DWBpWAnnZ0,143
|
|
5
|
+
multissh3-5.69.dist-info/top_level.txt,sha256=tUwttxlnpLkZorSsroIprNo41lYSxjd2ASuL8-EJIJw,10
|
|
6
|
+
multissh3-5.69.dist-info/RECORD,,
|
multissh3-5.68.dist-info/RECORD
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
multiSSH3.py,sha256=_Lr8Q00fGgVkJAtP6NXZGnfipNa5yqiZplxg5ZDXvqI,144176
|
|
2
|
-
multissh3-5.68.dist-info/METADATA,sha256=mwLzCxpuDPk_k0JqGCGE0CMVOmg9DBs7GHNOPtNvJ6A,18093
|
|
3
|
-
multissh3-5.68.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
|
4
|
-
multissh3-5.68.dist-info/entry_points.txt,sha256=xi2rWWNfmHx6gS8Mmx0rZL2KZz6XWBYP3DWBpWAnnZ0,143
|
|
5
|
-
multissh3-5.68.dist-info/top_level.txt,sha256=tUwttxlnpLkZorSsroIprNo41lYSxjd2ASuL8-EJIJw,10
|
|
6
|
-
multissh3-5.68.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|