2015年10月

使用 fabric

fabric是一个用python实现的远程部署工具,它可以批量操作远程服务器。实际工作中,很多时候需要在多台线上机器上执行同样的操作,这时fabric会很有用。

安装

pip install fabric

使用(fabric.py)

# from fabric.api import cd,run,env,hosts,execute,roles
from fabric.api import *

# 远程机器,多个机器fabric会依次启动
env.hosts = [
    'user@10.16.29.176:22',
    'user@10.16.29.44:22'
]
env.password = '*******'

# 进入/home/user目录,执行命令
def test():
    with cd('/home/user'):
        run('du -sh')

# ----在不同的机器上执行不同的任务
env.roledefs = {
    'server1': [
        'user@10.16.29.176:22',
    ],
    'server2': [
        'user@10.16.29.44:22',
    ]
}
env.password = '*******'

# server1执行task1
@roles('server1')
def task1():
    run('ls /home/ -l | wc -l')

# server2执行task2
@roles('server2')
def task2():
    run('du -sh /home/user')

def test1():
    # 遇到报错警告,而不是退出
    with settings(warn_only=True):
    execute(task1)
    execute(task2)
    exit()

# ----接收参数
def hello(foo):
    print 'Hello, %s'%foo;

执行

fab test

用fabric来部署代码也是一件很爽的事情(upload.py)

# coding=utf-8
from datetime import datetime
from fabric.api import *

env.hosts = ['user@10.16.29.176:22']
env.password = '********'

# 本地打包
def pack():
    tar_files = ['*.py', 'testdir/*']
    local('rm -f deploy.tar.gz')
    local('tar -zcvf deploy.tar.gz --exclude=\'*.tar.gz\' --exclude=\'upload.py\' %s' % ' '.join(tar_files))

# 部署
def deploy():
    tmp_dir = '/tmp/deploy.tar.gz'
    put('deploy.tar.gz', tmp_dir)

    tag = datetime.now().strftime('%y.%m.%d_%H.%M.%S')
    deploy_dir = '/home/user/%s' % tag

    run('mkdir %s' % deploy_dir)
    with cd(deploy_dir):
        run('tar -zxvf %s' % tmp_dir)

    run('rm %s' % tmp_dir)

如果文件名不是fabric.py,需要指定文件名

fab -f upload.py pack
fab -f upload.py deploy

参考

关于 .user.ini 文件

昨天转移一个wp站点的时候遇到的一个小问题,绕了不少弯路,写出来分享下。

由于域名不变,按照官网的流程,只需要复制代码,转移数据库文件,在新的服务器配置一个虚拟主机,最后修改IP指向,就OK了。

但是事情总不会那么顺利,访问网站,提示No input file specified,这个错误引发的原因可能性很多,于是看了下nginx的error.log,发现如下错误:

2015/10/14 21:14:13 [error] 1832#0: *130022 FastCGI sent in stderr: "PHP message: PHP Warning:  Unknown: open_basedir restriction in effect. File(/home/****/***/index.php) is not within the allowed path(s): (/tmp/:/proc/) in Unknown on line 0
PHP message: PHP Warning:  Unknown: failed to open stream: Operation not permitted in Unknown on line 0
Unable to open primary script: /home/****/***/index.php (Operation not permitted)" while reading response header from upstream, client: 218.30.116.8, server: zhangrenqin.com, request: "GET /favicon.ico HTTP/1.1", upstream: "fastcgi://unix:/var/run/php5-fpm.sock:", host: "***", referrer: "***"

答案已经很明显了,由于wp使用了open_basedir这个函数,这个函数可以访问系统中的任何文件,安全隐患比较大,要对其进行限制,一般在php.ini里禁用或者限制在哪些目录使用。所以只要在php.ini文件中将当前网站的root目录加入到open_basedir的配置中即可,用:分割

open_basedir=/home/****/***/:/tmp/:/proc/

好了,现在访问就正常了。

这样添加的一个问题是全局生效,如果配置了多个虚拟主机,其中一个站点的权限被拿掉,其他站点也就跟着倒霉。.user.ini文件可以完美的解决这个问题,它能动态扩展php.ini。将上面的配置写入.user.ini,然后放到网站根目录即可。

php.ini的配置清单可参考官方文档:http://www.php.net/manual/en/ini.list.php
其中Changeable为PHP_INI_PERDIR、PHP_INI_USER、PHP_INI_ALL可以配置到.user.ini中,而PHP_INI_SYSTEM只能配置到php.ini。

可以从配置中看到,open_basedir选项在PHP > 5.2.3版本中已经被加入。

Name    Default Changeable  Changelog
open_basedir    NULL    PHP_INI_ALL PHP_INI_SYSTEM in PHP < 5.2.3.