Search code examples
pythonlinuxsshparamikorobotframework-sshlibrary

Python SSH connection won't run specific commands on Linux machine


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.


Solution

  • 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")}')