I created Python GUI that takes a list of commands as input and executes the list through a Telnet or SSH session. While opening a SSH session (using Paramiko in Python) I run commands on various devices using this code in a for loop:
stdin.write(command+"\n")
then = time.time()
timeout=10.0
while not stdout.channel.exit_status_ready():
if timeout is not None:
timeTest =time.time() - then
if timeout <= timeTest:
break
# Only print data if there is data to read in the channel
if stdout.channel.recv_ready():
# Write data from stdout
temp=str(stdout.channel.recv(1024))
print temp
if (temp.endswith(delim)) or (temp.endswith("# ")) :
print "successful exit"
break
The code is designed to be used on modems that have BusyBox installed. Thus it's common for a user to enter a command to open busybox and run a sequence of commands in the BusyBox shell. As you can see in this line of code "if (temp.endswith(delim)) or (temp.endswith("# "))" the while loop is suppose to break when the command prompt of busybox is detected which is a "# " (this means the command has finished outputting).
The problem I'm having is that BusyBox isn't printing the command prompt to stdout or in the debug line "print temp". Why is this? The command outputs (an example is ls -l) are successfully printed to stdout but not the command prompt or busybox intro message: when a user enters busybox on these modems a introduction message is printed "BusyBox v1.17.2 (2014-10-02 10:50:35 PDT) built-in shell (ash) Enter 'help' for a list of built-in commands." which is also not printed to STDOUT. This is forcing the code to utilize the timeout for each command executed in busybox which is undesirable, i.e. it's slow and there could be command outputs that take longer than the desired timeout so it's best to look for the command prompt.
Is this issue due to the implementation of ash in BusyBox? Is there a way to receive the command prompt text?
First: If you're trying to recognize shell prompts when invoking a shell programmatically, you're Doing It Wrong.
If you use
exec_command()
on a new channel (over the same transport) for each command you want to run, you'll get a separate stdout, stderr, etc. for each command; have the exit status for that command individually reported, and never need to guess whether a piece of output is from the command or from the outer shell.Second: If you really want to do it that way (and, again, you shouldn't!), you should be using
invoke_shell()
after aget_pty()
call, notexec_command('sh')
.