第十章·shell编程-图形化跳板机

whiptail基本概述

在CentOS6系统中,我们可以使用setup指令来修改网卡的IP等信息,交互起来十分方便
在CentOS7系统中,setup命令已经没有了,但是还有nmtui命令,可以让我们修改IP和主机名。

那么whiptail命令的作用,就是出现一个可以交互的图形化界面,并且样式有很多。

在之前的课程中,我们已经使用流程控制语句,满足了一个跳板机的需求,但是我们还想是想更多的功能,当然脚本也都能实现,但是我们想要更炫酷的,脱离死气沉沉的命令行。

那么我们就一起来看一下,whiptail可以实现哪些需求吧...

消息框

file

1.语法

whiptail --title "<标题>" --msgbox "<信息>" <高度> <宽度>

2.实践

#!/bin/bash

## 消息框
whiptail --title "$HOSTNAME Disk Info" --msgbox "`df -h`" 30 60

--title:       #指定标题内容:$HOSTNAME Disk Info
--msgbox:      #指定信息内容:`df -h`
30:            #展示信息框的高度为:30
60:            #展示信息框的宽度为:60

3.返回值

不管是写脚本,还是写程序,做开发,最主要的一个点就是返回值,每输入一条命令,我想知道这条命令是否执行成功,能否把这条命令的输出结果传参给下一条命令

消息框返回值:

有返回值,如果想要做判断,只能使用shell中$?返回值是0,但是无法传递信息,可接受传参

布尔值选择框

file
1.语法

whiptail --title "<标题>" --yesno "<信息>" <高度> <宽度>

2.实践

#!/bin/bash
whiptail --title "你确定要这么做吗?" --yesno "请做出你的选择YES or NO !" 10 60
--yesno:#指定要做出选择的提示信息

3.返回值

yes:0
no:1

## 布尔值选择框案例一:
whiptail --title "你确定要这么做吗?" --yesno "请做出你的选择YES or NO !" 10 60
if [ $? -eq 0 ];then
        echo '选择的yes'
else
        echo '选择的是no'
fi

## 布尔值选择框案例二:
whiptail --title "你确定要这么做吗?" --yes-button "运维" --no-button "开发" --yesno "请选择你在公司的岗位" 10 60
if [ $? -eq 0 ];then
       echo '你的岗位是运维'
else
       echo '你的岗位是开发'
fi

--titlle:标题
--yes-button:yes的按钮可以改名
--no-button:no的按钮可以改名
--yesno:布尔值框,后面可以加框内的内容

交互式输入框

file

1.语法

whiptail --title "<标题>" --inputbox "<信息>" <高度> <宽度> <默认值>

2.实践

whiptail --title "罗炜的跳板机-10.0.0.61" --inputbox "请输入一个文件名路径:" 10 60 /etc/passwd 3>&1 1>&2 2>&3

3.返回值

## 交互式输入框
source_file=`whiptail --title "罗炜的跳板机-10.0.0.61" --inputbox "请输入源文件位置:" 10 60 3>&1 1>&2 2>&3`
if [ $? -eq 0 ];then
        dest_file=`whiptail --title "罗炜的跳板机-10.0.0.61" --inputbox "请输入对端存放位置:" 10 60 /etc/passwd 3>&1 1>&2 2>&3`
        if [ $? -eq 0 ];then
                scp $source_file 172.16.1.7:$dest_file &>/dev/null
        else
                echo '请输入一个目标路径'
        fi
else
        echo '请输入一个源文件路径'
fi

## 交互式输入框
source_file=`whiptail --title "罗炜的跳板机-10.0.0.61" --inputbox "请输入源文件位置:" 10 60 3>&1 1>&2 2>&3`

whiptail --title "$HOSTNAME Disk Info" --msgbox "$source_file" 30 60

## 选项
--inputbox:交互式输入框
10 60 /etc/passwd
10:高度
60:宽度
/etc/passwd:默认值

## 返回值
选择OK:0
选择Cancel:1

命令本身带输入内容,输入内容可以保存在变量中

密码输入框

file

1.语法

变量名=`whiptail --title "<标题>" --passwordbox "<信息>" <高度> <宽度> <默认值>`

2.实践

PASSWD=`whiptail --title "罗炜的跳板机-10.0.0.61" --passwordbox "请输入一个密码名路径:" 10 60  3>&1 1>&2 2>&3`

3.返回值

## 密码输入框
PASSWD=`whiptail --title "罗炜的跳板机-10.0.0.61" --passwordbox "请输入一个密码名路径:" 10 60  3>&1 1>&2 2>&3`
if [ $? -eq 0 ];then
        if [ ${#PASSWD} -ne 0 ];then
                echo "密码是:$PASSWD"
        else
                echo "密码为空"
        fi
else
        echo '选择了取消'
fi

# 返回值
选择OK:0
选择Cancel:1

命令本身带输入内容,输入内容可以保存在变量中

菜单栏

file

1.语法

变量名=$(whiptail --title "<标题>" --menu "<信息>" <高度> <宽度> <菜单显示几行内容>\
"1" "选项1" \
"2" "选项2" \
"3" "选项3" \
"4" "选项4" \
"5" "选项5" 3>&1 1>&2 2>&3)

2.实践

## 菜单栏
命令名=$(whiptail --title "罗炜的跳板机-10.0.0.61" --menu "根据菜单选吧老弟" 30 60 10 \
"1" "lb01" \
"2" "lb02" \
"3" "web01" \
"4" "web02" \
"5" "web03" 3>&1 1>&2 2>&3)

--menu:菜单栏
30:高度
60:宽度
10:菜单显示几行内容

3.返回值

## 返回值
选择OK:0
选择Cancel:1

选择的值,会将序号保存在OPTION变量中

## 实战
## 菜单栏
OPTION=$(whiptail --title "罗炜的跳板机-10.0.0.61" --menu "根据菜单选吧老弟" 30 60 10 \
"1" "lb01" \
"2" "lb02" \
"3" "web01" \
"4" "web02" \
"5" "web03" 3>&1 1>&2 2>&3)

if [ $? -eq 0 ];then
        case $OPTION in
        1)
                echo "连接 lb01"
                ;;
        3)
                ssh 172.16.1.7
                ;;
        esac
else
        echo "选择了退出"

fi

单选框

![image-20220727183324413]file

1.语法

DISTROS=$(whiptail --title "罗炜的跳板机-10.0.0.61" --radiolist "请在下面内容选择一项,上下左右移动,空格选中" 20 60 10 \
"send" "发送文件" OFF \
"useradd" "创建用户" OFF \
"ssh" "远程连接" ON \
"mem" "查看内存" OFF 3>&1 1>&2 2>&3)

2.选项

## 选项
--radiolist:单选框
OFF:默认没有被选中
ON:默认被选中
#多选没有意义,后面的选项会覆盖前面的选项

3.返回值

## 返回值
选择OK:0
选择Cancel:1

多选框

file

1.语法

DISTROS=$(whiptail --title "罗炜的跳板机-10.0.0.61" --checklist "请在下面内容选择一项,上下左右移动,空格选中" 20 60 10 \
"send" "发送文件" ON \
"useradd" "创建用户" OFF \
"ssh" "远程连接" OFF \
"mem" "查看内存" OFF 3>&1 1>&2 2>&3)

2.实战

send(){
        echo 执行send函数
}

mem(){
        echo 执行mem函数
}

DISTROS=$(whiptail --title "罗炜的跳板机-10.0.0.61" --checklist "请在下面内容选择一项,上下左右移动,空格选中" 20 60 10 \
"send" "发送文件" ON \
"useradd" "创建用户" OFF \
"ssh" "远程连接" OFF \
"mem" "查看内存" OFF 3>&1 1>&2 2>&3)

echo $?
echo $DISTROS

for n in $DISTROS;do
        ${n//\"/''}
done

3.返回值

选择OK:0
选择Cancel:1

进度条

file

语法

{
    for ((i = 0 ; i <= 100 ; i+=30)); do
        sleep 1
        echo $i
    done
} | whiptail --gauge "等一下子,正在安装" 6 60 0

{                         # 每次自增30
    for ((i = 0 ; i <= 100 ; i+=30)); do
        sleep 1 #睡眠一秒
        echo $i
    done
} | whiptail --gauge "等一下子,正在安装" 6 60 0

图形化跳板机

#!/bin/bash

lb01=10.0.0.5
lb02=10.0.0.6
web01=10.0.0.7
web02=10.0.0.8
web03=10.0.0.9
nfs=10.0.0.31
backup=10.0.0.41
db01=10.0.0.51
db02=10.0.0.52
m01=10.0.0.61
zabbix=10.0.0.71

title="欢迎进入罗炜的跳板机-$m01"

#跳板机函数
JUMP(){
                OPTION=$(whiptail --title "$title"  --menu "请选择你要连接的服务器:" 25 60 11 \
                 "1" "连接 lb01" \
                 "2" "连接 lb02" \
                 "3" "连接 web01" \
                 "4" "连接 web02" \
                 "5" "连接 web03" \
                 "6" "连接 nfs" \
                 "7" "连接 backup" \
                 "8" "连接 db01" \
                 "9" "连接 db02" \
                 "10" "连接 m01" \
                 "11" "连接 zabbix"  3>&1 1>&2 2>&3)

         exitstatus=$?
         if [ $exitstatus = 0 ]; then
            case $OPTION in
                        1)
                        connect $lb01
                        ;;
                        2)
                        connect $lb02
                        ;;
                        3)
                        connect $web01
                        ;;
                        4)
                        connect $web02
                        ;;
                        5)
                        connect $web03
                        ;;
                        6)
                        connect $nfs
                        ;;
                        7)
                        connect $backup
                        ;;
                        8)
                        connect $db01
                        ;;
                        9)
                        connect $db02
                        ;;
                        10)
                        connect $m01
                        ;;
                        11)
                        connect $zabbix
                        ;;
                        12)
                        connect $te
                        ;;
                        13)
                        connect $te_web
                        ;;
                        esac
        fi
}

#主机函数
HOST_INFO (){
            HOST=$(whiptail --title "$title" --checklist \
                "请选择要发送的主机名:" 25 60 11 \
                "$lb01" "发送给lb01" OFF \
                "$lb02" "发送给lb01" OFF \
                "$web01" "发送给web01" OFF \
                "$web02" "发送给web02" OFF \
                "$web03" "发送给web03" OFF \
                "$nfs" "发送给nfs" OFF \
                "$backup" "发送给backup" OFF \
                "$db01" "发送给db01" OFF \
                "$db02" "发送给db02" OFF \
                "$m01" "发送给m01" OFF \
                "$zabbix" "发送给zabbix" OFF 3>&1 1>&2 2>&3)
}

SER_INFO(){
                SER=$(whiptail --title "$title" --checklist \
                "请选择要检查的服务:" 25 60 10 \
                "nginx" "检查nginx" OFF \
                "mysqld" "检查mysqld" OFF \
                "php" "检查php" OFF \
                "tomcat" "检查tomcat" OFF \
                "sshd" "检查sshd" OFF \
                "httpd" "检查httpd" OFF \
                "vsftpd" "检查vsftpd" OFF \
                "docker" "检查docker" OFF \
                "saltstack" "检查saltstack" OFF \
                "rsyncd" "检查rsyncd" OFF 3>&1 1>&2 2>&3)
}

#连接函数
connect(){
  whiptail --title "$title" --yesno "你确定要连接这台机器么?想好了啊!!!" 10 60
  if [ $? -eq 0 ];then
            {
            ping -c 1 -w 1 $1 >/tmp/ping.txt 2>/dev/null
            if [ $? -ne 0 ];then
                for ((i = 0 ; i <= 100 ; i+=30)); do
                        sleep 1
                        echo $i
                done
            fi
            } | whiptail --gauge "emmmm...我正在连接$1,检测网络中,等我一哈子..." 6 60 0
            grep 'ttl' /tmp/ping.txt &>/dev/null
            if [ $? -eq 0 ];then
                ssh root@$1
            else
                whiptail --title "$title" --msgbox "网络检测失败,别连了,我的哥,$1机器都没开" 10 60
            fi

  fi
}

#推送文件函数
SCP (){
        HOST_INFO

                PA=$(whiptail --title "$title" --inputbox "请输入需要推送的文件本地路径:" 10 60 /etc/passwd 3>&1 1>&2 2>&3)
                DEST=$(whiptail --title "$title" --inputbox "请输入需要分发到主机的哪个目录:" 10 60 /tmp 3>&1 1>&2 2>&3)
                {
                for H in ${HOST};do
                        echo "scp $PA ${H}:${DEST}"|bash &>/dev/null
                        for ((i = 0 ; i <= 100 ; i+=50));do
                                sleep 1
                                echo $i
                        done
                done
                } | whiptail --gauge "别着急,正在传送中..." 6 60 0
}

#检查磁盘函数
CHECK_DISK (){
        HOST_INFO

                for H in ${HOST};do
            echo "ssh $H 'df -h' "|bash > /tmp/disk
            whiptail --title "$(date +%F-%T) | $H 磁盘信息" --msgbox "$(cat /tmp/disk)" 10 60
                done
}

#检查内存函数
CHECK_MEM (){
                HOST_INFO

                for H in ${HOST};do
                        echo "ssh $H 'free -m' "|bash > /tmp/meminfo
                        whiptail --title "$(date +%F-%T) | $H 内存信息" --msgbox "$(cat /tmp/meminfo)" 30 80
                done
}

#查看服务状态
CHECK_SER (){
        HOST_INFO
        SER_INFO

        for H in ${HOST};do
            for S in ${SER};do
                HO=`echo "$H"|awk -F \" '{print $2}'`
                PROC=`ssh $HO "ps -ef|grep $S|wc -l"`
                NUM=$( expr $PROC - 3 )
                if [[ $PROC > 3 ]];then
                    whiptail --title "$(date +%F-%T) | $H 服务信息" --msgbox "${S} 存活 | 进程数:$NUM" 10 60
                else
                    whiptail --title "$(date +%F-%T) | $H 服务信息" --msgbox "${S} 没有存活| 进程数:$NUM" 10 60
                fi
            done
        done
}

#批量之心命令函数
EXEC_CMD(){
        HOST_INFO

        CMD=$(whiptail --title "$title" --inputbox "请输入要执行的命令:" 10 60 ifconfig 3>&1 1>&2 2>&3)
                for H in ${HOST};do
            HO=`echo "$H"|awk -F \" '{print $2}'`
            RES=`ssh $HO "$CMD"`
            whiptail --title "$(date +%F-%T) | $H 命令执行结果" --msgbox "$RES" 40 80
        done

}

#退出函数
EXIT(){
                pass=$(whiptail --title "$title" --passwordbox "请输入你的退出密码" 10 60 3>&1 1>&2 2>&3)
                if [ $pass == '123456' ];then
                        exit
                else
                        whiptail --title "$title" --msgbox "密码错误,你不是运维,小样的~~~" 10 60
                        continue
                fi
}

 whiptail --title "$title" --msgbox "罗炜的跳板机,给你全新不一样的feel,进去了,就不想出来" 10 60

#抓取键盘信号
trap "" HUP INT TSTP
while true;do
    OPTION=$(whiptail --title "$title" --menu "请选择你的动作(轻点...)" 15 60 8 \
    "1" "SSH远程连接" \
    "2" "推送文件" \
    "3" "查看磁盘空间" \
    "4" "查看内存空间" \
    "5" "查看服务状态" \
    "6" "批量执行命令" \
    "7" "轻松一下(game)" \
    "8" "退出"  3>&1 1>&2 2>&3)

    exitstatus=$?
    if [ $exitstatus = 0 ]; then
        case $OPTION in
        1)
        JUMP
        ;;
        2)
        SCP
        ;;
        3)
        CHECK_DISK
        ;;
        4)
        CHECK_MEM
        ;;
        5)
        CHECK_SER
        ;;
        6)
        EXEC_CMD
        ;;
        7)
        sh /root/eluosi.sh
        ;;
        8)
        EXIT
        ;;
        esac
    fi
done

山林不向四季起誓 荣枯随缘