multiSSH3 5.25__tar.gz → 5.27__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: multiSSH3
3
- Version: 5.25
3
+ Version: 5.27
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
@@ -96,7 +96,7 @@ An example .ssh/config:
96
96
  Host *
97
97
  StrictHostKeyChecking no
98
98
  ControlMaster auto
99
- ControlPath /run/ssh_sockets_%r@%h-%p
99
+ ControlPath /tmp/%u_ssh_sockets_%r@%h-%p
100
100
  ControlPersist 3600
101
101
  ```
102
102
 
@@ -124,10 +124,10 @@ While leaving minimum 40 characters / 1 line for each host display by default. Y
124
124
  Use ```mssh --help``` for more info.
125
125
 
126
126
  ```bash
127
- usage: mssh [-h] [-u USERNAME] [-p PASSWORD] [-ea EXTRAARGS] [-11] [-f FILE] [-fs] [--scp] [-gm] [-t TIMEOUT] [-r REPEAT] [-i INTERVAL]
128
- [--ipmi] [-mpre IPMI_INTERFACE_IP_PREFIX] [-pre INTERFACE_IP_PREFIX] [-q] [-ww WINDOW_WIDTH] [-wh WINDOW_HEIGHT] [-sw] [-eo]
129
- [-no] [--no_env] [--env_file ENV_FILE] [-m MAX_CONNECTIONS] [-j] [--success_hosts] [-g] [-su] [-sh SKIP_HOSTS]
130
- [--store_config_file] [--debug] [--copy-id] [-V]
127
+ usage: mssh [-h] [-u USERNAME] [-p PASSWORD] [-k [KEY]] [-uk] [-ea EXTRAARGS] [-11] [-f FILE] [-fs] [--scp] [-gm] [-t TIMEOUT] [-r REPEAT]
128
+ [-i INTERVAL] [--ipmi] [-mpre IPMI_INTERFACE_IP_PREFIX] [-pre INTERFACE_IP_PREFIX] [-q] [-ww WINDOW_WIDTH] [-wh WINDOW_HEIGHT]
129
+ [-sw] [-eo] [-no] [--no_env] [--env_file ENV_FILE] [-m MAX_CONNECTIONS] [-j] [--success_hosts] [-g] [-su | -nsu]
130
+ [-sh SKIP_HOSTS] [--store_config_file] [--debug] [-ci] [-V]
131
131
  [hosts] [commands ...]
132
132
 
133
133
  Run a command on multiple hosts, Use #HOST# or #HOSTNAME# to replace the host name in the command. Config file: /etc/multiSSH3.config.json
@@ -144,6 +144,10 @@ options:
144
144
  (default: None)
145
145
  -p PASSWORD, --password PASSWORD
146
146
  The password to use to connect to the hosts, (default: )
147
+ -k [KEY], --key [KEY], --identity [KEY]
148
+ The identity file to use to connect to the hosts. Implies --use_key. Specify a folder for program to search for a
149
+ key. Use option without value to use ~/.ssh/ (default: None)
150
+ -uk, --use_key Attempt to use public key file to connect to the hosts. (default: False)
147
151
  -ea EXTRAARGS, --extraargs EXTRAARGS
148
152
  Extra arguments to pass to the ssh / rsync / scp command. Put in one string for multiple arguments.Use "=" ! Ex.
149
153
  -ea="--delete" (default: None)
@@ -181,16 +185,20 @@ options:
181
185
  Max number of connections to use (default: 4 * cpu_count)
182
186
  -j, --json Output in json format. (default: False)
183
187
  --success_hosts Output the hosts that succeeded in summary as wells. (default: False)
184
- -g, --greppable Output in greppable format. (default: False)
188
+ -g, --greppable, --table
189
+ Output in greppable format. (default: False)
185
190
  -su, --skip_unreachable
186
- Skip unreachable hosts while using --repeat. Note: Timedout Hosts are considered unreachable. Note: multiple
187
- command sequence will still auto skip unreachable hosts. (default: False)
191
+ Skip unreachable hosts. Note: Timedout Hosts are considered unreachable. Note: multiple command sequence will
192
+ still auto skip unreachable hosts. (default: False)
193
+ -nsu, --no_skip_unreachable
194
+ Do not skip unreachable hosts. Note: Timedout Hosts are considered unreachable. Note: multiple command sequence
195
+ will still auto skip unreachable hosts. (default: True)
188
196
  -sh SKIP_HOSTS, --skip_hosts SKIP_HOSTS
189
197
  Skip the hosts in the list. (default: None)
190
198
  --store_config_file Store / generate the default config file from command line argument and current config at
191
199
  /etc/multiSSH3.config.json
192
200
  --debug Print debug information
193
- --copy-id Copy the ssh id to the hosts
201
+ -ci, --copy_id Copy the ssh id to the hosts
194
202
  -V, --version show program's version number and exit
195
203
  ```
196
204
 
@@ -80,7 +80,7 @@ An example .ssh/config:
80
80
  Host *
81
81
  StrictHostKeyChecking no
82
82
  ControlMaster auto
83
- ControlPath /run/ssh_sockets_%r@%h-%p
83
+ ControlPath /tmp/%u_ssh_sockets_%r@%h-%p
84
84
  ControlPersist 3600
85
85
  ```
86
86
 
@@ -108,10 +108,10 @@ While leaving minimum 40 characters / 1 line for each host display by default. Y
108
108
  Use ```mssh --help``` for more info.
109
109
 
110
110
  ```bash
111
- usage: mssh [-h] [-u USERNAME] [-p PASSWORD] [-ea EXTRAARGS] [-11] [-f FILE] [-fs] [--scp] [-gm] [-t TIMEOUT] [-r REPEAT] [-i INTERVAL]
112
- [--ipmi] [-mpre IPMI_INTERFACE_IP_PREFIX] [-pre INTERFACE_IP_PREFIX] [-q] [-ww WINDOW_WIDTH] [-wh WINDOW_HEIGHT] [-sw] [-eo]
113
- [-no] [--no_env] [--env_file ENV_FILE] [-m MAX_CONNECTIONS] [-j] [--success_hosts] [-g] [-su] [-sh SKIP_HOSTS]
114
- [--store_config_file] [--debug] [--copy-id] [-V]
111
+ usage: mssh [-h] [-u USERNAME] [-p PASSWORD] [-k [KEY]] [-uk] [-ea EXTRAARGS] [-11] [-f FILE] [-fs] [--scp] [-gm] [-t TIMEOUT] [-r REPEAT]
112
+ [-i INTERVAL] [--ipmi] [-mpre IPMI_INTERFACE_IP_PREFIX] [-pre INTERFACE_IP_PREFIX] [-q] [-ww WINDOW_WIDTH] [-wh WINDOW_HEIGHT]
113
+ [-sw] [-eo] [-no] [--no_env] [--env_file ENV_FILE] [-m MAX_CONNECTIONS] [-j] [--success_hosts] [-g] [-su | -nsu]
114
+ [-sh SKIP_HOSTS] [--store_config_file] [--debug] [-ci] [-V]
115
115
  [hosts] [commands ...]
116
116
 
117
117
  Run a command on multiple hosts, Use #HOST# or #HOSTNAME# to replace the host name in the command. Config file: /etc/multiSSH3.config.json
@@ -128,6 +128,10 @@ options:
128
128
  (default: None)
129
129
  -p PASSWORD, --password PASSWORD
130
130
  The password to use to connect to the hosts, (default: )
131
+ -k [KEY], --key [KEY], --identity [KEY]
132
+ The identity file to use to connect to the hosts. Implies --use_key. Specify a folder for program to search for a
133
+ key. Use option without value to use ~/.ssh/ (default: None)
134
+ -uk, --use_key Attempt to use public key file to connect to the hosts. (default: False)
131
135
  -ea EXTRAARGS, --extraargs EXTRAARGS
132
136
  Extra arguments to pass to the ssh / rsync / scp command. Put in one string for multiple arguments.Use "=" ! Ex.
133
137
  -ea="--delete" (default: None)
@@ -165,16 +169,20 @@ options:
165
169
  Max number of connections to use (default: 4 * cpu_count)
166
170
  -j, --json Output in json format. (default: False)
167
171
  --success_hosts Output the hosts that succeeded in summary as wells. (default: False)
168
- -g, --greppable Output in greppable format. (default: False)
172
+ -g, --greppable, --table
173
+ Output in greppable format. (default: False)
169
174
  -su, --skip_unreachable
170
- Skip unreachable hosts while using --repeat. Note: Timedout Hosts are considered unreachable. Note: multiple
171
- command sequence will still auto skip unreachable hosts. (default: False)
175
+ Skip unreachable hosts. Note: Timedout Hosts are considered unreachable. Note: multiple command sequence will
176
+ still auto skip unreachable hosts. (default: False)
177
+ -nsu, --no_skip_unreachable
178
+ Do not skip unreachable hosts. Note: Timedout Hosts are considered unreachable. Note: multiple command sequence
179
+ will still auto skip unreachable hosts. (default: True)
172
180
  -sh SKIP_HOSTS, --skip_hosts SKIP_HOSTS
173
181
  Skip the hosts in the list. (default: None)
174
182
  --store_config_file Store / generate the default config file from command line argument and current config at
175
183
  /etc/multiSSH3.config.json
176
184
  --debug Print debug information
177
- --copy-id Copy the ssh id to the hosts
185
+ -ci, --copy_id Copy the ssh id to the hosts
178
186
  -V, --version show program's version number and exit
179
187
  ```
180
188
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: multiSSH3
3
- Version: 5.25
3
+ Version: 5.27
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
@@ -96,7 +96,7 @@ An example .ssh/config:
96
96
  Host *
97
97
  StrictHostKeyChecking no
98
98
  ControlMaster auto
99
- ControlPath /run/ssh_sockets_%r@%h-%p
99
+ ControlPath /tmp/%u_ssh_sockets_%r@%h-%p
100
100
  ControlPersist 3600
101
101
  ```
102
102
 
@@ -124,10 +124,10 @@ While leaving minimum 40 characters / 1 line for each host display by default. Y
124
124
  Use ```mssh --help``` for more info.
125
125
 
126
126
  ```bash
127
- usage: mssh [-h] [-u USERNAME] [-p PASSWORD] [-ea EXTRAARGS] [-11] [-f FILE] [-fs] [--scp] [-gm] [-t TIMEOUT] [-r REPEAT] [-i INTERVAL]
128
- [--ipmi] [-mpre IPMI_INTERFACE_IP_PREFIX] [-pre INTERFACE_IP_PREFIX] [-q] [-ww WINDOW_WIDTH] [-wh WINDOW_HEIGHT] [-sw] [-eo]
129
- [-no] [--no_env] [--env_file ENV_FILE] [-m MAX_CONNECTIONS] [-j] [--success_hosts] [-g] [-su] [-sh SKIP_HOSTS]
130
- [--store_config_file] [--debug] [--copy-id] [-V]
127
+ usage: mssh [-h] [-u USERNAME] [-p PASSWORD] [-k [KEY]] [-uk] [-ea EXTRAARGS] [-11] [-f FILE] [-fs] [--scp] [-gm] [-t TIMEOUT] [-r REPEAT]
128
+ [-i INTERVAL] [--ipmi] [-mpre IPMI_INTERFACE_IP_PREFIX] [-pre INTERFACE_IP_PREFIX] [-q] [-ww WINDOW_WIDTH] [-wh WINDOW_HEIGHT]
129
+ [-sw] [-eo] [-no] [--no_env] [--env_file ENV_FILE] [-m MAX_CONNECTIONS] [-j] [--success_hosts] [-g] [-su | -nsu]
130
+ [-sh SKIP_HOSTS] [--store_config_file] [--debug] [-ci] [-V]
131
131
  [hosts] [commands ...]
132
132
 
133
133
  Run a command on multiple hosts, Use #HOST# or #HOSTNAME# to replace the host name in the command. Config file: /etc/multiSSH3.config.json
@@ -144,6 +144,10 @@ options:
144
144
  (default: None)
145
145
  -p PASSWORD, --password PASSWORD
146
146
  The password to use to connect to the hosts, (default: )
147
+ -k [KEY], --key [KEY], --identity [KEY]
148
+ The identity file to use to connect to the hosts. Implies --use_key. Specify a folder for program to search for a
149
+ key. Use option without value to use ~/.ssh/ (default: None)
150
+ -uk, --use_key Attempt to use public key file to connect to the hosts. (default: False)
147
151
  -ea EXTRAARGS, --extraargs EXTRAARGS
148
152
  Extra arguments to pass to the ssh / rsync / scp command. Put in one string for multiple arguments.Use "=" ! Ex.
149
153
  -ea="--delete" (default: None)
@@ -181,16 +185,20 @@ options:
181
185
  Max number of connections to use (default: 4 * cpu_count)
182
186
  -j, --json Output in json format. (default: False)
183
187
  --success_hosts Output the hosts that succeeded in summary as wells. (default: False)
184
- -g, --greppable Output in greppable format. (default: False)
188
+ -g, --greppable, --table
189
+ Output in greppable format. (default: False)
185
190
  -su, --skip_unreachable
186
- Skip unreachable hosts while using --repeat. Note: Timedout Hosts are considered unreachable. Note: multiple
187
- command sequence will still auto skip unreachable hosts. (default: False)
191
+ Skip unreachable hosts. Note: Timedout Hosts are considered unreachable. Note: multiple command sequence will
192
+ still auto skip unreachable hosts. (default: False)
193
+ -nsu, --no_skip_unreachable
194
+ Do not skip unreachable hosts. Note: Timedout Hosts are considered unreachable. Note: multiple command sequence
195
+ will still auto skip unreachable hosts. (default: True)
188
196
  -sh SKIP_HOSTS, --skip_hosts SKIP_HOSTS
189
197
  Skip the hosts in the list. (default: None)
190
198
  --store_config_file Store / generate the default config file from command line argument and current config at
191
199
  /etc/multiSSH3.config.json
192
200
  --debug Print debug information
193
- --copy-id Copy the ssh id to the hosts
201
+ -ci, --copy_id Copy the ssh id to the hosts
194
202
  -V, --version show program's version number and exit
195
203
  ```
196
204
 
@@ -36,7 +36,7 @@ except AttributeError:
36
36
  # If neither is available, use a dummy decorator
37
37
  def cache_decorator(func):
38
38
  return func
39
- version = '5.25'
39
+ version = '5.27'
40
40
  VERSION = version
41
41
 
42
42
  CONFIG_FILE = '/etc/multiSSH3.config.json'
@@ -758,7 +758,7 @@ def __filterSumDic(sumDic):
758
758
  return newSumDic
759
759
 
760
760
  @cache_decorator
761
- def compact_hostnames(Hostnames):
761
+ def __compact_hostnames(Hostnames):
762
762
  """
763
763
  Compact a list of hostnames.
764
764
  Compact numeric numbers into ranges.
@@ -803,6 +803,43 @@ def compact_hostnames(Hostnames):
803
803
  rtnSet.add(''.join(hostnameList))
804
804
  return frozenset(rtnSet)
805
805
 
806
+ def compact_hostnames(Hostnames):
807
+ """
808
+ Compact a list of hostnames.
809
+ Compact numeric numbers into ranges.
810
+
811
+ Args:
812
+ Hostnames (list): A list of hostnames.
813
+
814
+ Returns:
815
+ list: A list of comapcted hostname list.
816
+
817
+ Example:
818
+ >>> compact_hostnames(['server15', 'server16', 'server17'])
819
+ ['server[15-17]']
820
+ >>> compact_hostnames(['server-1', 'server-2', 'server-3'])
821
+ ['server-[1-3]']
822
+ >>> compact_hostnames(['server-1-2', 'server-1-1', 'server-2-1', 'server-2-2'])
823
+ ['server-[1-2]-[1-2]']
824
+ >>> compact_hostnames(['server-1-2', 'server-1-1', 'server-2-2'])
825
+ ['server-1-[1-2]', 'server-2-2']
826
+ >>> compact_hostnames(['test1-a', 'test2-a'])
827
+ ['test[1-2]-a']
828
+ >>> compact_hostnames(['sub-s1', 'sub-s2'])
829
+ ['sub-s[1-2]']
830
+ """
831
+ global __global_suppress_printout
832
+ if not isinstance(Hostnames, frozenset):
833
+ hostSet = frozenset(Hostnames)
834
+ else:
835
+ hostSet = Hostnames
836
+ compact_hosts = __compact_hostnames(hostSet)
837
+ if set(expand_hostnames(compact_hosts)) != set(expand_hostnames(hostSet)):
838
+ if not __global_suppress_printout:
839
+ eprint(f"Error compacting hostnames: {hostSet} -> {compact_hosts}")
840
+ compact_hosts = hostSet
841
+ return compact_hosts
842
+
806
843
  # ------------ Expanding Hostnames ----------------
807
844
  @cache_decorator
808
845
  def __validate_expand_hostname(hostname):
@@ -823,10 +860,10 @@ def __validate_expand_hostname(hostname):
823
860
  return [hostname]
824
861
  elif not _no_env and hostname in os.environ:
825
862
  # we will expand these hostnames again
826
- return expand_hostnames(frozenset(os.environ[hostname].split(',')))
863
+ return expand_hostnames(os.environ[hostname].split(','))
827
864
  elif hostname in readEnvFromFile():
828
865
  # we will expand these hostnames again
829
- return expand_hostnames(frozenset(readEnvFromFile()[hostname].split(',')))
866
+ return expand_hostnames(readEnvFromFile()[hostname].split(','))
830
867
  elif getIP(hostname,local=False):
831
868
  return [hostname]
832
869
  else:
@@ -940,7 +977,7 @@ def __expand_hostname(text, validate=True):# -> set:
940
977
  return expandedhosts
941
978
 
942
979
  @cache_decorator
943
- def expand_hostnames(hosts) -> dict:
980
+ def __expand_hostnames(hosts) -> dict:
944
981
  '''
945
982
  Expand the hostnames in the hosts into a dictionary
946
983
 
@@ -951,8 +988,6 @@ def expand_hostnames(hosts) -> dict:
951
988
  dict: A dictionary of expanded hostnames with key: hostname, value: resolved IP address
952
989
  '''
953
990
  expandedhosts = {}
954
- if isinstance(hosts, str):
955
- hosts = [hosts]
956
991
  for host in hosts:
957
992
  host = host.strip()
958
993
  if not host:
@@ -963,6 +998,9 @@ def expand_hostnames(hosts) -> dict:
963
998
  username, host = host.split('@',1)
964
999
  username = username.strip()
965
1000
  host = host.strip()
1001
+ username, host = host.split('@',1)
1002
+ username = username.strip()
1003
+ host = host.strip()
966
1004
  # first we check if the hostname is an range of IP addresses
967
1005
  # This is done by checking if the hostname follows four fields of
968
1006
  # "(((\d{1,3}|x|\*|\?)(-(\d{1,3}|x|\*|\?))?)|(\[(\d{1,3}|x|\*|\?)(-(\d{1,3}|x|\*|\?))?\]))"
@@ -986,6 +1024,24 @@ def expand_hostnames(hosts) -> dict:
986
1024
  [expandedhosts.update({host:ip}) for host,ip in zip(hostSetToAdd,iplist)]
987
1025
  return expandedhosts
988
1026
 
1027
+ def expand_hostnames(hosts):
1028
+ '''
1029
+ Expand the hostnames in the hosts into a dictionary
1030
+
1031
+ Args:
1032
+ hosts (list): A list of hostnames
1033
+
1034
+ Returns:
1035
+ dict: A dictionary of expanded hostnames with key: hostname, value: resolved IP address
1036
+ '''
1037
+ if isinstance(hosts, str):
1038
+ hosts = [hosts]
1039
+ # change data type to frozenset if it is not hashable
1040
+ if not isinstance(hosts, frozenset):
1041
+ hosts = frozenset(hosts)
1042
+ return __expand_hostnames(hosts)
1043
+
1044
+
989
1045
  # ------------ Run Command Block ----------------
990
1046
  def __handle_reading_stream(stream,target, host):
991
1047
  '''
@@ -1763,17 +1819,13 @@ def print_output(hosts,usejson = False,quiet = False,greppable = False):
1763
1819
  outputs.setdefault(hostPrintOut, set()).add(host['name'])
1764
1820
  rtnStr = ''
1765
1821
  for output, hostSet in outputs.items():
1766
- hostSet = frozenset(hostSet)
1767
- compact_hosts = compact_hostnames(hostSet)
1768
- if set(expand_hostnames(compact_hosts)) != set(expand_hostnames(hostSet)):
1769
- eprint(f"Error compacting hostnames: {hostSet} -> {compact_hosts}")
1770
- compact_hosts = hostSet
1822
+ compact_hosts = sorted(compact_hostnames(hostSet))
1771
1823
  if __global_suppress_printout:
1772
1824
  rtnStr += f'Abnormal returncode produced by {",".join(compact_hosts)}:\n'
1773
1825
  rtnStr += output+'\n'
1774
1826
  else:
1775
1827
  rtnStr += '*'*80+'\n'
1776
- rtnStr += f'These hosts: "{",".join(sorted(compact_hosts))}" have a response of:\n'
1828
+ rtnStr += f'These hosts: "{",".join(compact_hosts)}" have a response of:\n'
1777
1829
  rtnStr += output+'\n'
1778
1830
  if not __global_suppress_printout or outputs:
1779
1831
  rtnStr += '*'*80+'\n'
@@ -2065,13 +2117,13 @@ def run_command_on_hosts(hosts = DEFAULT_HOSTS,commands = None,oneonone = DEFAUL
2065
2117
  if '@' not in host:
2066
2118
  skipHostStr[i] = userStr + host
2067
2119
  skipHostStr = ','.join(skipHostStr)
2068
- targetHostDic = expand_hostnames(frozenset(hostStr.split(',')))
2120
+ targetHostDic = expand_hostnames(hostStr.split(','))
2069
2121
  if __DEBUG_MODE:
2070
2122
  eprint(f"Target hosts: {targetHostDic!r}")
2071
- skipHostsDic = expand_hostnames(frozenset(skipHostStr.split(',')))
2072
- if skipHostsDic:
2073
- eprint(f"Skipping hosts: {skipHostsDic!r}")
2123
+ skipHostsDic = expand_hostnames(skipHostStr.split(','))
2074
2124
  skipHostSet = set(skipHostsDic).union(skipHostsDic.values())
2125
+ if skipHostSet:
2126
+ eprint(f"Skipping hosts: \"{' '.join(sorted(compact_hostnames(skipHostSet)))}\"")
2075
2127
  if copy_id:
2076
2128
  if 'ssh-copy-id' in _binPaths:
2077
2129
  # we will copy the id to the hosts
@@ -2421,18 +2473,15 @@ def main():
2421
2473
  succeededHosts.add(host.name)
2422
2474
  succeededHosts -= __failedHosts
2423
2475
  # sort the failed hosts and succeeded hosts
2424
- __failedHosts = sorted(__failedHosts)
2425
- succeededHosts = sorted(succeededHosts)
2426
2476
  if __mainReturnCode > 0:
2427
- if not __global_suppress_printout: eprint(f'Complete. Failed hosts (Return Code not 0) count: {__mainReturnCode}')
2428
- # with open('/tmp/bashcmd.stdin','w') as f:
2429
- # f.write(f"export failed_hosts={__failedHosts}\n")
2430
- if not __global_suppress_printout: eprint(f'failed_hosts: {",".join(__failedHosts)}')
2477
+ if not __global_suppress_printout:
2478
+ eprint(f'Complete. Failed hosts (Return Code not 0) count: {__mainReturnCode}')
2479
+ eprint(f'failed_hosts: {",".join(sorted(compact_hostnames(__failedHosts)))}')
2431
2480
  else:
2432
2481
  if not __global_suppress_printout: eprint('Complete. All hosts returned 0.')
2433
2482
 
2434
2483
  if args.success_hosts and not __global_suppress_printout:
2435
- eprint(f'succeeded_hosts: {",".join(succeededHosts)}')
2484
+ eprint(f'succeeded_hosts: {",".join(sorted(compact_hostnames(succeededHosts)))}')
2436
2485
 
2437
2486
  if threading.active_count() > 1:
2438
2487
  if not __global_suppress_printout: eprint(f'Remaining active thread: {threading.active_count()}')
@@ -2,7 +2,7 @@ from setuptools import setup
2
2
 
3
3
  setup(
4
4
  name='multiSSH3',
5
- version='5.25',
5
+ version='5.27',
6
6
  description='Run commands on multiple hosts via SSH',
7
7
  long_description=open('README.md').read(),
8
8
  long_description_content_type='text/markdown',
File without changes
File without changes