I a new to Python.
I am executing commands on a server and writing its output in a file and on tkinter text.
Code is given below.
Is there any way to write live output using tkinter?
Right now, after executing all commands a text window is popping up with the output. As I have written sessionoutput.mainloop() after for loop.
Please suggest any way to do it simultaneously (see channel is giving output and printing live output on tkinter text).
Eventually, I am going to create 2 sets of commands which will run in parallel. So I cannot just use the command line output, as the output of the 2 sessions will get mixed up when we use threads.
So I need a separate window to display the output.
import paramiko
import sys
import time
import tkinter
def connect_to_ssh():
hostname_ip = "1.1.1.1"
username = "admin"
password = "admin"
output_file = open("singlerunOutput.txt", "a+")
port = 22
#exception handling
i = 0
while True:
try:
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname_ip, 22, username, password)
break
except paramiko.AuthenticationException:
print("Authentication failed when connecting to %s" % hostname_ip)
sys.exit(1)
except:
print("Could not SSH to %s, waiting for it to start" % hostname_ip)
i += 1
time.sleep(2)
if i == 30:
print("Could not connect to %s. Giving up" % hostname_ip)
sys.exit(1)
print("\n****** Connection Successful ******")
output_cmd_list = list()
cmd1 ="config vdom"
cmd2 ="edit Test"
cmd3 ="diag sniffer packet any 100 l"
cmd5 = "end"
output_cmd_list.append(cmd1)
output_cmd_list.append(cmd2)
output_cmd_list.append(cmd3)
output_cmd_list.append(cmd5)
sessionoutput = tkinter.Tk()
sessionoutput.wm_title("outputwindow")
sessionoutput.geometry("600x400") # w and h
sessionop_text = tkinter.Text(sessionoutput, height=600, width=400)
session_output_tab = tkinter.Scrollbar(sessionoutput)
session_output_tab.pack(side=tkinter.RIGHT, fill=tkinter.Y)
session_output_tab.config(command=sessionop_text.yview)
sessionop_text.pack(side=tkinter.LEFT, fill=tkinter.Y)
channel = ssh.invoke_shell()
for command in output_cmd_list:
channel.send(command + '\n')
time.sleep(3)
channel.send(chr(3)) # CTRL+C
outlines = channel.recv(10240).decode("ascii")
sessionop_text.insert(tkinter.END, outlines)
print(outlines)
output_file.write(outlines)
sessionoutput.mainloop()
channel.close()
ssh.close()
output_file.close()
if __name__ == '__main__':
connect_to_ssh()
Related
I have created an application using Tkinter , it will connect to SSH and run few commands. This process is running in a loop using scheduler.
After 1st iteration , command prompt gets stuck and wont resume its display till I press enter. It just wont display output on command prompt. I am writing that output into a file. even file is not getting updated till I press any key at command prompt. Looks like it waits for some input/key stroke to start next iteration.
After pressing enter I can see that it was already running at background as suddenly it displays lots of output on the screen.
How to run/display/focus it continuously ? I am using a scheduler so that my job will keep on running for few hours. But due to command prompt stuck issue I can not see whether my program is running or not using command prompt.
If I keep open my command prompt window , everything works smoothly, output window appears and output gets written into the file, if the window is minimized , output window does not show up and file is not getting updated.
Looks like it only works when it is in focus ( command prompt is not minimized)
Please help.
code is here:
import tkinter.messagebox
import paramiko
import time
from datetime import datetime, timedelta
import tkinter.messagebox
import tkinter
import sys
import apscheduler
from apscheduler.schedulers.blocking import BlockingScheduler
import babel.numbers # for exe
def display_output(targetopname):
hostname_ip = "192.168.1.101"
username = "admin"
password = "admin"
# create /append output file
output_file = open(targetopname, "a+")
port = 22
i = 0
while True:
try:
ssh = paramiko.SSHClient()
#ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname_ip, 22, username, password)
break
except paramiko.AuthenticationException:
print("Authentication failed when connecting to %s" % hostname_ip)
sys.exit(1)
except:
print("Could not SSH to %s, waiting for it to start" % hostname_ip)
i += 1
time.sleep(2)
if i == 3:
print("Could not connect to %s. Giving up" % hostname_ip)
sys.exit(1)
cmd_list = list()
c1 = "config global"
c2 = "get sys status"
c3 = "end"
cmd_list.append(c1)
cmd_list.append(c2)
cmd_list.append(c3)
op_tk = tkinter.Tk()
op_tk.wm_title("p2trial")
op_tk.geometry("600x400")
op_text_window = tkinter.Text(op_tk, height=600, width=400)
op_scrollbar = tkinter.Scrollbar(op_tk)
op_scrollbar.pack(side=tkinter.RIGHT, fill=tkinter.Y)
op_scrollbar.config(command=op_text_window.yview)
op_text_window.pack(side=tkinter.LEFT, fill=tkinter.Y)
channel = ssh.invoke_shell()
for command in cmd_list:
time.sleep(1)
channel.send(command + '\n')
time.sleep(0.30)
if channel.recv_ready():
time.sleep(0.30)
outlines = channel.recv(10240).decode("ascii")
op_text_window.insert(tkinter.END, outlines)
op_text_window.pack(side=tkinter.LEFT, fill=tkinter.Y)
op_tk.update()
output_file.write(outlines)
else:
print("\nNo data for command ", command)
time.sleep(2)
channel.close()
ssh.close()
output_file.close()
op_tk.destroy()
dtnow = datetime.now()
print("\n*** End of the function ", dtnow)
if __name__ == '__main__':
scheduler = BlockingScheduler()
x = datetime.now() + timedelta(seconds=1)
x += timedelta(seconds=1)
targetfilename = "output.txt"
scheduler.add_job(display_output, 'interval', minutes=3,
max_instances=5, start_date=x,
end_date='2021-10-12 11:00:00.000000',args=[targetfilename])
scheduler.start()
Looks like it is related to command prompt and not tkinter.
I have referred the solution :
Command prompt gets stuck and continues on enter key press
It is solving my problem.
Thank you everyone.
I am using CMD2 to create a server. I have broken my code down to the smallest bit of code that still produces the problem.
import socket
import _thread
from cmd2 import *
def grab_data(conn):
while True:
try:
data = conn.recv(1024)
print(data)
except:
print("disconnected.")
break
def grab_client(sock):
while True:
conn, addr = sock.accept()
print("New connection")
_thread.start_new_thread(grab_data, (conn,))
def start_conn(ip, port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((ip, int(port)))
sock.listen(10)
print("Socket listening")
_thread.start_new_thread(grab_client, (sock,))
class CLI(Cmd):
def __init__(self):
Cmd.__init__(self)
self.prompt = "Prompt> "
def do_listen(self, arg):
start_conn('0.0.0.0', '4446')
def emptyline(self):
pass
def do_quit(self, arg):
return True
cli = CLI()
cli.cmdloop("Welcome to the server.")
The issue I run into is when a client connects. It does not reprint the prompt. It hangs at a empty line with just the cursor. I am not sure how to get the prompt to print back.
You're blocking trying to read 1024 bytes, so it's got to wait until that entire buffer is filled. To do proper line-based buffering is a bit tricky, but a simple (albeit non-performant) implementation is to read a character at a time and check if it's a newline:
line = ""
while True:
data = conn.recv(1)
line += data
if data in "\n\r":
break
(This is not great code, but let's see if that solves the problem and we can improve it.)
While learning through the network automation with python, I have created a script to capture the few network switch details with some sorts of commands. i have explicitely kept the commands in commands.txt and login credentilas in a file devices.json in a Jason format to pick it from and when i run this it works as expected by creating a file with command out details with time stamp.
What i Want: As i have commands.txt file which has diffrent commands, where i would like to have an idea of creating a separate file for each command which i have into commands.txt. as of now everything getting captured to a single file, desired example ..
prod-stvdx-sw_vcs_details.txt-Apr-10-2018:12:53
prod-stvdx-sw_vcs.txt-Apr-10-2018:12:53
prod-stvdx-sw_fabric_trunk.txt-Apr-10-2018:12:53
Below is the script version:
from __future__ import absolute_import, division, print_function
import json
import netmiko
import signal
import sys
import time
timestamp = time.strftime('%b-%d-%Y:%H:%M')
signal.signal(signal.SIGPIPE, signal.SIG_DFL) # IOError: Broken pipe
signal.signal(signal.SIGINT, signal.SIG_DFL) # KeyboardInterrupt: Ctrl-C
if len(sys.argv) < 3:
print('Usage: cmdrunner.py commands.txt devices.json')
exit()
netmiko_exceptions = (netmiko.ssh_exception.NetMikoTimeoutException,
netmiko.ssh_exception.NetMikoAuthenticationException)
#username, password = getPass.get_credentials()
with open(sys.argv[1]) as cmd_file:
commands = cmd_file.readlines()
with open(sys.argv[2]) as dev_file:
devices = json.load(dev_file)
for device in devices:
#device['username'] = username
#device['password'] = password
try:
print('~' * 79)
print('Connecting to device:', device['ip'])
connection = netmiko.ConnectHandler(**device)
filename = connection.base_prompt + '.txt' + '-' + timestamp
with open(filename, 'w') as out_file:
for command in commands:
out_file.write('++++ Output of ' + command + '\n\n')
out_file.write(connection.send_command(command) + '\n\n')
connection.disconnect()
except netmiko_exceptions as e:
print('Failed to ', device['ip'], e)
My commands.txt File:
$ cat commands.txt
show vcs details
show vcs
show fabric islports
show fabric isl
show fabric trunk
show logging raslog
show version
show ip int brief
Run
$ ./brocade_2.py commands.txt devices.json
-rw-r--r-- 1 moli moli 286K Apr 10 12:53 prod-stvdx-sw.txt-Apr-10-2018:12:53
I think if I understand correctly, you want to capture the output of each command in a separate file:
from __future__ import absolute_import, division, print_function
import json
import netmiko
import signal
import sys
import time
timestamp = time.strftime('%b-%d-%Y:%H:%M')
signal.signal(signal.SIGPIPE, signal.SIG_DFL) # IOError: Broken pipe
signal.signal(signal.SIGINT, signal.SIG_DFL) # KeyboardInterrupt: Ctrl-C
if len(sys.argv) < 3:
print('Usage: cmdrunner.py commands.txt devices.json')
exit()
netmiko_exceptions = (netmiko.ssh_exception.NetMikoTimeoutException,
netmiko.ssh_exception.NetMikoAuthenticationException)
#username, password = getPass.get_credentials()
with open(sys.argv[1]) as cmd_file:
commands = cmd_file.readlines()
with open(sys.argv[2]) as dev_file:
devices = json.load(dev_file)
for device in devices:
#device['username'] = username
#device['password'] = password
try:
print('~' * 79)
print('Connecting to device:', device['ip'])
connection = netmiko.ConnectHandler(**device)
for command in commands:
filename = connection.base_prompt +'-'+ command+'.txt' + '-' + timestamp
with open(filename, 'w') as out_file:
out_file.write('++++ Output of ' + command + '\n\n')
out_file.write(connection.send_command(command) + '\n\n')
connection.disconnect()
except netmiko_exceptions as e:
print('Failed to ', device['ip'], e)
everyone.
I use the parmiko with python 3.3.3 x64 on window 7 x64, the following is my code, and the strange is I need add time.sleep(0.01) for delay before using client.close() to end the session. Otherwise, a lot of processes will be existed in the SSH host and could not end automatically.
Could anyone do me a favor to explain these?
The paramiko used for python3:
(https://travis-ci.org/nischu7/paramiko)
Here is the steps for repeat:
A)remove the time.sleep(0.01) before client.close() and run the script
B)type the password for the SSH host
C)type the first command, for example: ls -la
D)type the command very frequently, for example, keep pressing the up-arrow and enter alternatively very fast with several times
E)when using ps -ef | grep dropbear (the SSH server, I have not tested about OpenSSH), a lot of processes exists
F) type exit and Ctrl + Z to terminate the script
G)keep the time.sleep(0.01) before client.close() and run the script again
H)do the above steps of B, C, D, then check with ps -ef | grep dropbear again, only one SSH process will generate by this script.
and here is the code:
from tkinter import *
from threading import Thread
from queue import Queue, Empty
import _thread
import time
from paramiko import SSHClient, Transport, AutoAddPolicy, WarningPolicy
import getpass
def start(client):
try :
client.connect(hostname='127.0.0.1', port=22, username='ubuntu', password=pw)
return True
except Exception as e:
client.close()
print(e)
return False
def check(client,outqueue):
while start(client):
outqueue.put("Command to run: ")
cmd = input()
if cmd == "exit":
client.close()
break
chan = client.get_transport().open_session()
outqueue.put("running '%s'" % cmd)
chan.exec_command(cmd)
while True:
if chan.recv_ready():
data = chan.recv(4096).decode('ascii')
outqueue.put("recv:\n%s" %data)
if chan.recv_stderr_ready():
error = chan.recv_stderr(4096).decode('ascii')
outqueue.put("error:\n%s" %error)
if chan.exit_status_ready():
exitcode = chan.recv_exit_status()
outqueue.put("exit status: %s" %exitcode)
#print('close s')
#print(client.close())
time.sleep(0.01)
client.close()
#print('close e')
#time.sleep(0.05)
break
def reader(outqueue):
while True:
while outqueue.qsize():
try:
data = outqueue.get()
if data:
print(data)
except Excetpiton as e:
print(e)
#continue
#time.sleep(0.5)
if __name__=='__main__':
pw = getpass.getpass()
client = SSHClient()
client.set_missing_host_key_policy(WarningPolicy())
#client.set_missing_host_key_policy(AutoAddPolicy())
outqueue = Queue()
r = Thread(target=reader,args=(outqueue,))
r.daemon = True
r.start()
t = Thread(target=check,args=(client,outqueue,))
#t.daemon = True
t.start()
t.join()
It's a mistake, I start the client more than one time, so solved by the following:
from threading import Thread
from queue import Queue, Empty
import _thread
import time
from paramiko import SSHClient, Transport, AutoAddPolicy, WarningPolicy
import getpass
def start(client):
try :
client.connect(hostname='127.0.0.1', port=22, username='ubuntu', password=pw)
return True
except Exception as e:
client.close()
print(e)
return False
def check(client,outqueue):
while True:
outqueue.put("Command to run: ")
cmd = input()
if cmd == "exit":
client.close()
break
chan = client.get_transport().open_session()
outqueue.put("running '%s'" % cmd)
chan.exec_command(cmd)
while True:
if chan.recv_ready():
data = chan.recv(4096).decode('ascii')
outqueue.put("recv:\n%s" %data)
if chan.recv_stderr_ready():
error = chan.recv_stderr(4096).decode('ascii')
outqueue.put("error:\n%s" %error)
if chan.exit_status_ready():
exitcode = chan.recv_exit_status()
outqueue.put("exit status: %s" %exitcode)
#print('close s')
#print(client.close())
#time.sleep(0.01)
#client.close()
#print('close e')
#time.sleep(0.05)
break
def reader(outqueue):
while True:
while outqueue.qsize():
try:
data = outqueue.get()
if data:
print(data)
except Excetpiton as e:
print(e)
#continue
#time.sleep(0.5)
if __name__=='__main__':
pw = getpass.getpass()
client = SSHClient()
client.set_missing_host_key_policy(WarningPolicy())
#client.set_missing_host_key_policy(AutoAddPolicy())
if not start(client):
#os._exit(0)
sys.exit(0)
outqueue = Queue()
r = Thread(target=reader,args=(outqueue,))
r.daemon = True
r.start()
t = Thread(target=check,args=(client,outqueue,))
#t.daemon = True
t.start()
t.join()
I tried to use pySerial to build a simple terminal to interact COM1 in my PC,
I create 2 threads , one is for READ , the other is for Write
however,
def write_comport():
global ser,cmd, log_file
print("enter Q to quit")
while True:
cmd = raw_input(">>:")
# print(repr(var))
if cmd=='Q':
ser.close()
sys.exit()
log_file.close()
else:
ser.write(cmd + '\r\n')
write_to_file("[Input]"+cmd, log_file)
time.sleep(1)
pass
def read_comport():
global ser, cmd, log_file
while True:
element = ser.readline().strip('\n')
if "~ #" in str(element):
continue
if cmd == str(element).strip():
continue
if "img" in str(element):
print("got:"+element)
beep()
print element
write_to_file(cmd, log_file)
pass
def write_to_file(str,f):
f.write(str)
f.flush
def main():
try:
global read_thr,write_thr
beep()
port_num='COM4'
baudrate=115200
init_serial_port(port_num,baudrate)
read_thr =Thread(target=read_comport)
read_thr.start()
write_thr =Thread(target=write_comport)
write_thr.start()
while True:
pass
except Exception as e:
print(e)
exit_prog()
but the behavior of my code is not as smart as putty or anyother.
cause my function can Not detect whenever the reader is done.
is there any better way to achieve this goal?
By the way, I tried to save the log into txt file real-time . But when I open the file during the process is running, it seems nothing write to my text log file?