I see the below error sometimes while running monkeyrunner scripts.
140501 17:01:58.950:S [MainThread] [com.android.chimpchat.adb.AdbChimpDevice] Error sending touch event: 500 515 DOWN_AND_UP
140501 17:01:58.950:S [MainThread] [com.android.chimpchat.adb.AdbChimpDevice]java.net.SocketException: Broken pipe
140501 17:01:58.950:S [MainThread] [com.android.chimpchat.adb.AdbChimpDevice] at java.net.SocketOutputStream.socketWrite0(Native Method)
140501 17:01:58.950:S [MainThread] [com.android.chimpchat.adb.AdbChimpDevice] at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
How do I catch these? There are post suggesting to use SocketException
from java.net import SocketException
However this doesnt seem to work
It may not be the most elegant solution, but here is what I came up with.
Since the issue is that when you kill a monkey script, the process on the android device doesn't clean up properly, so when you try to connect again, you get the pipe issue. You can kill -9 the monkey process on the device itself and you won't run into it anymore.
I have two scripts that work around the problem here.
This is the python:
3 from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
4 from time import sleep
5 import sys
6 import signal
7 import subprocess
8
9 device = None
10
11 def execute():
12 device = MonkeyRunner.waitForConnection()
13 #my code here
17
18 def exitGracefully(signum, frame):
19 print "Exiting Gracefully..."
20 subprocess.call(['./killmonkey.sh'])
21 sys.exit(1)
22
23 if __name__ == '__main__':
24 signal.signal(signal.SIGINT, exitGracefully)
25 execute()
And the kill monkey script:
#!/bin/bash
var=$(adb shell ps | grep monkey | awk '{print $2}')
echo $var
adb shell kill -9 $var
When I ctrl+c the python monkey script, it calls the killmonkey, which kills the process on the attached android device
This specifically only works if there are only one device attached as it doesn't specify a device ID. Not very elegant, but I find it effective.
It is impossible to catch it as an exception. You can't even use stderr.
If you'd really like to try catching it even an improper manner, you need to get into Java's logger:
from java.util.logging import Level, Logger, StreamHandler, SimpleFormatter
from java.io import ByteArrayOutputStream
device = # your code to get the device object
errors = ByteArrayOutputStream(100)
logger = Logger.getLogger('com.android.chimpchat.adb.AdbChimpDevice')
logger.addHandler(StreamHandler(errors, SimpleFormatter()))
device.touch(120, 120, 'DOWN_AND_UP')
if errors.size() > 0:
# any code you want
raise YourException
To catch any other Java error in MonkeyRunner you have to change the TAG in Logger.getLogger(TAG) to the class printing the log.
To actually get around the issue, you may also want to try: How do I catch SocketExceptions in MonkeyRunner?
I really like Brian's answer, but didn't like having to maintain another file just for this, so I ran the commands directly. Seems to be working so far.
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
import sys
import signal
import subprocess
device = None
def execute():
device = MonkeyRunner.waitForConnection()
#my code here
def exitGracefully(signum, frame):
"""
Kill monkey on the device or future connections will fail
"""
print "Exiting Gracefully..."
try:
subprocess.call("adb shell kill -9 $(adb shell ps | grep monkey | awk '{print $2}')", shell=True)
except Exception, e:
print(e)
sys.exit(1)
if __name__ == '__main__':
signal.signal(signal.SIGINT, exitGracefully)
execute()
Related
I am trying to set up Google secure LDAP on my Macbook Pro running Monterey 12.3 following these instructions from Google.
request.appendData_(NSData.dataWithBytes_length_(CONFIG,
len(CONFIG))) TypeError: Expecting byte-buffer, got str
See the script from the guide:
#!/usr/bin/python
from OpenDirectory import ODNode, ODSession, kODNodeTypeConfigure
from Foundation import NSMutableData, NSData
import os
import sys
# Reading plist
GOOGLELDAPCONFIGFILE = open(sys.argv[1], "r")
CONFIG = GOOGLELDAPCONFIGFILE.read()
GOOGLELDAPCONFIGFILE.close()
# Write the plist
od_session = ODSession.defaultSession()
od_conf_node, err = ODNode.nodeWithSession_type_error_(od_session, kODNodeTypeConfigure, None)
request = NSMutableData.dataWithBytes_length_(b'\x00'*32, 32)
request.appendData_(NSData.dataWithBytes_length_(CONFIG, len(CONFIG)))
response, err = od_conf_node.customCall_sendData_error_(99991, request, None)
# Edit the default search path and append the new node to allow for login
os.system("dscl -q localhost -append /Search CSPSearchPath /LDAPv3/ldap.google.com")
os.system("bash -c 'echo -e \"TLS_IDENTITY\tLDAP Client\" >> /etc/openldap/ldap.conf' ")
I have tried to find some solutions on Google (e.g. .encode, b'..) But I do not really understand it.
Thanks for the help.
Okay, I found the solution, actually here it was posted earlier.
Error running python script to create google ldap configuration on Macos
To start I know that TLSv1.0 is super old and should not be used, but I need to connect to some really old local hardware that isn't supporting anything else atm
#import ssl
from OpenSSL import SSL
try:
import urllib3.contrib.pyopenssl
urllib3.contrib.pyopenssl.inject_into_urllib3()
except ImportError:
pass
import requests sys, os, select, socket
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.poolmanager import PoolManager
from requests.packages.urllib3.util import ssl_
from requests.packages.urllib3.contrib import py
CIPHERS = (
'ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:
ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:AES256-SHA:'
)
class TlsAdapter(HTTPAdapter):
def __init__(self, ssl_options=0, **kwargs):
self.ssl_options = ssl_options
super(TlsAdapter, self).__init__(**kwargs)
def init_poolmanager(self, *pool_args, **pool_kwargs):
ctx = SSL.Context(SSL.TLSv1_METHOD)
self.poolmanager = PoolManager(*pool_args,
ssl_context=ctx,
**pool_kwargs)
session = requests.Session()
adapter = TlsAdapter(ssl.OP_NO_TLSv1_1 | ssl.OP_NO_TLSv1_2)
session.mount("https://", adapter)
data = { "key":"value"}
try:
r = session.post("https://192.168.1.1", data)
print(r)
except Exception as exception:
print(exception)
I've tried several ways. The above code is mostly ripped from similar issues posted here in the past but python3 ssl no longer supports TLSv1 so it throws an unsupported protocol error. I added the "import urllib3.contrib.pyopenssl" to try and force it to use pyOpenSSL instead per this urllib3 documentation. The current error with this code is
load_verify_locations() takes from 2 to 3 positional arguments but 4 were given
I know this is from the verify part of urllib3 context and I need to fix the context for pyOpenSSL but I've been stuck here trying to fix the context.
Analyzed the website in question in "https://www.ssllabs.com/" , the simulator doesn't use python for testing. I haven't been successful using python. However with jdk 1.8 , I was able to comment the line in the security file as mentioned in "https://www.youtube.com/watch?v=xSejtYOh4C0" and was able to work around the issue.
The server prefers these cipher suites. Is these supported ciphers in urllib3 ?
TLS_RSA_WITH_RC4_128_MD5 (0x4) INSECURE 128
TLS_RSA_WITH_RC4_128_SHA (0x5) INSECURE 128
TLS_RSA_WITH_3DES_EDE_CBC_SHA (0xa) WEAK
Right now I'm stuck with the below error:
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='{}', port={}): Max retries exceeded with url: /xxx.htm (Caused by ProtocolError('Connection aborted.', FileNotFoundError(2, 'No such file or directory')))
I'm writing a small program in Haskell which manipulates the commands arecordmidi and aplaymidi to record short improvisations on my digital piano through MIDI. I will press the R key, my program will create a new subprocess with the command arecordmidi. When I press R again, I want my recording to stop, by terminating the command arecordmidi.
How do I terminate the arecordmidi subprocess? If in a shell, CTRL+C would stop recording. This is what I want.
I'm using the following code to create the subprocess:
import System.Process
main = do
let rec_command = "arecordmidi -p \"CASIO USB-MIDI\" myRecording.midi"
process <- createProcess (shell rec_command)
-- I could try the following code, but the documentation of System.Process
-- says it's bad to use terminateProcess:
let (_, _, _, processHandle) = process
terminateProcess processHandle
terminateProcess sends a SIGTERM (terminate) signal to the process, which corresponds to the default behavior of the unix command kill, which generally is not what you want when trying to end a process nicely.
Ctrl+C sends the signal SIGINT (interrupt), which many applications handle by an orderly shutdown, and in your case probably results in the arecordmidi process saving outstanding data, and closing any pipes and files.
Looks like the way to send SIGINT with System.Process is with interruptProcessGroupOf.
I am setting up a system to connect to an AWS Redshift database from python. I am thinking that there's something wrong in the python script because I can connect via isql. I've installed all the relevant packages, and I am able to connect via isql as follows:
$ isql rndredshift readonly ***** -v
+---------------------------------------+
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+---------------------------------------+
SQL> quit
However, my python script is failing to connect. Here's the script:
import pyodbc
import sys
def main():
redshift_conn_str = assemble_connection_string(
Driver='{PostgreSQL}',
Server='10.191.4.97',
ServerName='rndredshift',
Port='5439',
Database='prod',
Uid='readonly',
Pwd='*******'
)
print("===========")
print(redshift_conn_str)
print("===========")
new_conn2 = pyodbc.connect(redshift_conn_str)
print(psql.read_sql('select top 10 * from rawdb.raw_imprequest_20150101', new_conn2))
def assemble_connection_string(**kwargs):
return ';'.join([k + '=' + v for (k, v) in kwargs.items()])
if __name__ == '__main__':
sys.exit(main())
Here's the output:
===========
Uid=readonly;Database=prod;ServerName=rndredshift;Driver={PostgreSQL}; Server=10.191.4.97;Pwd=********;Port=5439
===========
Traceback (most recent call last):
File "test_redshift.py", line 24, in <module>
sys.exit(main())
File "test_redshift.py", line 17, in main
new_conn2 = pyodbc.connect(redshift_conn_str)
pyodbc.Error: ('IM002', '[IM002] [unixODBC][Driver Manager]Data source name not found, and no default driver specified (0) (SQLDriverConnectW)')
The PosgreSQL driver is installed:
$ odbcinst -q -d
[PostgreSQL]
[MySQL]
And the data source is configured:
$ odbcinst -q -s
[rndredshift]
If you're using DSNs, you're going to need to specify that in your connection string. Also, if you want to use DSN-less connections, I believe the keyword is SERVER and not SERVERNAME.
Try this connection string?
Uid=readonly;Database=prod;DSN=rndredshift;Driver={PostgreSQL};Pwd=********;
Make sure you specify the full server name and port in odbc.ini as well. Also, since you're using PostgreSQL, any reason you're not using the native PostgreSQL driver?
https://wiki.postgresql.org/wiki/Psycopg
Good luck!
Also, I've been perplexed over the ways to obtain and install the PostgreSQL driver. When I installed unixODBC, the odbcinst.ini file was created and contained an entry for the PostgreSQL driver that looked this this:
[PostgreSQL]
Description = ODBC for PostgreSQL
Driver = /usr/lib/psqlodbc.so
Setup = /usr/lib/libodbcpsqlS.so
Driver64 = /usr/lib64/psqlodbc.so
Setup64 = /usr/lib64/libodbcpsqlS.so
FileUsage = 1
However, the files for Driver and Driver64 where not on the system. So then, I installed postgresql-odbc, which gave me the missing libraries. Is there a better way to do this? As I mentioned earlier, isql works fine, so I'm still thinking it's a python issue.
I decided to try using the psycopg2 package, and I got a connection to work! Here's my script:
import sys
import psycopg2
def main():
conn_string = "host='10.191.4.97' dbname='prod' user='readonly' password='****' port='5439'"
print("===========")
print(conn_string)
print("===========")
new_conn2 = psycopg2.connect(conn_string)
print("Connected using psycopg2!")
if __name__ == '__main__':
sys.exit(main())
So, while I'm happy that I can connect, the question still remains about pyodbc and the PostgreSQL connection string. Thoughts?
Here's the connection string:
Uid=readonly;Database=prod;ServerName=rndredshift;Driver={PostgreSQL}; Server=10.191.4.97;Pwd=********;Port=5439
Using DSN instead of ServerName didn't work.
Does anyone know how to use python to ping a local host to see if it is active or not? We (my team and I) have already tried using
os.system("ping 192.168.1.*")
But the response for destination unreachable is the same as the response for the host is up.
Thanks for your help.
Use this ...
import os
hostname = "localhost" #example
response = os.system("ping -n 1 " + hostname)
#and then check the response...
if response == 0:
print(hostname, 'is up!')
else:
print(hostname, 'is down!')
If using this script on unix/Linux replace -n switch with -c !
Thats all :)
I've found that using os.system(...) leads to false positives (as the OP said, 'destination host unreachable' == 0).
As stated before, using subprocess.Popen works. For simplicity I recommend doing that followed by parsing the results. You can easily do this like:
if ('unreachable' in output):
print("Offline")
Just check the various outputs you want to check from ping results. Make a 'this' in 'that' check for it.
Example:
import subprocess
hostname = "10.20.16.30"
output = subprocess.Popen(["ping.exe",hostname],stdout = subprocess.PIPE).communicate()[0]
print(output)
if ('unreachable' in output):
print("Offline")
The best way I could find to do this on Windows, if you don't want to be parsing the output is to use Popen like this:
num = 1
host = "192.168.0.2"
wait = 1000
ping = Popen("ping -n {} -w {} {}".format(num, wait, host),
stdout=PIPE, stderr=PIPE) ## if you don't want it to print it out
exit_code = ping.wait()
if exit_code != 0:
print("Host offline.")
else:
print("Host online.")
This works as expected. The exit code gives no false positives. I've tested it in Python 2.7 and 3.4 on Windows 7 and Windows 10.
I've coded a little program a while back. It might not be the exact thing you are looking for, but you can always run a program on the host OS that opens up a socket on startup. Here is the ping program itself:
# Run this on the PC that want to check if other PC is online.
from socket import *
def pingit(): # defining function for later use
s = socket(AF_INET, SOCK_STREAM) # Creates socket
host = 'localhost' # Enter the IP of the workstation here
port = 80 # Select port which should be pinged
try:
s.connect((host, port)) # tries to connect to the host
except ConnectionRefusedError: # if failed to connect
print("Server offline") # it prints that server is offline
s.close() #closes socket, so it can be re-used
pingit() # restarts whole process
while True: #If connected to host
print("Connected!") # prints message
s.close() # closes socket just in case
exit() # exits program
pingit() #Starts off whole process
And here you have the program that can recieve the ping request:
# this runs on remote pc that is going to be checked
from socket import *
HOST = 'localhost'
PORT = 80
BUFSIZ = 1024
ADDR = (HOST, PORT)
serversock = socket(AF_INET, SOCK_STREAM)
serversock.bind(ADDR)
serversock.listen(2)
while 1:
clientsock, addr = serversock.accept()
serversock.close()
exit()
To run a program without actually showing it, just save the file as .pyw instead of .py.
It makes it invisible until user checks running processes.
Hope it helped you
For simplicity, I use self-made functions based on socket.
def checkHostPort(HOSTNAME, PORT):
"""
check if host is reachable
"""
result = False
try:
destIp = socket.gethostbyname(HOSTNAME)
except:
return result
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(15)
try:
conn = s.connect((destIp, PORT))
result = True
conn.close()
except:
pass
return result
if Ip:Port is reachable, return True
If you wanna to simulate Ping, may refer to ping.py
Try this:
ret = os.system("ping -o -c 3 -W 3000 192.168.1.10")
if ret != 0:
print "Host is not up"
-o waits for only one packet
-W 3000 gives it only 3000 ms to reply to the packet.
-c 3 lets it try a few times so that your ping doesnt run forever
Use this and parse the string output
import subprocess
output = subprocess.Popen(["ping.exe","192.168.1.1"],stdout = subprocess.PIPE).communicate()[0]
How about the request module?
import requests
def ping_server(address):
try:
requests.get(address, timeout=1)
except requests.exceptions.ConnectTimeout:
return False
return True
No need to split urls to remove ports, or test ports, and no localhost false-positive.
Timeout amount doesn't really matter since it only hits the timeout when there is no server, which in my case meant performance no longer mattered. Otherwise, this returns at the speed of a request, which is plenty fast for me.
Timeout waits for the first bit, not total time, in case that matters.