I have two internet connections via LAN Cable. I am from India, so they are not reliable. If one internet stops working, I want to automatically switch to another internet connection.
I wrote this script to check, If Internet is working or not:
try:
request = requests.get("http://www.google.co.in", timeout=5)
except (requests.ConnectionError, requests.Timeout) as exception:
try:
request = requests.get("http://www.amazon.com", timeout=5)
except (requests.ConnectionError, requests.Timeout) as exception:
print("Internet not working, switching internet.....")
If there is no ping from google & amazon, I need to switch internet.
My connection name is "Wired connection 1" and "Wired connection 2".
Edit: If someone has a solution in any other language or using software, please let me know.
It is a bit tricky, because there can be different network connection management interfaces on Ubuntu.
One of the most popular is NetworkManager.
If your machine uses it, you can try getting and using NetworkManager python module.
It says that "You can use this interface to query NetworkManager about the overall state of the network and details of network devices like current IP addresses or DHCP options, and to configure, activate and deactivate network connections."
So it should work, provided your Ubuntu uses NetworkManager.
As I have never used it, I can't provide any technical details on how to set up connection switching.
If it turns out that module doesn't work or your Ubuntu doesn't use NetworkManager, you can always switch connections by using shell commands from within Python to change the connection, using whichever commands you would use from shell via os.system() calls or subprocess module.
I figured it out
import requests
import os
import time
sudoPassword = 'pass'
pingFailStreak = 0
url1 = "http://www.google.co.in"
url2 = "http://www.amazon.com"
timeout = 5
def doesInternetWork(url,timeout):
try:
request = requests.get(url, timeout=timeout)
return True
except (requests.ConnectionError, requests.Timeout) as exception:
return False
def connectInternet(netID):
if netID==1:
command = 'nmcli dev disconnect enp6s0'
p = os.system('echo %s|sudo -S %s' % (sudoPassword, command))
command = 'nmcli dev connect enp5s0'
p = os.system('echo %s|sudo -S %s' % (sudoPassword, command))
elif netID==2:
command = 'nmcli dev disconnect enp5s0'
p = os.system('echo %s|sudo -S %s' % (sudoPassword, command))
command = 'nmcli dev connect enp6s0'
p = os.system('echo %s|sudo -S %s' % (sudoPassword, command))
while True:
if doesInternetWork(url1,timeout) == False and doesInternetWork(url2,timeout) == False:
print("Internet not working")
pingFailStreak += 1
if pingFailStreak > 2:
print("Switching intetnet to 1")
connectInternet(1)
time.sleep(5)
if doesInternetWork(url1,timeout) == False and doesInternetWork(url2,timeout) == False:
print("Switching intetnet to 2")
connectInternet(2)
time.sleep(5)
time.sleep(2)
How do I ping a website or IP address with Python?
See this pure Python ping by Matthew Dixon Cowles and Jens Diemer. Also, remember that Python requires root to spawn ICMP (i.e. ping) sockets in linux.
import ping, socket
try:
ping.verbose_ping('www.google.com', count=3)
delay = ping.Ping('www.wikipedia.org', timeout=2000).do()
except socket.error, e:
print "Ping Error:", e
The source code itself is easy to read, see the implementations of verbose_ping and of Ping.do for inspiration.
Depending on what you want to achive, you are probably easiest calling the system ping command..
Using the subprocess module is the best way of doing this, although you have to remember the ping command is different on different operating systems!
import subprocess
host = "www.google.com"
ping = subprocess.Popen(
["ping", "-c", "4", host],
stdout = subprocess.PIPE,
stderr = subprocess.PIPE
)
out, error = ping.communicate()
print out
You don't need to worry about shell-escape characters. For example..
host = "google.com; `echo test`
..will not execute the echo command.
Now, to actually get the ping results, you could parse the out variable. Example output:
round-trip min/avg/max/stddev = 248.139/249.474/250.530/0.896 ms
Example regex:
import re
matcher = re.compile("round-trip min/avg/max/stddev = (\d+.\d+)/(\d+.\d+)/(\d+.\d+)/(\d+.\d+)")
print matcher.search(out).groups()
# ('248.139', '249.474', '250.530', '0.896')
Again, remember the output will vary depending on operating system (and even the version of ping). This isn't ideal, but it will work fine in many situations (where you know the machines the script will be running on)
You may find Noah Gift's presentation Creating Agile Commandline Tools With Python. In it he combines subprocess, Queue and threading to develop solution that is capable of pinging hosts concurrently and speeding up the process. Below is a basic version before he adds command line parsing and some other features. The code to this version and others can be found here
#!/usr/bin/env python2.5
from threading import Thread
import subprocess
from Queue import Queue
num_threads = 4
queue = Queue()
ips = ["10.0.1.1", "10.0.1.3", "10.0.1.11", "10.0.1.51"]
#wraps system ping command
def pinger(i, q):
"""Pings subnet"""
while True:
ip = q.get()
print "Thread %s: Pinging %s" % (i, ip)
ret = subprocess.call("ping -c 1 %s" % ip,
shell=True,
stdout=open('/dev/null', 'w'),
stderr=subprocess.STDOUT)
if ret == 0:
print "%s: is alive" % ip
else:
print "%s: did not respond" % ip
q.task_done()
#Spawn thread pool
for i in range(num_threads):
worker = Thread(target=pinger, args=(i, queue))
worker.setDaemon(True)
worker.start()
#Place work in queue
for ip in ips:
queue.put(ip)
#Wait until worker threads are done to exit
queue.join()
He is also author of: Python for Unix and Linux System Administration
http://ecx.images-amazon.com/images/I/515qmR%2B4sjL._SL500_AA240_.jpg
It's hard to say what your question is, but there are some alternatives.
If you mean to literally execute a request using the ICMP ping protocol, you can get an ICMP library and execute the ping request directly. Google "Python ICMP" to find things like this icmplib. You might want to look at scapy, also.
This will be much faster than using os.system("ping " + ip ).
If you mean to generically "ping" a box to see if it's up, you can use the echo protocol on port 7.
For echo, you use the socket library to open the IP address and port 7. You write something on that port, send a carriage return ("\r\n") and then read the reply.
If you mean to "ping" a web site to see if the site is running, you have to use the http protocol on port 80.
For or properly checking a web server, you use urllib2 to open a specific URL. (/index.html is always popular) and read the response.
There are still more potential meaning of "ping" including "traceroute" and "finger".
I did something similar this way, as an inspiration:
import urllib
import threading
import time
def pinger_urllib(host):
"""
helper function timing the retrival of index.html
TODO: should there be a 1MB bogus file?
"""
t1 = time.time()
urllib.urlopen(host + '/index.html').read()
return (time.time() - t1) * 1000.0
def task(m):
"""
the actual task
"""
delay = float(pinger_urllib(m))
print '%-30s %5.0f [ms]' % (m, delay)
# parallelization
tasks = []
URLs = ['google.com', 'wikipedia.org']
for m in URLs:
t = threading.Thread(target=task, args=(m,))
t.start()
tasks.append(t)
# synchronization point
for t in tasks:
t.join()
Here's a short snippet using subprocess. The check_call method either returns 0 for success, or raises an exception. This way, I don't have to parse the output of ping. I'm using shlex to split the command line arguments.
import subprocess
import shlex
command_line = "ping -c 1 www.google.comsldjkflksj"
args = shlex.split(command_line)
try:
subprocess.check_call(args,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
print "Website is there."
except subprocess.CalledProcessError:
print "Couldn't get a ping."
Most simple answer is:
import os
os.system("ping google.com")
I develop a library that I think could help you. It is called icmplib (unrelated to any other code of the same name that can be found on the Internet) and is a pure implementation of the ICMP protocol in Python.
It is completely object oriented and has simple functions such as the classic ping, multiping and traceroute, as well as low level classes and sockets for those who want to develop applications based on the ICMP protocol.
Here are some other highlights:
Can be run without root privileges.
You can customize many parameters such as the payload of ICMP packets and the traffic class (QoS).
Cross-platform: tested on Linux, macOS and Windows.
Fast and requires few CPU / RAM resources unlike calls made with subprocess.
Lightweight and does not rely on any additional dependencies.
To install it (Python 3.6+ required):
pip3 install icmplib
Here is a simple example of the ping function:
host = ping('1.1.1.1', count=4, interval=1, timeout=2, privileged=True)
if host.is_alive:
print(f'{host.address} is alive! avg_rtt={host.avg_rtt} ms')
else:
print(f'{host.address} is dead')
Set the "privileged" parameter to False if you want to use the library without root privileges.
You can find the complete documentation on the project page:
https://github.com/ValentinBELYN/icmplib
Hope you will find this library useful.
read a file name, the file contain the one url per line, like this:
http://www.poolsaboveground.com/apache/hadoop/core/
http://mirrors.sonic.net/apache/hadoop/core/
use command:
python url.py urls.txt
get the result:
Round Trip Time: 253 ms - mirrors.sonic.net
Round Trip Time: 245 ms - www.globalish.com
Round Trip Time: 327 ms - www.poolsaboveground.com
source code(url.py):
import re
import sys
import urlparse
from subprocess import Popen, PIPE
from threading import Thread
class Pinger(object):
def __init__(self, hosts):
for host in hosts:
hostname = urlparse.urlparse(host).hostname
if hostname:
pa = PingAgent(hostname)
pa.start()
else:
continue
class PingAgent(Thread):
def __init__(self, host):
Thread.__init__(self)
self.host = host
def run(self):
p = Popen('ping -n 1 ' + self.host, stdout=PIPE)
m = re.search('Average = (.*)ms', p.stdout.read())
if m: print 'Round Trip Time: %s ms -' % m.group(1), self.host
else: print 'Error: Invalid Response -', self.host
if __name__ == '__main__':
with open(sys.argv[1]) as f:
content = f.readlines()
Pinger(content)
import subprocess as s
ip=raw_input("Enter the IP/Domain name:")
if(s.call(["ping",ip])==0):
print "your IP is alive"
else:
print "Check ur IP"
If you want something actually in Python, that you can play with, have a look at Scapy:
from scapy.all import *
request = IP(dst="www.google.com")/ICMP()
answer = sr1(request)
That's in my opinion much better (and fully cross-platform), than some funky subprocess calls. Also you can have as much information about the answer (sequence ID.....) as you want, as you have the packet itself.
using system ping command to ping a list of hosts:
import re
from subprocess import Popen, PIPE
from threading import Thread
class Pinger(object):
def __init__(self, hosts):
for host in hosts:
pa = PingAgent(host)
pa.start()
class PingAgent(Thread):
def __init__(self, host):
Thread.__init__(self)
self.host = host
def run(self):
p = Popen('ping -n 1 ' + self.host, stdout=PIPE)
m = re.search('Average = (.*)ms', p.stdout.read())
if m: print 'Round Trip Time: %s ms -' % m.group(1), self.host
else: print 'Error: Invalid Response -', self.host
if __name__ == '__main__':
hosts = [
'www.pylot.org',
'www.goldb.org',
'www.google.com',
'www.yahoo.com',
'www.techcrunch.com',
'www.this_one_wont_work.com'
]
Pinger(hosts)
You can find an updated version of the mentioned script that works on both Windows and Linux here
using subprocess ping command to ping decode it because the response is binary:
import subprocess
ping_response = subprocess.Popen(["ping", "-a", "google.com"], stdout=subprocess.PIPE).stdout.read()
result = ping_response.decode('utf-8')
print(result)
you might try socket to get ip of the site and use scrapy to excute icmp ping to the ip.
import gevent
from gevent import monkey
# monkey.patch_all() should be executed before any library that will
# standard library
monkey.patch_all()
import socket
from scapy.all import IP, ICMP, sr1
def ping_site(fqdn):
ip = socket.gethostbyaddr(fqdn)[-1][0]
print(fqdn, ip, '\n')
icmp = IP(dst=ip)/ICMP()
resp = sr1(icmp, timeout=10)
if resp:
return (fqdn, False)
else:
return (fqdn, True)
sites = ['www.google.com', 'www.baidu.com', 'www.bing.com']
jobs = [gevent.spawn(ping_site, fqdn) for fqdn in sites]
gevent.joinall(jobs)
print([job.value for job in jobs])
On python 3 you can use ping3.
from ping3 import ping, verbose_ping
ip-host = '8.8.8.8'
if not ping(ip-host):
raise ValueError('{} is not available.'.format(ip-host))
If you only want to check whether a machine on an IP is active or not, you can just use python sockets.
import socket
s = socket.socket()
try:
s.connect(("192.168.1.123", 1234)) # You can use any port number here
except Exception as e:
print(e.errno, e)
Now, according to the error message displayed (or the error number), you can determine whether the machine is active or not.
Use this it's tested on python 2.7 and works fine it returns ping time in milliseconds if success and return False on fail.
import platform,subproccess,re
def Ping(hostname,timeout):
if platform.system() == "Windows":
command="ping "+hostname+" -n 1 -w "+str(timeout*1000)
else:
command="ping -i "+str(timeout)+" -c 1 " + hostname
proccess = subprocess.Popen(command, stdout=subprocess.PIPE)
matches=re.match('.*time=([0-9]+)ms.*', proccess.stdout.read(),re.DOTALL)
if matches:
return matches.group(1)
else:
return False
I have a program running a ping. On my terminal screen i get this:
--- google.com ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 47.963/47.963/47.963/0.000 ms
Connection successful
But on my console i am only getting:
Connection successful
I want my console to show the same ping statistics as my terminal does. I will eventually want to log the ping results onto a txt or csv file, but that will be down the road.
import platform # For getting the operating system name
import subprocess # For executing a shell command
import time
import logging
host = "google.com"
def ping(host):
param = '-n' if platform.system().lower()=='windows' else '-c'
command = ['ping', param, '1', host]
return subprocess.call(command) == 0
while ping(host) == False:
print("There is no network connection")
time.sleep(1)
while ping(host) == True:
print("Connection successful")
time.sleep(1)
How do i get my Terminal Ping statistics to display on my console output?
To log the full output of the command, use Popen.
import platform # For getting the operating system name
import subprocess # For executing a shell command
import time
host = "google.com"
def ping(host):
param = '-n' if platform.system().lower()=='windows' else '-c'
command = ['ping', param, '1', host]
return subprocess.Popen(command, stdout=subprocess.PIPE).stdout.read()
while True:
output = ping(host)
print(output)
time.sleep(1)
I tested on Ubuntu with Python 3.6.7
I re-edited for Linux to ping 3 times and output to a file. This will effectively tell you if the host is up or down. It should still print to terminal, you can use os.system('pause') though I don't remember if that works in Linux.
import os
def main():
f=['8.8.8.8','yahoo.com']
for ips in f:
response = os.system("ping -c3" + ips)
if response == 0:
writeToOut(ips,"host is up")
else:
writeToOut(ips, "host is down")
def writeToOut(ip,result):
f=open('C:/Users/user/Desktop/hostsResults.txt','a')
ip = ip.rstrip()
f.write(ip + "," + result + '\n')
f.close()
main()
Imagine a situation when two servers are available. One of them is constantly sshing to another one and executing some commands. The process takes around 5-10 seconds for each session since ssh connection must be established every time.
The question: is it possible to have a ready, established ssh connection in order to reduce the time of executing commands on remote server?
Here is an example for you. It can work as a ssh client. No need to recreate session everytime.
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import os,sys
import paramiko
import threading
import platform
curr_ssh = None
curr_prompt = ">>"
#how to use it
def printUsage():
print " !ls :list sessions."
print " !session id :connect session."
print " !conn host user password:connect host with user."
print " !exit :exit."
#connect using paramiko
def conn(ip,username,passwd):
try:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(ip,22,username,passwd,timeout=5)
print "Connect to ",ip," with ",username
global curr_prompt
curr_prompt=username+"#"+ip+">>"
return ssh
except:
return None
#get former session
sessions=[]
def loadSessions():
global sessions
try:
f = open("sessions")
sessions = f.readlines()
f.close()
except:
pass
#main function
def exe_cmd_local(cmd):
if(cmd == "!ls"):
loadSessions()
global sessions
i=0
print "Sessions:"
for s in sessions:
print"[%d] %s" %(i,s)
i+=1
else:
vals = cmd.split(' ')
if(vals[0]=="!session"):
id = (int)(vals[1])
if(id<len(sessions)):
os_name = platform.system()
new_console_cmd = ""
if(os_name == "Linux"):
new_console_cmd="gnome-terminal -e \"./ssh.py " + sessions[id]+"\""
elif(os_name == "Windows"):
new_console_cmd="start ssh.py " + sessions[id]
os.system(new_console_cmd)
else:
print "Didn't hava sessoin ",vals[1]
elif(vals[0]=="!conn"):
global curr_ssh
curr_ssh = conn(vals[1],vals[2],vals[3])
f = open("sessions","a")
line = vals[1]+" "+vals[2]+" "+vals[3]+"\n"
f.write(line)
f.close()
#execute command remotely
def exe_cmd_ssh(ssh,cmd):
if(ssh == None):
print "Didn't connect to a server. Use '!conn' to connect please."
return
stdin, stdout, stderr = ssh.exec_command(cmd)
print stdout.read()
print stderr.read()
if __name__=='__main__':
loadSessions()
if(len(sys.argv)==4):
curr_ssh = conn(sys.argv[1],sys.argv[2],sys.argv[3])
else:
printUsage()
while True:
cmd = raw_input(curr_prompt)
if(len(cmd)==0):
continue
if(cmd == "!exit"):
if(curr_ssh != None):
curr_ssh.close();
break
else:
if(cmd[0] == '!'):
exe_cmd_local(cmd)
else:
exe_cmd_ssh(curr_ssh,cmd)
Hope it helps. :)
One could use an existing ssh connection, by configuring ssh to re-use an already established connection. Please see man ssh_config:
ControlMaster
Enables the sharing of multiple sessions over a single network connection. When set to “yes”, ssh(1) will ...
So your ~/.ssh/config could contain:
Host firstServer
ControlMaster auto
ControlPath ~/.ssh/tmp/controlPath_%h_%p_%r
This will create a socket as a file named by 'ControlPath'. The next ssh connection will go through that same socket and will be lightning fast.
Enjoy
How can I check if there is still connection from a specific ip address using python.
ping the ip address
import os
#192.168.1.10 is the ip address
ret = os.system("ping -o -c 3 -W 3000 192.168.1.10")
if ret != 0:
print "pc still alive"
well in any case you really want to check for availability of incoming connection on the PC you are trying to connect you need to make a program that will receive the connection which is already out of the question.
As far as I understood the OP is looking for active connection FROM certain ip, meaning he wants to check locally if there is active connection exists. It looks like something along lines of netstat to me. There are several options:
You can use psutils as demonstrated in this post. You will want to cycle the active processes and query active connections.
You could use netstat.py - a clone of netstat by Jay Loden, Giampaolo Rodola' to do the job for you.
Added:
You can do something like that:
import psutil
def remote_ips():
'''
Returns the list of IPs for current active connections
'''
remote_ips = []
for process in psutil.process_iter():
try:
connections = process.get_connections(kind='inet')
except psutil.AccessDenied or psutil.NoSuchProcess:
pass
else:
for connection in connections:
if connection.remote_address and connection.remote_address[0] not in remote_ips:
remote_ips.append(connection.remote_address[0])
return remote_ips
def remote_ip_present(ip):
return ip in remote_ips()
This is how it works:
>>>remote_ips()
['192.168.1.50', '192.168.1.15', '192.168.1.52', '198.252.206.16', '198.252.206.17']
>>>remote_ip_present('192.168.1.52')
True
>>>remote_ip_present('10.1.1.1')
False
You can use socket library:
import socket
try:
socket.gethostbyaddr(your_ip_adrress)
except socket.herror:
print u"Unknown host"
if you are on Windows:
import os
ret = os.system("ping -n 3 1.1.1.1")
if ret != 0:
print("Ip address responding")
The -n argument is for how many times to ping it
if you are on LInux:
import os
ret = os.system("ping -c 3 1.1.1.1")
if ret != 0:
print("Ip address responding")
import os
address = "my_ip_address"
os.system('ping ' + address)