我在写shell自动部署脚本碰到的问题

如题,最早接触shell脚本是大学的时候,感觉好复杂,最近几年工作中也零零散散的接触过很多,很多都是网上找资源进行解决,这两天在写自动部署的初始化脚本,感觉还是挺多不足的。

shell脚本写的有点c语言的感觉,是过程语言,但是如何模块化就非常重要了,首先我的第一个版本是完成了从远端服务器获取资源文件,一键部署tomcat,jdk,生成backup目录,log目录,web目录,script目录,tools目录,生成tomcat自启动脚本。以及和远端服务器的交互等。整个shell脚本写下来花了半天的时间,一个方法搞定全部,没有错误处理机制,没有合适的操作日志。所有就有了下面的重构。

shell脚本中遇到的问题

    1.执行脚本的日志打印,错误记录,类似于日志机制没有

       v1.0的版本采用的日志方式是,直接print,遇到错误直接return

        v2.0的方式,现在的方式是模块化日志方式,看代码

#调试,调用wget记录日志
debug()
{ 
   if [ $global_is_debug = "true" ];then
      debug_str=$1
      echo "debug:##### ${debug_str} #####\n"
   fi
}

#错误,调用wget记录日志
error()
{ 
      echo "error:########### $1 ############\n"
}

    2.用wget方式和远程服务器交互,特殊字符处理

          v1.0:直接wget –i 一个列表,然后存到本地,一系列操做后,删除文件

               优点是,简单粗暴,缺点是不能适应自动化部署

          v2.0:封装wget模块,通过和远程服务器交换,动态获取下载列表,根据需要保存到指定目录,优点:更具有扩展性,缺点是,服务器请求多

          在和远端服务器交换的时候设计到特殊字符及汉子的处理,v2.0封装了一个urlencode方法,进行转码。代码如下:

#进行编码,编码结果放在全局变量里面
urlEncode() 
{
  #需要被编码的字符串
  encode_str_params1=$1
  debug "${encode_str_params1}"
  #编码
  global_encode_str=`echo "${encode_str_params1}" | tr -d '\n' | xxd -plain | sed 's/\(..\)/%\1/g'` 
  return 
}

      补充一点:wget 对于请求的url带有特殊字符的处理,我后台采用的是struts2,提供的api接口带有 例如 http//t.cn/api/linux!errorDebug?xx=oo&oo=xx

  你采用传统的方式都会报bad参数的错误,调试很久都未果,我的经验是,采用post方式,如果有特殊字符的 需要用 ‘’  包含起来,比如上述的。

下面的代码中wgetPost是封装了一个将请求文件存到指定目录的功能,文件名命名方式为 debug_时间_全局的自增字段。

第一行请求变量参数里有特殊字符,后面跟着的字符串也需要用‘’包含起来,具体为什么,应该是shell的解释器就是这样规定的,‘’小括号里不能包含变量

wgetPost ${global_log_url}'logDebug?' ${global_project_log_debug_path}/ "debug_"$(date +%Y-%m-%d-%H-%M-%S)"_${global_debug_file_log_num}" ${inner_post_data}
 

#wget简单封装
#inner_url:  访问地址
#inner_dir:  目录
#inner_file: 文件名称
#inner_post_data  请求的数据
wgetPost()
{
   inner_url=$1
   inner_dir=$2
   inner_file=$3
   inner_post_data=$4
   #容错处理
   mkdir -p -m 777 ${inner_dir}
   wget --post-data="${inner_post_data}" ${inner_url}  -O ${inner_dir}${inner_file}".bk" -o /dev/null
   inner_bytes=$(du -s ${inner_dir}${inner_file}.bk | awk '{print $1}')
   if [ $inner_bytes -ne 0 ];then
        cp -rf ${inner_dir}${inner_file}.bk ${inner_dir}${inner_file}
   else
        echo "wget ${inner_url} failed"
   fi
}

    3.sed命令在处理特殊字符替换的时候处理

       sed –i ‘s/a/b/g’ 一般是这种方式,但是如果遇到要替换的字符或者被替换的字符有*_/ \的时候,就不适用了,解决的方式是利用#号

     可以通用点,就是将源字符串,替换为目标字符串

source_str="abc"
target_str="xxoo"

sed -i "s#${source_str}#${target_str}#g"  str.txt

 

    4.合理的代码编程规范

        编码规范很重要,v1.0版本写的比较随意,变量名比较混乱,维护花时间,

      v2.0注意这个问题,目前的规范是:

            1.所有的静态变量 前缀为 static_xx_xx

            2.所有的全局变量 前缀为 global_xx_oxx

            3.参数为 in_xx_xx

            4.方法内的局部变量为 inner_xxdf

            5.方法的命名规则遵循通俗易懂

            6.模块化操作,讲究代码

    5.目录的权限问题

          目录的权限问题是个非常头疼的问题,因为所有的操作为root操作,如果控制到非常精细力度的权限,这块都要头疼死,在v2.0稳定的基础上,保证自动部署系统的如期完成,顶级目录不开放修改,子目录为777权限,任何人可以修改,等自动部署系统前台完成后,就可以完全回收权限了

    6.日志记录的级别

         日志这个东西很重要,v1.0的版本是采用打印到控制台的方式

        v2.0采用方式是进行级别控制 ,分为debug 和error 方式,debug模式有开关配置,error模式之间输出,并且通过wget方式入库,及时反馈到前台

    7.应用服务器及依赖环境的准备方式

        依赖环境也很重要,自动部署讲究一个自动部署,统一规范,但是线上的版本很多,比如jdk有1.5,1.6,1,7 同时 tomcat也会有各种版本,memcache等都各不相同。为了统一,首先取线上稳定的tomcat版本清理后作为基础版本,例如tomcat.7.39.tar.gz,解压后利用脚本动态更改配置后就可以使用,还有jdk的安装目录等,现在的做法就是 把线上的版本都收集起来,通过后台网页工具进行选择,自定义配置,首先应用环境的基础版本是清洁版本,配置文件已经进行过优化,只需要替换几个常量即可,这里完成的是,1.tomcat的端口号,关闭端口,启动时的jdk目录,自启动脚本的tomcat-home等

posted on 2013-05-04 00:18  巴郎  阅读(479)  评论(0编辑  收藏  举报

导航