LinuxMonitor 1.1.0__tar.gz → 1.1.2__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.
- {linuxmonitor-1.1.0 → linuxmonitor-1.1.2/LinuxMonitor.egg-info}/PKG-INFO +2 -1
- {linuxmonitor-1.1.0/LinuxMonitor.egg-info → linuxmonitor-1.1.2}/PKG-INFO +2 -1
- {linuxmonitor-1.1.0 → linuxmonitor-1.1.2}/README.md +1 -0
- {linuxmonitor-1.1.0 → linuxmonitor-1.1.2}/linuxmonitor/__main__.py +7 -7
- {linuxmonitor-1.1.0 → linuxmonitor-1.1.2}/linuxmonitor/linuxmonitor.py +57 -45
- {linuxmonitor-1.1.0 → linuxmonitor-1.1.2}/setup.py +1 -1
- {linuxmonitor-1.1.0 → linuxmonitor-1.1.2}/LICENSE.md +0 -0
- {linuxmonitor-1.1.0 → linuxmonitor-1.1.2}/LinuxMonitor.egg-info/SOURCES.txt +0 -0
- {linuxmonitor-1.1.0 → linuxmonitor-1.1.2}/LinuxMonitor.egg-info/dependency_links.txt +0 -0
- {linuxmonitor-1.1.0 → linuxmonitor-1.1.2}/LinuxMonitor.egg-info/requires.txt +0 -0
- {linuxmonitor-1.1.0 → linuxmonitor-1.1.2}/LinuxMonitor.egg-info/top_level.txt +0 -0
- {linuxmonitor-1.1.0 → linuxmonitor-1.1.2}/linuxmonitor/__init__.py +0 -0
- {linuxmonitor-1.1.0 → linuxmonitor-1.1.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: LinuxMonitor
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.2
|
|
4
4
|
Summary: Get information and warning status of Linux server like service, port, ping, ssl certificate, disk/folder/cpu/ram/swap usage, ip connection, ... (Python and shell library, Linux ONLY)
|
|
5
5
|
Home-page: https://github.com/QuentinCG/Linux-Monitor-Python-Library
|
|
6
6
|
Author: Quentin Comte-Gaz
|
|
@@ -52,6 +52,7 @@ List of 'check' functionalities:
|
|
|
52
52
|
- Check services status and restart them if needed
|
|
53
53
|
- Check certificates expiration and validity
|
|
54
54
|
- Check last user connections IPs
|
|
55
|
+
- Check uptime (to inform if the server has been rebooted)
|
|
55
56
|
|
|
56
57
|
Additionnal functionalities:
|
|
57
58
|
- Get hostname, OS details, kernel version, server datetime, uptime
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: LinuxMonitor
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.2
|
|
4
4
|
Summary: Get information and warning status of Linux server like service, port, ping, ssl certificate, disk/folder/cpu/ram/swap usage, ip connection, ... (Python and shell library, Linux ONLY)
|
|
5
5
|
Home-page: https://github.com/QuentinCG/Linux-Monitor-Python-Library
|
|
6
6
|
Author: Quentin Comte-Gaz
|
|
@@ -52,6 +52,7 @@ List of 'check' functionalities:
|
|
|
52
52
|
- Check services status and restart them if needed
|
|
53
53
|
- Check certificates expiration and validity
|
|
54
54
|
- Check last user connections IPs
|
|
55
|
+
- Check uptime (to inform if the server has been rebooted)
|
|
55
56
|
|
|
56
57
|
Additionnal functionalities:
|
|
57
58
|
- Get hostname, OS details, kernel version, server datetime, uptime
|
|
@@ -24,6 +24,7 @@ List of 'check' functionalities:
|
|
|
24
24
|
- Check services status and restart them if needed
|
|
25
25
|
- Check certificates expiration and validity
|
|
26
26
|
- Check last user connections IPs
|
|
27
|
+
- Check uptime (to inform if the server has been rebooted)
|
|
27
28
|
|
|
28
29
|
Additionnal functionalities:
|
|
29
30
|
- Get hostname, OS details, kernel version, server datetime, uptime
|
|
@@ -98,7 +98,7 @@ def main() -> None:
|
|
|
98
98
|
if args.ping:
|
|
99
99
|
handled = True
|
|
100
100
|
print("Pinging websites...")
|
|
101
|
-
out_msg: str = monitoring.ping_all_websites(is_private=True, display_only_if_critical=False)
|
|
101
|
+
out_msg: str = asyncio.run(monitoring.ping_all_websites(is_private=True, display_only_if_critical=False))
|
|
102
102
|
print(out_msg)
|
|
103
103
|
|
|
104
104
|
if args.certificates:
|
|
@@ -110,24 +110,24 @@ def main() -> None:
|
|
|
110
110
|
if args.reboot_server:
|
|
111
111
|
handled = True
|
|
112
112
|
print("Restarting the entire server...")
|
|
113
|
-
out_msg: str = monitoring.reboot_server()
|
|
113
|
+
out_msg: str = asyncio.run(monitoring.reboot_server())
|
|
114
114
|
print(out_msg)
|
|
115
115
|
|
|
116
116
|
if args.services_status:
|
|
117
117
|
handled = True
|
|
118
118
|
print("Checking if services are running and restart if down...")
|
|
119
|
-
out_msg: str = monitoring.check_all_services_status_and_restart_if_down(is_private=True)
|
|
119
|
+
out_msg: str = asyncio.run(monitoring.check_all_services_status_and_restart_if_down(is_private=True))
|
|
120
120
|
print(out_msg)
|
|
121
121
|
|
|
122
122
|
if args.restart_all:
|
|
123
123
|
handled = True
|
|
124
124
|
print("Restarting all services...")
|
|
125
|
-
out_msg: str = monitoring.restart_all_services(is_private=True)
|
|
125
|
+
out_msg: str = asyncio.run(monitoring.restart_all_services(is_private=True))
|
|
126
126
|
|
|
127
127
|
if args.restart_service is not None:
|
|
128
128
|
handled = True
|
|
129
129
|
print(f"Restarting service: {args.restart_service}...")
|
|
130
|
-
out_msg: str = monitoring.restart_service(is_private=True, service_name=args.restart_service)
|
|
130
|
+
out_msg: str = asyncio.run(monitoring.restart_service(is_private=True, service_name=args.restart_service))
|
|
131
131
|
print(out_msg)
|
|
132
132
|
|
|
133
133
|
if args.list_services:
|
|
@@ -139,7 +139,7 @@ def main() -> None:
|
|
|
139
139
|
if args.ports:
|
|
140
140
|
handled = True
|
|
141
141
|
print("Checking ports...")
|
|
142
|
-
out_msg: str = monitoring.check_all_ports(is_private=True, display_only_if_critical=False, restart_if_down=False)
|
|
142
|
+
out_msg: str = asyncio.run(monitoring.check_all_ports(is_private=True, display_only_if_critical=False, restart_if_down=False))
|
|
143
143
|
print(out_msg)
|
|
144
144
|
|
|
145
145
|
if args.list_processes:
|
|
@@ -151,7 +151,7 @@ def main() -> None:
|
|
|
151
151
|
if args.kill_process is not None:
|
|
152
152
|
handled = True
|
|
153
153
|
print(f"Stopping process with PID: {args.kill_process}...")
|
|
154
|
-
out_msg: str = monitoring.kill_process(pid=args.kill_process)
|
|
154
|
+
out_msg: str = asyncio.run(monitoring.kill_process(pid=args.kill_process))
|
|
155
155
|
print(out_msg)
|
|
156
156
|
|
|
157
157
|
if args.start_scheduled_task_check_for_issues:
|
|
@@ -13,6 +13,7 @@ Non exhaustive list of features (available by using it in shell or in python scr
|
|
|
13
13
|
- Check services status and restart them if needed
|
|
14
14
|
- Check certificates expiration and validity
|
|
15
15
|
- Check last user connections IPs
|
|
16
|
+
- Check uptime (to inform if the server has been rebooted)
|
|
16
17
|
|
|
17
18
|
- Get hostname, OS details, kernel version, server datetime, uptime
|
|
18
19
|
- Get connected users
|
|
@@ -28,7 +29,7 @@ __email__ = "quentin@comte-gaz.com"
|
|
|
28
29
|
__license__ = "MIT License"
|
|
29
30
|
__copyright__ = "Copyright Quentin Comte-Gaz (2024)"
|
|
30
31
|
__python_version__ = "3.+"
|
|
31
|
-
__version__ = "1.1.
|
|
32
|
+
__version__ = "1.1.2 (2024/09/14)"
|
|
32
33
|
__status__ = "Usable for any Linux project"
|
|
33
34
|
|
|
34
35
|
import json
|
|
@@ -173,9 +174,9 @@ class LinuxMonitor:
|
|
|
173
174
|
|
|
174
175
|
#region Execute Command
|
|
175
176
|
|
|
176
|
-
def execute_and_verify(self, command: List[str], display_name: str, timeout_in_sec: Optional[int] = None, display_only_if_critical: bool = False, check_also_stdout_not_containing: Optional[str] = None) -> Tuple[Optional[bool], str]:
|
|
177
|
+
async def execute_and_verify(self, command: List[str], display_name: str, timeout_in_sec: Optional[int] = None, display_only_if_critical: bool = False, check_also_stdout_not_containing: Optional[str] = None) -> Tuple[Optional[bool], str]:
|
|
177
178
|
"""
|
|
178
|
-
Execute a shell command and verify its correct execution.
|
|
179
|
+
Execute a shell command asynchronously and verify its correct execution.
|
|
179
180
|
|
|
180
181
|
:param command: A list of strings representing the command and its arguments.
|
|
181
182
|
:param display_name: The name of the command to display in the output message.
|
|
@@ -185,18 +186,24 @@ class LinuxMonitor:
|
|
|
185
186
|
|
|
186
187
|
:return: A tuple containing a boolean indicating if the command was executed successfully and a string containing the result message.
|
|
187
188
|
"""
|
|
188
|
-
returncode: int =
|
|
189
|
+
returncode: Optional[int] = None
|
|
189
190
|
|
|
190
191
|
try:
|
|
191
192
|
logging.debug(msg=f"Executing command {display_name} (command: {command})...")
|
|
192
|
-
|
|
193
|
+
process = await asyncio.create_subprocess_exec(
|
|
194
|
+
*command,
|
|
195
|
+
stdout=asyncio.subprocess.PIPE,
|
|
196
|
+
stderr=asyncio.subprocess.PIPE,
|
|
197
|
+
shell=False
|
|
198
|
+
)
|
|
199
|
+
|
|
193
200
|
try:
|
|
194
|
-
stdout, stderr =
|
|
195
|
-
returncode =
|
|
196
|
-
except
|
|
201
|
+
stdout, stderr = await asyncio.wait_for(process.communicate(), timeout=timeout_in_sec)
|
|
202
|
+
returncode = process.returncode
|
|
203
|
+
except asyncio.TimeoutError:
|
|
197
204
|
logging.warning(msg=f"Timeout expired for {display_name} (command: {command})")
|
|
198
|
-
|
|
199
|
-
|
|
205
|
+
process.kill()
|
|
206
|
+
return None, f"⚠️ **Error {display_name}**:\n- Failed to execute the command in less than {timeout_in_sec} seconds)"
|
|
200
207
|
except Exception as e:
|
|
201
208
|
# Failed to execute the command
|
|
202
209
|
out_msg = f"⚠️ **Error {display_name}**:\n```sh\n{e}\n```"
|
|
@@ -208,7 +215,7 @@ class LinuxMonitor:
|
|
|
208
215
|
stderr_str: str = stderr.decode(encoding='utf-8').replace('`', '"').strip()
|
|
209
216
|
|
|
210
217
|
# Check if the command executed successfully
|
|
211
|
-
res: Optional[bool] = (returncode == 0) if (returncode !=
|
|
218
|
+
res: Optional[bool] = (returncode == 0) if (returncode != None) else None
|
|
212
219
|
if res and check_also_stdout_not_containing:
|
|
213
220
|
res = check_also_stdout_not_containing not in stdout_str
|
|
214
221
|
|
|
@@ -243,7 +250,7 @@ class LinuxMonitor:
|
|
|
243
250
|
|
|
244
251
|
#region Reboot
|
|
245
252
|
|
|
246
|
-
def reboot_server(self) -> str:
|
|
253
|
+
async def reboot_server(self) -> str:
|
|
247
254
|
"""
|
|
248
255
|
Reboot the server.
|
|
249
256
|
|
|
@@ -252,7 +259,7 @@ class LinuxMonitor:
|
|
|
252
259
|
IMPORTANT: To be usable, the user must have the right to execute `sudo /sbin/reboot` command without password.
|
|
253
260
|
"""
|
|
254
261
|
logging.info(msg="Rebooting the server...")
|
|
255
|
-
_, out_msg = self.execute_and_verify(command=["sudo", "/sbin/reboot"], display_name="Server reboot", timeout_in_sec=None, display_only_if_critical=False)
|
|
262
|
+
_, out_msg = await self.execute_and_verify(command=["sudo", "/sbin/reboot"], display_name="Server reboot", timeout_in_sec=None, display_only_if_critical=False)
|
|
256
263
|
return out_msg
|
|
257
264
|
|
|
258
265
|
#endregion
|
|
@@ -675,13 +682,16 @@ class LinuxMonitor:
|
|
|
675
682
|
dispo += f"{int(minutes)}min "
|
|
676
683
|
if seconds >= 1:
|
|
677
684
|
dispo += f"{int(seconds)}sec "
|
|
685
|
+
dispo += "ago"
|
|
678
686
|
|
|
679
687
|
out_msg: str = ""
|
|
680
688
|
if uptime_seconds < self.critical_uptime_seconds:
|
|
681
|
-
out_msg = f"- 🚨 **Server restarted recently**:\n- {dispo}(started on {boot_time})"
|
|
689
|
+
out_msg = f"- 🚨 **Server restarted recently**:\n- {dispo} (started on {boot_time})"
|
|
690
|
+
logging.warning(msg=out_msg)
|
|
682
691
|
elif not display_only_if_critical:
|
|
683
692
|
if uptime_seconds < self.warning_uptime_seconds:
|
|
684
|
-
out_msg = f"- ⚠️ **Server restarted recently**: {dispo}(started on {boot_time})"
|
|
693
|
+
out_msg = f"- ⚠️ **Server restarted recently**: {dispo} (started on {boot_time})"
|
|
694
|
+
logging.warning(msg=out_msg)
|
|
685
695
|
else:
|
|
686
696
|
# Funny emoji depending on uptime if everything is fine
|
|
687
697
|
emoji: str = ""
|
|
@@ -702,7 +712,7 @@ class LinuxMonitor:
|
|
|
702
712
|
else:
|
|
703
713
|
emoji = "☢️"
|
|
704
714
|
|
|
705
|
-
out_msg = f"- {emoji} **{dispo}**(started on {boot_time})"
|
|
715
|
+
out_msg = f"- {emoji} **{dispo}** (started on {boot_time})"
|
|
706
716
|
|
|
707
717
|
if out_msg != "":
|
|
708
718
|
out_msg = f"# 🕒 System availability 🕒\n{out_msg}"
|
|
@@ -717,7 +727,7 @@ class LinuxMonitor:
|
|
|
717
727
|
|
|
718
728
|
#region Ping Websites
|
|
719
729
|
|
|
720
|
-
def _ping_website(self, website: str, display_name: str, timeout_in_sec: int, display_only_if_critical: bool=False) -> str:
|
|
730
|
+
async def _ping_website(self, website: str, display_name: str, timeout_in_sec: int, display_only_if_critical: bool=False) -> str:
|
|
721
731
|
"""
|
|
722
732
|
Ping a website.
|
|
723
733
|
|
|
@@ -731,7 +741,7 @@ class LinuxMonitor:
|
|
|
731
741
|
display_name = f"[{display_name}](https://{website})"
|
|
732
742
|
|
|
733
743
|
start_time: float = time.time()
|
|
734
|
-
res, out_msg = self.execute_and_verify(command=ping_command, display_name=f"ping {display_name}", timeout_in_sec=timeout_in_sec, display_only_if_critical=display_only_if_critical)
|
|
744
|
+
res, out_msg = await self.execute_and_verify(command=ping_command, display_name=f"ping {display_name}", timeout_in_sec=timeout_in_sec, display_only_if_critical=display_only_if_critical)
|
|
735
745
|
end_time: float = time.time()
|
|
736
746
|
|
|
737
747
|
if res == True and not display_only_if_critical:
|
|
@@ -741,7 +751,7 @@ class LinuxMonitor:
|
|
|
741
751
|
|
|
742
752
|
return out_msg
|
|
743
753
|
|
|
744
|
-
def ping_all_websites(self, is_private: bool, display_only_if_critical: bool=False) -> str:
|
|
754
|
+
async def ping_all_websites(self, is_private: bool, display_only_if_critical: bool=False) -> str:
|
|
745
755
|
"""
|
|
746
756
|
Ping all websites configured in the JSON configuration file.
|
|
747
757
|
|
|
@@ -754,7 +764,7 @@ class LinuxMonitor:
|
|
|
754
764
|
for ping_config in self.config['pings']:
|
|
755
765
|
if is_private or is_private == ping_config['is_private']:
|
|
756
766
|
timeout_in_sec: int = ping_config.get('timeout_in_sec', 5)
|
|
757
|
-
result: str = self._ping_website(website=ping_config['website'], display_name=ping_config['display_name'], timeout_in_sec=timeout_in_sec, display_only_if_critical=display_only_if_critical)
|
|
767
|
+
result: str = await self._ping_website(website=ping_config['website'], display_name=ping_config['display_name'], timeout_in_sec=timeout_in_sec, display_only_if_critical=display_only_if_critical)
|
|
758
768
|
if result:
|
|
759
769
|
if out_msg:
|
|
760
770
|
out_msg += "\n"
|
|
@@ -797,7 +807,7 @@ class LinuxMonitor:
|
|
|
797
807
|
logging.info(msg=out_msg)
|
|
798
808
|
return out_msg
|
|
799
809
|
|
|
800
|
-
def restart_service(self, is_private: bool, service_name: str) -> str:
|
|
810
|
+
async def restart_service(self, is_private: bool, service_name: str) -> str:
|
|
801
811
|
"""
|
|
802
812
|
Restart a specific service.
|
|
803
813
|
|
|
@@ -831,7 +841,7 @@ class LinuxMonitor:
|
|
|
831
841
|
logging.info(f"Trying to restart {display_name} (command: {service_call}) in less than {timeout_in_sec}sec...")
|
|
832
842
|
|
|
833
843
|
start_time: float = time.time()
|
|
834
|
-
res, out_msg = self.execute_and_verify(command=service_call, display_name=f"restart {display_name}", timeout_in_sec=timeout_in_sec, display_only_if_critical=False)
|
|
844
|
+
res, out_msg = await self.execute_and_verify(command=service_call, display_name=f"restart {display_name}", timeout_in_sec=timeout_in_sec, display_only_if_critical=False)
|
|
835
845
|
end_time: float = time.time()
|
|
836
846
|
|
|
837
847
|
if res == True:
|
|
@@ -841,7 +851,7 @@ class LinuxMonitor:
|
|
|
841
851
|
|
|
842
852
|
return out_msg
|
|
843
853
|
|
|
844
|
-
def restart_all_services(self, is_private: bool) -> str:
|
|
854
|
+
async def restart_all_services(self, is_private: bool) -> str:
|
|
845
855
|
"""
|
|
846
856
|
Restart all services allowed to restart which are configured in the JSON configuration file.
|
|
847
857
|
|
|
@@ -852,7 +862,7 @@ class LinuxMonitor:
|
|
|
852
862
|
out_msg: str = ""
|
|
853
863
|
for service_name in self.config["services"].keys():
|
|
854
864
|
if is_private or self.config["services"][service_name]['is_private'] == is_private:
|
|
855
|
-
res: str = self.restart_service(is_private=is_private, service_name=service_name)
|
|
865
|
+
res: str = await self.restart_service(is_private=is_private, service_name=service_name)
|
|
856
866
|
if res != "":
|
|
857
867
|
if out_msg:
|
|
858
868
|
out_msg += "\n"
|
|
@@ -863,7 +873,7 @@ class LinuxMonitor:
|
|
|
863
873
|
|
|
864
874
|
return out_msg
|
|
865
875
|
|
|
866
|
-
def _get_service_status(self, is_private: bool, service_name: str) -> Tuple[Optional[bool], str]:
|
|
876
|
+
async def _get_service_status(self, is_private: bool, service_name: str) -> Tuple[Optional[bool], str]:
|
|
867
877
|
"""
|
|
868
878
|
Get the status of a specific service.
|
|
869
879
|
|
|
@@ -887,10 +897,10 @@ class LinuxMonitor:
|
|
|
887
897
|
status_command = service['status_command']
|
|
888
898
|
check_also_stdout_not_containing = service.get('check_also_stdout_not_containing', None)
|
|
889
899
|
|
|
890
|
-
res, out_msg = self.execute_and_verify(command=status_command, display_name=f"état de {display_name}", timeout_in_sec=timeout_in_sec, display_only_if_critical=False, check_also_stdout_not_containing=check_also_stdout_not_containing)
|
|
900
|
+
res, out_msg = await self.execute_and_verify(command=status_command, display_name=f"état de {display_name}", timeout_in_sec=timeout_in_sec, display_only_if_critical=False, check_also_stdout_not_containing=check_also_stdout_not_containing)
|
|
891
901
|
return res, out_msg
|
|
892
902
|
|
|
893
|
-
def check_all_services_status(self, is_private: bool) -> str:
|
|
903
|
+
async def check_all_services_status(self, is_private: bool) -> str:
|
|
894
904
|
"""
|
|
895
905
|
Check the status of all services configured in the JSON configuration file.
|
|
896
906
|
|
|
@@ -919,7 +929,7 @@ class LinuxMonitor:
|
|
|
919
929
|
|
|
920
930
|
for service_name in self.config["services"].keys():
|
|
921
931
|
if is_private or self.config["services"][service_name]['is_private'] == is_private:
|
|
922
|
-
status, status_msg = self._get_service_status(is_private=is_private, service_name=service_name)
|
|
932
|
+
status, status_msg = await self._get_service_status(is_private=is_private, service_name=service_name)
|
|
923
933
|
service_status: str = status_to_string(res=status)
|
|
924
934
|
service_icon: str = status_to_icon(res=status)
|
|
925
935
|
if out_msg != "":
|
|
@@ -933,7 +943,7 @@ class LinuxMonitor:
|
|
|
933
943
|
|
|
934
944
|
return out_msg
|
|
935
945
|
|
|
936
|
-
def check_all_services_status_and_restart_if_down(self, is_private: bool) -> str:
|
|
946
|
+
async def check_all_services_status_and_restart_if_down(self, is_private: bool) -> str:
|
|
937
947
|
"""
|
|
938
948
|
Check the status of all services configured in the JSON configuration file and restart them if they are inactive.
|
|
939
949
|
|
|
@@ -945,7 +955,7 @@ class LinuxMonitor:
|
|
|
945
955
|
try:
|
|
946
956
|
for service_name in self.config["services"].keys():
|
|
947
957
|
if is_private or self.config["services"][service_name]['is_private'] == is_private:
|
|
948
|
-
status, status_msg = self._get_service_status(is_private=is_private, service_name=service_name)
|
|
958
|
+
status, status_msg = await self._get_service_status(is_private=is_private, service_name=service_name)
|
|
949
959
|
if status is False:
|
|
950
960
|
out_msg: str = f"❌ **{self.config['services'][service_name]['display_name']} inactive**. Restarting the service is necessary."
|
|
951
961
|
logging.warning(msg=out_msg)
|
|
@@ -953,7 +963,7 @@ class LinuxMonitor:
|
|
|
953
963
|
out_msg += f"\n{status_msg}"
|
|
954
964
|
|
|
955
965
|
out_msg_full += out_msg + "\n"
|
|
956
|
-
out_msg_full += self.restart_service(is_private=is_private, service_name=service_name) + "\n"
|
|
966
|
+
out_msg_full += await self.restart_service(is_private=is_private, service_name=service_name) + "\n"
|
|
957
967
|
elif status is None:
|
|
958
968
|
out_msg: str = f"⚠️ **Error checking status of {self.config['services'][service_name]['display_name']}** (not restarting it)."
|
|
959
969
|
logging.error(msg=out_msg)
|
|
@@ -1367,7 +1377,7 @@ class LinuxMonitor:
|
|
|
1367
1377
|
|
|
1368
1378
|
return res, out_msg
|
|
1369
1379
|
|
|
1370
|
-
def check_all_ports(self, is_private: bool, display_only_if_critical: bool=False, restart_if_down: bool=False) -> str:
|
|
1380
|
+
async def check_all_ports(self, is_private: bool, display_only_if_critical: bool=False, restart_if_down: bool=False) -> str:
|
|
1371
1381
|
"""
|
|
1372
1382
|
Check all ports configured in the JSON configuration file (and restart the service if the port is down and service_name_to_restart added in config file).
|
|
1373
1383
|
|
|
@@ -1401,7 +1411,7 @@ class LinuxMonitor:
|
|
|
1401
1411
|
if out_msg != "":
|
|
1402
1412
|
out_msg += "\n"
|
|
1403
1413
|
|
|
1404
|
-
restart_res: str = self.restart_service(is_private=is_private, service_name=service_name_to_restart)
|
|
1414
|
+
restart_res: str = await self.restart_service(is_private=is_private, service_name=service_name_to_restart)
|
|
1405
1415
|
out_msg += f" - {restart_res}"
|
|
1406
1416
|
|
|
1407
1417
|
if out_msg != "":
|
|
@@ -1480,7 +1490,7 @@ class LinuxMonitor:
|
|
|
1480
1490
|
logging.info(msg=full_res)
|
|
1481
1491
|
return full_res
|
|
1482
1492
|
|
|
1483
|
-
def kill_process(self, pid: int, timeout_in_sec: int = 10) -> str:
|
|
1493
|
+
async def kill_process(self, pid: int, timeout_in_sec: int = 10) -> str:
|
|
1484
1494
|
"""
|
|
1485
1495
|
Kills a process with the specified PID.
|
|
1486
1496
|
1. Tries to terminate the process gracefully
|
|
@@ -1518,7 +1528,7 @@ class LinuxMonitor:
|
|
|
1518
1528
|
|
|
1519
1529
|
# Attempt to terminate the process
|
|
1520
1530
|
terminate_command: List[str] = ['sudo', '/bin/kill', '-TERM', str(pid)]
|
|
1521
|
-
result_terminate, _ = self.execute_and_verify(command=terminate_command, display_name=f"stop process {pid} ({process_name})", timeout_in_sec=timeout_in_sec, display_only_if_critical=False)
|
|
1531
|
+
result_terminate, _ = await self.execute_and_verify(command=terminate_command, display_name=f"stop process {pid} ({process_name})", timeout_in_sec=timeout_in_sec, display_only_if_critical=False)
|
|
1522
1532
|
|
|
1523
1533
|
if result_terminate == True:
|
|
1524
1534
|
out_msg = f"✅ **Process {pid} ({process_name}) stopped with success** (nicely)).\n"
|
|
@@ -1530,7 +1540,7 @@ class LinuxMonitor:
|
|
|
1530
1540
|
|
|
1531
1541
|
# Attempt to kill the process
|
|
1532
1542
|
kill_command = ['sudo', '/bin/kill', '-KILL', str(pid)]
|
|
1533
|
-
_, strerror_kill = self.execute_and_verify(command=kill_command, display_name=f"kill process {pid} ({process_name})", timeout_in_sec=timeout_in_sec, display_only_if_critical=False)
|
|
1543
|
+
_, strerror_kill = await self.execute_and_verify(command=kill_command, display_name=f"kill process {pid} ({process_name})", timeout_in_sec=timeout_in_sec, display_only_if_critical=False)
|
|
1534
1544
|
out_msg += strerror_kill
|
|
1535
1545
|
|
|
1536
1546
|
if process_cpu_percent > 0:
|
|
@@ -1620,7 +1630,8 @@ class LinuxMonitor:
|
|
|
1620
1630
|
if not self.allow_scheduled_tasks_check_for_issues:
|
|
1621
1631
|
raise Exception("Scheduled tasks are not allowed")
|
|
1622
1632
|
|
|
1623
|
-
|
|
1633
|
+
logging.info(msg=f"Waiting for 45 seconds before starting the execution of {'private' if is_private else 'public'} scheduled tasks to allow the discord bot and linux server to be ready...")
|
|
1634
|
+
await asyncio.sleep(delay=45) # Sleep for 45 sec before lauching the scheduled tasks (to allow the lib to be ready)
|
|
1624
1635
|
|
|
1625
1636
|
datetime_last_disk_usage_error_displayed: Optional[datetime] = None
|
|
1626
1637
|
datetime_last_folder_usage_error_displayed: Optional[datetime] = None
|
|
@@ -1635,7 +1646,7 @@ class LinuxMonitor:
|
|
|
1635
1646
|
datetime_last_services_error_displayed: Optional[datetime] = None
|
|
1636
1647
|
need_to_check_uptime: bool = True # No need to check uptime every time (since once ok, it can't be wrong)
|
|
1637
1648
|
|
|
1638
|
-
if not self.
|
|
1649
|
+
if not self.start_scheduled_tasks_immediately:
|
|
1639
1650
|
logging.info(msg=f"Waiting for {self.duration_in_sec_wait_between_each_schedule_task_execution} seconds before starting the execution of {'private' if is_private else 'public'} scheduled tasks...")
|
|
1640
1651
|
await asyncio.sleep(delay=self.duration_in_sec_wait_between_each_schedule_task_execution)
|
|
1641
1652
|
|
|
@@ -1645,7 +1656,7 @@ class LinuxMonitor:
|
|
|
1645
1656
|
logging.info(msg="Checking services status and all disk usage, CPU, RAM, Swap, CPU temperature and ping of websites periodically...")
|
|
1646
1657
|
try:
|
|
1647
1658
|
# Services status
|
|
1648
|
-
msg: str = self.check_all_services_status_and_restart_if_down(is_private=is_private)
|
|
1659
|
+
msg: str = await self.check_all_services_status_and_restart_if_down(is_private=is_private)
|
|
1649
1660
|
if msg != "":
|
|
1650
1661
|
logging.warning(msg=msg)
|
|
1651
1662
|
if datetime_last_services_error_displayed is None or ((datetime.now() - datetime_last_services_error_displayed).total_seconds() > self.max_duration_seconds_showing_same_error_again_in_scheduled_tasks):
|
|
@@ -1729,7 +1740,7 @@ class LinuxMonitor:
|
|
|
1729
1740
|
logging.info(msg="- ✅ Certificates are OK.")
|
|
1730
1741
|
|
|
1731
1742
|
# Ping
|
|
1732
|
-
msg = self.ping_all_websites(is_private=is_private, display_only_if_critical=True)
|
|
1743
|
+
msg = await self.ping_all_websites(is_private=is_private, display_only_if_critical=True)
|
|
1733
1744
|
if msg != "":
|
|
1734
1745
|
logging.warning(msg=msg)
|
|
1735
1746
|
if datetime_last_ping_error_displayed is None or ((datetime.now() - datetime_last_ping_error_displayed).total_seconds() > self.max_duration_seconds_showing_same_error_again_in_scheduled_tasks):
|
|
@@ -1750,7 +1761,7 @@ class LinuxMonitor:
|
|
|
1750
1761
|
logging.info(msg="- ✅ Ping of all websites are OK.")
|
|
1751
1762
|
|
|
1752
1763
|
# Ports
|
|
1753
|
-
msg = self.check_all_ports(is_private=is_private, display_only_if_critical=True, restart_if_down=True)
|
|
1764
|
+
msg = await self.check_all_ports(is_private=is_private, display_only_if_critical=True, restart_if_down=True)
|
|
1754
1765
|
if msg != "":
|
|
1755
1766
|
logging.warning(msg=msg)
|
|
1756
1767
|
if datetime_last_port_error_displayed is None or ((datetime.now() - datetime_last_port_error_displayed).total_seconds() > self.max_duration_seconds_showing_same_error_again_in_scheduled_tasks):
|
|
@@ -1918,7 +1929,8 @@ class LinuxMonitor:
|
|
|
1918
1929
|
if not self.allow_scheduled_task_show_info:
|
|
1919
1930
|
raise Exception("Scheduled show info tasks are not allowed")
|
|
1920
1931
|
|
|
1921
|
-
|
|
1932
|
+
logging.info(msg=f"Waiting for 45 seconds before starting the execution of {'private' if is_private else 'public'} show info scheduled tasks to allow the discord bot and linux server to be ready...")
|
|
1933
|
+
await asyncio.sleep(delay=45)
|
|
1922
1934
|
|
|
1923
1935
|
if not self.start_scheduled_task_show_info_immediately:
|
|
1924
1936
|
logging.info(msg=f"Waiting for {self.duration_in_sec_wait_between_each_schedule_task_show_info_execution} seconds before starting the execution of {'private' if is_private else 'public'} show info scheduled tasks...")
|
|
@@ -1930,7 +1942,7 @@ class LinuxMonitor:
|
|
|
1930
1942
|
logging.info(msg="-----------------------------------------------")
|
|
1931
1943
|
|
|
1932
1944
|
# Services status
|
|
1933
|
-
msg: str = self.check_all_services_status_and_restart_if_down(is_private=is_private)
|
|
1945
|
+
msg: str = await self.check_all_services_status_and_restart_if_down(is_private=is_private)
|
|
1934
1946
|
if msg != "":
|
|
1935
1947
|
if out_msg != "":
|
|
1936
1948
|
out_msg += "\n"
|
|
@@ -1958,14 +1970,14 @@ class LinuxMonitor:
|
|
|
1958
1970
|
out_msg += msg
|
|
1959
1971
|
|
|
1960
1972
|
# Ping
|
|
1961
|
-
msg = self.ping_all_websites(is_private=is_private, display_only_if_critical=False)
|
|
1973
|
+
msg = await self.ping_all_websites(is_private=is_private, display_only_if_critical=False)
|
|
1962
1974
|
if msg != "":
|
|
1963
1975
|
if out_msg != "":
|
|
1964
1976
|
out_msg += "\n"
|
|
1965
1977
|
out_msg += msg
|
|
1966
1978
|
|
|
1967
1979
|
# Ports
|
|
1968
|
-
msg = self.check_all_ports(is_private=is_private, display_only_if_critical=False, restart_if_down=False)
|
|
1980
|
+
msg = await self.check_all_ports(is_private=is_private, display_only_if_critical=False, restart_if_down=False)
|
|
1969
1981
|
if msg != "":
|
|
1970
1982
|
if out_msg != "":
|
|
1971
1983
|
out_msg += "\n"
|
|
@@ -6,7 +6,7 @@ with io.open(file='README.md', mode='r', encoding='utf-8') as readme_file:
|
|
|
6
6
|
|
|
7
7
|
setup(
|
|
8
8
|
name="LinuxMonitor",
|
|
9
|
-
version="1.1.
|
|
9
|
+
version="1.1.2",
|
|
10
10
|
description="Get information and warning status of Linux server like service, port, ping, ssl certificate, disk/folder/cpu/ram/swap usage, ip connection, ... (Python and shell library, Linux ONLY)",
|
|
11
11
|
long_description=readme,
|
|
12
12
|
long_description_content_type="text/markdown",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|