SSH鏈接與自動化部署工具paramiko與Fabric

paramiko

paramiko是基於Python實現的SSH2遠程安全鏈接,支持認證及密鑰方法。能夠實現遠程命令執行,文件傳輸,中間SSH代理等功能,相對於Pexpect,封裝層次更高。html

pip install Paramikopython

http://www.paramiko.org/
demo:https://github.com/paramiko/p...mysql

若是在linux環境,還需安裝依賴:crypto,ecdsa,python3-devel。linux

paramiko包含兩個核心組件:SSHClient類,SFTPClient類nginx

密鑰方式登陸

import paramiko, base64,getpass
 
paramiko.util.log_to_file('syslogin.log') #日誌記錄
try:
        key=paramiko.RSAKey.from_private_key_file('pk_path')
except paramiko.PasswordRequiredException:
        password = getpass.getpass('RSA key password: ')
        key = paramiko.RSAKey.from_private_key_file('pk_path', password)    # 須要口令的私鑰
#key = paramiko.RSAKey(data=base64.decodestring('AAA...'))
client = paramiko.SSHClient()
# client.get_host_keys().add('ssh.example.com', 'ssh-rsa', key)
client.load_system_host_keys()#~/.ssh/known_hosts
client.connect('ssh.example.com', 22,username='strongbad', password='thecheat',pkey=key)
stdin, stdout, stderr = client.exec_command('ls')
# stdin, stdout, stderr=ssh.exec_command('sudo su')
# stdin.write('123456')
for line in stdout:
    print('... ' + line.strip('\n'))
#使用send
# cmds=['sudo su\n', 'cd /var/log\n', 'ls\n'] #利用send函數發送cmd到SSH server,添加'\n'作回車來執行shell命令。注意不一樣的狀況,若是執行完telnet命令後,telnet的換行符是\r\n
# ssh=s.invoke_shell() #在SSH server端建立一個交互式的shell,且能夠按本身的需求配置僞終端,能夠在invoke_shell()函數中添加參數配置。
# for cmd in cmds:
#         time.sleep(1)
#         ssh.send(cmd) #利用send函數發送cmd到SSH server,
#         out = ssh.recv(1024) #.recv(bufsize)經過recv函數獲取回顯。
#         print out
client.close()

用戶名密碼方式登陸

#####################################################################################
import paramiko
 
paramiko.util.log_to_file('syslogin.log') #日誌記錄
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('192.168.8.248', 22, username='root', password='password', timeout=4)
stdin, stdout, stderr = client.exec_command('ls -l')
#print(stdout.read())
for line in stdout.readlines():
  print(line)
client.close()

SSHClient方法參數說明
connect(hostname, port=22, username=None, password=None, pkey=None, key_filename=None, timeout=None, allow_agent=True, look_for_keys=True, compress=False, sock=None, gss_auth=False, gss_kex=False, gss_deleg_creds=True, gss_host=None, banner_timeout=None)git

pkey-私鑰類型
key_filename-str or list(str) 私鑰文件或其列表
timeout-以秒爲單位
allow_agent-爲False時禁用鏈接到SSH代理
look_for_keys-爲False時禁用在~/.ssh中搜索私鑰文件
exec_command(command, bufsize=-1, timeout=None, get_pty=False)
command-字符串github

load_system_host_keys(filename=None)指定公鑰文件,默認爲~/.ssh/known_hostsweb

set_missing_host_key_policy(policy):設置鏈接的遠程主機沒有本地主機密鑰時的策略。目前支持三種: RejectPolicy (the default), AutoAddPolicy, WarningPolicysql

上傳與下載文件

#上傳批量文件到遠程主機
import paramiko
import os
import datetime
 
hostname = '74.63.229.*'
username = 'root'
password = 'abc123'
port = 22
local_dir = '/tmp/'
remote_dir = '/tmp/test/'
if __name__ == "__main__":
    #    try:
    t = paramiko.Transport((hostname, port))
    t.connect(username=username, password=password)
    sftp = paramiko.SFTPClient.from_transport(t)
    #        files=sftp.listdir(dir_path)
    files = os.listdir(local_dir)
    for f in files:
        '#########################################'
        'Beginning to upload file %s ' % datetime.datetime.now()
        'Uploading file:', os.path.join(local_dir, f)
        # sftp.get(os.path.join(dir_path,f),os.path.join(local_path,f))
        sftp.put(os.path.join(local_dir, f), os.path.join(remote_dir, f))
        'Upload file success %s ' % datetime.datetime.now()
    t.close()

參考http://www.cnblogs.com/yangsh...shell

Fabric

Fabric是基於paramiko的基礎上作了一層更高的封裝,操做起來更加方便。
官網:http://www.fabfile.org/index....
github:https://github.com/fabric/fab...

依賴crypto,paramiko.注意:fabric目前不支持Python3.不過github上有個支持py3的版本https://github.com/mathiasert...

在windows上的安裝:
一、安裝pycrypto.
有幾種方式安裝:
A.win7下安裝 MSVC2010,而後經過pip install pycrypto編譯安裝.

B.選擇別人編譯好的。
pycrypto-for-python-3-2及如下
pycrypto-for-python-3-4

二、支持Python3的版本安裝:pip install Fabric3

fabfile.py
from fabric.api import run
def host_type():
    run('uname -s')

經過fab命令執行。-f指定文件,-H指定主機列表.

$ fab -f fabfile.py -H localhost,linuxbox host_type

fab參數說明:
-f 指定入口3文件
-g 指定網關設備(中轉,堡壘機)IP
-H 指定目標主機,多個用「,」分割
-P 異步運行多主機任務
-R 指定角色,以角色來區分機組
-t 設備鏈接超時時間,秒
-T 遠程主機命令執行超時時間,秒
-w 當命令執行失敗,發出警告,而不是終止任務。
固然咱們徹底能夠在代碼中設定這些選項值,而無需在命令行指定。以下:全局屬性設定
env對象的做用是定義fabfile的全局設定,支持多個屬性及自定義屬性。

env.hosts,定義目標主機,列表
env.exclude_hosts,排除主機,列表
env.user,定義用戶名,str
env.port , 定義端口,str
env.password,定義密碼,str
env.passwords,字典,可是形式以下:env.passwords={ 'root@192.168.1.21:22':'123456','root@192.168.2.21:22':'1234'}
env.key_filename=None 指定SSH密鑰文件,str or list
env.gateway指定網關設備(中轉,堡壘機)IP,str
env.roledefs定義角色分組,字典:env.roledefs={ 'web':['192.168.1.21','192.168.1.23'],'db':['192.168.1.22','192.168.1.24']}
env.parallel=False是否併發執行任務
env.path=' ' 定義在run/sudo/local使用的$PATH環境變量
env.command_timeout=None
env.timeout=10
env.shell=「/bin/bash -l -c」
env.ssh_config_path=「$HOME/.ssh/config」
env.sudo_password=None
env.sudo_passwords={}
env.use_ssh_config=False
env.warn_only=False,若是爲True,當操做遇到錯誤時,發出警告並繼續執行,而不是終止
env.變量名 自定義變量

例如:

@roles('web')
def webtask():
    run('/etc/init.d/nginx start')
@roles('db')
def dbtask():
    run('/etc/init.d/mysql start')
 
@roles('web','db')
def publicstask():
    run('uptime')
def deploy():
    execute(webtask)
    execute(dbtask)
    execute(publictask)

而後終端執行命令就能夠了

$ fab deploy

命令行傳參:

def hello(name="world"):
    print("Hello %s!" % name)
$ fab hello:name=Jeff
Hello Jeff!
Done.

經常使用API

fabric.api模塊:

local,執行本地命令,如local('uname -s')
lcd,切換本地目錄,如lcd('/home')
cd,切換遠程目錄
run,執行遠程命令
sudo,sudo方式執行遠程命令
put,上傳文件到遠程主機 put('/home/aaa','/home/xby/aaa')
get,從遠程主機下載文件到本地 get('/opt/bbb','/home/bbb')
prompt,獲取用戶輸入
confirm,得到提示信息確認,如confirm('Continue[Y/N]?')
reboot,重啓遠程主機,如reboot()
@task函數裝飾器,標識函數爲fab可調用的,不然對fab不可見
@runs_once,標識函數只會執行一次,不受多臺主機影響。
@roles,表示函數執行時的主機角色
@parallel(pool_size=)
@with_settings()

fabric.contrib.console.confirm(question, default=True) 用戶輸入Y/n,返回True/False

示例1:查看本地與遠程主機信息:

from fabric.api import *
 
env.user='root'
env.hosts=['192.168.1.2','192.168.1.3']
env.password='123'
 
@runs_once #即便有多臺主機,但它只會執行一次
def local_task():
    local('uname -a')
def remote_task():
    with cd("/data/logs"): #這個with的做用是讓後面的表達式語句繼承當前的狀態,實現"cd /data/logs && ls -l"的效果。
        run("ls -l")
$ fab -f sample.py local_task
$ fab -f sample.py remote_task

示例2:動態獲取遠程目錄

from fabric.api import *
from fabric.contrib.console import confirm
 
env.user='root'
env.hosts=['192.168.1.2','192.168.1.3']
env.password='123'
 
@runs_once
def input_raw():
    return prompt("please input dir name:",default='/home')
def worktask(dirname):
    run("ls -l "+dirname)
@task
def go():
    dirname=input_raw()
    worktask(dirname)

示例3:網關模式文件上傳與執行

其實只要定義好env.gateway的ip就好了。相比paramiko確實簡化了很多。

from fabric.api import *
from fabric.contrib.console import confirm
from fabric.context_managers import *
 
env.user='root'
env.hosts=['192.168.1.2','192.168.1.3']
env.password='123'
env.gateway='192.168.22.2'
 
lpath='/home/install/lnmp.tar.gz'
rpath='/tmp/install'
 
@task
def put_task():
      run("mkdir -p /tmp/install")
      with settings(warn_only=True): #put出現異常時,發出警告,繼續執行,不要終止。
        result=put(lpath,rpath) #上傳
       if result.failed and not confirm("put failed,continue[Y/N]?"):
        abort("Aborting")
@task 
def run_task():
      with cd("/tmp/install"):
         run("tar -zxvf lnmp.tar.gz")
       with cd("lnmp"):
        run("./install.sh")
 
@task go():
  put_task()
  run_task()

多彩輸出

fabric.colors.blue(text, bold=False)
fabric.colors.cyan(text, bold=False)
fabric.colors.green(text, bold=False)
fabric.colors.magenta(text, bold=False)
fabric.colors.red(text, bold=False)
fabric.colors.white(text, bold=False)
fabric.colors.yellow(text, bold=False)

from fabric.colors import red, green
print(red("This sentence is red, except for " + green("these words, which are green") + "."))

示例-Fabric部署Flask應用

示例1:它能夠把當前的源代碼上傳至服務器,並安裝到一個預先存在 的 virtual 環境:

from fabric.api import *
# 使用遠程命令的用戶名
env.user = 'appuser'
# 執行命令的服務器
env.hosts = ['server1.example.com', 'server2.example.com']
def pack():
    # 建立一個新的分發源,格式爲 tar 壓縮包
    local('python setup.py sdist --formats=gztar', capture=False)
def deploy():
    # 定義分發版本的名稱和版本號
    dist = local('python setup.py --fullname', capture=True).strip()
    # 把 tar 壓縮包格式的源代碼上傳到服務器的臨時文件夾
    put('dist/%s.tar.gz' % dist, '/tmp/yourapplication.tar.gz')
    # 建立一個用於解壓縮的文件夾,並進入該文件夾
    run('mkdir /tmp/yourapplication')
    with cd('/tmp/yourapplication'):
        run('tar xzf /tmp/yourapplication.tar.gz')
        # 如今使用 virtual 環境的 Python 解釋器來安裝包
        run('/var/www/yourapplication/env/bin/python setup.py install')
    # 安裝完成,刪除文件夾
    run('rm -rf /tmp/yourapplication /tmp/yourapplication.tar.gz')
    # 最後 touch .wsgi 文件,讓 mod_wsgi 觸發應用重載
    run('touch /var/www/yourapplication.wsgi')

參考:<<Python自動化運維>>

相關文章
相關標籤/搜索