shell脚本进阶1——精读ansible+shell脚本

一、脚本规划思路

  • 运维实施部署平台时,需要先对系统进行初始化,安装所有基础服务环境及依赖包,关闭防火墙和selinux等操作之后,才能开始正式部署第三方插件和微服务。
  • 那系统初始化具体是干什么的呢?这就包括设置防火墙、服务器免密、配置基础环境和yum源、时间同步等等。
  • 当服务器太多时,我们不可能一台台登录上去操作,这极为耗时,所以可以结合ansible来写脚本,选一台主控机即可完成所有操作。

脚本思路:

  • 第一步:确定主控机,其他机器作为受控端,把我们后面要写的ansible脚本放在主控机上进行操作。
  • 第二步:预想用户在使用脚本时的大概要操作哪些步骤。
    • 防火墙、免密登录、配置yum源等等,这么多步骤,我们是不是应该要分条目来进行?先干什么,再干什么,理个顺序出来。
    • 是不是得搞个对话框出来与用户交互,让用户输入主控机信息?若在脚本里把主控机信息写死,那换个部署环境就不能玩了,或者很麻烦需要修改主控机信息,这就只能算半自动化了,没达到目的。
  • 第三步:规划脚本整体框架。当执行脚本时,第一步应该是主控机先对自己做系统初始化,然后再对受控机做,等所有机器的基础环境都具备后,才能再做其他设置。
    1. 确定主控机系统初始化脚本。主控机初始化和受控机操作得分开,我们规划只在主控机上存放脚本,提供基础环境的服务包和源,尽量把第三方服务和微服务安装在受控机,做到层次分明。
    2. 那受控机的脚本要怎么做呢?可以结合ansbile来玩,让主控机对其操作,这就需要定义清单文件、默认变量文件、静态文件、jinja2模板文件、角色任务、playbook剧本,还可以定义需要修改的变量、handlers处理程序任务,最后调试时再根据业务实际情况修改ansible配置文件参数,比如多进程并发数、ssh第一次登录访问会检查key的设置参数,理清需要使用的模块等等。这都需要一点点去调试修改,无误后才能上线正式环境。
  • 第四步:细化脚本执行步骤。上面我们只是理了下脚本框架,那脚本具体要做什么步骤需要规划清楚。
    1. 脚本输出的字体需要考虑,美化用户使用观感,比如tput、printf、echo命令。
    2. 确定对话框效果,比如whiptail、dialog工具。
    3. 定义函数。可以将用户在交互的对话框页面选择的所有操作类目分别定义成一个个子函数,最后再搞个总函数对其引用,比如主控机系统初始化定义成第1个子函数,对受控机的操作定义成第2个子函数…,当用户选择操作类目时,主函数根据用户的选择类目执行对应子函数。那怎么才能让主函数精确的执行对应的子函数呢?可以使用If语句对用户选择的类目结果进行判断,也可以使用case语句根据选择类目结果直接匹配。
    4. 编写playbook剧本。playbook中的内容需尽量简化,什么意思?正常的一个playbook中可以定义任务名称、主机、变量、tasks任务。若playbook简短还行,像系统初始化这种需要操作很多东西的情况下,是需要用到很多个模块,搞多个任务的,一趟下来palybook是很冗长的,要避免这种情况,尽量简洁。
      • 可以把变量和tasks任务全部放在角色里,根据标签对角色进行操作。
      • 定义清单文件,填写受控主机信息。为什么只填受控机的呢?因为主控机是单独设计的脚本操作。
      • 编写角色任务,根据用户选择的菜单条目来写,一个角色对应一个条目。
      • 角色任务中会涉及到安装包、yum源、二进制文件等等,这种就可以当作静态文件。
    5. 确定受控机的yum源。再给受控机安装服务时,受控机的源要怎么配置?可以在主控机上安装一个nginx服务,把提前下载好的离线安装包塞进一个统一目录下,利用nginx将这个目录映射到服务器外部,以web页面的方式让受控机去挂载配置本地yum源。
  • 第五步:理清子函数条目。我们前面说,可以根据用户的选择条目来定义子函数。那用户在对话框菜单中能选择哪些条目?我们可以规划一下:
    1. 首先得有个菜单吧,可以把生成菜单的命令段定义成第1个子函数。
    2. 设置防火墙类目,将其命令段定义成第2个子函数。
    3. 服务器免密操作类目,定义成第3个子函数。
    4. 安装服务器依赖类目,定义成第4个子函数。
    5. 设置时间同步类目,定义成第5个子函数。
    6. 设置harbor仓库域名解析类目,定义成第6个子函数。
  • 第六步: 理清主控机初始化脚本步骤。
    1. 配置本地yum源仓库。
    2. 关闭防火墙以及SELINUX。刚开时部署服务时需要关闭,等最后调试完后在设置防火墙规则。
    3. 安装docker、docker-compose服务、ansible、python-pip,将docker设置为系统服务。
    4. 配置本机提供外部使用的yum仓库,供受控机使用为本地源。
    5. 主控机本机免密登录。
    6. 安装常用运维工具包。
    7. 配置pip的docker依赖。
    8. 配置环境变量。
    9. 最后就是优化脚本,包括脚本输出的显示内容、避免脚本是否会输出打印敏感信息。
  • 第七步:以上就是我们要写的ansible脚本整体规划,整个框架写完后,再一点点改进。

二、主控机shell脚本

  • 先把主控机系统初始化脚本写出来,再写对受控机的操作脚本。

2.1 脚本输出字体特效

1.定义字体输出特效,提高用户使用观感。每种颜色特效都定义成一个子函数,当我想知道用户选择的条目执行结果时,就可以再这个条目的命令段最后引用颜色函数。

set +e
set -o noglob
bold=$(tput bold)
underline=$(tput sgr 0 1)
reset=$(tput sgr0)
red=$(tput setaf 1)
green=$(tput setaf 2)
yellow=$(tput setaf 3)
blue=$(tput setaf 4)
magenta=$(tput setaf 5)
cyan=$(tput setaf 6)
white=$(tput setaf 7)
underline() {
    printf "${underline}${bold}%s${reset}\n" "$@"
}
h1() {
    printf "\n${underline}${bold}${cyan}%s${reset}\n" "$@"
}
h2() {
    printf "\n${underline}${bold}${white}%s${reset}\n" "$@"
}
debug() {
    printf "${white}%s${reset}\n" "$@"
}
info() {
    printf "${white}-> %s${reset}\n" "$@"
}
success() {
    printf "${bold}${green}✔ %s${reset}\n" "$@"
}
error() {
    printf "${red}✖ %s${reset}\n" "$@"
}
warn() {
    printf "${yellow}%s${reset}\n" "$@"
}
bold() {
    printf "${bold}%s${reset}\n" "$@"
}
note() {
    printf "\n${underline}${bold}${blue}Note:${reset} ${blue}%s${reset}\n" "$@"
}

2.定义数组,写要安装的运维工具包。

set -e
set +o noglob
item=1
base_dir=$(readlink -f "$(dirname "$0")")    ##定位出符号链接所指向的位置。
list=(
    bash-completion
    bind-utils
    chrony
    cifs-utils
    cockpit
    cockpit-dashboard
    createrepo
    dstat
    expect
    ftp
    haveged
    iotop
    lrzsz
    lsof
    net-tools
    nfs-utils
    openvpn
    rsync
    screen
    sysstat
    tcpdump
    telnet
    tree
    unzip
    vim
    wget
    zip
    traceroute
    jq
)

2.2 生成菜单栏对话框

基本了解:

  • 当执行脚本后,得设计成与用户交互的功能,提供一个菜单供用户输入主控机信息,可以使用whiptail来实现。
  • 让用户输入ip和输入密码的两段命令段逻辑相同,下面拿输入ip命令段做解析。

代码解读:

  1. 新手先从while循环内容看,里面的核心是两个whiptail语句和一个if判断语句,其他内容都是定义变量被whiptail语句引用,最后再输出了第2个whiptail语句结果,是主控机Ip,供后面使用。
  2. while循环是个死循环,当用户用户输入信息错误时应该再重新输出,而不是直接退出。
  3. 第一个whiptail语句是个表单输入对话框,让用户输入主控机ip,若返回结果不等于0则退出,若输出的内容为exit则退出。
  4. 第二个whiptail语句也是表单输入对话框,是让用户再次输入主控机ip,用于信息核对确认。
  5. 往下有个if判断,对第一个whiptail和第2个whiptail输出结果进行判断,若输入值为空,或两次输入内容不等都会退出脚本
  6. continue语句遇错跳过本次循环,执行后面的;break语句遇错直接退出本次循环,不再执行后面的。
  7. 最后再把第2次输入的结果定义成变量。

1.第一步,输入主控机ip。

local_address() {
    local address1=""
    local address2=""
    title_box="获取本机IP地址"
    while true; do
        reg_box="请输入本机本机IP地址:"
        address1=$(whiptail --title "${title_box}" --inputbox "${reg_box}" 8 78 3>&1 1>&2 2>&3)
        [ $? != 0 ] && exit
        [ "${address1,,}" == "exit" ] && exit
        reg2_box="请再次输入本机本机IP地址:"
        address2=$(whiptail --title "${title_box}" --inputbox "${reg2_box}" 8 78 3>&1 1>&2 2>&3)
        [ $? != 0 ] && exit
        [ "${address2,,}" == "exit" ] && exit
        if [ -z "${address1}" ] || [ -z "${address2}" ] || [ "${address1}" != "${address2}" ]; then
            msg_box="两次输入不一致,请重新设置"
            whiptail --title "${title_box}" --msgbox "${msg_box}" 8 78
            [ $? != 0 ] && exit
            [ "${address,,}" == "exit" ] && exit
            continue
        fi
        break
    done
    address=${address2}
}

2.输入主控机密码。

local_password() {
    local passwd1=""
    local passwd2=""
    title_box="获取本机ROOT用户密码"
    while true; do
        reg_box="请输入本机ROOT用户密码:"
        passwd1=$(whiptail --title "${title_box}" --passwordbox "${reg_box}" 8 78 3>&1 1>&2 2>&3)
        [ $? != 0 ] && exit
        [ "${passwd1,,}" == "exit" ] && exit
        reg2_box="请再次输入本机ROOT用户密码:"
        passwd2=$(whiptail --title "${title_box}" --passwordbox "${reg2_box}" 8 78 3>&1 1>&2 2>&3)
        [ $? != 0 ] && exit
        [ "${passwd2,,}" == "exit" ] && exit
        if [ -z "${pas
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

百慕卿君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值