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.
Files changed (268) hide show
  1. atomicshop/__init__.py +1 -1
  2. atomicshop/{addons/mains → a_mains}/FACT/update_extract.py +3 -2
  3. atomicshop/a_mains/addons/process_list/compile.cmd +7 -0
  4. atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.dll +0 -0
  5. atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.exp +0 -0
  6. atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.lib +0 -0
  7. atomicshop/{addons → a_mains/addons}/process_list/process_list.cpp +8 -1
  8. atomicshop/a_mains/dns_gateway_setting.py +11 -0
  9. atomicshop/a_mains/get_local_tcp_ports.py +85 -0
  10. atomicshop/a_mains/github_wrapper.py +11 -0
  11. atomicshop/a_mains/install_ca_certificate.py +172 -0
  12. atomicshop/{addons/mains → a_mains}/msi_unpacker.py +3 -1
  13. atomicshop/a_mains/process_from_port.py +119 -0
  14. atomicshop/a_mains/set_default_dns_gateway.py +90 -0
  15. atomicshop/a_mains/update_config_toml.py +38 -0
  16. atomicshop/appointment_management.py +5 -3
  17. atomicshop/basics/ansi_escape_codes.py +3 -1
  18. atomicshop/basics/argparse_template.py +2 -0
  19. atomicshop/basics/booleans.py +27 -30
  20. atomicshop/basics/bytes_arrays.py +43 -0
  21. atomicshop/basics/classes.py +149 -1
  22. atomicshop/basics/dicts.py +12 -0
  23. atomicshop/basics/enums.py +2 -2
  24. atomicshop/basics/exceptions.py +5 -1
  25. atomicshop/basics/list_of_classes.py +29 -0
  26. atomicshop/basics/list_of_dicts.py +69 -5
  27. atomicshop/basics/lists.py +14 -0
  28. atomicshop/basics/multiprocesses.py +374 -50
  29. atomicshop/basics/package_module.py +10 -0
  30. atomicshop/basics/strings.py +160 -7
  31. atomicshop/basics/threads.py +14 -0
  32. atomicshop/basics/tracebacks.py +13 -4
  33. atomicshop/certificates.py +153 -52
  34. atomicshop/config_init.py +12 -7
  35. atomicshop/console_user_response.py +7 -14
  36. atomicshop/consoles.py +9 -0
  37. atomicshop/datetimes.py +98 -0
  38. atomicshop/diff_check.py +340 -40
  39. atomicshop/dns.py +128 -12
  40. atomicshop/etws/_pywintrace_fix.py +17 -0
  41. atomicshop/etws/const.py +38 -0
  42. atomicshop/etws/providers.py +21 -0
  43. atomicshop/etws/sessions.py +43 -0
  44. atomicshop/etws/trace.py +168 -0
  45. atomicshop/etws/traces/trace_dns.py +162 -0
  46. atomicshop/etws/traces/trace_sysmon_process_creation.py +126 -0
  47. atomicshop/etws/traces/trace_tcp.py +130 -0
  48. atomicshop/file_io/csvs.py +222 -24
  49. atomicshop/file_io/docxs.py +35 -18
  50. atomicshop/file_io/file_io.py +35 -19
  51. atomicshop/file_io/jsons.py +49 -0
  52. atomicshop/file_io/tomls.py +139 -0
  53. atomicshop/filesystem.py +864 -293
  54. atomicshop/get_process_list.py +133 -0
  55. atomicshop/{process_name_cmd.py → get_process_name_cmd_dll.py} +52 -19
  56. atomicshop/http_parse.py +149 -93
  57. atomicshop/ip_addresses.py +6 -1
  58. atomicshop/mitm/centered_settings.py +132 -0
  59. atomicshop/mitm/config_static.py +207 -0
  60. atomicshop/mitm/config_toml_editor.py +55 -0
  61. atomicshop/mitm/connection_thread_worker.py +875 -357
  62. atomicshop/mitm/engines/__parent/parser___parent.py +4 -17
  63. atomicshop/mitm/engines/__parent/recorder___parent.py +108 -51
  64. atomicshop/mitm/engines/__parent/requester___parent.py +116 -0
  65. atomicshop/mitm/engines/__parent/responder___parent.py +75 -114
  66. atomicshop/mitm/engines/__reference_general/parser___reference_general.py +10 -7
  67. atomicshop/mitm/engines/__reference_general/recorder___reference_general.py +5 -5
  68. atomicshop/mitm/engines/__reference_general/requester___reference_general.py +47 -0
  69. atomicshop/mitm/engines/__reference_general/responder___reference_general.py +95 -13
  70. atomicshop/mitm/engines/create_module_template.py +58 -14
  71. atomicshop/mitm/import_config.py +359 -139
  72. atomicshop/mitm/initialize_engines.py +160 -74
  73. atomicshop/mitm/message.py +64 -23
  74. atomicshop/mitm/mitm_main.py +892 -0
  75. atomicshop/mitm/recs_files.py +183 -0
  76. atomicshop/mitm/shared_functions.py +4 -10
  77. atomicshop/mitm/ssh_tester.py +82 -0
  78. atomicshop/mitm/statistic_analyzer.py +257 -166
  79. atomicshop/mitm/statistic_analyzer_helper/analyzer_helper.py +136 -0
  80. atomicshop/mitm/statistic_analyzer_helper/moving_average_helper.py +525 -0
  81. atomicshop/monitor/change_monitor.py +96 -120
  82. atomicshop/monitor/checks/dns.py +139 -70
  83. atomicshop/monitor/checks/file.py +77 -0
  84. atomicshop/monitor/checks/network.py +81 -77
  85. atomicshop/monitor/checks/process_running.py +33 -34
  86. atomicshop/monitor/checks/url.py +94 -0
  87. atomicshop/networks.py +671 -0
  88. atomicshop/on_exit.py +205 -0
  89. atomicshop/package_mains_processor.py +84 -0
  90. atomicshop/permissions/permissions.py +22 -0
  91. atomicshop/permissions/ubuntu_permissions.py +239 -0
  92. atomicshop/permissions/win_permissions.py +33 -0
  93. atomicshop/print_api.py +24 -41
  94. atomicshop/process.py +63 -17
  95. atomicshop/process_poller/__init__.py +0 -0
  96. atomicshop/process_poller/pollers/__init__.py +0 -0
  97. atomicshop/process_poller/pollers/psutil_pywin32wmi_dll.py +95 -0
  98. atomicshop/process_poller/process_pool.py +207 -0
  99. atomicshop/process_poller/simple_process_pool.py +311 -0
  100. atomicshop/process_poller/tracer_base.py +45 -0
  101. atomicshop/process_poller/tracers/__init__.py +0 -0
  102. atomicshop/process_poller/tracers/event_log.py +46 -0
  103. atomicshop/process_poller/tracers/sysmon_etw.py +68 -0
  104. atomicshop/python_file_patcher.py +1 -1
  105. atomicshop/python_functions.py +27 -75
  106. atomicshop/question_answer_engine.py +2 -2
  107. atomicshop/scheduling.py +24 -5
  108. atomicshop/sound.py +4 -2
  109. atomicshop/speech_recognize.py +8 -0
  110. atomicshop/ssh_remote.py +158 -172
  111. atomicshop/startup/__init__.py +0 -0
  112. atomicshop/startup/win/__init__.py +0 -0
  113. atomicshop/startup/win/startup_folder.py +53 -0
  114. atomicshop/startup/win/task_scheduler.py +119 -0
  115. atomicshop/system_resource_monitor.py +61 -46
  116. atomicshop/system_resources.py +8 -8
  117. atomicshop/tempfiles.py +1 -2
  118. atomicshop/timer.py +30 -11
  119. atomicshop/urls.py +41 -0
  120. atomicshop/venvs.py +28 -0
  121. atomicshop/versioning.py +27 -0
  122. atomicshop/web.py +110 -25
  123. atomicshop/web_apis/__init__.py +0 -0
  124. atomicshop/web_apis/google_custom_search.py +44 -0
  125. atomicshop/web_apis/google_llm.py +188 -0
  126. atomicshop/websocket_parse.py +450 -0
  127. atomicshop/wrappers/certauthw/certauth.py +1 -0
  128. atomicshop/wrappers/cryptographyw.py +29 -8
  129. atomicshop/wrappers/ctyping/etw_winapi/__init__.py +0 -0
  130. atomicshop/wrappers/ctyping/etw_winapi/const.py +335 -0
  131. atomicshop/wrappers/ctyping/etw_winapi/etw_functions.py +393 -0
  132. atomicshop/wrappers/ctyping/file_details_winapi.py +67 -0
  133. atomicshop/wrappers/ctyping/msi_windows_installer/cabs.py +2 -1
  134. atomicshop/wrappers/ctyping/msi_windows_installer/extract_msi_main.py +13 -9
  135. atomicshop/wrappers/ctyping/msi_windows_installer/tables.py +35 -0
  136. atomicshop/wrappers/ctyping/setup_device.py +466 -0
  137. atomicshop/wrappers/ctyping/win_console.py +39 -0
  138. atomicshop/wrappers/dockerw/dockerw.py +113 -2
  139. atomicshop/wrappers/elasticsearchw/config_basic.py +0 -12
  140. atomicshop/wrappers/elasticsearchw/elastic_infra.py +75 -0
  141. atomicshop/wrappers/elasticsearchw/elasticsearchw.py +2 -20
  142. atomicshop/wrappers/factw/get_file_data.py +12 -5
  143. atomicshop/wrappers/factw/install/install_after_restart.py +89 -5
  144. atomicshop/wrappers/factw/install/pre_install_and_install_before_restart.py +20 -14
  145. atomicshop/wrappers/factw/postgresql/firmware.py +4 -6
  146. atomicshop/wrappers/githubw.py +583 -51
  147. atomicshop/wrappers/loggingw/consts.py +49 -0
  148. atomicshop/wrappers/loggingw/filters.py +102 -0
  149. atomicshop/wrappers/loggingw/formatters.py +58 -71
  150. atomicshop/wrappers/loggingw/handlers.py +459 -40
  151. atomicshop/wrappers/loggingw/loggers.py +19 -0
  152. atomicshop/wrappers/loggingw/loggingw.py +1010 -178
  153. atomicshop/wrappers/loggingw/reading.py +344 -19
  154. atomicshop/wrappers/mongodbw/__init__.py +0 -0
  155. atomicshop/wrappers/mongodbw/mongo_infra.py +31 -0
  156. atomicshop/wrappers/mongodbw/mongodbw.py +1432 -0
  157. atomicshop/wrappers/netshw.py +271 -0
  158. atomicshop/wrappers/playwrightw/engine.py +34 -19
  159. atomicshop/wrappers/playwrightw/infra.py +5 -0
  160. atomicshop/wrappers/playwrightw/javascript.py +7 -3
  161. atomicshop/wrappers/playwrightw/keyboard.py +14 -0
  162. atomicshop/wrappers/playwrightw/scenarios.py +172 -5
  163. atomicshop/wrappers/playwrightw/waits.py +9 -7
  164. atomicshop/wrappers/powershell_networking.py +80 -0
  165. atomicshop/wrappers/psutilw/processes.py +81 -0
  166. atomicshop/wrappers/psutilw/psutil_networks.py +85 -0
  167. atomicshop/wrappers/psutilw/psutilw.py +9 -0
  168. atomicshop/wrappers/pyopensslw.py +9 -2
  169. atomicshop/wrappers/pywin32w/__init__.py +0 -0
  170. atomicshop/wrappers/pywin32w/cert_store.py +116 -0
  171. atomicshop/wrappers/pywin32w/console.py +34 -0
  172. atomicshop/wrappers/pywin32w/win_event_log/__init__.py +0 -0
  173. atomicshop/wrappers/pywin32w/win_event_log/fetch.py +174 -0
  174. atomicshop/wrappers/pywin32w/win_event_log/subscribe.py +212 -0
  175. atomicshop/wrappers/pywin32w/win_event_log/subscribes/__init__.py +0 -0
  176. atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_create.py +57 -0
  177. atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_terminate.py +49 -0
  178. atomicshop/wrappers/pywin32w/win_event_log/subscribes/schannel_logging.py +97 -0
  179. atomicshop/wrappers/pywin32w/winshell.py +19 -0
  180. atomicshop/wrappers/pywin32w/wmis/__init__.py +0 -0
  181. atomicshop/wrappers/pywin32w/wmis/msft_netipaddress.py +113 -0
  182. atomicshop/wrappers/pywin32w/wmis/win32_networkadapterconfiguration.py +259 -0
  183. atomicshop/wrappers/pywin32w/wmis/win32networkadapter.py +112 -0
  184. atomicshop/wrappers/pywin32w/wmis/wmi_helpers.py +236 -0
  185. atomicshop/wrappers/socketw/accepter.py +21 -7
  186. atomicshop/wrappers/socketw/certificator.py +216 -150
  187. atomicshop/wrappers/socketw/creator.py +190 -50
  188. atomicshop/wrappers/socketw/dns_server.py +500 -173
  189. atomicshop/wrappers/socketw/exception_wrapper.py +45 -52
  190. atomicshop/wrappers/socketw/process_getter.py +86 -0
  191. atomicshop/wrappers/socketw/receiver.py +144 -102
  192. atomicshop/wrappers/socketw/sender.py +65 -35
  193. atomicshop/wrappers/socketw/sni.py +334 -165
  194. atomicshop/wrappers/socketw/socket_base.py +134 -0
  195. atomicshop/wrappers/socketw/socket_client.py +137 -95
  196. atomicshop/wrappers/socketw/socket_server_tester.py +14 -9
  197. atomicshop/wrappers/socketw/socket_wrapper.py +717 -116
  198. atomicshop/wrappers/socketw/ssl_base.py +15 -14
  199. atomicshop/wrappers/socketw/statistics_csv.py +148 -17
  200. atomicshop/wrappers/sysmonw.py +157 -0
  201. atomicshop/wrappers/ubuntu_terminal.py +65 -26
  202. atomicshop/wrappers/win_auditw.py +189 -0
  203. atomicshop/wrappers/winregw/__init__.py +0 -0
  204. atomicshop/wrappers/winregw/winreg_installed_software.py +58 -0
  205. atomicshop/wrappers/winregw/winreg_network.py +232 -0
  206. {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info}/METADATA +31 -49
  207. atomicshop-3.10.5.dist-info/RECORD +306 -0
  208. {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info}/WHEEL +1 -1
  209. atomicshop/_basics_temp.py +0 -101
  210. atomicshop/addons/a_setup_scripts/install_psycopg2_ubuntu.sh +0 -3
  211. atomicshop/addons/a_setup_scripts/install_pywintrace_0.3.cmd +0 -2
  212. atomicshop/addons/mains/install_docker_rootless_ubuntu.py +0 -11
  213. atomicshop/addons/mains/install_docker_ubuntu_main_sudo.py +0 -11
  214. atomicshop/addons/mains/install_elastic_search_and_kibana_ubuntu.py +0 -10
  215. atomicshop/addons/mains/install_wsl_ubuntu_lts_admin.py +0 -9
  216. atomicshop/addons/package_setup/CreateWheel.cmd +0 -7
  217. atomicshop/addons/package_setup/Setup in Edit mode.cmd +0 -6
  218. atomicshop/addons/package_setup/Setup.cmd +0 -7
  219. atomicshop/addons/process_list/compile.cmd +0 -2
  220. atomicshop/addons/process_list/compiled/Win10x64/process_list.dll +0 -0
  221. atomicshop/addons/process_list/compiled/Win10x64/process_list.exp +0 -0
  222. atomicshop/addons/process_list/compiled/Win10x64/process_list.lib +0 -0
  223. atomicshop/archiver/_search_in_zip.py +0 -189
  224. atomicshop/archiver/archiver.py +0 -34
  225. atomicshop/archiver/search_in_archive.py +0 -250
  226. atomicshop/archiver/sevenz_app_w.py +0 -86
  227. atomicshop/archiver/sevenzs.py +0 -44
  228. atomicshop/archiver/zips.py +0 -293
  229. atomicshop/etw/dns_trace.py +0 -118
  230. atomicshop/etw/etw.py +0 -61
  231. atomicshop/file_types.py +0 -24
  232. atomicshop/mitm/engines/create_module_template_example.py +0 -13
  233. atomicshop/mitm/initialize_mitm_server.py +0 -240
  234. atomicshop/monitor/checks/hash.py +0 -44
  235. atomicshop/monitor/checks/hash_checks/file.py +0 -55
  236. atomicshop/monitor/checks/hash_checks/url.py +0 -62
  237. atomicshop/pbtkmultifile_argparse.py +0 -88
  238. atomicshop/permissions.py +0 -110
  239. atomicshop/process_poller.py +0 -237
  240. atomicshop/script_as_string_processor.py +0 -38
  241. atomicshop/ssh_scripts/process_from_ipv4.py +0 -37
  242. atomicshop/ssh_scripts/process_from_port.py +0 -27
  243. atomicshop/wrappers/_process_wrapper_curl.py +0 -27
  244. atomicshop/wrappers/_process_wrapper_tar.py +0 -21
  245. atomicshop/wrappers/dockerw/install_docker.py +0 -209
  246. atomicshop/wrappers/elasticsearchw/infrastructure.py +0 -265
  247. atomicshop/wrappers/elasticsearchw/install_elastic.py +0 -232
  248. atomicshop/wrappers/ffmpegw.py +0 -125
  249. atomicshop/wrappers/loggingw/checks.py +0 -20
  250. atomicshop/wrappers/nodejsw/install_nodejs.py +0 -139
  251. atomicshop/wrappers/process_wrapper_pbtk.py +0 -16
  252. atomicshop/wrappers/socketw/base.py +0 -59
  253. atomicshop/wrappers/socketw/get_process.py +0 -107
  254. atomicshop/wrappers/wslw.py +0 -191
  255. atomicshop-2.11.47.dist-info/RECORD +0 -251
  256. /atomicshop/{addons/mains → a_mains}/FACT/factw_fact_extractor_docker_image_main_sudo.py +0 -0
  257. /atomicshop/{addons → a_mains/addons}/PlayWrightCodegen.cmd +0 -0
  258. /atomicshop/{addons → a_mains/addons}/ScriptExecution.cmd +0 -0
  259. /atomicshop/{addons/mains → a_mains/addons}/inits/init_to_import_all_modules.py +0 -0
  260. /atomicshop/{addons → a_mains/addons}/process_list/ReadMe.txt +0 -0
  261. /atomicshop/{addons/mains → a_mains}/search_for_hyperlinks_in_docx.py +0 -0
  262. /atomicshop/{archiver → etws}/__init__.py +0 -0
  263. /atomicshop/{etw → etws/traces}/__init__.py +0 -0
  264. /atomicshop/{monitor/checks/hash_checks → mitm/statistic_analyzer_helper}/__init__.py +0 -0
  265. /atomicshop/{wrappers/nodejsw → permissions}/__init__.py +0 -0
  266. /atomicshop/wrappers/pywin32w/{wmi_win32process.py → wmis/win32process.py} +0 -0
  267. {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info/licenses}/LICENSE.txt +0 -0
  268. {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info}/top_level.txt +0 -0
@@ -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