while True:
command = raw_input("=> ")
if command == 'Exit':
tn.write(command + "\r\n")
time.sleep(1)
tn.close()
break
tn.write(command + "\r\n")
time.sleep(2)
print tn.read_very_eager()
I've established a connection to the Telnet and I'm passing through basic commands. I want to avoid a 1 or 2 second timer between each write command because I don't want 30 write commands to take up to a minute. If I remove 'time.sleep,' I can't read the output in time for the next command. Can anyone help?
Related
This question already has answers here:
Reading command output with Paramiko invoke_shell/send/recv never finishes
(1 answer)
Execute multiple dependent commands individually with Paramiko and find out when each command finishes
(1 answer)
Closed 6 months ago.
I'm fairly new to Python, but trying to create a small script that will SSH into a server on my work and navigate through various menus. Normally I would do that with Putty client.
I did succeed in this using code below:
from socket import setdefaulttimeout
import time
import paramiko
from getpass import getpass
from prompt_toolkit import ANSI
# Connection parameters for SSH + create connection.
hostname = 'workhostname'
port = 22
user = input('User (server): ')
passwd = getpass('Password (server): ')
programlogin = input('User (hyperspace): ')
programpass = getpass('Password (hyperspace): ')
exportdir = "/home/" + user + "/PYTHONTEST1"
commandsequence = ["2", "1", programlogin, programpass, "", "6", "DEP", "", "1", "7", "6", "", "17030", "24650", "", "995", "1121042", "1121806", "", exportdir, "", ""]
client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(hostname,port=port,username=user,password=passwd)
# Create shell via paramiko.
chan = client.invoke_shell(term='xterm')
# Time.sleep for more than 5 seconds to make sure that the program initial screen pause of 5 seconds is passed.
# "This message will disapper in 5 seconds"
time.sleep(7)
# Loop through command sequence.
for command in commandsequence:
# Send command.
chan.send(command + '\r')
time.sleep(2.3)
print(chan.recv(4096).decode('ISO-8859-1')) # For debugging purposes - to check whats actually going on in the console
if command == programpass:
print("Command: PASSWORD HIDDEN completed")
else:
print("Command: " + command + " completed")
# Trying to create some loop to check if all bytes has been received from the channel. loops out, if not ready after 10 checks.
"""
counter = 0
while not chan.recv_ready():
print("Not ready")
time.sleep(1)
if counter < 10:
counter += 1
else:
break
"""
# Get all bytes + decode the data (so it is readable through print)
#s = chan.recv(4096).decode()
s = chan.recv(4096).decode('ISO-8859-1')
print(s)
client.close()
However this only works because I give the client enough time (time.sleep(2.3)) between each command. I have read somewhere that paramikos exec command is the only real reliable way to tell if the command was actually completed. However I don't think I will be able to use the exec command to navigate this "program" that I'm facing when doing the shell approach. I can use linux terminal commands like "hostname" to get that returned, but I have no idea how to start the program and navigate through it this way.
Will I somehow be able to tell, by reading the chan.recv() if I'm done receiving output from the server, instead of "blindly" trust some high timer? - Or what would the approach be?
I am trying to execute a number of commands remotely using paramiko, however the recv_ready() does not return the correct value.
For example after a pwd \n command it will continuously report that the channel is not still ready (obviously false). For some commands it works properly e.g. ls.
Is there something wrong with what I am doing, or is there an issue with paramiko?
import paramiko
import re
import time
def sudo_ssh(hostname, usernameIn, passIn, cmd):
# Create an SSH client
client = paramiko.SSHClient()
# Make sure that we add the remote server's SSH key automatically
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# Connect to the client
client.connect(hostname, username=usernameIn, password=passIn)
# Create a raw shell
channel = client.invoke_shell()
# Send the sudo command
for command in cmd:
print("CMD= " + command + "\n")
time.sleep(1)
# wait until channel is ready
while not channel.recv_ready() :
print("NOT READY " + str(channel.recv_ready()) + "\n \n")
time.sleep(1)
# Send the command
channel.send(command)
channel.send("\n")
# Wait a bit, if necessary
time.sleep(1)
# Flush the receive buffer
receive_buffer = channel.recv(4096)
# If promted send the sudo pass
if re.search(b".*\[sudo\].*", receive_buffer):
time.sleep(1)
print(" TYPING SUDO PASSWORD .... \n")
channel.send( "sudoPass" + "\n" )
receive_buffer = channel.recv(4096)
# Print the receive buffer, if necessary
print(receive_buffer)
print("Executed all of the commands. Now will exit \n")
client.close()
com = []
com.append("sudo ls")
com.append("cd /home/user/Downloads")
com.append("sleep 5")
com.append("ls")
com.append("pwd")
com.append("cd /opt/")
sudo_ssh("myhost.com", "user", "pass", com)
The recv_ready method is to check if the data of channel is ready to read or not i.e. data is buffered or not. It doesn't check if channel itself is ready, see - recv_ready().
So you should move the recv_ready() while loop just before the receive_buffer = channel.recv(4096) to make it work.
On a vm I used the command: nc -l -p 8221 -e /bin/bash and made a python3 script:
def netcat():
print ("starting connection")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.168.1.60", 8221))
while True:
user = input("what to send?: ")
s.sendall(bytes(user, "utf-8"))
time.sleep(5)
word = "bob"
data = s.recv(4096)
if data == b"":
pass
else:
data = data.decode("utf-8")
print ("Received:", repr(data))
print ("Connection closed.")
s.shutdown(socket.SHUT_WR)
s.close()
netcat()
this script doesn't work. By don't work I mean when I run a command with my python script, lets say "pwd", it just loads but never runs.
When, instead of running the python script I would run nc 192.168.1.60 8221, it would work fine. Any ideas why?
From input()'s documentation:
The function then reads a line from input, converts it to a string
(stripping a trailing newline), and returns that.
But Bash is operating in canonical mode and won't process input till a new line arrives. This won't happen, leading to recv blocking forever.
add a + '\n' after the user = input("what to send?: ") to fix it.
I am trying to talk to a Stanford Research Systems SR760 spectrum analyzer on my mac (10.7.5) via Serial, using a Serial-to-USB adapter to connect to my laptop. I am using the Prolific USB-serial driver. Not sure which but I installed it recently. It probably is the PL2303 one.
Using Python, here's some sample code
import time
import serial
# configure the serial connections (the parameters differs on the device you
# are connecting to)
ser = serial.Serial(
port='/dev/cu.PL2303-0000201A',
baudrate=19200,
parity=serial.PARITY_NONE,
bytesize=serial.EIGHTBITS,
stopbits=serial.STOPBITS_ONE,
rtscts=0,
dsrdtr=0,
timeout=2,
)
if ser.isOpen():
ser.flushInput()
ser.flushOutput()
print """Enter your commands below.\r\nInsert "exit" to leave the
application."""
while 1:
# get keyboard input
input = raw_input(">> ")
if input == 'exit':
ser.close()
exit()
else:
ser.write(input + '\r')
out = ''
# let's wait one second before reading output (let's give device
# time to answer)
lines = 0
while 1:
time.sleep(1)
out = out + ser.readline()
lines = lines + 1
if lines > 5:
break
print "read data: " + out
Using the SR760's manual, I send it: *IDN?, a basic "identify" command. I expect for something to pop up in my terminal, nothing does. It just times out. However, if I look at the send queue on the SR760, it will show the identity string, and in fact responds to a bunch of different commands. I'm just not getting anything on my computer and that is the problem. I know it is supposed to work that way because my colleague wrote code that words on his computer (a windows laptop).
How do I even start debugging this? I've tweaked the timeout, and confirmed the sr760 had the same parameters I was expecting.
I'm trying to type-check the commands I want to send to a server from a client. I want to use select so I don't block anything, but if I blatantly ask for input(), I block. So, it seems I should use sys.stdin.readline() instead. However, then there is a disconnect between the commands entered and the type checking I want to do:
while not self.flag:
sock_read, sock_write, sock_except = \
select.select([sys.stdin, self.client], [], [])
for sock in sock_read:
if sock == sys.stdin:
data = sys.stdin.readline().strip()
if data:
self.client.send(data.encode('utf_8'))
elif sock == self.client:
data = sock.recv(bufsize)
if data.decode('utf_8') is '': # server closed connection
print("Lost connection to server, shutting down...")
self.flag = True
break
else: # process data '\n' delimited
readbuf += data
while b'\n' in readbuf:
msg,readbuf = readbuf.split(b'\n', 1) # separate by \n
msg = msg.decode('utf_8')
msg.strip('\n')
# make below into a function
# got data from server
if msg == 'BEGIN':
self.playstarted = True
elif msg == 'GO':
#command = input("Your turn: ")
# typecheck command, something like
# while is_not_valid_command():
# keep asking for input
print("You",command)
command += '\n' # delimiter
sock.send(command.encode('utf_8'))
else:
sys.stdout.write(msg + "\n")
sys.stdout.flush()
Basically, if the client does not recognize the received data as a command, the client assumes it is just a chat message and writes it to stdout accordingly. But, when I get a command like 'GO', I need the client to prompt (or just display a message asking for input so I don't block with input()) the user for command input so I can type-check the command within the same nest. Is this possible without threads?
I don't think it is possible to use input() in a non-blocking way without resorting to threads.