I have a python script (running on Mac OS X) that needs to be restarted when the internet goes down. If the internet is down, I would like to kill the current script, wait for the internet to go back up, and then restart it. Or, if possible, restart the function from within.
The problematic section of the Python code is as follows:
import tweetstream
# ...
with tweetstream.FilterStream(username, password, track = words) as stream:
for tweet in stream:
db.tweets.save(tweet)
Currently, if the internet goes down, the stream stops and doesn't reconnect.
It depends from os. There are few os specific methods.
First cross platform method will be own ping which will be send some packets to the Internet server. If you can not receive info that means Internet is goes down.
Try using this python implementation of ping as a subprocess. Thus, if too many timeouts occur, then you'll know the network's down and you can re-initiate the tweet process (however, to do this, you should probably put the entire tweeting process in a function of its own)
Perhaps you could try something like this:
import urllib2
def internet_on():
try:
response=urllib2.urlopen('http://74.125.131.94/',timeout=1)
return True
except urllib2.URLError as err: pass
return False
74.125.131.94 is the ip address of google.co.in . You can use whatever site you think will respond more quickly. Using a numerical IP-address avoids a DNS lookup, which may block the urllib2.urlopen call.The timeout=1 parameter makes sure that the call to urlopen will not take longer than 1 second even if the internet is not available.
Now you just need to call the internet_on() function. It will return true if the connection is on, else return false. Then you might want to wrap all the tweeting code inside a function and call it. (As #inspectorG4dget suggested).
EDIT:
For continuous checking you could do something like
def check():
while not internet_on():
pass
print "internet connection is on"
// call the tweet stuff function here.
Then when your stream stops just call the check() function and when the internet connection is back , it will call your tweet function to restart it.
Related
I have just started using ngrok, and while using the standard procedure, I can start the tunnel using ./ngrok tcp 22 and see that tunnel open in my dashboard,
But I would like to use pyngrok, and here when I use:
from pyngrok.conf import PyngrokConfig
from pyngrok import ngrok
ngrok.set_auth_token("<NGROK_AUTH_TOKEN>")
pyngrok_config = PyngrokConfig(config_path="/opt/ngrok/ngrok.yml")
ngrok.get_tunnels(pyngrok_config=pyngrok_config)
ssh_url = ngrok.connect()
It connects and generates a tunnel, but I can't see anything open in the dashboard, why?
Maybe because the python script executes and generates URL and then stops and comes out of it, but then how to make it keep running, or how to even start a tunnel using python or even API ? Please suggest the correct script, using python or API?
The thread with the ngrok tunnel will terminate as soon as the Python process terminates. So you are correct, the reason this is happening is because your script is not long lived. The easiest way to accomplish this is by following the example in the documentation.
Another issue is how you're setting the authtoken. Since you're not using the default config_path, you need to set this before setting the authtoken so it gets updated in the correct file (you'd also need to pass it to connect()). There are a couple ways to do this, but the easiest way from the docs is to just update the default config (since that's what will be used if you don't pass a pyngrok_config to any future method calls).
I also see that you're response variable is ssh_url, so you probably want to start a TCP tunnel to a port other than 80 (the default)—perhaps you've configured this in your ngrok.yml, but if not, I've updated the call to connect() to ensure this is the type of tunnel started for you and in case others try to use this same code snippet.
Full disclosure, I am the developer of pyngrok. Here is your code snippet updated with my changes.
import os, time
from pyngrok.conf import PyngrokConfig
from pyngrok import ngrok, conf
conf.get_default().config_path = "/opt/ngrok/ngrok.yml"
ngrok.set_auth_token(os.environ.get("NGROK_AUTH_TOKEN"))
ssh_tunnel = ngrok.connect(22, "tcp")
ngrok_process = ngrok.get_ngrok_process()
try:
# Block until CTRL-C or some other terminating event
ngrok_process.proc.wait()
except KeyboardInterrupt:
print(" Shutting down server.")
ngrok.kill()
I tried to make a simple chat system with the socket module in Python. everything works, except, that i need to kill the process everytime when i want to shutdown the server. And i don't want to do this everytime.
So my question is:
How can i make a function, that when i type shutdown in the server terminal, it shutdowns the whole server?
I already tried to do this:
def close(self):
server.close(self)
server.shutdown(self)
But it doesn't work. When i type close(), nothing happens. Nothing.
Heres the full code of the server.py:
https://pastebin.com/gA4QYmQe
Every help is useful. Thanks.
Well... there are many problems with the code (your "MY IP" and "SERVERIP" are probably not what you want, but this is beside the point.
Your close() function has a "self" parameter, which is pointless as this is not a class. You also need to move the close function to the beginning of your code if you want to call it from your try-except -structure. You need to call shutdown() first and then close(), and shutdown takes an argument. I modified your close() to do this and it works.
def close():
server.shutdown(socket.SHUT_RDWR)
server.close()
print ("closed")
When you open your socket, you should also set SO_REUSEADDR to make the address reusable (meaning you can start the server again if you shut it down, instead of waiting for a minute for TIME_WAIT status to finish with your server port):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
But how exactly are you calling close() when you type "shutdown" somewhere? You are not doing this. Your program is in the socket loop and is not reading keyboard input.
I see no point whatsoever adding keyboard input to this program. First, it adds complexity as you are operating with two possibly blocking inputs (socket input and keyboard input) and you would need to manage this. It is possible but definitely complicated. Second, it is faster to press Control + C instead of typing "shutdown" and hitting enter.
You currently do not call close after a keyboard interrupt. I added this to the inner KeyboardInterrupt (the outer you can remove - it is not doing anything and is never reached) and it now shuts down your program neatly, closing all connections. Remember to move close() function from the bottom of your code to the front before the try: statement:
except KeyboardInterrupt:
print("[!] Keyboard Interrupted!")
close()
break
If you want a remote shutdown (server shuts down if you type "shutdown" to the socket), you can add this to your server loop:
if message == "shutdown":
close()
exit(0)
There are other problems as well. For example, if you start your server, connect to it and shut down the connection, your server exits as it does not return to listen().
This is also (in my opinion), somewhat bad programming, as you use "server" as a global variable. I would rather create a class and put all socket operations in it, but if style is not important, this should work.
Hannu
One other approach would be having a default admin-client that can control the server. Admin-client will be created when the server starts and from that client admin can shutdown and do any of the admin tasks on the server.
I wish to use RPyC to provide an API for a hardware board as a service.
The board can only cater for a single user at a time.
Is there any way I can get RPyC to enforce that only a single user can get access at a time?
I'm not sure if this would work (or work well), but you can try starting a OneShotServer inside a loop, thus at any given moment only one connection is served. When the connection is closed, the server terminates, and you start another one for the next client.
Something like:
is_aborting = False
while not is_aborting:
server = OneShotServer(myservice, *args, **kwargs)
# serve the next client:
server.start()
# done serving the client
If this doesn't work, your best bet is to subclass ThreadedServer, and override the _accept_method method to keep track if there's already a connection open, and return an error if there is.
The log output of my python program (using the builtin logging module, but occurs even when using simple prints) is partially messed up, as you can see in the following image. Note the first line, first word still being correct and then it gets mixed up:
I tried to visualize the situation where this happens:
Basically in my main thread/program I start a simple socketserver.TCPServer to listen for incoming messages. That server runs on its own thread (QtCore.QThread) so my program is not blocked. If some other application sends a message the request handler of the TCPServer will simply forward the message to the main thread using a QtCore.SIGNAL like:
self.emit(QtCore.SIGNAL('received(const QString)'), receivedMessage)
The program then does some parsing and computation with that message and logs those, thereby producing the gibberish seen above. At some point the logging returns back to working normally.
I am not sure if this is related to sockets or threading or both, but I guess it may be a common issue and therefore I am thankful for any hints why this occurs.
I think I have located the problem:
When the external application wants to send a message it will always create a new client socket, connect to the server, send the message and then close the client socket.
The sock.close() does not seem to close immediately, the docs say I should call sock.shutdown(how) first, but unfortunately this did not help as well. I can use a small time.sleep(0.5) after the close to fix the logging issue, but instead I did something like this:
def ensure_closed(self):
while True:
try:
self.sock.recv(1024)
except:
break
def close_connection(self):
self.sock.close()
self.ensure_closed()
# Continue with other stuff.
# Now the logging behaves normally.
There might be better ways to do it.
I have a raspberry pi (I'm using linux) and a device that measures some values.
I have a python server and when a client sends a "I want the values" command, I ask the device some values. This is the function for my device:
def usbDevice:
dev = usb.core.find(idVendor=0xXXXX, idProduct=0xXXXX)
if dev is None:
return 'Not found'
dev.set_configuration()
dev.write(1, '\x05', 0) # ask for the values
time.sleep(2)
ret = dev.read(0x81,2048 , 0,1200) # endpoint, siz, interf, timeout ->meas. vals
print ret
return ret
When I start the communication it always goes well (both ways, I send the command and I get the
proper response ...).However, the second time I try it (no matter if I wait too long or not) I'm getting no response from the device. I know I can send the request (I used a print "step XX" to see where it is failing), but I get no answer... I am usually getting a timeout exception, but sometimes getting a "resource busy" exception.
Should I close the usb communication after using it the first time? How? Despite, I'm always compiling with sudo permissions, I created a .rules file, so I think there's not the problem.
Apart from this, I would really like to know if something's wrong with this way to establish the USB communication as I used something similar in the past. ( and I'm not good with python...)
Can you provide additional information such as the linux distribution and kernel number e.g.
uname -a
There are known USB issues. The good news is that a recent fix may have resolved them. Basically, use rpi-update and it should update the kernel (you want at least #389).