2.6. SSH

2.6.1. paramiko

import paramiko

client = paramiko.SSHClient()

client.connect('example.com', username='myusername')
# Traceback (most recent call last):
# paramiko.ssh_exception.SSHException: Server 'example.com' not found in known_hosts
import paramiko

client = paramiko.SSHClient()

client.load_system_host_keys()
client.load_host_keys('/home/brandon/.ssh/known_hosts')
client.connect('example.com', username='myusername')

2.6.2. Password Auth

client.connect('example.com', username='myusername', password='mypassword')
client.connect('example.com')

2.6.3. Public/Private Key Auth

client.connect('example.com', key_filename='/home/brandon/.ssh/id_sysadmin')

2.6.4. Running commands

import sys
import getpass
import paramiko


hostname = sys.argv[1]
username = sys.argv[2]
password = getpass.getpass()


client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy)
client.connect(hostname, username=username, password=password)

commands = [
    'echo "Hello, world!"',
    'uname',
    'uptime',
]

for command in commands:
    stdin, stdout, stderr = client.exec_command(command)
    stdin.close()
    print(repr(stdout.read()))
    stdout.close()
    stderr.close()

client.close

2.6.5. SCP

  • File transfer over SSH

2.6.6. SFTP

  • It is not FTPS

import sys
import paramiko

host = "example.com"
port = 22
username = "myusername"
password = "mypassword"


transport = paramiko.Transport((host, port))
transport.connect(username=username, password=password)
sftp = paramiko.SFTPClient.from_transport(transport)

path_local = 'README.txt'
path_remote = '/tmp/README.txt'

sftp.put(path_local, path_remote)

sftp.close()
transport.close()

2.6.7. pysftp

$ pip install pysftp
import pysftp
import sys


host = "example.com"
port = 22
username = "myusername"
password = "mypassword"

path_local = 'README.txt'
path_remote = '/tmp/README.txt'


with pysftp.Connection(host, username=username, password=password) as sftp:
    sftp.put(path_local, path_remote)

2.6.8. fabric

$ pip install fabric

2.6.9. Examples

from fabric.api import *

env.hosts = ['example.com']
env.user = 'myusername'
env.password = 'mypassword'

def put_file(file):
    put(file, './mydirectory/')
$ fab -f fab_putfile.py put_file:file=./path/to/my/file

2.6.10. Local

from fabric.api import local

def prepare_deploy():
    local("./manage.py test my_app")
    local("git add -p && git commit")
    local("git push")
$ fab prepare_deploy
[localhost] run: ./manage.py test my_app
Creating test database...
Creating tables
Creating indexes
..........................................
----------------------------------------------------------------------
Ran 42 tests in 9.138s

OK
Destroying test database...

[localhost] run: git add -p && git commit

<interactive Git add / git commit edit message session>

[localhost] run: git push

<git push session, possibly merging conflicts interactively>

Done.

2.6.11. Organization

from fabric.api import local

def test():
    local("./manage.py test my_app")

def commit():
    local("git add -p && git commit")

def push():
    local("git push")

def prepare_deploy():
    test()
    commit()
    push()

2.6.12. Failure handling

from fabric.api import local, settings, abort
from fabric.contrib.console import confirm

def test():
    with settings(warn_only=True):
        result = local('./manage.py test my_app', capture=True)

    if result.failed and not confirm("Tests failed. Continue anyway?"):
        abort("Aborting at user request.")

2.6.13. Executing on remote host

from fabric import SerialGroup

result = SerialGroup('web1', 'web2').run('hostname')
# web1
# web2

# it's a dict!
result.items()
# [(<Connection host=web1>, <Result cmd='hostname' exited=0>),
# ...]
from fabric.api import *
from fabric.contrib.console import confirm

env.hosts = ['my_server']

def test():
    with settings(warn_only=True):
        result = local('./manage.py test my_app', capture=True)

    if result.failed and not confirm("Tests failed. Continue anyway?"):
        abort("Aborting at user request.")

def commit():
    local("git add -p && git commit")

def push():
    local("git push")

def prepare_deploy():
    test()
    commit()
    push()

def deploy():
    code_dir = '/srv/django/myproject'

    with settings(warn_only=True):
        if run("test -d %s" % code_dir).failed:
            run("git clone myusername@example.com:/path/to/repo/.git %s" % code_dir)

    with cd(code_dir):
        run("git pull")
        run("touch app.wsgi")
from fabric.api import *

def deploy():
    sudo("~/install_script.py")
    sudo("mkdir /var/www/", user="www-data")
    sudo("ls /home/watney", user=1001)
    result = sudo("ls /tmp/")

    with settings(sudo_user='root'):
        sudo('whoami')
        # 'root'

2.6.14. Host

from fabric.api import hosts

@hosts(['127.0.0.1', 'localhost'])
def whoami():
    sudo('whoami')

2.6.15. pssh

../../_images/ssh-pssh-11.jpg
../../_images/ssh-pssh-21.png
../../_images/ssh-pssh-31.png