multiSSH3 5.73__tar.gz → 5.75__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.
- {multissh3-5.73 → multissh3-5.75}/PKG-INFO +1 -1
- {multissh3-5.73 → multissh3-5.75}/multiSSH3.egg-info/PKG-INFO +1 -1
- {multissh3-5.73 → multissh3-5.75}/multiSSH3.py +76 -13
- {multissh3-5.73 → multissh3-5.75}/README.md +0 -0
- {multissh3-5.73 → multissh3-5.75}/multiSSH3.egg-info/SOURCES.txt +0 -0
- {multissh3-5.73 → multissh3-5.75}/multiSSH3.egg-info/dependency_links.txt +0 -0
- {multissh3-5.73 → multissh3-5.75}/multiSSH3.egg-info/entry_points.txt +0 -0
- {multissh3-5.73 → multissh3-5.75}/multiSSH3.egg-info/requires.txt +0 -0
- {multissh3-5.73 → multissh3-5.75}/multiSSH3.egg-info/top_level.txt +0 -0
- {multissh3-5.73 → multissh3-5.75}/setup.cfg +0 -0
- {multissh3-5.73 → multissh3-5.75}/setup.py +0 -0
- {multissh3-5.73 → multissh3-5.75}/test/test.py +0 -0
- {multissh3-5.73 → multissh3-5.75}/test/testCurses.py +0 -0
- {multissh3-5.73 → multissh3-5.75}/test/testCursesOld.py +0 -0
- {multissh3-5.73 → multissh3-5.75}/test/testPerfCompact.py +0 -0
- {multissh3-5.73 → multissh3-5.75}/test/testPerfExpand.py +0 -0
|
@@ -10,6 +10,7 @@ __curses_available = False
|
|
|
10
10
|
__resource_lib_available = False
|
|
11
11
|
try:
|
|
12
12
|
import curses
|
|
13
|
+
import curses.panel
|
|
13
14
|
__curses_available = True
|
|
14
15
|
except ImportError:
|
|
15
16
|
pass
|
|
@@ -54,10 +55,10 @@ except AttributeError:
|
|
|
54
55
|
# If neither is available, use a dummy decorator
|
|
55
56
|
def cache_decorator(func):
|
|
56
57
|
return func
|
|
57
|
-
version = '5.
|
|
58
|
+
version = '5.75'
|
|
58
59
|
VERSION = version
|
|
59
60
|
__version__ = version
|
|
60
|
-
COMMIT_DATE = '2025-
|
|
61
|
+
COMMIT_DATE = '2025-06-17'
|
|
61
62
|
|
|
62
63
|
CONFIG_FILE_CHAIN = ['./multiSSH3.config.json',
|
|
63
64
|
'~/multiSSH3.config.json',
|
|
@@ -312,6 +313,7 @@ DEFAULT_PRINT_SUCCESS_HOSTS = False
|
|
|
312
313
|
DEFAULT_GREPPABLE_MODE = False
|
|
313
314
|
DEFAULT_SKIP_UNREACHABLE = True
|
|
314
315
|
DEFAULT_SKIP_HOSTS = ''
|
|
316
|
+
DEFAULT_ENCODING = 'utf-8'
|
|
315
317
|
SSH_STRICT_HOST_KEY_CHECKING = False
|
|
316
318
|
ERROR_MESSAGES_TO_IGNORE = [
|
|
317
319
|
'Pseudo-terminal will not be allocated because stdin is not a terminal',
|
|
@@ -359,6 +361,7 @@ __curses_color_table = {}
|
|
|
359
361
|
__curses_current_color_index = 10
|
|
360
362
|
__max_connections_nofile_limit_supported = 0
|
|
361
363
|
__thread_start_delay = 0
|
|
364
|
+
_encoding = DEFAULT_ENCODING
|
|
362
365
|
if __resource_lib_available:
|
|
363
366
|
# Get the current limits
|
|
364
367
|
_, __system_nofile_limit = resource.getrlimit(resource.RLIMIT_NOFILE)
|
|
@@ -1122,11 +1125,12 @@ def __handle_reading_stream(stream,target, host):
|
|
|
1122
1125
|
Returns:
|
|
1123
1126
|
None
|
|
1124
1127
|
'''
|
|
1128
|
+
global _encoding
|
|
1125
1129
|
def add_line(current_line,target, host, keepLastLine=True):
|
|
1126
1130
|
if not keepLastLine:
|
|
1127
1131
|
target.pop()
|
|
1128
1132
|
host.output.pop()
|
|
1129
|
-
current_line_str = current_line.decode(
|
|
1133
|
+
current_line_str = current_line.decode(_encoding,errors='backslashreplace')
|
|
1130
1134
|
target.append(current_line_str)
|
|
1131
1135
|
host.output.append(current_line_str)
|
|
1132
1136
|
host.lineNumToPrintSet.add(len(host.output)-1)
|
|
@@ -1157,7 +1161,7 @@ def __handle_reading_stream(stream,target, host):
|
|
|
1157
1161
|
current_line.append(char[0])
|
|
1158
1162
|
else:
|
|
1159
1163
|
# curser is bigger than the length of the line
|
|
1160
|
-
current_line += b' '*(curser_position - len(current_line)) + char
|
|
1164
|
+
current_line += b' '*(curser_position - len(current_line)) + char[0]
|
|
1161
1165
|
curser_position += 1
|
|
1162
1166
|
if time.monotonic() - previousUpdateTime > 0.1:
|
|
1163
1167
|
# if the time since the last update is more than 10ms, we update the output
|
|
@@ -1180,15 +1184,16 @@ def __handle_writing_stream(stream,stop_event,host):
|
|
|
1180
1184
|
None
|
|
1181
1185
|
'''
|
|
1182
1186
|
global __keyPressesIn
|
|
1187
|
+
global _encoding
|
|
1183
1188
|
# __keyPressesIn is a list of lists.
|
|
1184
1189
|
# Each list is a list of characters to be sent to the stdin of the process at once.
|
|
1185
1190
|
# We do not send the last line as it may be incomplete.
|
|
1186
1191
|
sentInput = 0
|
|
1187
1192
|
while not stop_event.is_set():
|
|
1188
1193
|
if sentInput < len(__keyPressesIn) - 1 :
|
|
1189
|
-
stream.write(''.join(__keyPressesIn[sentInput]).encode())
|
|
1194
|
+
stream.write(''.join(__keyPressesIn[sentInput]).encode(encoding=_encoding,errors='backslashreplace'))
|
|
1190
1195
|
stream.flush()
|
|
1191
|
-
line = '> ' + ''.join(__keyPressesIn[sentInput]).encode().decode().replace('\n', '↵')
|
|
1196
|
+
line = '> ' + ''.join(__keyPressesIn[sentInput]).encode(encoding=_encoding,errors='backslashreplace').decode(encoding=_encoding,errors='backslashreplace').replace('\n', '↵')
|
|
1192
1197
|
host.output.append(line)
|
|
1193
1198
|
host.stdout.append(line)
|
|
1194
1199
|
host.lineNumToPrintSet.add(len(host.output)-1)
|
|
@@ -1865,9 +1870,11 @@ def _get_hosts_to_display (hosts, max_num_hosts, hosts_to_display = None, indexO
|
|
|
1865
1870
|
return new_hosts_to_display , {'running':len(running_hosts), 'failed':len(failed_hosts), 'finished':len(finished_hosts), 'waiting':len(waiting_hosts)}, rearrangedHosts
|
|
1866
1871
|
|
|
1867
1872
|
def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min_char_len = DEFAULT_CURSES_MINIMUM_CHAR_LEN, min_line_len = DEFAULT_CURSES_MINIMUM_LINE_LEN,single_window=DEFAULT_SINGLE_WINDOW, config_reason = 'New Configuration'):
|
|
1873
|
+
global _encoding
|
|
1868
1874
|
_ = config_reason
|
|
1869
1875
|
try:
|
|
1870
1876
|
box_ansi_color = None
|
|
1877
|
+
refresh_all = True
|
|
1871
1878
|
org_dim = stdscr.getmaxyx()
|
|
1872
1879
|
# To do this, first we need to know the size of the terminal
|
|
1873
1880
|
max_y, max_x = org_dim
|
|
@@ -1951,6 +1958,33 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
1951
1958
|
#bottom_border.addnstr(0, 0, '-' * (max_x - 1), max_x - 1)
|
|
1952
1959
|
_curses_add_string_to_window(window=bottom_border, y=0, line='-' * (max_x - 1),fill_char='-',box_ansi_color=box_ansi_color)
|
|
1953
1960
|
bottom_border.refresh()
|
|
1961
|
+
help_window_hight = min(14, max_y)
|
|
1962
|
+
help_window_width = min(31, max_x)
|
|
1963
|
+
# Create a centered help window
|
|
1964
|
+
help_window_y = (max_y - help_window_hight) // 2
|
|
1965
|
+
help_window_x = (max_x - help_window_width) // 2
|
|
1966
|
+
help_window = curses.newwin(help_window_hight, help_window_width, help_window_y, help_window_x)
|
|
1967
|
+
help_window.leaveok(True)
|
|
1968
|
+
help_window.scrollok(True)
|
|
1969
|
+
help_window.idlok(True)
|
|
1970
|
+
help_window.box()
|
|
1971
|
+
_curses_add_string_to_window(window=help_window,y=0,line='Help', color_pair_list=[-1,-1,1], centered=True, fill_char='─', lead_str='┌', box_ansi_color=box_ansi_color)
|
|
1972
|
+
_curses_add_string_to_window(window=help_window,y=1,line='? : Toggle Help Menu', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1973
|
+
_curses_add_string_to_window(window=help_window,y=2,line='_ or + : Change window hight', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1974
|
+
_curses_add_string_to_window(window=help_window,y=3,line='{ or } : Change window width', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1975
|
+
_curses_add_string_to_window(window=help_window,y=4,line='< or > : Change host index', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1976
|
+
_curses_add_string_to_window(window=help_window,y=5,line='|(pipe) : Toggle single host', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1977
|
+
_curses_add_string_to_window(window=help_window,y=6,line='Ctrl+D : Exit', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1978
|
+
_curses_add_string_to_window(window=help_window,y=7,line='Ctrl+R : Force refresh', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1979
|
+
_curses_add_string_to_window(window=help_window,y=8,line='↑ or ↓ : Navigate history', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1980
|
+
_curses_add_string_to_window(window=help_window,y=9,line='← or → : Move cursor', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1981
|
+
_curses_add_string_to_window(window=help_window,y=10,line='PgUp/Dn : Scroll history by 5', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1982
|
+
_curses_add_string_to_window(window=help_window,y=11,line='Home/End: Jump cursor', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1983
|
+
_curses_add_string_to_window(window=help_window,y=12,line='Esc : Clear line', color_pair_list=[-1,-1,1], lead_str='│', box_ansi_color=box_ansi_color)
|
|
1984
|
+
help_panel = curses.panel.new_panel(help_window)
|
|
1985
|
+
help_panel.hide()
|
|
1986
|
+
help_shown = False
|
|
1987
|
+
curses.panel.update_panels()
|
|
1954
1988
|
indexOffset = 0
|
|
1955
1989
|
while host_stats['running'] > 0 or host_stats['waiting'] > 0:
|
|
1956
1990
|
# Check for keypress
|
|
@@ -1961,7 +1995,7 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
1961
1995
|
# When we encounter a newline, we add a new list to the list of lists. ( a new line of input )
|
|
1962
1996
|
# with open('keylog.txt','a') as f:
|
|
1963
1997
|
# f.write(str(key)+'\n')
|
|
1964
|
-
if key == 410: # 410 is the key code for resize
|
|
1998
|
+
if key == 410 or key == curses.KEY_RESIZE: # 410 is the key code for resize
|
|
1965
1999
|
return (lineToDisplay,curserPosition , min_char_len, min_line_len, single_window, 'Terminal resize requested')
|
|
1966
2000
|
# if the user pressed ctrl + d and the last line is empty, we will exit by adding 'exit\n' to the last line
|
|
1967
2001
|
elif key == 4 and not __keyPressesIn[-1]:
|
|
@@ -1991,12 +2025,15 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
1991
2025
|
# We handle positional keys
|
|
1992
2026
|
# if the key is up arrow, we will move the line to display up
|
|
1993
2027
|
elif key == 259: # 259 is the key code for up arrow
|
|
2028
|
+
# also scroll curserPosition to last if it is currently at the last line and curserPosition is at 0
|
|
1994
2029
|
lineToDisplay = max(lineToDisplay - 1, -len(__keyPressesIn))
|
|
2030
|
+
if lineToDisplay == -2 and not __keyPressesIn[-1]:
|
|
2031
|
+
curserPosition = len(__keyPressesIn[lineToDisplay])
|
|
1995
2032
|
# if the key is down arrow, we will move the line to display down
|
|
1996
2033
|
elif key == 258: # 258 is the key code for down arrow
|
|
1997
2034
|
lineToDisplay = min(lineToDisplay + 1, -1)
|
|
1998
2035
|
# if the key is left arrow, we will move the cursor left
|
|
1999
|
-
elif key == 260: # 260 is the key
|
|
2036
|
+
elif key == 260: # 260 is the key code for left arrow
|
|
2000
2037
|
curserPosition = min(max(curserPosition - 1, 0), len(__keyPressesIn[lineToDisplay]) -1)
|
|
2001
2038
|
# if the key is right arrow, we will move the cursor right
|
|
2002
2039
|
elif key == 261: # 261 is the key code for right arrow
|
|
@@ -2013,6 +2050,23 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
2013
2050
|
# if the key is end, we will move the cursor to the end of the line
|
|
2014
2051
|
elif key == 360: # 360 is the key code for end
|
|
2015
2052
|
curserPosition = len(__keyPressesIn[lineToDisplay])
|
|
2053
|
+
elif key == curses.KEY_REFRESH or key == curses.KEY_F5 or key == 18: # 18 is the key code for ctrl + R
|
|
2054
|
+
# if the key is refresh, we will refresh the screen
|
|
2055
|
+
return (lineToDisplay,curserPosition , min_char_len, min_line_len, single_window, 'Refresh requested')
|
|
2056
|
+
elif key == curses.KEY_EXIT or key == 27: # 27 is the key code for ESC
|
|
2057
|
+
# if the key is exit, we will exit the program
|
|
2058
|
+
return
|
|
2059
|
+
elif key == curses.KEY_HELP or key == 63 or key == curses.KEY_F1: # 63 is the key code for ?
|
|
2060
|
+
# if the key is help, we will display the help message
|
|
2061
|
+
if not help_shown:
|
|
2062
|
+
help_panel.show()
|
|
2063
|
+
help_shown = True
|
|
2064
|
+
else:
|
|
2065
|
+
help_panel.hide()
|
|
2066
|
+
help_shown = False
|
|
2067
|
+
refresh_all = True
|
|
2068
|
+
#return (lineToDisplay,curserPosition , min_char_len, min_line_len, single_window, 'Help closed')
|
|
2069
|
+
curses.panel.update_panels()
|
|
2016
2070
|
# We are left with these are keys that mofidy the current line.
|
|
2017
2071
|
else:
|
|
2018
2072
|
# This means the user have done scrolling and is committing to modify the current line.
|
|
@@ -2052,13 +2106,13 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
2052
2106
|
stats = f"Total: {len(hosts)} Running: {host_stats['running']} Failed: {host_stats['failed']} Finished: {host_stats['finished']} Waiting: {host_stats['waiting']} ww: {min_char_len} wh:{min_line_len} i:{indexOffset} "
|
|
2053
2107
|
else:
|
|
2054
2108
|
# we use the stat bar to display the key presses
|
|
2055
|
-
encodedLine = ''.join(__keyPressesIn[lineToDisplay]).encode().decode().strip('\n') + ' '
|
|
2109
|
+
encodedLine = ''.join(__keyPressesIn[lineToDisplay]).encode(encoding=_encoding,errors='backslashreplace').decode(encoding=_encoding,errors='backslashreplace').strip('\n') + ' '
|
|
2056
2110
|
#stats = '┍'+ f"Send CMD: {encodedLine}"[:max_x - 2].center(max_x - 2, "━")
|
|
2057
2111
|
# format the stats line with chracter at curser position inverted using ansi escape sequence
|
|
2058
2112
|
# displayCurserPosition is needed as the curserPosition can be larger than the length of the encodedLine. This is wanted to keep scrolling through the history less painful
|
|
2059
2113
|
displayCurserPosition = min(curserPosition,len(encodedLine) -1)
|
|
2060
2114
|
stats = f'Send CMD: {encodedLine[:displayCurserPosition]}\x1b[7m{encodedLine[displayCurserPosition]}\x1b[0m{encodedLine[displayCurserPosition + 1:]}'
|
|
2061
|
-
if stats != old_stat :
|
|
2115
|
+
if stats != old_stat or refresh_all:
|
|
2062
2116
|
old_stat = stats
|
|
2063
2117
|
# calculate the real curser position in stats as we centered the stats
|
|
2064
2118
|
# if 'Send CMD: ' in stats:
|
|
@@ -2078,7 +2132,7 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
2078
2132
|
#target_length = max_x - 2 + len('\x1b[33m\x1b[0m\x1b[31m\x1b[0m\x1b[32m\x1b[0m')
|
|
2079
2133
|
#bottom_stats = '└'+ f" Total: {len(hosts)} Running: \x1b[33m{host_stats['running']}\x1b[0m Failed: \x1b[31m{host_stats['failed']}\x1b[0m Finished: \x1b[32m{host_stats['finished']}\x1b[0m Waiting: {host_stats['waiting']} "[:target_length].center(target_length, "─")
|
|
2080
2134
|
bottom_stats = f" Total: {len(hosts)} Running: \x1b[33m{host_stats['running']}\x1b[0m Failed: \x1b[31m{host_stats['failed']}\x1b[0m Finished: \x1b[32m{host_stats['finished']}\x1b[0m Waiting: {host_stats['waiting']} "
|
|
2081
|
-
if bottom_stats != old_bottom_stat:
|
|
2135
|
+
if bottom_stats != old_bottom_stat or refresh_all:
|
|
2082
2136
|
old_bottom_stat = bottom_stats
|
|
2083
2137
|
#bottom_border.clear()
|
|
2084
2138
|
#bottom_border.addnstr(0, 0, bottom_stats, max_x - 1)
|
|
@@ -2087,6 +2141,9 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
2087
2141
|
# set the maximum refresh rate to 100 Hz
|
|
2088
2142
|
if time.perf_counter() - last_refresh_time < 0.01:
|
|
2089
2143
|
time.sleep(max(0,0.01 - time.perf_counter() + last_refresh_time))
|
|
2144
|
+
if refresh_all:
|
|
2145
|
+
rearrangedHosts = set(hosts_to_display)
|
|
2146
|
+
refresh_all = False
|
|
2090
2147
|
#stdscr.clear()
|
|
2091
2148
|
for host_window, host in zip(host_windows, hosts_to_display):
|
|
2092
2149
|
# we will only update the window if there is new output or the window is not fully printed
|
|
@@ -2201,6 +2258,7 @@ def curses_print(stdscr, hosts, threads, min_char_len = DEFAULT_CURSES_MINIMUM_C
|
|
|
2201
2258
|
def generate_output(hosts, usejson = False, greppable = False):
|
|
2202
2259
|
global __keyPressesIn
|
|
2203
2260
|
global __global_suppress_printout
|
|
2261
|
+
global __encoding
|
|
2204
2262
|
if __global_suppress_printout:
|
|
2205
2263
|
# remove hosts with returncode 0
|
|
2206
2264
|
hosts = [dict(host) for host in hosts if host.returncode != 0]
|
|
@@ -2234,7 +2292,7 @@ def generate_output(hosts, usejson = False, greppable = False):
|
|
|
2234
2292
|
rtnStr += pretty_format_table(rtnList)
|
|
2235
2293
|
rtnStr += '*'*80+'\n'
|
|
2236
2294
|
if __keyPressesIn[-1]:
|
|
2237
|
-
CMDsOut = [''.join(cmd).encode('
|
|
2295
|
+
CMDsOut = [''.join(cmd).encode(encoding=_encoding,errors='backslashreplace').decode(encoding=_encoding,errors='backslashreplace').replace('\\n', '↵') for cmd in __keyPressesIn if cmd]
|
|
2238
2296
|
rtnStr += 'User Inputs: '+ '\nUser Inputs: '.join(CMDsOut)
|
|
2239
2297
|
#rtnStr += '\n'
|
|
2240
2298
|
else:
|
|
@@ -2265,7 +2323,7 @@ def generate_output(hosts, usejson = False, greppable = False):
|
|
|
2265
2323
|
if not __global_suppress_printout or outputs:
|
|
2266
2324
|
rtnStr += '*'*80+'\n'
|
|
2267
2325
|
if __keyPressesIn[-1]:
|
|
2268
|
-
CMDsOut = [''.join(cmd).encode('
|
|
2326
|
+
CMDsOut = [''.join(cmd).encode(encoding=_encoding,errors='backslashreplace').decode(encoding=_encoding,errors='backslashreplace').replace('\\n', '↵') for cmd in __keyPressesIn if cmd]
|
|
2269
2327
|
#rtnStr += f"Key presses: {''.join(__keyPressesIn).encode('unicode_escape').decode()}\n"
|
|
2270
2328
|
#rtnStr += f"Key presses: {__keyPressesIn}\n"
|
|
2271
2329
|
rtnStr += "User Inputs: \n "
|
|
@@ -2863,6 +2921,7 @@ def generate_default_config(args):
|
|
|
2863
2921
|
'DEFAULT_GREPPABLE_MODE': args.greppable,
|
|
2864
2922
|
'DEFAULT_SKIP_UNREACHABLE': args.skip_unreachable,
|
|
2865
2923
|
'DEFAULT_SKIP_HOSTS': args.skip_hosts,
|
|
2924
|
+
'DEFAULT_ENCODING': args.encoding,
|
|
2866
2925
|
'SSH_STRICT_HOST_KEY_CHECKING': SSH_STRICT_HOST_KEY_CHECKING,
|
|
2867
2926
|
'ERROR_MESSAGES_TO_IGNORE': ERROR_MESSAGES_TO_IGNORE,
|
|
2868
2927
|
}
|
|
@@ -2918,6 +2977,7 @@ def main():
|
|
|
2918
2977
|
global _env_file
|
|
2919
2978
|
global __DEBUG_MODE
|
|
2920
2979
|
global __configs_from_file
|
|
2980
|
+
global _encoding
|
|
2921
2981
|
_emo = False
|
|
2922
2982
|
# We handle the signal
|
|
2923
2983
|
signal.signal(signal.SIGINT, signal_handler)
|
|
@@ -2969,6 +3029,7 @@ def main():
|
|
|
2969
3029
|
parser.add_argument('-I','-nh','--no_history', action='store_true', help=f'Do not record the command to history. Default: {DEFAULT_NO_HISTORY}', default=DEFAULT_NO_HISTORY)
|
|
2970
3030
|
parser.add_argument('-hf','--history_file', type=str, help=f'The file to store the history. (default: {DEFAULT_HISTORY_FILE})', default=DEFAULT_HISTORY_FILE)
|
|
2971
3031
|
parser.add_argument('--script', action='store_true', help='Run the command in script mode, short for -SCRIPT or --no_watch --skip_unreachable --no_env --no_history --greppable --error_only')
|
|
3032
|
+
parser.add_argument('-e','--encoding', type=str, help=f'The encoding to use for the output. (default: {DEFAULT_ENCODING})', default=DEFAULT_ENCODING)
|
|
2972
3033
|
parser.add_argument("-V","--version", action='version', version=f'%(prog)s {version} @ {COMMIT_DATE} with [ {", ".join(_binPaths.keys())} ] by {AUTHOR} ({AUTHOR_EMAIL})')
|
|
2973
3034
|
|
|
2974
3035
|
# parser.add_argument('-u', '--user', metavar='user', type=str, nargs=1,
|
|
@@ -3057,6 +3118,8 @@ def main():
|
|
|
3057
3118
|
# set timeout to the default script timeout if timeout is not set
|
|
3058
3119
|
if args.timeout == DEFAULT_CLI_TIMEOUT:
|
|
3059
3120
|
args.timeout = DEFAULT_TIMEOUT
|
|
3121
|
+
|
|
3122
|
+
_encoding = args.encoding
|
|
3060
3123
|
|
|
3061
3124
|
if not __global_suppress_printout:
|
|
3062
3125
|
cmdStr = getStrCommand(args.hosts,args.commands,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|