I'm trying to find a means of monitoring the output to the console of a remove server over ssh, and from within Python.
Paramiko and Fabric python modules provide a good means of getting an ssh connection and executing specific commands on the remote server and getting the output from these commands.
However I don't want to execute anything I just want to "screen scrape" so to speak all the output being spitted out to the console on that machine.
Can Paramiko be used for this purpose, or does anyone know of another Python utility that can achieve this ?
Ok so I've managed to get this working using SSHClient.invoke_shell(), and monitoring it's output. Solaris hardware all come with ILOM (Integrated Lights Out Manager) configured, which is very useful getting a serial console on a machine.
client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect("9.9.9.9", 22, "username", "password")
channel = client.invoke_shell()
channel.settimeout(0.0)
while True:
r, w, e = select.select([channel], [], [])
try:
console_data = ""
while channel.recv_ready():
console_data += channel.recv(1024)
if len(console_data) == 0:
print "\n*** EOF\n"
break
# Search console_data for console prompt
# If found, start a serial console
if re.search("->", console_data):
channel.send("start -script SP/Console")
elif re.search("y/n", console_data):
channel.send("y\n")
elif re.search("SOME STRING ON CONSOLE", console_data):
print "Action completed"
break
except socket.timeout:
pass
channel.close()
client.close()
Above code connects to Service port on ILOM and waits for "->" prompt, once received it starts the serial console via "start -script SP/Console", and then anwsers "y" to continue prompt.
Now we have serial console and can monitor all output to this serial console, when some predefined string is output to the console I can exit.
Related
I have this function on a thread running with kivy when i close the app i have to close this socket manually so i can re-run it i tried to socket.SO_REUSEADDR, 1 but it did'nt work and i have this after at end of the code chat_recv_socket.close(). What i want is a more efficient way to kill or end this socket at the except block.
def func_chat_recv_socket():
global chat_recv_string, myip, chat_recv_socket
while True:
if myip != '':
break
while True:
try:
chat_recv_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
chat_recv_socket.bind((myip, 4600))
chat_recv_socket.listen(10)
while True:
clientsocket, address = chat_recv_socket.accept()
while True:
chat_recv = clientsocket.recv(100)
print('recieving msg')
chat_recv_string = chat_recv.decode("utf-8")
print(chat_recv)
clientsocket.close()
break
except:
### sys or os workaround on android
time.sleep(0.5)
print('binding')
This part was add after
After using this
os.system('freeport 4600')
I am getting this :
Process Type: 'python3' Port: 4600. Kill?[yes/no]
How can u say say from python?
this solution wont work because this command needs to be executed width the sudo. here is the output:
sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
No process running on port 4600 by current user. Checking if root is running the proecess
No process found running on port 4600.
the app has a different behavior on Android, with the catlog from adb android it seems that after closing and opening the app the socket is closed with it, on reopening no error is printed and the socket gets binded as expected. its not a solution but its enough for me right now.
Hi I am trying to create a function which remotely executes my packet sniffing script on my raspberry pi using paramiko and ssh.
def startPacketReceiver():
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(AutoAddPolicy())
ssh.connect(RECV_IP_ADDRESS, username="pi", password="raspberry")
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command("sudo gcc Code/test.c && sudo ./a.out")
print("Done")
The test.c file is the packet sniffing script. It will only terminate with a CTRL-C (or equivalent method). It does not terminate naturally/eventually.
I want to be able to start the receiver and then quit the receiver e.g:
startPacketReceiver()
...
stopPacketReceiver()
Currently when I run the python script I never get the "Done" print message, meaning that the program is hung on the exec_command and will not continue until it is terminated.
Additional Info
The test.c file loops infinitely, essentially:
while(1)
{
saddr_size = sizeof saddr;
//Receive a packet
data_size = recvfrom(sock_raw , buffer , 65536 , 0 , &saddr , (socklen_t*)&saddr_size);
//fprintf(stderr,"%d",data_size);
if(data_size <0 )
{
fprintf(stderr,"Failed to get packet\n");
printf("Recvfrom error , failed to get packets\n");
return 1;
}
//Now process the packet
ProcessPacket(buffer , data_size);
}
and so to stop it you must CTRL-C it.
You need to send your password to the sudo command. Please enable tty mode for executing your command by passing get_pty = True argument to exec_command function call. And then you need to pass your password through ssh_stdin file interface.
def startPacketReceiver():
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(AutoAddPolicy())
ssh.connect(RECV_IP_ADDRESS, username="pi", password="raspberry")
ssh.stdin, ssh_stdout, ssh_stderr = ssh.exec_command("gcc Code/test.c && sudo ./a.out", get_pty=True)
print("raspberry", ssh_stdin) # Your password for sudo command
print("Done")
return ssh, ssh_stdin, ssh_stdout, ssh_stderr
And then you can write your stopPacketReceiver to send Ctrl-C signal.
def stopPacketReceiver(ssh, ssh_stdin, ssh_stdout, ssh_stderr):
print('\x03', file=ssh_stdin) # Send Ctrl-C signal
print(ssh_stdout.read()) #print the stdout
print(ssh_stderr.read())
I suggest taking a look at daemon(3)
Then you can capture SIGNALS or reopen standard input.
Depends on what you would like to do with your python script.
(If you don't want to use any python any python library other than sys and os)
EDIT:
I am pretty sure when the python script will terminate the ssh connection will obviously close and so any program running on that tty by the user who initiated the connection will be terminated.
For that reason your c program needs to be daemonized and may need
to have its uid and/or euid changed.
Despite that i tried to reproduce your code and I ran into a similar problem: the python script was running the command then print "Done"
but as I tried to read stdout, the entire script was pause.
I think it was waiting for the script return status.
So i did the following changes:
try:
port = '22'
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('<host_name>', port=22, username='<username>',
password='<password>')
chan = client.get_transport().open_session()
chan.get_pty()
chan.exec_command("cd <script_directory>;\
; gcc test.c; ./a.out")
while True:
print(chan.recv(1024))
finally:
client.close()
The while loop here is to get output of the c program.
But if you close the python script the c program will follow.
I did not dug to much into this library.
EDIT 2:
Look up nohup
if you don't want to use de daemon approach.
I am new to this concept so please help!
I am using Paramiko Channel to execute a command and start a trace. I want the trace to continue running until I send a stop request to trace. If I use channel.send(cmd) it starts and stops the trace whereas I want that the trace should be continue and only stop when I send any stop request as I have other actions to perform before stopping the trace.
Note: I am doing SSH in one machine with Paramiko and starting a new channel in that machine to ssh into one more machine to start the trace there. I tried exec_command but it closes the socket.
Thing I want to know:
How can I start the trace and not let the command stop it before returning
How to stop the trace after I perform my actions after starting the trace.
The code I am using:
chan = sshClient.get_transport().open_session()
chan.get_pty()
chan.invoke_shell()
chan.send(cmdline +'\n')
while not sshClient.recv_ready():
print("Waiting")
resp = chan.recv(9999)
print(resp)
Thanks for your help in advance!
The following example shows that in the while loop that goes for-ever you execute a command and then print the output. After this is finished it sends again a command
import base64
import paramiko
import time
key = paramiko.RSAKey(data=base64.b64decode(b'AAA...'))
client = paramiko.SSHClient()
client.get_host_keys().add('ssh.example.com', 'ssh-rsa', key)
client.connect('ssh.example.com', username='strongbad', password='thecheat')
while True:
time.sleep(5)
stdin, stdout, stderr = client.exec_command('ls')
for line in stdout:
print('... ' + line.strip('\n'))
client.close()
It is possible that you need to send a newline \n after each command so that client.exec_command('ls') becomes -> client.exec_command('ls\n')
Though it's late, putting it across :
exec_command will close the channel as soon as command is executed.
You may try using something like :
# Get a client
chan = client.invoke_shell()
time.sleep(1) ## You may test with smaller time as well & see what fits best
chan.send('<command>\r')
output = chan.recv(4096)
print(output)
while <Event_is_not_yet_triggered> :
time.sleep(10)
chan.send('\x03') # Send Ctrl+C
time.sleep(1)
output = chan.recv(4096)
client.close()
In the end it really depends on the server to which you are connected allows. Above will work with most of them.
My code read like this-
import paramiko
import time
import sys
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
def runScripts():
parameter1 = 1000
client.connect('mysite.com', username='user', password='pass')
print ("Logged in into Site server")
stdin, stdout, stderr = client.exec_command("cd parent_folder/Sub_folder/script_folder; ./script1.sh %s" % parameter1)
print ("Script executed perfectly")
client.close()
runScripts()
And i got output on console as below-
Logged in into Site server
Script executed perfectly
But checked the file which was going to get affected due to the script.sh 1000 has no changes. the problem is not with script.sh because i can run the same manually and it behaves as expected.
Is client not able to detect end of the command?
I found out answer to my own query on a video over youtube for interactive commands.
Some how it was problem with command termination and client was unable to find end of it as it is not unix/system defined command ("system commands like ls -lrt, cd, grep works perfectly fine with client")
So i tried channel like below code to execute the shell script located on server which needs parameter-
def runScripts():
parameter1 = 1000
client.connect('mysite.com', username='user', password='pass')
channel = client.invoke_shell()
print ("Logged in into Site server")
channel.send("cd parent_folder/Sub_folder/script_folder; ./script1.sh %s" % parameter1)
print ("Script executed perfectly")
client.close()
runScripts()
In above runScripts function i have introduced new channel which invokes shell, and then we can send any command or data over this channel once send command gets completed the execution happens andchannel closes.
Accept the answer if its useful to you guys too.Thank you.
Just using my first paramiko script, we have an opengear console server, so I'm trying to automate setup of any device we plug into it.
The open gear listens for ssh connections on ports, for example a device in port 1 would be 3001. I am connecting to a device on port 8, which works and my script runs, but for some reason, after I get the "Interactive SSH session established" message, I need to hit return on the session to make it run (so I have a ssh session and the script does too, its shared).
It just waits there until I hit return, I've tried sending returns as you can see but they don't work, only a manual return works, which is odd because technically they are the same thing?
import paramiko
import time
def disable_paging(remote_conn):
'''Disable paging on a Cisco router'''
remote_conn.send("terminal length 0\n")
time.sleep(1)
# Clear the buffer on the screen
output = remote_conn.recv(1000)
return output
if __name__ == '__main__':
# VARIABLES THAT NEED CHANGED
ip = '192.168.1.10'
username = 'root'
password = 'XXXXXX'
port = 3008
# Create instance of SSHClient object
remote_conn_pre = paramiko.SSHClient()
# Automatically add untrusted hosts (make sure okay for security policy in your environment)
remote_conn_pre.set_missing_host_key_policy(
paramiko.AutoAddPolicy())
# initiate SSH connection
remote_conn_pre.connect(ip, username=username, password=password,port=port, look_for_keys=False, allow_agent=False)
print "SSH connection established to %s" % ip
# Use invoke_shell to establish an 'interactive session'
remote_conn = remote_conn_pre.invoke_shell()
print "Interactive SSH session established"
time.sleep(1)
remote_conn.send("\n")
# Strip the initial router prompt
#output = remote_conn.recv(1000)
# See what we have
#print output
# Turn off paging
#disable_paging(remote_conn)
# clear any config sessions
is_global = remote_conn.recv(1024)
if ")#" in is_global:
remote_conn.send("end\n")
time.sleep(2)
# if not in enable mode go to enable mode
is_enable = remote_conn.recv(1024)
if ">" in is_enable:
remote_conn.send("enable\n")
time.sleep(1)
remote_conn.send("conf t\n")
remote_conn.send("int g0/0/1\n")
remote_conn.send("ip address 192.168.1.21 255.255.255.0\n")
remote_conn.send("no shut\n")
remote_conn.send("end\n")
# Wait for the command to complete
time.sleep(2)
remote_conn.send("ping 192.168.1.1\n")
time.sleep(1)
output = remote_conn.recv(5000)
print output
I tried this and saw that
is_global = remote_conn.recv(1024)
hangs,
Are you sure '192.168.1.10' sends somthing to be received ?
Try setting a timeout
remote_conn.settimeout(3)
3 seconds for example, do it after this line:
remote_conn = remote_conn_pre.invoke_shell()
this way the recv func does not hang and continues when timeout expires
works for me
first send some command "ls -ltr\n" and then call sleep
remote_conn.send("ls -ltr\n")
time.sleep(1)
Try running your command in a debugger and find out what line is waiting for input. You might also try sending \r or \r\n instead if just \n. Remember the enter key is really ^M
You might also try turning on detailed logging.
import logging
# ...
logging.getLogger("paramiko").setLevel(logging.DEBUG)
ive found another module (netmiko) which does exactly what i want and does all these checks. ive since abandoned trying to do it myself when someone else has already done it better.
use Netmiko! :)