I'm working on a little python program to speed up managing various Raspberry Pi servers over SSH. It's all done but for one thing. Interacting with an SSH session isn't wokring the way I want it to.
I can interact with a command but some commands (specifically apt full-upgrade) which ask or have potential to ask questions whilst they're running aren't working. So when it reaches the point where it asks do you want to continue [Y/n] it falls over. I believe it's because apt can't read from the stdin so aborts.
I know I could run the apt command with the -y flag and bypass the question but ideally I'd like to be able to capture requests and ask the user for input. I've been using Paramiko to manage my SSH sessions and what I'm doing is capturing the stdout and passing it to the find function to look for things like [Y/n] and if it finds that then redirect the user to an input prompt which works but because theres no stdin when apt asks the question it aborts and when I send my user input back to the SSH session I get a socket closed error.
I've been looking for alternatives or ways to get round the issue but apart from seeing fabric mentioned as an alternative to paramiko I can't see a lot of other options out there. Does anyone know of any alternatives I can try to paramiko. I don't think fabric will work for me given its based off paramiko so I assume I'd hit the same error there. I'd appreciate any recoomendations or pointers if there's other parts of Paramiko I can try (I've stuck to using exec_command). I have tried channels which work to a point but I don't think keeping the SSH session open is the issue I think I need someway to keep stdin open/accessible to the apt command on the remote machine so it doesn't abort the command.
At the minute the best idea I've got to get round it is to run the command let it potentially abort look in stdout for the relevant phrases then run the command again after giving the user chance to set their inputs and pass the whole lot to stdin?
EDIT:
My program in steps:
- login to the remote host
- issue a command
- use .find on the command to check for the use of 'sudo'
- if sudo is present additionally send the user password to stdin along with the command
- read the stdout to check for keywords/phrases like '[Y/n]' which are present when the user is being asked for input when running a command
- if a keyword is found then ask the user for their input which can then be sent back to stdin to continue the command.
Steps 5 and 6 are where it fails and returns with a socket closed error. Looking online I don't think the issue is with paramiko as such but with the command running on the remote host. In my case sudo apt full-upgrade.
When I run that command it runs up to the 'Would you like to continue' point the automatically aborts, I believe the issue there is because there is nothing present in the stdin at that point (thats what I'm asking the user for) Apt automatically aborts
This is the part of my code where I'm running the commands:
admin = issue_cmd.find('sudo')
connect.connect(ip_addr, port, uname, passwd)
stdin, stdout, stderr = connect.exec_command(issue_cmd, get_pty=True)
if admin != -1:
print('Sudo detected. Attempting to elevate privileges...')
stdin.write(passwd + '\n')
stdin.flush()
else:
continue
output = stdout.read()
search = str(output).find('[Y/n]')
if search != -1:
resp = input(': ')
print(resp)
stdin.write(resp + '\n')
stdin.flush()
else:
pass
print(stdout.read().decode('utf-8').strip("\n"))
print(stderr.read().decode('utf-8').strip("\n"))
connect.close()
and here's the error message I'm seeing:
OSError: Socket is closed