atomicshop 2.11.47__py3-none-any.whl → 3.10.5__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.
- atomicshop/__init__.py +1 -1
- atomicshop/{addons/mains → a_mains}/FACT/update_extract.py +3 -2
- atomicshop/a_mains/addons/process_list/compile.cmd +7 -0
- atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.dll +0 -0
- atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.exp +0 -0
- atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.lib +0 -0
- atomicshop/{addons → a_mains/addons}/process_list/process_list.cpp +8 -1
- atomicshop/a_mains/dns_gateway_setting.py +11 -0
- atomicshop/a_mains/get_local_tcp_ports.py +85 -0
- atomicshop/a_mains/github_wrapper.py +11 -0
- atomicshop/a_mains/install_ca_certificate.py +172 -0
- atomicshop/{addons/mains → a_mains}/msi_unpacker.py +3 -1
- atomicshop/a_mains/process_from_port.py +119 -0
- atomicshop/a_mains/set_default_dns_gateway.py +90 -0
- atomicshop/a_mains/update_config_toml.py +38 -0
- atomicshop/appointment_management.py +5 -3
- atomicshop/basics/ansi_escape_codes.py +3 -1
- atomicshop/basics/argparse_template.py +2 -0
- atomicshop/basics/booleans.py +27 -30
- atomicshop/basics/bytes_arrays.py +43 -0
- atomicshop/basics/classes.py +149 -1
- atomicshop/basics/dicts.py +12 -0
- atomicshop/basics/enums.py +2 -2
- atomicshop/basics/exceptions.py +5 -1
- atomicshop/basics/list_of_classes.py +29 -0
- atomicshop/basics/list_of_dicts.py +69 -5
- atomicshop/basics/lists.py +14 -0
- atomicshop/basics/multiprocesses.py +374 -50
- atomicshop/basics/package_module.py +10 -0
- atomicshop/basics/strings.py +160 -7
- atomicshop/basics/threads.py +14 -0
- atomicshop/basics/tracebacks.py +13 -4
- atomicshop/certificates.py +153 -52
- atomicshop/config_init.py +12 -7
- atomicshop/console_user_response.py +7 -14
- atomicshop/consoles.py +9 -0
- atomicshop/datetimes.py +98 -0
- atomicshop/diff_check.py +340 -40
- atomicshop/dns.py +128 -12
- atomicshop/etws/_pywintrace_fix.py +17 -0
- atomicshop/etws/const.py +38 -0
- atomicshop/etws/providers.py +21 -0
- atomicshop/etws/sessions.py +43 -0
- atomicshop/etws/trace.py +168 -0
- atomicshop/etws/traces/trace_dns.py +162 -0
- atomicshop/etws/traces/trace_sysmon_process_creation.py +126 -0
- atomicshop/etws/traces/trace_tcp.py +130 -0
- atomicshop/file_io/csvs.py +222 -24
- atomicshop/file_io/docxs.py +35 -18
- atomicshop/file_io/file_io.py +35 -19
- atomicshop/file_io/jsons.py +49 -0
- atomicshop/file_io/tomls.py +139 -0
- atomicshop/filesystem.py +864 -293
- atomicshop/get_process_list.py +133 -0
- atomicshop/{process_name_cmd.py → get_process_name_cmd_dll.py} +52 -19
- atomicshop/http_parse.py +149 -93
- atomicshop/ip_addresses.py +6 -1
- atomicshop/mitm/centered_settings.py +132 -0
- atomicshop/mitm/config_static.py +207 -0
- atomicshop/mitm/config_toml_editor.py +55 -0
- atomicshop/mitm/connection_thread_worker.py +875 -357
- atomicshop/mitm/engines/__parent/parser___parent.py +4 -17
- atomicshop/mitm/engines/__parent/recorder___parent.py +108 -51
- atomicshop/mitm/engines/__parent/requester___parent.py +116 -0
- atomicshop/mitm/engines/__parent/responder___parent.py +75 -114
- atomicshop/mitm/engines/__reference_general/parser___reference_general.py +10 -7
- atomicshop/mitm/engines/__reference_general/recorder___reference_general.py +5 -5
- atomicshop/mitm/engines/__reference_general/requester___reference_general.py +47 -0
- atomicshop/mitm/engines/__reference_general/responder___reference_general.py +95 -13
- atomicshop/mitm/engines/create_module_template.py +58 -14
- atomicshop/mitm/import_config.py +359 -139
- atomicshop/mitm/initialize_engines.py +160 -74
- atomicshop/mitm/message.py +64 -23
- atomicshop/mitm/mitm_main.py +892 -0
- atomicshop/mitm/recs_files.py +183 -0
- atomicshop/mitm/shared_functions.py +4 -10
- atomicshop/mitm/ssh_tester.py +82 -0
- atomicshop/mitm/statistic_analyzer.py +257 -166
- atomicshop/mitm/statistic_analyzer_helper/analyzer_helper.py +136 -0
- atomicshop/mitm/statistic_analyzer_helper/moving_average_helper.py +525 -0
- atomicshop/monitor/change_monitor.py +96 -120
- atomicshop/monitor/checks/dns.py +139 -70
- atomicshop/monitor/checks/file.py +77 -0
- atomicshop/monitor/checks/network.py +81 -77
- atomicshop/monitor/checks/process_running.py +33 -34
- atomicshop/monitor/checks/url.py +94 -0
- atomicshop/networks.py +671 -0
- atomicshop/on_exit.py +205 -0
- atomicshop/package_mains_processor.py +84 -0
- atomicshop/permissions/permissions.py +22 -0
- atomicshop/permissions/ubuntu_permissions.py +239 -0
- atomicshop/permissions/win_permissions.py +33 -0
- atomicshop/print_api.py +24 -41
- atomicshop/process.py +63 -17
- atomicshop/process_poller/__init__.py +0 -0
- atomicshop/process_poller/pollers/__init__.py +0 -0
- atomicshop/process_poller/pollers/psutil_pywin32wmi_dll.py +95 -0
- atomicshop/process_poller/process_pool.py +207 -0
- atomicshop/process_poller/simple_process_pool.py +311 -0
- atomicshop/process_poller/tracer_base.py +45 -0
- atomicshop/process_poller/tracers/__init__.py +0 -0
- atomicshop/process_poller/tracers/event_log.py +46 -0
- atomicshop/process_poller/tracers/sysmon_etw.py +68 -0
- atomicshop/python_file_patcher.py +1 -1
- atomicshop/python_functions.py +27 -75
- atomicshop/question_answer_engine.py +2 -2
- atomicshop/scheduling.py +24 -5
- atomicshop/sound.py +4 -2
- atomicshop/speech_recognize.py +8 -0
- atomicshop/ssh_remote.py +158 -172
- atomicshop/startup/__init__.py +0 -0
- atomicshop/startup/win/__init__.py +0 -0
- atomicshop/startup/win/startup_folder.py +53 -0
- atomicshop/startup/win/task_scheduler.py +119 -0
- atomicshop/system_resource_monitor.py +61 -46
- atomicshop/system_resources.py +8 -8
- atomicshop/tempfiles.py +1 -2
- atomicshop/timer.py +30 -11
- atomicshop/urls.py +41 -0
- atomicshop/venvs.py +28 -0
- atomicshop/versioning.py +27 -0
- atomicshop/web.py +110 -25
- atomicshop/web_apis/__init__.py +0 -0
- atomicshop/web_apis/google_custom_search.py +44 -0
- atomicshop/web_apis/google_llm.py +188 -0
- atomicshop/websocket_parse.py +450 -0
- atomicshop/wrappers/certauthw/certauth.py +1 -0
- atomicshop/wrappers/cryptographyw.py +29 -8
- atomicshop/wrappers/ctyping/etw_winapi/__init__.py +0 -0
- atomicshop/wrappers/ctyping/etw_winapi/const.py +335 -0
- atomicshop/wrappers/ctyping/etw_winapi/etw_functions.py +393 -0
- atomicshop/wrappers/ctyping/file_details_winapi.py +67 -0
- atomicshop/wrappers/ctyping/msi_windows_installer/cabs.py +2 -1
- atomicshop/wrappers/ctyping/msi_windows_installer/extract_msi_main.py +13 -9
- atomicshop/wrappers/ctyping/msi_windows_installer/tables.py +35 -0
- atomicshop/wrappers/ctyping/setup_device.py +466 -0
- atomicshop/wrappers/ctyping/win_console.py +39 -0
- atomicshop/wrappers/dockerw/dockerw.py +113 -2
- atomicshop/wrappers/elasticsearchw/config_basic.py +0 -12
- atomicshop/wrappers/elasticsearchw/elastic_infra.py +75 -0
- atomicshop/wrappers/elasticsearchw/elasticsearchw.py +2 -20
- atomicshop/wrappers/factw/get_file_data.py +12 -5
- atomicshop/wrappers/factw/install/install_after_restart.py +89 -5
- atomicshop/wrappers/factw/install/pre_install_and_install_before_restart.py +20 -14
- atomicshop/wrappers/factw/postgresql/firmware.py +4 -6
- atomicshop/wrappers/githubw.py +583 -51
- atomicshop/wrappers/loggingw/consts.py +49 -0
- atomicshop/wrappers/loggingw/filters.py +102 -0
- atomicshop/wrappers/loggingw/formatters.py +58 -71
- atomicshop/wrappers/loggingw/handlers.py +459 -40
- atomicshop/wrappers/loggingw/loggers.py +19 -0
- atomicshop/wrappers/loggingw/loggingw.py +1010 -178
- atomicshop/wrappers/loggingw/reading.py +344 -19
- atomicshop/wrappers/mongodbw/__init__.py +0 -0
- atomicshop/wrappers/mongodbw/mongo_infra.py +31 -0
- atomicshop/wrappers/mongodbw/mongodbw.py +1432 -0
- atomicshop/wrappers/netshw.py +271 -0
- atomicshop/wrappers/playwrightw/engine.py +34 -19
- atomicshop/wrappers/playwrightw/infra.py +5 -0
- atomicshop/wrappers/playwrightw/javascript.py +7 -3
- atomicshop/wrappers/playwrightw/keyboard.py +14 -0
- atomicshop/wrappers/playwrightw/scenarios.py +172 -5
- atomicshop/wrappers/playwrightw/waits.py +9 -7
- atomicshop/wrappers/powershell_networking.py +80 -0
- atomicshop/wrappers/psutilw/processes.py +81 -0
- atomicshop/wrappers/psutilw/psutil_networks.py +85 -0
- atomicshop/wrappers/psutilw/psutilw.py +9 -0
- atomicshop/wrappers/pyopensslw.py +9 -2
- atomicshop/wrappers/pywin32w/__init__.py +0 -0
- atomicshop/wrappers/pywin32w/cert_store.py +116 -0
- atomicshop/wrappers/pywin32w/console.py +34 -0
- atomicshop/wrappers/pywin32w/win_event_log/__init__.py +0 -0
- atomicshop/wrappers/pywin32w/win_event_log/fetch.py +174 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribe.py +212 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/__init__.py +0 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_create.py +57 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_terminate.py +49 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/schannel_logging.py +97 -0
- atomicshop/wrappers/pywin32w/winshell.py +19 -0
- atomicshop/wrappers/pywin32w/wmis/__init__.py +0 -0
- atomicshop/wrappers/pywin32w/wmis/msft_netipaddress.py +113 -0
- atomicshop/wrappers/pywin32w/wmis/win32_networkadapterconfiguration.py +259 -0
- atomicshop/wrappers/pywin32w/wmis/win32networkadapter.py +112 -0
- atomicshop/wrappers/pywin32w/wmis/wmi_helpers.py +236 -0
- atomicshop/wrappers/socketw/accepter.py +21 -7
- atomicshop/wrappers/socketw/certificator.py +216 -150
- atomicshop/wrappers/socketw/creator.py +190 -50
- atomicshop/wrappers/socketw/dns_server.py +500 -173
- atomicshop/wrappers/socketw/exception_wrapper.py +45 -52
- atomicshop/wrappers/socketw/process_getter.py +86 -0
- atomicshop/wrappers/socketw/receiver.py +144 -102
- atomicshop/wrappers/socketw/sender.py +65 -35
- atomicshop/wrappers/socketw/sni.py +334 -165
- atomicshop/wrappers/socketw/socket_base.py +134 -0
- atomicshop/wrappers/socketw/socket_client.py +137 -95
- atomicshop/wrappers/socketw/socket_server_tester.py +14 -9
- atomicshop/wrappers/socketw/socket_wrapper.py +717 -116
- atomicshop/wrappers/socketw/ssl_base.py +15 -14
- atomicshop/wrappers/socketw/statistics_csv.py +148 -17
- atomicshop/wrappers/sysmonw.py +157 -0
- atomicshop/wrappers/ubuntu_terminal.py +65 -26
- atomicshop/wrappers/win_auditw.py +189 -0
- atomicshop/wrappers/winregw/__init__.py +0 -0
- atomicshop/wrappers/winregw/winreg_installed_software.py +58 -0
- atomicshop/wrappers/winregw/winreg_network.py +232 -0
- {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info}/METADATA +31 -49
- atomicshop-3.10.5.dist-info/RECORD +306 -0
- {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info}/WHEEL +1 -1
- atomicshop/_basics_temp.py +0 -101
- atomicshop/addons/a_setup_scripts/install_psycopg2_ubuntu.sh +0 -3
- atomicshop/addons/a_setup_scripts/install_pywintrace_0.3.cmd +0 -2
- atomicshop/addons/mains/install_docker_rootless_ubuntu.py +0 -11
- atomicshop/addons/mains/install_docker_ubuntu_main_sudo.py +0 -11
- atomicshop/addons/mains/install_elastic_search_and_kibana_ubuntu.py +0 -10
- atomicshop/addons/mains/install_wsl_ubuntu_lts_admin.py +0 -9
- atomicshop/addons/package_setup/CreateWheel.cmd +0 -7
- atomicshop/addons/package_setup/Setup in Edit mode.cmd +0 -6
- atomicshop/addons/package_setup/Setup.cmd +0 -7
- atomicshop/addons/process_list/compile.cmd +0 -2
- atomicshop/addons/process_list/compiled/Win10x64/process_list.dll +0 -0
- atomicshop/addons/process_list/compiled/Win10x64/process_list.exp +0 -0
- atomicshop/addons/process_list/compiled/Win10x64/process_list.lib +0 -0
- atomicshop/archiver/_search_in_zip.py +0 -189
- atomicshop/archiver/archiver.py +0 -34
- atomicshop/archiver/search_in_archive.py +0 -250
- atomicshop/archiver/sevenz_app_w.py +0 -86
- atomicshop/archiver/sevenzs.py +0 -44
- atomicshop/archiver/zips.py +0 -293
- atomicshop/etw/dns_trace.py +0 -118
- atomicshop/etw/etw.py +0 -61
- atomicshop/file_types.py +0 -24
- atomicshop/mitm/engines/create_module_template_example.py +0 -13
- atomicshop/mitm/initialize_mitm_server.py +0 -240
- atomicshop/monitor/checks/hash.py +0 -44
- atomicshop/monitor/checks/hash_checks/file.py +0 -55
- atomicshop/monitor/checks/hash_checks/url.py +0 -62
- atomicshop/pbtkmultifile_argparse.py +0 -88
- atomicshop/permissions.py +0 -110
- atomicshop/process_poller.py +0 -237
- atomicshop/script_as_string_processor.py +0 -38
- atomicshop/ssh_scripts/process_from_ipv4.py +0 -37
- atomicshop/ssh_scripts/process_from_port.py +0 -27
- atomicshop/wrappers/_process_wrapper_curl.py +0 -27
- atomicshop/wrappers/_process_wrapper_tar.py +0 -21
- atomicshop/wrappers/dockerw/install_docker.py +0 -209
- atomicshop/wrappers/elasticsearchw/infrastructure.py +0 -265
- atomicshop/wrappers/elasticsearchw/install_elastic.py +0 -232
- atomicshop/wrappers/ffmpegw.py +0 -125
- atomicshop/wrappers/loggingw/checks.py +0 -20
- atomicshop/wrappers/nodejsw/install_nodejs.py +0 -139
- atomicshop/wrappers/process_wrapper_pbtk.py +0 -16
- atomicshop/wrappers/socketw/base.py +0 -59
- atomicshop/wrappers/socketw/get_process.py +0 -107
- atomicshop/wrappers/wslw.py +0 -191
- atomicshop-2.11.47.dist-info/RECORD +0 -251
- /atomicshop/{addons/mains → a_mains}/FACT/factw_fact_extractor_docker_image_main_sudo.py +0 -0
- /atomicshop/{addons → a_mains/addons}/PlayWrightCodegen.cmd +0 -0
- /atomicshop/{addons → a_mains/addons}/ScriptExecution.cmd +0 -0
- /atomicshop/{addons/mains → a_mains/addons}/inits/init_to_import_all_modules.py +0 -0
- /atomicshop/{addons → a_mains/addons}/process_list/ReadMe.txt +0 -0
- /atomicshop/{addons/mains → a_mains}/search_for_hyperlinks_in_docx.py +0 -0
- /atomicshop/{archiver → etws}/__init__.py +0 -0
- /atomicshop/{etw → etws/traces}/__init__.py +0 -0
- /atomicshop/{monitor/checks/hash_checks → mitm/statistic_analyzer_helper}/__init__.py +0 -0
- /atomicshop/{wrappers/nodejsw → permissions}/__init__.py +0 -0
- /atomicshop/wrappers/pywin32w/{wmi_win32process.py → wmis/win32process.py} +0 -0
- {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info/licenses}/LICENSE.txt +0 -0
- {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info}/top_level.txt +0 -0
atomicshop/process_poller.py
DELETED
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
import threading
|
|
2
|
-
import multiprocessing
|
|
3
|
-
import time
|
|
4
|
-
from typing import Literal, Union
|
|
5
|
-
|
|
6
|
-
from .wrappers.pywin32w import wmi_win32process
|
|
7
|
-
from .wrappers.psutilw import psutilw
|
|
8
|
-
from .basics import list_of_dicts, dicts
|
|
9
|
-
from .process_name_cmd import ProcessNameCmdline
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def get_process_time_tester(
|
|
13
|
-
get_method: Literal['psutil', 'pywin32', 'process_dll'] = 'process_dll',
|
|
14
|
-
times_to_test: int = 50
|
|
15
|
-
):
|
|
16
|
-
"""
|
|
17
|
-
The function will test the time it takes to get the list of processes with different methods and cycles.
|
|
18
|
-
|
|
19
|
-
:param get_method: str, The method to get the list of processes. Default is 'process_list_dll'.
|
|
20
|
-
'psutil': Get the list of processes by 'psutil' library. Resource intensive and slow.
|
|
21
|
-
'pywin32': Get the list of processes by 'pywin32' library, using WMI. Not resource intensive, but slow.
|
|
22
|
-
'process_dll'. Not resource intensive and fast. Probably works only in Windows 10 x64
|
|
23
|
-
:param times_to_test: int, how many times to test the function.
|
|
24
|
-
"""
|
|
25
|
-
|
|
26
|
-
import timeit
|
|
27
|
-
|
|
28
|
-
setup_code = '''
|
|
29
|
-
from atomicshop import process_poller
|
|
30
|
-
get_process_list = process_poller.GetProcessList(get_method=get_method, connect_on_init=True)
|
|
31
|
-
'''
|
|
32
|
-
|
|
33
|
-
test_code = '''
|
|
34
|
-
test = get_process_list.get_processes()
|
|
35
|
-
'''
|
|
36
|
-
|
|
37
|
-
# globals need to be specified, otherwise the setup_code won't work with passed variables.
|
|
38
|
-
times = timeit.timeit(setup=setup_code, stmt=test_code, number=times_to_test, globals=locals())
|
|
39
|
-
print(f'Execution time: {times}')
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
class GetProcessList:
|
|
43
|
-
def __init__(
|
|
44
|
-
self,
|
|
45
|
-
get_method: Literal['psutil', 'pywin32', 'process_dll'] = 'process_dll',
|
|
46
|
-
connect_on_init: bool = False
|
|
47
|
-
):
|
|
48
|
-
"""
|
|
49
|
-
:param get_method: str, The method to get the list of processes. Default is 'process_list_dll'.
|
|
50
|
-
'psutil': Get the list of processes by 'psutil' library. Resource intensive and slow.
|
|
51
|
-
'pywin32': Get the list of processes by 'pywin32' library, using WMI. Not resource intensive, but slow.
|
|
52
|
-
'process_dll'. Not resource intensive and fast. Probably works only in Windows 10 x64
|
|
53
|
-
:param connect_on_init: bool, if True, will connect to the service on init. 'psutil' don't need to connect.
|
|
54
|
-
"""
|
|
55
|
-
self.get_method = get_method
|
|
56
|
-
self.process_polling_instance = None
|
|
57
|
-
|
|
58
|
-
self.connected = False
|
|
59
|
-
|
|
60
|
-
if self.get_method == 'psutil':
|
|
61
|
-
self.process_polling_instance = psutilw.PsutilProcesses()
|
|
62
|
-
self.connected = True
|
|
63
|
-
elif self.get_method == 'pywin32':
|
|
64
|
-
self.process_polling_instance = wmi_win32process.Pywin32Processes()
|
|
65
|
-
elif self.get_method == 'process_dll':
|
|
66
|
-
self.process_polling_instance = ProcessNameCmdline()
|
|
67
|
-
|
|
68
|
-
if connect_on_init:
|
|
69
|
-
self.connect()
|
|
70
|
-
|
|
71
|
-
def connect(self):
|
|
72
|
-
"""
|
|
73
|
-
Connect to the service. 'psutil' don't need to connect.
|
|
74
|
-
"""
|
|
75
|
-
|
|
76
|
-
# If the service is not connected yet. Since 'psutil' don't need to connect.
|
|
77
|
-
if not self.connected:
|
|
78
|
-
if self.get_method == 'pywin32':
|
|
79
|
-
self.process_polling_instance.connect()
|
|
80
|
-
self.connected = True
|
|
81
|
-
elif self.get_method == 'process_dll':
|
|
82
|
-
self.process_polling_instance.load()
|
|
83
|
-
self.connected = True
|
|
84
|
-
|
|
85
|
-
def get_processes(self, as_dict: bool = True) -> Union[list, dict]:
|
|
86
|
-
"""
|
|
87
|
-
The function will get the list of opened processes and return it as a list of dicts.
|
|
88
|
-
|
|
89
|
-
:return: list of dicts, of opened processes.
|
|
90
|
-
"""
|
|
91
|
-
|
|
92
|
-
if as_dict:
|
|
93
|
-
if self.get_method == 'psutil':
|
|
94
|
-
return self.process_polling_instance.get_processes_as_dict(
|
|
95
|
-
attrs=['pid', 'name', 'cmdline'], cmdline_to_string=True)
|
|
96
|
-
elif self.get_method == 'pywin32':
|
|
97
|
-
processes = self.process_polling_instance.get_processes_as_dict(
|
|
98
|
-
attrs=['ProcessId', 'Name', 'CommandLine'])
|
|
99
|
-
|
|
100
|
-
# Convert the keys from WMI to the keys that are used in 'psutil'.
|
|
101
|
-
converted_process_dict = dict()
|
|
102
|
-
for pid, process_info in processes.items():
|
|
103
|
-
converted_process_dict[pid] = dicts.convert_key_names(
|
|
104
|
-
process_info, {'Name': 'name', 'CommandLine': 'cmdline'})
|
|
105
|
-
|
|
106
|
-
return converted_process_dict
|
|
107
|
-
elif self.get_method == 'process_dll':
|
|
108
|
-
return self.process_polling_instance.get_process_details(as_dict=True)
|
|
109
|
-
else:
|
|
110
|
-
if self.get_method == 'psutil':
|
|
111
|
-
return self.process_polling_instance.get_processes_as_list_of_dicts(
|
|
112
|
-
attrs=['pid', 'name', 'cmdline'], cmdline_to_string=True)
|
|
113
|
-
elif self.get_method == 'pywin32':
|
|
114
|
-
processes = self.process_polling_instance.get_processes_as_list_of_dicts(
|
|
115
|
-
attrs=['ProcessId', 'Name', 'CommandLine'])
|
|
116
|
-
|
|
117
|
-
# Convert the keys from WMI to the keys that are used in 'psutil'.
|
|
118
|
-
for process_index, process_info in enumerate(processes):
|
|
119
|
-
processes[process_index] = dicts.convert_key_names(
|
|
120
|
-
process_info, {'ProcessId': 'pid', 'Name': 'name', 'CommandLine': 'cmdline'})
|
|
121
|
-
|
|
122
|
-
return processes
|
|
123
|
-
elif self.get_method == 'process_dll':
|
|
124
|
-
return self.process_polling_instance.get_process_details(as_dict=as_dict)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
class ProcessPollerPool:
|
|
128
|
-
"""
|
|
129
|
-
The class is responsible for polling processes and storing them in a pool.
|
|
130
|
-
Currently, this works with 'psutil' library and takes up to 16% of CPU on my machine.
|
|
131
|
-
Because 'psutil' fetches 'cmdline' for each 'pid' dynamically, and it takes time and resources
|
|
132
|
-
Later, I'll find a solution to make it more efficient.
|
|
133
|
-
"""
|
|
134
|
-
def __init__(
|
|
135
|
-
self, store_cycles: int = 200,
|
|
136
|
-
interval_seconds: Union[int, float] = 0,
|
|
137
|
-
operation: Literal['thread', 'process'] = 'thread',
|
|
138
|
-
poller_method: Literal['psutil', 'pywin32', 'process_dll'] = 'process_dll'
|
|
139
|
-
):
|
|
140
|
-
"""
|
|
141
|
-
:param store_cycles: int, how many cycles to store. Each cycle is polling processes.
|
|
142
|
-
Example: Specifying 3 will store last 3 polled cycles of processes.
|
|
143
|
-
|
|
144
|
-
Default is 200, which means that 200 latest cycles original PIDs and their process names will be stored.
|
|
145
|
-
|
|
146
|
-
You can execute the 'get_process_time_tester' function in order to find the optimal number of cycles
|
|
147
|
-
and how much time it will take.
|
|
148
|
-
:param interval_seconds: float, how many seconds to wait between each cycle.
|
|
149
|
-
Default is 0, which means that the polling will be as fast as possible.
|
|
150
|
-
|
|
151
|
-
Basically, you want it to be '0' if you want to get the most recent processes.
|
|
152
|
-
Any polling by itself takes time, so if you want to get the most recent processes, you want to do it as fast
|
|
153
|
-
as possible.
|
|
154
|
-
:param operation: str, 'thread' or 'process'. Default is 'process'.
|
|
155
|
-
'process': The polling will be done in a new process.
|
|
156
|
-
'thread': The polling will be done in a new thread.
|
|
157
|
-
|
|
158
|
-
Python is slow, if you are going to use 'thread' all other operations inside this thread will be very slow.
|
|
159
|
-
You can even get exceptions, if you're using process polling for correlations of PIDs and process names.
|
|
160
|
-
It is advised to use the 'process' operation, which will not affect other operations in the thread.
|
|
161
|
-
:param poller_method: str. Default is 'process_dll'. Available:
|
|
162
|
-
'psutil': Get the list of processes by 'psutil' library. Resource intensive and slow.
|
|
163
|
-
'pywin32': Get the list of processes by 'pywin32' library, using WMI. Not resource intensive, but slow.
|
|
164
|
-
'process_dll'. Not resource intensive and fast. Probably works only in Windows 10 x64.
|
|
165
|
-
"""
|
|
166
|
-
|
|
167
|
-
self.store_cycles: int = store_cycles
|
|
168
|
-
self.interval_seconds: float = interval_seconds
|
|
169
|
-
self.operation: str = operation
|
|
170
|
-
self.poller_method = poller_method
|
|
171
|
-
|
|
172
|
-
self.get_processes_list = GetProcessList(get_method=self.poller_method)
|
|
173
|
-
|
|
174
|
-
# Current process pool.
|
|
175
|
-
self.processes: dict = dict()
|
|
176
|
-
|
|
177
|
-
# The variable is responsible to stop the thread if it is running.
|
|
178
|
-
self.running: bool = False
|
|
179
|
-
|
|
180
|
-
self.queue = multiprocessing.Queue()
|
|
181
|
-
|
|
182
|
-
def start(self):
|
|
183
|
-
if self.operation == 'thread':
|
|
184
|
-
self._start_thread()
|
|
185
|
-
elif self.operation == 'process':
|
|
186
|
-
self._start_process()
|
|
187
|
-
else:
|
|
188
|
-
raise ValueError(f'Invalid operation type [{self.operation}]')
|
|
189
|
-
|
|
190
|
-
def stop(self):
|
|
191
|
-
self.running = False
|
|
192
|
-
|
|
193
|
-
def _start_thread(self):
|
|
194
|
-
self.running = True
|
|
195
|
-
# threading.Thread(target=self._worker, args=(self.process_polling_instance,)).start()
|
|
196
|
-
threading.Thread(target=self._worker).start()
|
|
197
|
-
|
|
198
|
-
def _start_process(self):
|
|
199
|
-
self.running = True
|
|
200
|
-
multiprocessing.Process(target=self._worker).start()
|
|
201
|
-
threading.Thread(target=self._thread_get_queue).start()
|
|
202
|
-
|
|
203
|
-
# def _worker(self, process_polling_instance):
|
|
204
|
-
def _worker(self):
|
|
205
|
-
# We must initiate the connection inside the thread/process, because it is not thread-safe.
|
|
206
|
-
self.get_processes_list.connect()
|
|
207
|
-
|
|
208
|
-
list_of_processes: list = list()
|
|
209
|
-
while self.running:
|
|
210
|
-
# If the list is full (to specified 'store_cycles'), remove the first element.
|
|
211
|
-
if len(list_of_processes) == self.store_cycles:
|
|
212
|
-
del list_of_processes[0]
|
|
213
|
-
|
|
214
|
-
# Get the current processes and reinitialize the instance of the dict.
|
|
215
|
-
current_processes: dict = dict(self.get_processes_list.get_processes())
|
|
216
|
-
|
|
217
|
-
# Remove Command lines that contains only numbers, since they are useless.
|
|
218
|
-
for pid, process_info in current_processes.items():
|
|
219
|
-
if process_info['cmdline'].isnumeric():
|
|
220
|
-
current_processes[pid]['cmdline'] = str()
|
|
221
|
-
elif process_info['cmdline'] == 'Error':
|
|
222
|
-
current_processes[pid]['cmdline'] = str()
|
|
223
|
-
|
|
224
|
-
# Append the current processes to the list.
|
|
225
|
-
list_of_processes.append(current_processes)
|
|
226
|
-
|
|
227
|
-
# Merge all dicts in the list to one dict, updating with most recent PIDs.
|
|
228
|
-
self.processes = list_of_dicts.merge_to_dict(list_of_processes)
|
|
229
|
-
|
|
230
|
-
if self.operation == 'process':
|
|
231
|
-
self.queue.put(self.processes)
|
|
232
|
-
|
|
233
|
-
time.sleep(self.interval_seconds)
|
|
234
|
-
|
|
235
|
-
def _thread_get_queue(self):
|
|
236
|
-
while True:
|
|
237
|
-
self.processes = self.queue.get()
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
"""Loading resources using stdlib importlib.resources APIs (Python 3.7+)
|
|
2
|
-
https://docs.python.org/3/library/importlib.html#module-importlib.resources"""
|
|
3
|
-
import importlib.resources
|
|
4
|
-
|
|
5
|
-
from .print_api import print_api
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class ScriptAsStringProcessor:
|
|
9
|
-
def __init__(self):
|
|
10
|
-
self.resources_directory_name: str = 'ssh_scripts'
|
|
11
|
-
|
|
12
|
-
# string variable that is going to be exchanged with variable from main script.
|
|
13
|
-
self.exchange_input_variable_string: str = "exchange_input_variable"
|
|
14
|
-
self.script_string: str = str()
|
|
15
|
-
|
|
16
|
-
def read_script_to_string(self, script_file_name: str):
|
|
17
|
-
self.script_string = importlib.resources.read_text(
|
|
18
|
-
f'{__package__}.{self.resources_directory_name}',
|
|
19
|
-
f'{script_file_name}.py')
|
|
20
|
-
|
|
21
|
-
return self
|
|
22
|
-
|
|
23
|
-
def put_variable_into_script_string(self, input_variable: any, print_kwargs: dict = None):
|
|
24
|
-
# Defining variables
|
|
25
|
-
function_result: str = str()
|
|
26
|
-
|
|
27
|
-
if self.exchange_input_variable_string in self.script_string:
|
|
28
|
-
# string.replace(old, new, count)
|
|
29
|
-
# old – old substring you want to replace.
|
|
30
|
-
# new – new substring which would replace the old substring.
|
|
31
|
-
# count – the number of times you want to replace the old substring with the new substring. (Optional)
|
|
32
|
-
# We want to replace our string only one time in the beginning.
|
|
33
|
-
function_result = self.script_string.replace(self.exchange_input_variable_string, str(input_variable), 1)
|
|
34
|
-
else:
|
|
35
|
-
message = f"The script string provided doesn't contain {self.exchange_input_variable_string}"
|
|
36
|
-
print_api(message, error_type=True, logger_method='error', **print_kwargs)
|
|
37
|
-
|
|
38
|
-
return function_result
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# importing the psutil library to get the source ports and get the process full command line from it.
|
|
2
|
-
import psutil
|
|
3
|
-
# 'psutil.Process(connection.pid).cmdline()' returns list of full command line parts, it is needed to reassemble
|
|
4
|
-
# these parts to regular command line string.
|
|
5
|
-
import shlex
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
# User defined exception.
|
|
9
|
-
class StopAllIterations(Exception):
|
|
10
|
-
pass
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
# 'input_variable' will be string exchanged in the real script. It is the first line, so it won't take time to find the
|
|
14
|
-
# line for the main script.
|
|
15
|
-
# noinspection PyUnresolvedReferences
|
|
16
|
-
remote_ipv4_list = exchange_input_variable
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
try:
|
|
20
|
-
# for iteration in range(100):
|
|
21
|
-
# Iterating through all the connections on the computer.
|
|
22
|
-
for connection in psutil.net_connections(kind='all'):
|
|
23
|
-
# 'connection.raddr' is a tuple consisting of IPv4 address [0] and the port [1].
|
|
24
|
-
# Sometimes, if there's no remote address, "raddr" will be empty and since it's a tuple, we need to check that
|
|
25
|
-
# before getting the first [0] index.
|
|
26
|
-
if connection.raddr:
|
|
27
|
-
for address in remote_ipv4_list:
|
|
28
|
-
if connection.raddr[0] == address:
|
|
29
|
-
# Get the command line from the connection PID.
|
|
30
|
-
command_line = psutil.Process(connection.pid).cmdline()
|
|
31
|
-
# Command line object is returned as list of parameters. We need 'shlex.join' to join the iterables
|
|
32
|
-
# to regular, readable string.
|
|
33
|
-
print(shlex.join(command_line))
|
|
34
|
-
# Break the loops, when first match is found.
|
|
35
|
-
raise StopAllIterations
|
|
36
|
-
except StopAllIterations:
|
|
37
|
-
pass
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
# importing the psutil library to get the source ports and get the process full command line from it.
|
|
2
|
-
import psutil
|
|
3
|
-
# 'psutil.Process(connection.pid).cmdline()' returns list of full command line parts, it is needed to reassemble
|
|
4
|
-
# these parts to regular command line string.
|
|
5
|
-
import shlex
|
|
6
|
-
|
|
7
|
-
# 'input_variable' will be string exchanged in the real script. It is the first line, so it won't take time to find the
|
|
8
|
-
# line for the main script.
|
|
9
|
-
# noinspection PyUnresolvedReferences
|
|
10
|
-
source_port = exchange_input_variable
|
|
11
|
-
|
|
12
|
-
# Iterating through all the connections on the computer.
|
|
13
|
-
for connection in psutil.net_connections():
|
|
14
|
-
# 'connection.laddr' is a tuple consisting of IPv4 address [0] and the port [1].
|
|
15
|
-
if connection.laddr[1] == source_port:
|
|
16
|
-
# Get the command line from the connection PID.
|
|
17
|
-
command_line = psutil.Process(connection.pid).cmdline()
|
|
18
|
-
# Command line object is returned as list of parameters. We need 'shlex.join' to join the iterables
|
|
19
|
-
# to regular, readable string.
|
|
20
|
-
result = shlex.join(command_line)
|
|
21
|
-
# If the result is still a PID, we'll try to get process name.
|
|
22
|
-
if result.isnumeric():
|
|
23
|
-
# Get the process name from the connection PID.
|
|
24
|
-
result = psutil.Process(connection.pid).name()
|
|
25
|
-
print(result)
|
|
26
|
-
# Break the loop, when first match is found.
|
|
27
|
-
break
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
# v1.0.2 - 21.03.2023 13:40
|
|
2
|
-
import sys
|
|
3
|
-
import shlex
|
|
4
|
-
|
|
5
|
-
from .. import process
|
|
6
|
-
from .. import web
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def download_file_with_curl(file_url: str, target_directory: str) -> None:
|
|
10
|
-
"""
|
|
11
|
-
The function receives url and target filesystem directory to download the file.
|
|
12
|
-
|
|
13
|
-
:param file_url: full URL to download the file.
|
|
14
|
-
:param target_directory: The directory on the filesystem to save the file to.
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
# Get only the filename from URL.
|
|
18
|
-
file_name = web.get_filename_from_url(file_url=file_url)
|
|
19
|
-
|
|
20
|
-
cmd: str = f'curl -L {file_url} --output "{target_directory}"'
|
|
21
|
-
cmd_list: list = shlex.split(cmd)
|
|
22
|
-
|
|
23
|
-
output_list: list = process.execute_with_live_output(cmd=cmd_list)
|
|
24
|
-
# If there was error in curl.
|
|
25
|
-
if 'curl: ' in output_list[-1]:
|
|
26
|
-
print('Curl error. Exiting...')
|
|
27
|
-
sys.exit()
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# v1.0.2 - 21.03.2023 18:30
|
|
2
|
-
import shlex
|
|
3
|
-
|
|
4
|
-
from .. import process
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def extract_archive_with_tar(file_path: str, target_directory: str) -> None:
|
|
8
|
-
"""
|
|
9
|
-
Function extracts the archive to target directory.
|
|
10
|
-
|
|
11
|
-
:param file_path: Full file path to archived file to extract.
|
|
12
|
-
:param target_directory: The directory on the filesystem to extract the file to.
|
|
13
|
-
:return: None
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
# -v: Verbose, shows list of extracted files.
|
|
17
|
-
# -C: Output directory.
|
|
18
|
-
cmd: str = f'tar -xzvf "{file_path}" -C "{target_directory}"'
|
|
19
|
-
cmd_list: list = shlex.split(cmd)
|
|
20
|
-
|
|
21
|
-
output_list = process.execute_with_live_output(cmd=cmd_list)
|
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
import subprocess
|
|
3
|
-
import getpass
|
|
4
|
-
|
|
5
|
-
from ... import process, filesystem, permissions
|
|
6
|
-
from ...print_api import print_api
|
|
7
|
-
from .. import ubuntu_terminal
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def is_docker_installed():
|
|
11
|
-
"""
|
|
12
|
-
The function will check if docker is installed.
|
|
13
|
-
:return: bool.
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
try:
|
|
17
|
-
# Run the command 'docker --version'
|
|
18
|
-
result = subprocess.run(['docker', '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
|
19
|
-
|
|
20
|
-
# Check if the command was successful
|
|
21
|
-
if result.returncode == 0:
|
|
22
|
-
message = f"Docker is installed. Version: {result.stdout.strip()}"
|
|
23
|
-
print_api(message, color='green')
|
|
24
|
-
return True
|
|
25
|
-
else:
|
|
26
|
-
print_api("Docker is not installed.")
|
|
27
|
-
return False
|
|
28
|
-
except FileNotFoundError:
|
|
29
|
-
print_api("Docker command not found. Docker is not installed.")
|
|
30
|
-
return False
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def add_current_user_to_docker_group(print_kwargs: dict = None):
|
|
34
|
-
"""
|
|
35
|
-
The function will add the current user to the docker group.
|
|
36
|
-
|
|
37
|
-
:param print_kwargs: dict, the print arguments.
|
|
38
|
-
:return:
|
|
39
|
-
"""
|
|
40
|
-
# Check if current user that executed the script is a sudo user. If not, use the current user.
|
|
41
|
-
sudo_executer_username: str = permissions.get_ubuntu_sudo_executer_username()
|
|
42
|
-
if sudo_executer_username:
|
|
43
|
-
current_user = sudo_executer_username
|
|
44
|
-
else:
|
|
45
|
-
current_user = getpass.getuser()
|
|
46
|
-
|
|
47
|
-
# Add the current user to the docker group.
|
|
48
|
-
# subprocess.check_call(['sudo', 'usermod', '-aG', 'docker', current_user])
|
|
49
|
-
command = f"sudo usermod -aG docker {current_user}"
|
|
50
|
-
# Execute the command
|
|
51
|
-
subprocess.run(command, shell=True, capture_output=True, text=True)
|
|
52
|
-
|
|
53
|
-
# Check if the user was added to the docker group.
|
|
54
|
-
result = subprocess.run(['groups', current_user], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
|
55
|
-
if 'docker' in result.stdout:
|
|
56
|
-
print_api(f"User {current_user} was added to the docker group.", color='green', **(print_kwargs or {}))
|
|
57
|
-
return True
|
|
58
|
-
else:
|
|
59
|
-
print_api(f"User {current_user} was not added to the docker group. Try executing with sudo", color='red',
|
|
60
|
-
**(print_kwargs or {}))
|
|
61
|
-
return False
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def install_docker_ubuntu(
|
|
65
|
-
use_docker_installer: bool = True,
|
|
66
|
-
rootless: bool = False,
|
|
67
|
-
add_current_user_to_docker_group_bool: bool = False
|
|
68
|
-
):
|
|
69
|
-
"""
|
|
70
|
-
The function will install docker on ubuntu.
|
|
71
|
-
Note: If you want to install docker in rootless mode, you need to run the script without sudo.
|
|
72
|
-
|
|
73
|
-
:param rootless: bool, if True, the rootless installation will be performed.
|
|
74
|
-
Meaning, you will be able to run the 'docker' command without sudo and you will not need to add the
|
|
75
|
-
current user to the docker group.
|
|
76
|
-
:param use_docker_installer: bool, if True, the docker installer will be used.
|
|
77
|
-
If False, the docker will be installed using the apt package manager, custom repo and keyring.
|
|
78
|
-
:param add_current_user_to_docker_group_bool: bool, if True, the current user will be added to the docker group.
|
|
79
|
-
So the user will be able to run the 'docker' command without sudo. If you install docker in rootless mode
|
|
80
|
-
this is not needed.
|
|
81
|
-
|
|
82
|
-
Usage in main.py (run with sudo):
|
|
83
|
-
from atomicshop.wrappers.dockerw import install_docker
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
def main():
|
|
87
|
-
install_docker.install_docker_ubuntu()
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if __name__ == '__main__':
|
|
91
|
-
main()
|
|
92
|
-
"""
|
|
93
|
-
|
|
94
|
-
if rootless and permissions.is_admin():
|
|
95
|
-
print_api('Rootless installation requires running the script without sudo.', color='red')
|
|
96
|
-
sys.exit()
|
|
97
|
-
|
|
98
|
-
if use_docker_installer:
|
|
99
|
-
if not ubuntu_terminal.is_executable_exists('curl'):
|
|
100
|
-
print_api('curl is not installed, installing...', color='yellow')
|
|
101
|
-
ubuntu_terminal.update_system_packages()
|
|
102
|
-
ubuntu_terminal.install_packages(['curl'])
|
|
103
|
-
|
|
104
|
-
# Use the docker installer script.
|
|
105
|
-
# The script will install docker and add the current user to the docker group.
|
|
106
|
-
# The script will also install docker-compose and docker-buildx.
|
|
107
|
-
# process.execute_script('curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh', shell=True)
|
|
108
|
-
process.execute_script('curl -fsSL https://get.docker.com | sh', shell=True)
|
|
109
|
-
# process.execute_script('curl -fsSL https://get.docker.com -o get-docker.sh', shell=True)
|
|
110
|
-
# process.execute_script('sh get-docker.sh', shell=True)
|
|
111
|
-
# filesystem.remove_file('get-docker.sh')
|
|
112
|
-
else:
|
|
113
|
-
# Remove the existing keyrings, so we will not be asked to overwrite it if it exists.
|
|
114
|
-
docker_keyring_file_path: str = "/etc/apt/keyrings/docker.gpg"
|
|
115
|
-
filesystem.remove_file(docker_keyring_file_path)
|
|
116
|
-
|
|
117
|
-
script = f"""
|
|
118
|
-
# Step 1: Set up Docker's apt repository
|
|
119
|
-
sudo apt-get update
|
|
120
|
-
sudo apt-get install -y ca-certificates curl gnupg
|
|
121
|
-
sudo install -m 0755 -d /etc/apt/keyrings
|
|
122
|
-
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
|
123
|
-
sudo chmod a+r /etc/apt/keyrings/docker.gpg
|
|
124
|
-
|
|
125
|
-
# Add the repository to Apt sources
|
|
126
|
-
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
|
127
|
-
sudo apt-get update
|
|
128
|
-
|
|
129
|
-
# Step 2: Install the Docker packages
|
|
130
|
-
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras
|
|
131
|
-
|
|
132
|
-
# Step 3: Verify the installation
|
|
133
|
-
# sudo docker run hello-world
|
|
134
|
-
|
|
135
|
-
# Add Privileges to run docker without sudo. Add current user to Docker superuser group.
|
|
136
|
-
# sudo usermod -aG docker $USER
|
|
137
|
-
"""
|
|
138
|
-
|
|
139
|
-
process.execute_script(script, shell=True)
|
|
140
|
-
|
|
141
|
-
if rootless:
|
|
142
|
-
# Install uidmap package.
|
|
143
|
-
if not ubuntu_terminal.is_package_installed('uidmap'):
|
|
144
|
-
print_api('uidmap is not installed, installing...', color='yellow')
|
|
145
|
-
ubuntu_terminal.update_system_packages()
|
|
146
|
-
ubuntu_terminal.install_packages(['uidmap'])
|
|
147
|
-
|
|
148
|
-
with permissions.temporary_regular_permissions():
|
|
149
|
-
# After 'get-docker.sh' execution, we will install docker in rootless mode.
|
|
150
|
-
# process.execute_script('dockerd-rootless-setuptool.sh install', shell=True, as_regular_user=True)
|
|
151
|
-
process.execute_script(
|
|
152
|
-
'/usr/bin/dockerd-rootless-setuptool.sh install',
|
|
153
|
-
as_regular_user=True,
|
|
154
|
-
shell=True,
|
|
155
|
-
executable=None)
|
|
156
|
-
|
|
157
|
-
# Start and enable the docker service in user mode.
|
|
158
|
-
docker_start_command = ubuntu_terminal.get_command_execution_as_sudo_executer(
|
|
159
|
-
'systemctl --user start docker.service')
|
|
160
|
-
docker_enable_command = ubuntu_terminal.get_command_execution_as_sudo_executer(
|
|
161
|
-
'systemctl --user enable docker.service')
|
|
162
|
-
print_api('Starting and enabling the docker service in user mode...')
|
|
163
|
-
process.execute_script(docker_start_command, shell=True, executable=None)
|
|
164
|
-
process.execute_script(docker_enable_command, shell=True, executable=None)
|
|
165
|
-
|
|
166
|
-
print_api('Executing "loginctl enable-linger" to enable Docker to run when the user is not logged in...')
|
|
167
|
-
non_sudo_executer = permissions.get_ubuntu_sudo_executer_username()
|
|
168
|
-
# Enable lingering so Docker runs when the user is not logged in
|
|
169
|
-
process.execute_script(f'sudo loginctl enable-linger {non_sudo_executer}', shell=True)
|
|
170
|
-
|
|
171
|
-
print_api('Adding $HOME/bin to your PATH...')
|
|
172
|
-
# Add $HOME/bin to your PATH if it's not already there.
|
|
173
|
-
with permissions.temporary_regular_permissions():
|
|
174
|
-
ubuntu_terminal.add_path_to_bashrc(as_regular_user=True)
|
|
175
|
-
|
|
176
|
-
# Add appropriate permissions to the docker socket, so the user can run docker commands without sudo in python.
|
|
177
|
-
# with open('/etc/profile.d/docker_vars.sh', 'w') as file:
|
|
178
|
-
# file.write('export DOCKER_HOST=unix:///run/user/1000/docker.sock')
|
|
179
|
-
|
|
180
|
-
# Since we are installing the rootless mode, this script runs without sudo, so to add the DOCKER_HOST variable
|
|
181
|
-
# to the environment, we need to add it to the /etc/profile.d/docker_vars.sh file with sudo.
|
|
182
|
-
command = "echo 'export DOCKER_HOST=unix:///run/user/1000/docker.sock' | sudo tee /etc/profile.d/docker_vars.sh"
|
|
183
|
-
subprocess.run(command, shell=True, check=True)
|
|
184
|
-
|
|
185
|
-
# ubuntu_terminal.add_line_to_bashrc(
|
|
186
|
-
# 'export DOCKER_HOST=unix:///run/user/1000/docker.sock', as_regular_user=True)
|
|
187
|
-
# process.execute_script('export DOCKER_HOST=unix:///run/user/1000/docker.sock', shell=True)
|
|
188
|
-
# Restart shell.
|
|
189
|
-
# process.execute_script('source ~/.bashrc', shell=True)
|
|
190
|
-
|
|
191
|
-
if add_current_user_to_docker_group_bool:
|
|
192
|
-
# Check if current user that executed the script is a sudo user. If not, use the current user.
|
|
193
|
-
# Add the current user to the docker group.
|
|
194
|
-
add_current_user_to_docker_group()
|
|
195
|
-
|
|
196
|
-
# Verify the installation.
|
|
197
|
-
result: list = process.execute_with_live_output('sudo docker run hello-world')
|
|
198
|
-
else:
|
|
199
|
-
result: list = process.execute_with_live_output('docker run hello-world')
|
|
200
|
-
|
|
201
|
-
print_api('\n'.join(result))
|
|
202
|
-
|
|
203
|
-
if 'Hello from Docker!' in '\n'.join(result):
|
|
204
|
-
print_api('Docker installed successfully.', color='green')
|
|
205
|
-
return True
|
|
206
|
-
else:
|
|
207
|
-
print_api('Docker installation failed.', color='red')
|
|
208
|
-
print_api('Please check the logs above for more information.', color='red')
|
|
209
|
-
return False
|