开发中,一般有三个环境,本地环境、线上测试环境、线上正式环境。
各个环境可能有其对应的数据库配置信息,Redis配置信息;有些情境下,本地环境到线上测试环境的发布可能比较频繁;那么如何在保证开发效率的同时保证发布的安全呢?
本地环境搭建
首先,需要 搭建本地调试环境,使其可以通过某个自定义域名进行访问。
如果开发环境需要用到 MySQL,可参考 OS X - MySQL 的安装。
配置文件独立
将配置文件独立出来,不要和其他代码耦合,以需要用到 MySQL
以及 COOKIE_DOMAIN
的 Conf.php
为例,在本地环境中,配置文件永远是本地环境的信息,也就是说即使本地工程泄露,线上的隐私也不会泄露出去。
1 2 3 4 5 6 7 8 9 10 11
| class Conf { const DEBUG = true;
const MYSQL_HOST = '127.0.0.1'; const MYSQL_DB_NAME = 'my_db'; const MYSQL_ACCOUNT = 'my_account'; const MYSQL_PASSWORD = 'my_password';
const COOKIE_DOMAIN = '.local.com'; }
|
发布脚本独立
DEBUG 标识位
DEBUG 标识位是第一道保险,毕竟一键发布过于方便可能会造成手误。当标识位为 true 的时候,企图发布到正式环境会失败;当它为 false 的时候,企图发布到测试环境会失败。
使用脚本替换配置文件信息
在执行发布脚本时,需要去替换配置文件信息。为此可以独立写一个功能脚本,根据实际情况去替换配置信息。
在同步到线上环境之前,把配置文件替换为线上环境的相应信息;同步完成之后,再将配置文件替换为本地环境的相应信息。
发布脚本示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| DEBUG_MODE=`cat ${CONFIG_PATH} | grep 'const DEBUG =' | sed -n "s/^.*const\ DEBUG\ =\ \([a-z]*\).*$/\1/p"`
if [ "$1" == "release" ]; then if [ "${DEBUG_MODE}" != "false" ]; then echo "SEHLL DEBUG_MODE: false" echo "PHP DEBUG_MODE: ${DEBUG_MODE}" echo "发布失败!!!" exit fi
SYNC_MODE='release' else if [ "${DEBUG_MODE}" != "true" ]; then echo "SEHLL DEBUG_MODE: true" echo "PHP DEBUG_MODE: ${DEBUG_MODE}" echo "发布失败!!!" exit fi SYNC_MODE='debug' fi
php change_config.php ${SYNC_MODE}
…… …… …… echo "发布成功!!!"
php change_config.php "local" echo "已复原回本地配置"
|
替换功能脚本示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| <?php
if(count($argv) < 2) { die('PHP 参数错误'); }
$target = $argv[1];
if($target == 'release') { $MYSQL_HOST = 'MYSQL_HOST_REAL'; $MYSQL_DB_NAME = 'MYSQL_DB_NAME_REAL'; $MYSQL_ACCOUNT = 'MYSQL_ACCOUNT_REAL'; $MYSQL_PASSWORD = 'MYSQL_PASSWORD_REAL'; $COOKIE_DOMAIN = 'COOKIE_DOMAIN_REAL'; } else if($target == 'debug') { $MYSQL_HOST = 'MYSQL_HOST_DEBUG'; $MYSQL_DB_NAME = 'MYSQL_DB_NAME_DEBUG'; $MYSQL_ACCOUNT = 'MYSQL_ACCOUNT_DEBUG'; $MYSQL_PASSWORD = 'MYSQL_PASSWORD_DEBUG'; $COOKIE_DOMAIN = 'COOKIE_DOMAIN_DEBUG'; } else if($target == 'local') { $MYSQL_HOST = 'MYSQL_HOST_LOCAL'; $MYSQL_DB_NAME = 'MYSQL_DB_NAME_LOCAL'; $MYSQL_ACCOUNT = 'MYSQL_ACCOUNT_LOCAL'; $MYSQL_PASSWORD = 'MYSQL_PASSWORD_LOCAL'; $COOKIE_DOMAIN = 'COOKIE_DOMAIN_LOCAL'; } else { die('参数不合法'); }
function replace_variables($data, $var_name) { $reg = sprintf("#(const\ %s\ =\ ')[^']*(')#", $var_name); $var_value = $GLOBALS[$var_name];
return preg_replace_callback($reg, function ($matches) use($var_value) { return sprintf('%s%s%s', $matches[1], $var_value, $matches[2]); }, $data ); }
$file = 'YOUR_CONFIG_FILE_PATH'; $data = file_get_contents($file);
$data = replace_variables($data, 'MYSQL_HOST'); $data = replace_variables($data, 'MYSQL_DB_NAME'); $data = replace_variables($data, 'MYSQL_ACCOUNT'); $data = replace_variables($data, 'MYSQL_PASSWORD'); $data = replace_variables($data, 'COOKIE_DOMAIN');
if($target == 'local') { $data = preg_replace("#(const\ DEBUG\ =\ )[^;]*(;)#", "$1true$2", $data); }
file_put_contents($file, $data);
|
实践
假设发布脚本名为 sync.sh
发布到线上测试环境
发布到线上正式环境
首先,先去修改配置文件,将 DEBUG 标识位 设置为 false,然后执行命令。
为了安全,发布到正式环境必须加一个步骤进行确认;而正式发版这个工作并不频繁,多一个步骤也并不过分。