I think this can be useful for others.
I have a python script that should run some .sh
scripts on a linux machine where I can connect only using SSH
.
The problem is that the python script gets stuck when I try to run a .sh
script but I can run multiple other commands like: cd, rm, mv, cp, ls
The code below was my first try:
client = SSHClient()
client.set_missing_host_key_policy(AutoAddPolicy())
client.connect("myHost", username="myUsername", key_filename="SSH_Key_Location")
stdin, stdout, stderr = client.exec_command("/test.sh -h")
print(f'STDOUT: {stdout.read().decode("utf8")}')
print(f'STDERR: {stderr.read().decode("utf8")}')
I also tried with SSHLibrary
and also tried different .sh
scripts on the machine (even some test scripts containg only echo "test"
) but none of them worked.
A strange thing was that using Cygwin
to connect using SSH
I was able to run those scripts manually without a problem.
So after some research I've found that running the .sh
scripts required a password, that I was not providing. The same behavior would appear for any kind of input you need to provide after the commands you sent are executed (like: y/n
, paths
, etc).
So there remains the strange thing, why it asks for a password using the Python SSH connection but not in Cygwin. It looks like connecting through Cygwin would create a session that doesn't require the password for certain actions, but using Python (SSHLibrary or Paramiko) would create a session a little bit different and therefor a password is required (depends on the configurations on the machine) - Strange settings from the IT guys
So the code above becomes the following and it works perfectly (please notice using the stdin.channel.shutdown_write()
line. Looks like if you don't shutdown that channel, the input you send using write()
will not actually be sent):
client = SSHClient()
client.set_missing_host_key_policy(AutoAddPolicy())
client.connect("myHost", username="myUsername", key_filename="SSH_Key_Location")
stdin, stdout, stderr = client.exec_command("/test.sh -h")
stdin.write("yourAdditionalInfo\n") # Don't forget about the \n; This line can be used multiple times, to send multiple lines
stdin.flush()
stdin.channel.shutdown_write() #! This is really important. Without closing the write channel, the lines sent with **write** will not have effect
print(f'STDOUT: {stdout.read().decode("utf8")}')
print(f'STDERR: {stderr.read().decode("utf8")}')