0

I am translating a bash program to Python and have got everything up to the last bit working. Here is the bash code, which simply SSHs into a server, executes a PostgreSQL database dump, and if there was no error, saves it to a file.

output="$(ssh "$SSH_LOCATION" bash <<< "$(printf 'PGPASSWORD=%q pg_dump -U %q %q' "$pg_pass" "$pg_user" "$database")")"

if [[ $? -ne 0 ]]
then
    echo "$output"
    echo "An error occurred while dumping the database"
    exit $?
else
    echo "$output" > ~/"$LOCAL_DIR"/"$database"
fi

The variables SSH_LOCATION, LOCAL_DIR, pg_pass, pg_user and database are all defined within the Python program.

Escaping of the variables for the remote shell, especially pg_pass, is very important. This was handled in the bash code by printf '%q'.

What is the best way to translate the above bash code to Python?

Edit: and another caveat, the authentication is handled by public key, not password. Of course, the ssh shell command handles this automatically.

4
  • I want to say "throw subprocess at this". But I really would be at a loss if asked "exactly how?" Commented Dec 30, 2014 at 21:24
  • @inspectorG4dget I could do subproccess.Popen(['bash', '-c', """BASH CODE"""]), and feed all the variables from python. That feels a little too hacky though. Commented Dec 30, 2014 at 21:25
  • 1
    possible duplicate of How to make a ssh connection with python? Commented Dec 30, 2014 at 21:26
  • You can also consider pexpect Commented Dec 30, 2014 at 21:29

2 Answers 2

1

Your python code would look something similar to the following if you want to use paramiko to ssh into the box.

import paramiko
import copy

def ssh_server(server, username=username, password=password, pg_pass, ps_user, database):
    client = paramiko.SSHClient()
    client.load_system_host_keys()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect(server, username, password)
    stdin, stdout, stderr = client.exec_command("PGPASSWORD=%s pg_dump -U %s %s" % (pg_pass, $pg_user, $database))
    output = copy.deepcopy(stdout.readlines())
    error = copy.deepcopy(stderr.readlines())
    client.close()
    if not error and output:
        return stdout.readlines()
    else:
        print "An error occured\n%s" % error
        return False

The following code is just an example. It needs to be tweaked to your needs, of course. Paramiko has support for RSA keys as well as password. If you can ssh passwordless, you don't need to provide a password then and you take the password parameter out.

Sign up to request clarification or add additional context in comments.

Comments

0

What is the best way to translate the above bash code to Python?

The answer to such question, more often than not, is: use plumbum.

Borrowing from the docs, which should be enough to easily demonstrate how you can use it (and how awesome it is), you can do something like:

rem = SshMachine("hostname", user = "john", keyfile = "/path/to/idrsa")
output = rem.which("ls")

1 Comment

Thanks, this was the simplest answer. All I had to do was your first line of code and then print(rem["ls"]()) to get the output of ls remotely.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.