Posts: 56
Threads: 23
Joined: Jul 2021
Jun-24-2022, 11:29 AM
(This post was last modified: Jun-27-2022, 08:28 AM by AlphaInc.)
Hello everybody,
I have a script which should do something (to make an example, I let it create a folder). Therefore I defined a function which does just that:
def folder():
path = os.getcwd()
newPath = path+"/tmp"
os.mkdir(newPath) But I only want my function to be executed when at least one of my clients are online. The ip addresses are defined in a json file:
[
{
"Name": "Client 1",
"ip": "192.168.1.2"
},
{
"Name": "Client 2",
"ip": "192.168.1.3"
}
] Now I want to define a new function which checks all ip addresses. The question I have is, how do I get the ips from my json and ping them one after another to check if at least one of them is online and if they are execute my folder-function? This is all I have so far:
def ipCheck():
f = open('clients.json')
data = json.load(f)
for i in data:
print(i)
f.close()
Posts: 582
Threads: 1
Joined: Aug 2019
Hi @ AlphaInc ,
I understand you have two problems:
- You need to read a JSON file,
- You need to know if an IP address responds.
You dit almost right reading the JSON file, but you missed a detail. Look at the file: it starts with "[" so it is a list. There is one comma, so the list contains two items. The items start with "{" so they are dictionaries. You want the IP-address, and you see these addresses have key "ip".
So to extract these adresses you should do someting like:
import json
with open("clients.json") as f:
data = json.load(f)
for i in data:
print(i["ip"]) Now for the ping(). You could use pythonping, but if I understand the manual right, you need to be superuser to run a script using pythonping. I consider this to be bad practice.
So you need to use the default ping on your computer. On Windows you should execute one ping with "ping /n 1 192.168.1.2". On Linux-like systems you need to use "-c" (count) instead of "/n". So you could define a function like this:
from subprocess import call, DEVNULL
import platform
def ping(host_or_ip: str) -> bool :
"""ping() executes:
on windows:
ping /n 1 host_or_ip
on Linux or Mac:
ping -c 1 host_or_ip
Meaning: execute one ping to host_or_ip.
Returns True if host_or_ip responded,
else False.
"""
if platform.system().lower() == "windows":
countoption = "/n"
else:
countoption = "-c"
return not call(["ping", countoption, "1", host_or_ip],
stdout=DEVNULL, stderr=DEVNULL) Please show us how you use these building blocks to create your program. Let us know if you run into troubles.
Posts: 7,313
Threads: 123
Joined: Sep 2016
Jun-26-2022, 11:03 PM
(This post was last modified: Jun-26-2022, 11:04 PM by snippsat.)
icmplib is coolâ¨
We had a Thread about this before ping program in Python.
So to write a example on how it can be done,this also works as an unprivileged user.
import asyncio
from icmplib import async_multiping
import json
def read_json():
ip_lst = []
with open("clients.json") as f:
data = json.load(f)
# Add one to test online status
ip_lst.append('python-forum.io')
for ip in data:
ip_lst.append(ip["ip"])
return ip_lst
async def are_alive(addresses):
check_ip = []
hosts = await async_multiping(addresses, privileged=False)
for host in hosts:
if host.is_alive:
print(f'{host.address} is up!')
check_ip.append('up')
else:
print(f'{host.address} is down!')
check_ip.append('down')
return check_ip
if __name__ == '__main__':
ips = read_json()
status = asyncio.run(are_alive(ips))
if 'up' in status:
print('One host is online')
# Do someting
else:
print('No host is online') Output: 172.67.168.227 is up!
192.168.1.2 is down!
192.168.1.3 is down!
One host is online
Posts: 56
Threads: 23
Joined: Jul 2021
(Jun-26-2022, 05:15 PM)ibreeden Wrote: Hi @AlphaInc ,
I understand you have two problems:
- You need to read a JSON file,
- You need to know if an IP address responds.
You dit almost right reading the JSON file, but you missed a detail. Look at the file: it starts with "[" so it is a list. There is one comma, so the list contains two items. The items start with "{" so they are dictionaries. You want the IP-address, and you see these addresses have key "ip".
So to extract these adresses you should do someting like:
import json
with open("clients.json") as f:
data = json.load(f)
for i in data:
print(i["ip"]) Now for the ping(). You could use pythonping, but if I understand the manual right, you need to be superuser to run a script using pythonping. I consider this to be bad practice.
So you need to use the default ping on your computer. On Windows you should execute one ping with "ping /n 1 192.168.1.2". On Linux-like systems you need to use "-c" (count) instead of "/n". So you could define a function like this:
from subprocess import call, DEVNULL
import platform
def ping(host_or_ip: str) -> bool :
"""ping() executes:
on windows:
ping /n 1 host_or_ip
on Linux or Mac:
ping -c 1 host_or_ip
Meaning: execute one ping to host_or_ip.
Returns True if host_or_ip responded,
else False.
"""
if platform.system().lower() == "windows":
countoption = "/n"
else:
countoption = "-c"
return not call(["ping", countoption, "1", host_or_ip],
stdout=DEVNULL, stderr=DEVNULL) Please show us how you use these building blocks to create your program. Let us know if you run into troubles.
Okay, now I understand how to read the json file. But I still have trouble to ping the ips I wrote in my json file. This is my current code:
from subprocess import call, DEVNULL
import platform
import json
import sys
import os
def folder():
path = os.getcwd()
newPath = path+"/tmp"
os.mkdir(newPath)
def ip_check(host_or_ip: str) -> bool :
with open("clients.json") as f:
data = json.load(f)
for i in data:
print(i["ip"])
if platform.system().lower() == "windows":
countoption = "/n"
else:
countoption = "-c"
return not call(["ping", countoption, "1", host_or_ip],
stdout=DEVNULL, stderr=DEVNULL)
ip_check(host_or_ip)
#End
sys.exit() After executing the script I get this error message:
Traceback (most recent call last):
File "/home/pi/system/debug/modules/ipCheck/v0.6.py", line 31, in <module>
ip_check(host_or_ip)
NameError: name 'host_or_ip' is not defined
Posts: 582
Threads: 1
Joined: Aug 2019
Jun-27-2022, 07:16 AM
(This post was last modified: Jun-27-2022, 07:17 AM by ibreeden.)
No. You must read the ip addresses from the json file one by one, and for each address test if it responds.
from subprocess import call, DEVNULL
import platform
import json
import os
def folder():
path = os.getcwd()
newPath = path + "/tmp"
os.mkdir(newPath)
def ping(host_or_ip: str) -> bool :
"""ping(): execute one ping to host_or_ip.
Returns True if host_or_ip responded,
else False.
"""
if platform.system().lower() == "windows":
countoption = "/n"
else:
countoption = "-c"
return not call(["ping", countoption, "1", host_or_ip],
stdout=DEVNULL, stderr=DEVNULL)
responding_hosts = 0
with open("clients.json") as f:
data = json.load(f)
for i in data:
print(f"pinging: {i['ip']}")
if ping(i["ip"]):
responding_hosts += 1
print(f"Number of responding hosts: {responding_hosts}")
if responding_hosts > 0 :
folder()
Posts: 56
Threads: 23
Joined: Jul 2021
(Jun-27-2022, 07:16 AM)ibreeden Wrote: No. You must read the ip addresses from the json file one by one, and for each address test if it responds.
from subprocess import call, DEVNULL
import platform
import json
import os
def folder():
path = os.getcwd()
newPath = path + "/tmp"
os.mkdir(newPath)
def ping(host_or_ip: str) -> bool :
"""ping(): execute one ping to host_or_ip.
Returns True if host_or_ip responded,
else False.
"""
if platform.system().lower() == "windows":
countoption = "/n"
else:
countoption = "-c"
return not call(["ping", countoption, "1", host_or_ip],
stdout=DEVNULL, stderr=DEVNULL)
responding_hosts = 0
with open("clients.json") as f:
data = json.load(f)
for i in data:
print(f"pinging: {i['ip']}")
if ping(i["ip"]):
responding_hosts += 1
print(f"Number of responding hosts: {responding_hosts}")
if responding_hosts > 0 :
folder()
Okay nice, this worked great!
Sorry, but I have one last question. I tried to check for two different json files (one contains a list of IPs which should be offline and one which should be online) but I'm running into some problems once again:
#!/usr/bin/env python3
#Imports
from subprocess import call, DEVNULL
import platform
import json
import os
#IP Configuration
responding_clients1 = 0
responding_clients2 = 0
#Folder Creation
def folder():
path = os.getcwd()
newPath = path + "/tmp"
os.mkdir(newPath)
#Pinp Configuration
def ping(host_or_ip: str) -> bool :
if platform.system().lower() == "windows":
countoption = "/n"
else:
countoption = "-c"
return not call(["ping", countoption, "1", host_or_ip],
stdout=DEVNULL, stderr=DEVNULL)
#Clients1 Check
with open("clients1.json") as f1:
data1 = json.load(f1)
for i in data1:
if ping(i["ip"]):
responding_clients1 += 1
#Clients2 Check
with open("clients2.json") as f2:
data2 = json.load(f2)
for i in data2:
if ping(i["ip"]):
responding_clients2 += 1
#ToDo
if responding_clients1 > 0 :
if responding_clients2 == 0:
folder()
#End
sys.exit() And I get this error message:
Traceback (most recent call last):
File "/home/pi/system/debug/ipCheck/v1.0.py", line 37, in <module>
data2 = json.load(f2)
File "/usr/local/lib/python3.10/json/__init__.py", line 293, in load
return loads(fp.read(),
File "/usr/local/lib/python3.10/json/__init__.py", line 346, in loads
return _default_decoder.decode(s)
File "/usr/local/lib/python3.10/json/decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/local/lib/python3.10/json/decoder.py", line 353, in raw_decode
obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Expecting ',' delimiter: line 9 column 3 (char 112)
Posts: 56
Threads: 23
Joined: Jul 2021
(Jun-27-2022, 08:02 AM)AlphaInc Wrote: (Jun-27-2022, 07:16 AM)ibreeden Wrote: No. You must read the ip addresses from the json file one by one, and for each address test if it responds.
from subprocess import call, DEVNULL
import platform
import json
import os
def folder():
path = os.getcwd()
newPath = path + "/tmp"
os.mkdir(newPath)
def ping(host_or_ip: str) -> bool :
"""ping(): execute one ping to host_or_ip.
Returns True if host_or_ip responded,
else False.
"""
if platform.system().lower() == "windows":
countoption = "/n"
else:
countoption = "-c"
return not call(["ping", countoption, "1", host_or_ip],
stdout=DEVNULL, stderr=DEVNULL)
responding_hosts = 0
with open("clients.json") as f:
data = json.load(f)
for i in data:
print(f"pinging: {i['ip']}")
if ping(i["ip"]):
responding_hosts += 1
print(f"Number of responding hosts: {responding_hosts}")
if responding_hosts > 0 :
folder()
Okay nice, this worked great!
Sorry, but I have one last question. I tried to check for two different json files (one contains a list of IPs which should be offline and one which should be online) but I'm running into some problems once again:
#!/usr/bin/env python3
#Imports
from subprocess import call, DEVNULL
import platform
import json
import os
#IP Configuration
responding_clients1 = 0
responding_clients2 = 0
#Folder Creation
def folder():
path = os.getcwd()
newPath = path + "/tmp"
os.mkdir(newPath)
#Pinp Configuration
def ping(host_or_ip: str) -> bool :
if platform.system().lower() == "windows":
countoption = "/n"
else:
countoption = "-c"
return not call(["ping", countoption, "1", host_or_ip],
stdout=DEVNULL, stderr=DEVNULL)
#Clients1 Check
with open("clients1.json") as f1:
data1 = json.load(f1)
for i in data1:
if ping(i["ip"]):
responding_clients1 += 1
#Clients2 Check
with open("clients2.json") as f2:
data2 = json.load(f2)
for i in data2:
if ping(i["ip"]):
responding_clients2 += 1
#ToDo
if responding_clients1 > 0 :
if responding_clients2 == 0:
folder()
#End
sys.exit() And I get this error message:
Traceback (most recent call last):
File "/home/pi/system/debug/ipCheck/v1.0.py", line 37, in <module>
data2 = json.load(f2)
File "/usr/local/lib/python3.10/json/__init__.py", line 293, in load
return loads(fp.read(),
File "/usr/local/lib/python3.10/json/__init__.py", line 346, in loads
return _default_decoder.decode(s)
File "/usr/local/lib/python3.10/json/decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/local/lib/python3.10/json/decoder.py", line 353, in raw_decode
obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Expecting ',' delimiter: line 9 column 3 (char 112)
Nevermind, there was a missing comma in my second .json file. Thank you all for your help
|