linux shell 脚本详解 | 服务器排障常用命令 | 创建窗口部件

注:本文为 “shell” 相关文章合辑。


Linux Shell 脚本入门到实战详解

宝山的博客 已于 2023-01-01 21:57:19 修改

一、Shell 入门简介

1.1 什么是 Shell

  • Shell 脚本简介

    网上有很多关于 Shell 的概念介绍,大多较为官方化。如果对 Linux 命令很熟悉,那么编写 Shell 脚本并非难事。Shell 本质上是将 Linux 命令组合在一起,实现某个目标,从而减轻工作量,提高工作效率。

  • 官方化的 Shell 介绍

    Shell 通过提示用户输入,向操作系统解释该输入,然后处理来自操作系统的任何结果输出。简单来说,Shell 是一个用户与操作系统之间的命令解释器。

  • 常见的 Shell 有哪些

    • Bourne Shell(/usr/bin/sh/bin/sh
    • Bourne Again Shell(/bin/bash
    • C Shell(/usr/bin/csh
    • K Shell(/usr/bin/ksh
    • Shell for Root(/sbin/sh

    最常用的 Shell 是 Bash(Bourne Again Shell)。由于其易用性和免费性,Bash 在日常工作中被广泛使用,也是大多数 Linux 操作系统默认的 Shell 环境。

    Shell 环境

1.2 Shell 编程注意事项

  • Shell 命名:Shell 脚本名称通常为英文,后缀以 .sh 结尾,避免使用特殊符号和空格。
  • 命名要直观,一眼能看出功能。
  • Shell 脚本首行需要以 #!/bin/bash 开头。
  • Shell 脚本变量不能以数字或特殊符号开头,可以使用下划线 _,但不能使用破折号 -

1.3 第一个 Shell 脚本:Hello World

  • 创建一个伟大的编程项目 — Hello World

    # 创建一个 Helloword.sh 文件
    [root@aly_server01~]# touch Helloword.sh
    
    # 编辑 Helloword.sh 文件
    [root@aly_server01~]# vim Helloword.sh
    
    [root@aly_server01~]# cat Helloword.sh
    #!/bin/bash
    # This is our first shell
    # by author rivers 2021.09
    echo "hello world"
    
    [root@aly_server01~]# ll Helloword.sh
    -rw-r--r-- 1 root root 85 Sep 20 22:26 Helloword.sh
    
    # 赋予执行权限
    [root@aly_server01~]# chmod o+x Helloword.sh
    
    # 运行 Helloword.sh 脚本
    [root@aly_server01~]# ./Helloword.sh
    hello world
    

    运行结果

二、Shell 环境变量讲解

2.1 Shell 变量详解

  • 环境变量介绍

    # 什么是变量
    很多人可能会说,可以变化的量就是变量。但有时汉语的意思虽强大,却不一定能完全理解。这里可以理解为 a = 1,同时还可以 a = 2、a = 3,不同的值都可以赋给同一个变量 a。
    
    # 常见的三种变量
    Shell 编程中变量分为三种:系统变量、环境变量和用户变量。Shell 变量名在定义时,首个字符必须为字母(a-z,A-Z),不能以数字开头,中间不能有空格,可以使用下划线(_),不能使用(-),也不能使用标点符号等。
    
    # 简单的变量介绍
    [root@keeplived_server~]# a=18
    [root@keeplived_server~]# echo $a
    18
    

2.2 Shell 系统变量介绍

  • 系统变量

    # Shell 常见的变量之一是系统变量,主要用于参数判断和命令返回值判断。
    
    $0          当前脚本的名称;
    $n          当前脚本的第 n 个参数,n = 1, 2, ..., 9$*          当前脚本的所有参数(不包括程序本身);
    $#          当前脚本的参数个数(不包括程序本身);
    $?          命令或程序执行完后的状态,返回 0 表示执行成功;
    $$          程序本身的 PID 号。
    

2.3 Shell 环境变量介绍

2.3.1 常见的系统环境变量
  • 环境变量介绍

    # Shell 常见的变量之二:环境变量,主要在程序运行时需要设置。
    
    PATH        命令路径,以冒号为分隔;
    HOME        打印用户家目录;
    SHELL       显示当前 Shell 类型;
    USER        打印当前用户名;
    ID          打印当前用户 ID 信息;
    PWD         显示当前所在路径;
    TERM        打印当前终端类型;
    HOSTNAME    显示当前主机名;
    PS1         定义主机命令提示符;
    HISTSIZE    历史命令大小,可通过 HISTTIMEFORMAT 变量设置命令执行时间;
    RANDOM      随机生成一个 032767 的整数。
    

2.4 Shell 用户环境变量介绍

2.4.1 自定义 Shell 环境变量
  • 用户自定义变量

    # 用户变量又称为局部变量,主要用于 Shell 脚本内部或临时局部使用。
    
    a=rivers                          自定义变量 A;
    Httpd_sort=httpd-2.4.6-97.tar     自定义变量 N_SOFT;
    BACK_DIR=/data/backup/            自定义变量 BACK_DIR;
    IPaddress=10.0.0.1                自定义变量 IP1;
    
2.4.2 使用 echo 打印菜单栏
  • 使用 echo 打印菜单栏,显示 http-2.4 安装过程

    # 创建 httpd_2.4 安装脚本
    [root@web-server01~]# touch httpd_2.4_install.sh
    
    # 赋予执行权限
    [root@web-server01~]# chmod o+x httpd_2.4_install.sh
    
    # 运行脚本
    [root@web-server01~]# ./httpd_2.4_install.sh
    

    运行结果

2.4.3 Shell 中彩色输出 HelloWorld
  • echo -e 扩展

    #!/bin/bash
    # This is echo color shell
    # by author rivers 2021.09-23
    
    # 字体颜色
    for i in {31..37}; do
        echo -e "\033[$i;40mHello world!\033[0m"
    done
    
    # 背景颜色
    for i in {41..47}; do
        echo -e "\033[47;${i}mHello world!\033[0m"
    done
    
    # 显示方式
    for i in {1..8}; do
        echo -e "\033[$i;31;40mHello world!\033[0m"
    done
    

    运行结果

三、Shell 编程流程控制语句

3.1 if 条件语句介绍

3.1.1 常用的单/双分支
  • if 条件语句

    # If 条件判断语句,通常以 if 开头,fi 结尾。也可加入 else 或 elif 进行多条件判断。
    
    # 单分支语句 —— 比较大小
    if [ 条件表达式 ]; then
        语句1
    fi
    
    # 双分支 if 语句
    if [ 表达式 ]; then
        语句1
    else
        语句2
    fi
    
    # 多分支条件语句 —— 判断成绩
    if [ 表达式 ]; then
        语句1
    elif [ 表达式 ]; then
        语句2
    else
        语句3
    fi
    
3.1.2 if 常见判断逻辑运算符详解
  • 常见逻辑判断运算符

    -f          判断文件是否存在,例如:if [ -f filename ];
    -d          判断目录是否存在,例如:if [ -d dir ];
    -eq         等于,应用于整型比较;
    -ne         不等于,应用于整型比较;
    -lt         小于,应用于整型比较;
    -gt         大于,应用于整型比较;
    -le         小于或等于,应用于整型比较;
    -ge         大于或等于,应用于整型比较;
    -a          逻辑与(and);
    -o          逻辑或(or);
    -z          判断字符串是否为空;
    -x          判断文件是否具有可执行权限;
    ||          逻辑或;
    &&          逻辑与。
    
3.1.3 使用单分支语句判断 crond 进程是否在运行 — 案例
  • 判断 crond 服务是否运行

    #!/bin/bash
    # this is check crond
    # by author rivers on 2021-9-23
    
    # 定义一个变量名
    name=crond
    num=$(ps -ef | grep $name | grep -vc grep)
    if [ $num -eq 1 ]; then
        echo "$num running!"
    else
        echo "$num is not running!"
    fi
    
3.1.4 判断系统目录是否存在 — 案例
  • 判断系统目录是否存在

    #!/bin/bash
    # this is check directory
    # by author rivers on 2021-9-27
    if [ ! -d /data/rivers -a ! -d /tmp/rivers ]; then
        mkdir -p /data/rivers
    fi
    
3.1.5 多个条件判断学生分数等级 — 案例
  • 判断学生成绩等级

    #!/bin/bash
    # this check grade shell
    # by author rivers on 2021-09-27
    
    grade=$1
    if [ $grade -gt 90 ]; then
        echo "It's very good!"
    elif [ $grade -gt 70 ]; then
        echo "It's good!"
    elif [ $grade -ge 60 ]; then
        echo "pass"
    else
        echo "no pass"
    fi
    

    运行结果

3.2 for 循环语句介绍

  • for 循环语句

    # 格式:for name [ [ in [ word ... ] ] ; ] do list ; done
    for 变量名 in 取值列表; do
        语句
    done
    
3.2.1 检查同一局域网多台主机是否存活
  • 检查多台主机存活情况

    #!/bin/bash
    # check hosts is on/off
    # by rivers on 2021-9-23
    
    Network=$1
    for Host in $(seq 1 254); do
        ping -c 1 $Network.$Host > /dev/null && result=0 || result=1
    
        if [ "$result" == 0 ]; then
            echo -e "\033[32;1m$Network.$Host is up\033[0m"
            echo "$Network.$Host" >> /tmp/up.txt
        else
            echo -e "\033[31;1m$Network.$Host is down\033[0m"
            echo "$Network.$Host" >> /tmp/down.txt
        fi
    done
    

    运行结果

3.3 while 循环语句介绍

  • while 循环语句

    # While 循环语句与 for 循环功能类似,主要用于对某个数据域进行循环读取、对文件进行遍历。通常用于需要循环某个文件或列表,满足循环条件会一直循环,不满足则退出循环。
    # while 关联的还有一个 until 语句,它与 while 不同之处在于,当条件表达式为 false 时才循环,实际使用中比较少,这里不再讲解。
    
    while [ 表达式 ]; do
        语句
    done
    
  • break 和 continue 语句

    # break 是终止循环。
    # continue 是跳出当前循环。
    
    # 示例 1:在死循环中,满足条件终止循环
    while true; do
        let N++
        if [ $N -eq 5 ]; then
            break
        fi
        echo $N
    done
    # 输出:1 2 3 4
    
    # 示例 2:说明 continue 的用法
    N=0
    while [ $N -lt 5 ]; do
        let N++
        if [ $N -eq 3 ]; then
            continue
        fi
        echo $N
    done
    # 输出:1 2 4
    
    # 打印 1-100 数字
    i=0
    while ((i <= 100)); do
        echo $i
        i=$((i + 1))
    done
    
3.3.1 While 循环求 1-100 的总和 — 案例
  • 求 1-100 的总和

    #!/bin/bash
    # by author rivers on 2021-9-27
    j=0
    i=1
    while ((i <= 100)); do
        j=$((j + i))
        ((i++))
    done
    echo $j
    

    运行结果

3.3.2 每 10 秒循环判断一次 hbs 用户是否登录系统 — 案例
  • 每 10 秒循环判断系统登录

    [root@web-server01~/script]# vim login.sh
    #!/bin/bash
    # Check File to change.
    # By author rivers 2021-9-27
    USERS="hbs"
    while true; do
        echo "The Time is $(date +%F-%T)"
        sleep 10
        NUM=$(who | grep "$USERS" | wc -l)
        if [[ $NUM -ge 1 ]]; then
            echo "The $USERS is login in system."
        fi
    done
    

    运行结果

3.4 case 选择语句介绍

  • case 选择语句

    # Case 选择语句,主要用于对多个选择条件进行匹配输出,与 if elif 语句结构类似,通常用于脚本传递输入参数,打印输出结果及内容。
    # 语法格式以 Case…in 开头,esac 结尾。每个模式必须以右括号结束,命令结尾以双分号结束。
    
    case 模式名 in
        模式1)
            命令
            ;;
        模式2)
            命令
            ;;
        *)
            不符合以上模式执行的命令
            ;;
    esac
    
3.4.1 使用 case 编写一个 httpd 服务启动脚本
  • 编写 http 服务启动脚本

    [root@web-server01~/script]# vim httpd_start.sh
    #!/bin/bash
    # check http server start|stop|status
    # by author rivers on 2021-9-27
    
    while true; do
        echo -e "
        \033[31m start \033[0m
        \033[32m stop \033[0m
        \033[33m status \033[0m
        \033[34m quit \033[0m
        "
        read -p "请输入选择(start|stop|quit):" char
        case $char in
            start)
                systemctl start httpd && echo "httpd服务已经开启" || echo "开启失败"
                ;;
            stop)
                systemctl stop httpd && echo "httpd服务已经关闭" || echo "关闭失败"
                ;;
            restart)
                systemctl restart httpd && echo "httpd服务已经重启" || echo "重启失败"
                ;;
            status)
                systemctl status httpd
                ;;
            quit)
                exit
                ;;
            *)
                echo "输入错误,请重新输入!"
                ;;
        esac
    done
    

    运行结果

3.5 select 选择语句介绍

  • select 选择语句

    # select 是一个类似于 for 循环的语句,常用于选择菜单的创建,可以配合 PS3 打印菜单的输出信息。
    # 语法格式以 select…in do 开头,done 结尾。
    
    select i in (表达式); do
        语句
    done
    
3.5.1 使用 select 打印 lnmp 菜单栏 — 案例
  • 打印 lnmp 选择菜单

    #!/bin/bash
    # by author rivers on 2021-9-27
    PS3="Please enter your select install menu:"
    select i in http php mysql quit; do
        case $i in
            http)
                echo -e "\033[31m Test Httpd \033[0m"
                ;;
            php)
                echo -e "\033[32m Test PHP \033[0m"
                ;;
            mysql)
                echo -e "\033[33m Test MySQL \033[0m"
                ;;
            quit)
                echo -e "\033[32m The System exit. \033[0m"
                exit
                ;;
            *)
                echo "输入错误,请重新输入!"
                ;;
        esac
    done
    

    运行结果

3.6 Shell 函数、数组编程实战

  • 函数

    # Shell 允许将一组命令集或语句形成一个可用块,这些块称为 Shell 函数。Shell 函数的用途在于只需定义一次,后期随时使用即可,无需在 Shell 脚本中添加重复的语句块。
    # Shell 函数的语法格式以 function name() { 开头,以 } 结尾。
    
    func() {
        command1
        command2
        ...
    }
    func  # 直接调用函数名
    
    # 示例:
    #!/bin/bash
    func() {
        VAR=$((1 + 1))
        return $VAR
        echo "This is a function."
    }
    func
    echo $?
    # 输出:2
    
  • 数组

    # 数组是相同类型的元素按一定顺序排列的集合。
    # 格式:array=(元素1 元素2 元素3 ...)
    # 用小括号初始化数组,元素之间用空格分隔。
    
    # 定义方法 1:初始化数组 array=(a b c)
    # 定义方法 2:新建数组并添加元素 array[下标]=元素
    # 定义方法 3:将命令输出作为数组元素 array=($(command))
    
    # 示例:
    IP=(10.0.0.1 10.0.0.2 10.0.0.3)
    for i in "${IP[@]}"; do
        echo $i
    done
    
3.6.1 定义一个 httpd 安装的函数 — 案例
  • 创建 apache 软件安装函数

    [root@web-server01~/script]# vim xx.sh
    #!/bin/bash
    # auto install apache
    # By author rivers 2021-09-27
    
    FILES=httpd-2.2.31.tar.bz2
    LES_DIR=httpd-2.2.31
    URL=http://mirrors.cnnic.cn/apache/httpd/
    PREFIX=/usr/local/apache2/
    
    function Apache_install() {
        # Install httpd web server
        if [[ "$1" -eq "1" ]]; then
            wget -c $URL/$FILES && tar -jxvf $FILES && cd $LES_DIR && ./configure
            if [ $? -eq 0 ]; then
                make && make install
                echo -e "\n\033[32m--------------------------------------------\033[0m"
                echo -e "\033[32mThe $LES_DIR Server Install Success !\033[0m"
            else
                echo -e "\033[31mThe $LES_DIR Make or Make install ERROR, Please Check......\033[0m"
                exit 0
            fi
        fi
    }
    Apache_install 1
    # 调用函数,传参为 1
    
3.6.2 遍历数组元素 — 案例
  • 遍历数组元素

    # 方法 1:
    #!/bin/bash
    IP=(10.0.0.1 10.0.0.2 10.0.0.3)
    for ((i = 0; i < ${#IP[*]}; i++)); do
        echo ${IP[$i]}
    done
    
    # 方法 2:
    #!/bin/bash
    IP=(10.0.0.1 10.0.0.2 10.0.0.3)
    for ip in "${IP[@]}"; do
        echo $ip
    done
    

四、Shell 编程实战案例

4.1 Shell 脚本实战之系统备份脚本 — 案例

  • Tar 工具全备、增量备份网站,Shell 脚本实现自动打包备份

    #!/bin/bash
    # Auto Backup Linux System Files
    # by author rivers on 2021-09-28
    
    SOURCE_DIR=("$@")
    TARGET_DIR=/data/backup/
    YEAR=$(date +%Y)
    MONTH=$(date +%m)
    DAY=$(date +%d)
    WEEK=$(date +%u)
    A_NAME=$(date +%H%M)
    FILES=system_backup.tgz
    CODE=$?
    
    if [ -z "$@" ]; then
        echo -e "\033[32mUsage:\nPlease Enter Your Backup Files or Directories\n--------------------------------------------\n\nUsage: { $0 /boot /etc}\033[0m"
        exit
    fi
    
    # Determine Whether the Target Directory Exists
    if [ ! -d $TARGET_DIR/$YEAR/$MONTH/$DAY ]; then
        mkdir -p $TARGET_DIR/$YEAR/$MONTH/$DAY
        echo -e "\033[32mThe $TARGET_DIR Created Successfully !\033[0m"
    fi
    
    # EXEC Full_Backup Function Command
    Full_Backup() {
        if [ "$WEEK" -eq "7" ]; then
            rm -rf $TARGET_DIR/snapshot
            cd $TARGET_DIR/$YEAR/$MONTH/$DAY && tar -g $TARGET_DIR/snapshot -czvf $FILES "${SOURCE_DIR[@]}"
            [ "$CODE" == "0" ] && echo -e "--------------------------------------------\n\033[32mThese Full_Backup System Files Backup Successfully !\033[0m"
        fi
    }
    
    # Perform incremental BACKUP Function Command
    Add_Backup() {
        if [ $WEEK -ne "7" ]; then
            cd $TARGET_DIR/$YEAR/$MONTH/$DAY && tar -g $TARGET_DIR/snapshot -czvf $A_NAME$FILES "${SOURCE_DIR[@]}"
            [ "$CODE" == "0" ] && echo -e "-----------------------------------------\n\033[32mThese Add_Backup System Files $TARGET_DIR/$YEAR/$MONTH/$DAY/${YEAR}_$A_NAME$FILES Backup Successfully !\033[0m"
        fi
    }
    
    sleep 3
    Full_Backup
    Add_Backup
    

4.2 Shell 脚本实战之收集系统信息 — 案例

  • Shell 脚本实现服务器信息自动收集

    cat <<EOF
    ++++++++++++++++++++++++++++++++++++++++++++++
    ++++++++Welcome to use system Collect+++++++++
    ++++++++++++++++++++++++++++++++++++++++++++++
    EOF
    
    ip_info=$(ifconfig | grep "Bcast" | tail -1 | awk '{print $2}' | cut -d: -f2)
    cpu_info1=$(cat /proc/cpuinfo | grep 'model name' | tail -1 | awk -F: '{print $2}' | sed 's/^ //g' | awk '{print $1, $3, $4, $NF}')
    cpu_info2=$(cat /proc/cpuinfo | grep "physical id" | sort | uniq -c | wc -l)
    serv_info=$(hostname | tail -1)
    disk_info=$(fdisk -l | grep "Disk" | grep -v "identifier" | awk '{print $2, $3, $4}' | sed 's/,//g')
    mem_info=$(free -m | grep "Mem" | awk '{print "Total", $1, $2"M"}')
    load_info=$(uptime | awk '{print "Current Load: "$(NF-2)}' | sed 's/\,//g')
    mark_info='BeiJing_IDC'
    
    echo -e "\033[32m-------------------------------------------\033[1m"
    echo IPADDR:$ip_info
    echo HOSTNAME:$serv_info
    echo CPU_INFO:${cpu_info1} X${cpu_info2}
    echo DISK_INFO:$disk_info
    echo MEM_INFO:$mem_info
    echo LOAD_INFO:$load_info
    echo -e "\033[32m-------------------------------------------\033[0m"
    
    echo -e -n "\033[36mYou want to write the data to the databases? \033[1m"
    read ensure
    
    if [ "$ensure" == "yes" -o "$ensure" == "y" -o "$ensure" == "Y" ]; then
        echo "--------------------------------------------"
        echo -e '\033[31mmysql -uaudit -p123456 -D audit -e "insert into audit_system values('','${ip_info}','$serv_info','${cpu_info1} X${cpu_info2}','$disk_info','$mem_info','$load_info','$mark_info')"\033[0m '
        mysql -uroot -p123456 -D test -e "insert into audit_system values('','${ip_info}','$serv_info','${cpu_info1} X${cpu_info2}','$disk_info','$mem_info','$load_info','$mark_info')"
    else
        echo "Please wait, exit......"
        exit
    fi
    

4.3 Shell 脚本实战之一键部署 LNMP 架构 — 案例

  • 批量部署 LNMP 架构

    [root@web-server01~/script]# vim lnmp.sh
    #!/bin/bash
    # install lnmp
    # by author rivers on 2021-9-28
    
    # Nginx 环境准备
    Nginx_url=https://nginx.org/download/nginx-1.20.1.tar.gz
    Nginx_prefix=/usr/local/nginx
    
    # MySQL 环境准备
    Mysql_version=mysql-5.5.20.tar.gz
    Mysql_dir=mysql-5.5.20
    Mysql_url=https://downloads.mysql.com/archives/get/p/23/file/mysql-5.5.20.tar.gz
    Mysql_prefix=/usr/local/mysql/
    
    # PHP 环境准备
    Php_version=php-7.2.10.tar.gz
    Php_prefix=/usr/local/php-7.2.10/
    
    function nginx_install() {
        if [[ "$1" -eq "1" ]]; then
            wget $Nginx_url && tar xf $Nginx_version && cd $Nginx_dir && ./configure --prefix=$Nginx_prefix
            if [ $? -eq 0 ]; then
                make && make install
                echo -e "\033[32mThe $Nginx_dir Server Install Success !\033[0m"
            else
                echo -e "\033[31mThe $Nginx_dir Make or Make install ERROR, Please Check......\033[0m"
                exit 0
            fi
        fi
    }
    
    function mysql_install() {
        if [[ "$1" -eq "2" ]]; then
            wget $Mysql_url && tar xf $Mysql_version && cd $Mysql_dir
            cmake . -DMYSQL_UNIX_ADDR=/tmp/mysql.sock \
                   -DMYSQL_DATADIR=/data/mysql \
                   -DSYSCONFDIR=/etc \
                   -DMYSQL_USER=mysql \
                   -DMYSQL_TCP_PORT=3306 \
                   -DWITH_XTRADB_STORAGE_ENGINE=1 \
                   -DWITH_INNOBASE_STORAGE_ENGINE=1 \
                   -DWITH_PARTITION_STORAGE_ENGINE=1 \
                   -DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
                   -DWITH_MYISAM_STORAGE_ENGINE=1 \
                   -DWITH_READLINE=1 \
                   -DENABLED_LOCAL_INFILE=1 \
                   -DWITH_EXTRA_CHARSETS=1 \
                   -DDEFAULT_CHARSET=utf8 \
                   -DDEFAULT_COLLATION=utf8_general_ci \
                   -DEXTRA_CHARSETS=all
            if [ $? -eq 0 ]; then
                make && make install
                echo -e "\033[32mThe $Mysql_dir Server Install Success !\033[0m"
            else
                echo -e "\033[31mThe $Mysql_dir Make or Make install ERROR, Please Check......\033[0m"
                exit 0
            fi
            /bin/cp support-files/my-small.cnf /etc/my.cnf
            /bin/cp support-files/mysql.server /etc/init.d/mysqld
            chmod +x /etc/init.d/mysqld
            chkconfig --add mysqld
            chkconfig mysqld on
        fi
    }
    
    function php_install() {
        if [[ "$1" -eq "3" ]]; then
            wget $Php_url && tar xf $Php_version && cd $Php_dir
            yum install libxml2* bzip2* libcurl* libjpeg* libpng* freetype* gmp* libmcrypt* readline* libxslt* -y
            ./configure --prefix=$Php_prefix --disable-fileinfo --enable-fpm --with-config-file-path=/etc --with-config-file-scan-dir=/etc/php.d --with-openssl --with-zlib --with-curl --enable-ftp --with-gd --with-xmlrpc --with-jpeg-dir --with-png-dir --with-freetype-dir --enable-gd-native-ttf --enable-mbstring --with-mcrypt=/usr/local/libmcrypt --enable-zip --enable-mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-mysql-sock=/var/lib/mysql/mysql.sock --without-pear --enable-bcmath
            if [ $? -eq 0 ]; then
                make ZEND_EXTRA_LIBS='-liconv' && make install
                echo -e "\033[32mThe $Php_version Server Install Success !\033[0m"
            else
                echo -e "\033[31mThe $Php_version Make or Make install ERROR, Please Check......\033[0m"
                exit 0
            fi
        fi
    }
    
    PS3="Please enter your select install menu:"
    select i in nginx mysql php quit; do
        case $i in
            nginx)
                nginx_install 1
                ;;
            mysql)
                mysql_install 2
                ;;
            php)
                php_install 3
                ;;
            quit)
                exit
                ;;
            *)
                echo "Invalid option, please try again."
                ;;
        esac
    done
    

总结

Shell 是工作中很重要的一部分,在企业生产环境中,服务器规模可能成百上千,如果依靠人工去维护和管理是非常吃力的。基于 Shell 编程脚本管理和维护服务器可以变得简单、从容,对企业自动化运维之路的建设起到极大的推动作用。

因此,无论是学习书籍、资料还是视频,每个老师讲的侧重点都不一样,但基础是一致的。要想学好 Shell,需要反复动手实践、思考并理解其精髓,才能真正掌握 Shell 编程。


服务器排障常用命令

宝山的博客 已于 2022-11-17 23:11:07 修改

1. ifconfig 命令

  • Linux ifconfig 命令用于显示或设置网络设备。
  • ifconfig 可设置网络设备的状态,或显示当前的设置。
# 1. ifconfig 查看 IP 地址(等同于 ip add 命令)
[root@rivers ~]# ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.10.103  netmask 255.255.255.0  broadcast 192.168.10.255
        inet6 fe80::313d:5ec5:2360:b413  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:73:a6:4f  txqueuelen 1000  (Ethernet)
        RX packets 72197  bytes 61229101 (58.3 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 50277  bytes 3210398 (3.0 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
  • 第一行

    • UP:标识网络接口为启用状态(down 为关闭状态)。
    • Broadcast:支持广播。
    • RUNNING:网卡设备已连接。
    • MULTICAST:支持组播。
    • MTU:数据最大传输单元。
  • 第二行:IP 地址、子网掩码、广播地址。

  • 第三行:IPv6 地址。

  • 第四行

    • Ethernet:表示连接类型为以太网。
    • ether:标识为 MAC 地址。
  • 第五行:接收数据包个数及大小统计信息。

  • 第六行:异常接收包的个数(如丢包、错误等)。

  • 第七行:发送数据包个数及大小统计信息。

  • 第八行:发送数据包的个数(如丢包量、错误等)。

# 打开(up)或关闭(down)适配器
ifconfig <网络名> <up|down>
[root@rivers ~]# ifconfig ens33 up
[root@rivers ~]# ifconfig ens33 down
# 为适配器分配 IP 地址(重启后失效)
ifconfig <网络名> <ip地址>
[root@rivers ~]# ifconfig ens33 192.168.10.103
# 为适配器分配第二个 IP 地址
ifconfig <网络名:实例数> <ip地址>

2. ping 命令

Linux ping 命令用于检测主机。

执行 ping 指令会使用 ICMP 传输协议,发出要求回应的信息。若远端主机的网络功能正常,就会回应该信息,从而得知该主机运行正常。

# Linux 命令参数
ping [-dfnqrRv][-c<完成次数>][-i<间隔秒数>][-I<网络界面>][-l<前置载入>][-p<范本样式>][-s<数据包大小>][-t<存活数值>][主机名称或 IP 地址]
# Windows 命令参数:
ping (ip地址或主机名) (-t) (-a) (-n count) (-l size)
    -t:不停地向目标主机发送数据;
    -a:以 IP 地址格式显示目标主机的网络地址;
    -n count:指定要 ping 的次数,具体次数由 count 指定;
    -l size:指定发送到目标主机的数据包大小。
# 示例:ping 指定主机
[root@rivers ~]# ping www.baidu.com -c 1
PING www.a.shifen.com (39.156.66.14) 56(84) bytes of data.
64 bytes from 39.156.66.14 (39.156.66.14): icmp_seq=1 ttl=128 time=5.28 ms
# 使用特定网络接口发送 ping 请求
[root@rivers ~]# ping www.baidu.com -c 2 -I ens33 -s 100
PING www.a.shifen.com (39.156.66.14) from 192.168.10.103 ens33: 100(128) bytes of data.
108 bytes from 39.156.66.14 (39.156.66.14): icmp_seq=1 ttl=128 time=5.84 ms
108 bytes from 39.156.66.14 (39.156.66.14): icmp_seq=2 ttl=128 time=6.57 ms
# 每隔 3 秒发送一个 1000 字节的 ping 包,共发送 1000 个
[root@rivers ~]# ping -i 3 -s 1000 -c 1000 www.baidu.com
PING www.a.shifen.com (110.242.68.3) 100(128) bytes of data.
108 bytes from 110.242.68.3 (110.242.68.3): icmp_seq=1 ttl=128 time=11.1 ms
108 bytes from 110.242.68.3 (110.242.68.3): icmp_seq=2 ttl=128 time=28.8 ms
……

3. arp 命令

  • arp 命令的英文全拼为 “Address Resolution Protocol”,用于操作主机的 ARP 缓存。
  • 它可以显示 ARP 缓存中的所有条目、删除指定条目或添加静态的 IP 地址与 MAC 地址对应关系。
  • 常用参数:
    • -n:以数字方式显示。
    • -i:指定网络接口。
    • -d:删除 ARP 记录。
# 显示本机 ARP 缓存中的所有记录
[root@rivers ~]# arp
Address                  HWtype  HWaddress           Flags Mask           Iface
gateway                  ether   00:50:56:ff:3a:57     C                 ens33
192.168.10.1               ether   00:50:56:c0:00:08     C                 ens33
# 以数字方式显示指定主机的 ARP 缓存条目
[root@rivers ~]# arp -n
Address                  HWtype  HWaddress           Flags Mask           Iface
192.168.10.2               ether   00:50:56:ff:3a:57      C                ens33
192.168.10.1               ether   00:50:56:c0:00:08      C                 ens33
# 删除接口 ens33 上的 192.168.10.2 的 ARP 表项
[root@rivers ~]# arp -i ens33 -d 192.168.10.2
# 使用 ens33 的 MAC 地址回答 eth0 上的 192.168.10.2 的 ARP 请求
[root@rivers ~]# arp -i ens33 -Ds 192.168.10.2 ens33 pub

4. arping 命令

  • arping 命令基于 ARP 数据包,通过类似 ping 的方式测试网络。
  • 它可以检测一个 IP 地址是否已被使用,并获取更多设备信息。功能类似于 ping
  • 由于 arping 基于 ARP 广播机制,因此只能测试同一网段或子网的网络主机连通性。
  • ping 命令基于 ICMP 协议,可以测试任意网段的主机网络连通性。
  • 常用参数:
    • -D:重复地址检测模式。
    • -A:更新邻近主机的 ARP 缓存。
    • -c:指定发送 ARP 请求的个数。
    • -l:指定 ARP 请求报文的网络接口。
    • -s:指定发送 ARP 请求数据包的源地址。
    • -U:更新邻近主机的 ARP 缓存。
# 测试目标主机的存活状态
[root@rivers ~]# arping -f 192.168.10.1
ARPING 192.168.10.1 from 192.168.10.102 ens33
Unicast reply from 192.168.10.1 [00:50:56:C0:00:08]  0.689ms
Sent 1 probes (1 broadcast(s))
Received 1 response(s)
# 向目标主机发送 3 次 ARP 请求报文
[root@rivers ~]# arping -c 3 192.168.10.1
ARPING 192.168.10.1 from 192.168.10.102 ens33
Unicast reply from 192.168.10.1 [00:50:56:C0:00:08]  0.769ms
Unicast reply from 192.168.10.1 [00:50:56:C0:00:08]  0.648ms
Unicast reply from 192.168.10.1 [00:50:56:C0:00:08]  0.675ms
Sent 3 probes (1 broadcast(s))
Received 3 response(s)

5. telnet 命令

  • telnet 命令用于控制远程设备。
  • 它可以帮助用户从本地设备远程登录到开启了 telnet 服务的设备(如路由器、交换机、Linux 服务器等)。
  • 常用参数:
    • -d:启动排错模式。
    • -l:指定登录用户名。
    • -a:尝试自动登录远端系统。
# 指定登录端口
[root@rivers ~]# telnet 192.168.10.2 19880
Trying 192.168.10.2...
# 指定登录用户名
[root@rivers ~]# telnet -l admin 192.168.10.2

7. SSH 命令

  • ssh 命令用于安全的远程连接服务器主机系统。
  • 它是 OpenSSH 套件中的客户端工具,基于 SSH 加密协议进行远程主机访问,从而实现对远程服务器的管理工作。
  • 常用参数:
    • -1/2:强制使用 SSH 协议 V1/V2 版本。
    • -4/6:强制使用 IPv4/IPv6 地址。
    • -A:开启认证代理连接转发功能。
    • -a:关闭认证代理连接转发功能。
    • -l:指定连接远程服务器的登录用户名。
    • -p:指定远程服务器上的端口。
# 使用指定的用户身份登录远程服务器主机系统
[root@rivers ~]# ssh -l linuxprobe 192.168.10.2
# 登录远程服务器主机系统后执行一条命令
[root@rivers ~]# ssh 192.168.10.2 "free -m"
# 强制使用 v1 版本的 SSH 加密协议连接远程服务器主机
[root@rivers ~]# ssh -1 192.168.10.2

8. route 相关命令

  • route 命令用于显示与设置路由信息,是 Linux 系统中常用的静态路由配置工具。
  • 它可以为不同子网之间的服务器配置路由信息,提供网络连接的支撑。
  • 常用参数:
    • -A:设置地址类型(默认为 IPv4)。
    • -n:以数字形式显示 IP 地址。
    • -net:指定网络。
    • -host:指定主机。
    • add:增加指定的路由记录。
    • del:删除指定的路由记录。
    • gw:设置默认网关。
    • dev:指定路由记录所表示的网络接口。
# 显示当前路由
[root@localhost ~]# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.10.0    0.0.0.0         255.255.255.0   U     100    0        0 ens160
192.168.122.0   0.0.0.0         255.255.255.0   U     0      0        0 virbr0
# 添加一条指定的路由信息
[root@localhost ~]# route add -net 192.168.10.0 netmask 255.255.255.0 dev ens160
# 删除一条网络路由
[root@localhost ~]# route del -net 192.168.10.0 netmask 255.255.255.0 dev ens160
# 增加/删除默认网关
route add/del default gw 192.168.10.1
# 获取 192.168.10.2 的路由
[root@rivers ~]# ip route get 192.168.10.2
192.168.10.2 dev ens33 src 192.168.10.102 
    cache 
# 查看路由信息
[root@rivers ~]# ip route show
default via 192.168.10.2 dev ens33 proto static metric 100 
192.168.10.0/24 dev ens33 proto kernel scope link src 192.168.10.102 metric 100 
# 设置永久路由的方法
# 在 /etc/rc.local 中添加

9. traceroute 命令

  • traceroute 命令用于追踪数据包在网络上的传输路径。
  • 它默认发送的数据包大小为 40 字节,通过测量每次跳转的时间(ms)来确定路径。
  • 常用参数:
    • -n:不显示主机名。
    • -m:设置跳数(最大存活数值 TTL 的大小)。
    • -q:设置检测包的数量。
    • -f:设置第一个检测数据包的存活数值 TTL 的大小。
# 追踪本地数据包到 www.baidu.com 的传输路径
[root@rivers ~]# traceroute www.baidu.com
# 显示 IP 地址,不解析主机名
[root@rivers ~]# traceroute www.baidu.com -n -m 1
traceroute to www.baidu.com (39.156.66.14), 1 hops max, 60 byte packets
 1  192.168.10.2  0.088 ms  0.053 ms  0.044 ms
# 把探测包的个数设置为 100
[root@rivers ~]# traceroute www.baidu.com -q 100
# 跳数设置为 2
[root@rivers ~]# traceroute www.baidu.com -m 2
traceroute to www.baidu.com (39.156.66.14), 2 hops max, 60 byte packets
 1  gateway (192.168.10.2)  0.109 ms  0.044 ms  0.040 ms
 2  * * *
# 把对外发探测包的等待响应时间设置为 3 秒
[root@rivers ~]# traceroute www.baidu.com -q 10 -m 1 -w 3
traceroute to www.baidu.com (39.156.66.18), 1 hops max, 60 byte packets
 1  gateway (192.168.10.2)  0.094 ms  0.091 ms  0.043 ms  0.080 ms  0.040 ms  0.084 ms  0.041 ms  0.040 ms  0.051 ms  0.057 ms

10. tcpdump 命令

  • tcpdump 命令用于监听网络流量,是一款数据嗅探工具。
  • 它能够记录所有经过服务器的数据包信息,需要使用管理员身份执行。
  • 常用参数:
    • -A:以 ASCII 格式打印所有分组,并最小化链路层头部。
    • -c:在收到指定数量的分组后停止。
    • -C:在将一个原始分组写入文件之前,检查文件当前大小是否超过指定大小(单位为 MB)。
    • -d:将匹配信息包的代码以汇编格式给出。
    • -dd:将匹配信息包的代码以 C 语言程序段格式给出。
    • -ddd:将匹配信息包的代码以十进制形式给出。
    • -D:打印系统中所有可用于 tcpdump 截包的网络接口。
    • -e:在输出中打印数据链路层头部信息。
    • -E:解密 IPsec ESP 分组。
    • -f:将外部 Internet 地址以数字形式打印。
    • -F:从指定文件中读取表达式,忽略命令行中给出的表达式。
    • -i:指定监听的网络接口。
    • -l:使标准输出变为缓冲行形式。
    • -L:列出网络接口的已知数据链路。
    • -m:导入 SMI MIB 模块定义。
    • -M:验证 TCP-MD5 选项摘要。
    • -n:不将网络地址转换为名字。
    • -N:不输出主机名中的域名部分。
    • -t:不在每一行中输出时间戳。
    • -O:不运行分组匹配代码优化程序。
    • -P:不将网络接口设置为混杂模式。
    • -q:快速输出,只显示较少的协议信息。
    • -r:从指定文件中读取包。
    • -S:以绝对值形式输出 TCP 序列号。
    • -s:从每个分组中读取指定数量的字节。
    • -T:将监听到的包直接解释为指定类型的报文。
    • -u:输出未解码的 NFS 句柄。
    • -v:输出稍微详细的信息。
    • -vv:输出详细报文信息。
    • -w:直接将分组写入文件,而不是分析并打印出来。
    • -x:以 16 进制形式显示报文(去掉链路层报头)。
    • -xx:以 16 进制形式显示报文(包含链路层报头)。
    • -y:设置 tcpdump 捕获的数据链路层协议类型。
    • -Z:放弃超级用户权限,并将当前 tcpdump 的用户 ID 设置为指定用户。
# 01. 抓取所有网络包,并在终端中显示抓取结果(以 16 进制形式显示)
tcpdump
# 02. 抓取所有网络包,并存入 result.cap 文件中
tcpdump -w result.cap
# 03. 抓取经过 eth0 网卡的所有网络包,并存入 result.cap 文件中
tcpdump -i eth0 -w result.cap
# 04. 抓取源地址为 192.168.1.100 的包,并存入 result.cap 文件中
tcpdump src host 192.168.1.100 -w result.cap
# 05. 抓取地址包含 192.168.1.100 的包,并存入 result.cap 文件中
tcpdump host 192.168.1.100 -w result.cap
# 06. 抓取目的地址为 192.168.1.100 的包,并存入 result.cap 文件中
tcpdump dest host 192.168.1.100 -w result.cap
# 07. 抓取主机地址为 192.168.1.100 的数据包
tcpdump -i eth0 -vnn host 192.168.1.100
# 08. 抓取包含 192.168.1.0/24 网段的数据包
tcpdump -i eth0 -vnn net 192.168.1.0/24
# 09. 抓取网卡 eth0 上所有包含端口 22 的数据包
tcpdump -i eth0 -vnn port 22
# 10. 抓取指定协议格式的数据包(如 udp、icmp、arp、ip)
tcpdump udp -i eth0 -vnn
# 11. 抓取经过 eth0 网卡的源 IP 为 192.168.1.100 的数据包
tcpdump -i eth0 -vnn src host 192.168.1.100
# 12. 抓取经过 eth0 网卡目的 IP 为 192.168.1.100 的数据包
tcpdump -i eth0 -vnn dst host 192.168.1.100
# 13. 抓取源端口为 22 的数据包
tcpdump -i eth0 -vnn src port 22
# 14. 抓取源 IP 为 192.168.1.100 且目的端口为 22 的数据包
tcpdump -i eth0 -vnn src host 192.168.1.100 and dst port 22
# 15. 抓取源 IP 为 192.168.1.100 或包含端口为 22 的数据包
tcpdump -i eth0 -vnn src host 192.168.1.100 or port 22
# 16. 抓取源 IP 为 192.168.1.100 且端口不是 22 的数据包
tcpdump -i eth0 -vnn src host 192.168.1.100 and not port 22
# 17. 抓取源 IP 为 192.168.1.100 且目的端口为 22,或源 IP 为 192.168.1.102 且目的端口为 80 的数据包
tcpdump -i eth0 -vnn (src host 192.168.1.100 and dst port 22) or (src host 192.168.1.102 and dst port 80)
# 18. 把抓取的数据包记录存入 /tmp/result 文件中,当抓取 100 个数据包后退出
tcpdump -i eth0 -vnn -w /tmp/result -c 100
# 19. 从 /tmp/result 记录中读取 TCP 协议的数据包
tcpdump -i eth0 tcp -vnn -r /tmp/result
# 20. 抓取主机 192.168.1.100 的所有通信数据包
tcpdump host 192.168.1.100
# 21. 抓取主机 192.168.1.100 与主机 192.168.1.101 之间的通信数据包
tcpdump ip host 192.168.1.100 and ! 192.168.1.101
# 22. 抓取主机 192.168.1.100 的 telnet 数据包
tcpdump tcp port 23 host 192.168.1.100
# 查看 HTTP 请求的 header
tcpdump -s 1024 -l -A -n host 192.168.9.56
tcpdump -s 1024 -l -A src 192.168.9.56 or dst 192.168.9.56
sudo tcpdump -A -s 1492 dst port 80
# 查看本地网络中 IP 地址为 192.168.0.5 的主机与外界通信的情况
sudo tcpdump -i eth0 src host 192.168.0.5
# 查看网卡 eth0 的 HTTP 请求的 TCP 包
tcpdump -i eth0 port http
tcpdump -i eth0 port http or port smtp or port imap or port pop3 -l -A | egrep -i 'pass=|pwd=|log=|login=|user=|username=|pw=|passw=|passwd=|password=|pass:|user:|username:|password:|login:|pass |user '
# 查看 TCP、UDP、ICMP(非 SSH)的包
tcpdump -n -v tcp or udp or icmp and not port 22
# 查看 HTTP 请求的 request 包
sudo tcpdump -i eth0 port 80 -w -
# 过滤 HTTP 响应的 GET 和 Host 头信息
sudo tcpdump -i en1 -n -s 0 -w - | grep -a -o -E "GET \/.*|Host\: .*"
# DNS 查询请求响应包
sudo tcpdump -i en0 'udp port 53'

11. dig 命令

  • dig 命令的全称是 “domain information groper”,用于灵活查询 DNS 信息。
  • 它会打印出 DNS 域名服务器的回应,主要用来从 DNS 域名服务器查询主机地址信息。
  • dig 命令与 nslookup 命令功能基本相同,但 dig 更灵活、易用且输出清晰。
  • 常用参数:
    • @:指定进行域名解析的域名服务器。
    • -b:使用指定的本机 IP 地址向域名服务器发送请求。
    • -x:执行逆向域名查询。
    • -t:指定要查询的 DNS 数据类型(默认为 A)。
    • -p:指定域名服务器使用的端口号。
    • -4:使用 IPv4(默认)。
    • -6:使用 IPv6。
    • -h:显示命令帮助信息。
# 查询域名对应的 IP 地址
[root@rivers ~]# dig www.baidu.com
# 对目标 IP 进行反向解析查询
[root@rivers ~]# dig -x 114.114.114.114
# 查询目标域名的 MX 记录
[root@rivers ~]# dig -t MX www.baidu.com

12. iftop 命令

  • iftop 是一款实时流量监控工具,用于监控 TCP/IP 连接。
  • 缺点是没有报表功能。
  • 必须以 root 身份运行。
  • 常用参数:
    • -i:指定要监控的网卡。
    • -n:直接显示 IP,不进行 DNS 反解析。
# 默认监控第一块网卡的流量
[root@rivers ~]# iftop
# 监控 ens33 网卡的流量
[root@rivers ~]# iftop -i ens33
# 直接显示 IP,不进行 DNS 反解析
[root@rivers ~]# iftop -n

13. nload 命令

  • nload 默认会分页展示各个网卡的实时流量信息。
  • 可以通过按键盘上的 ← → 或 Enter/Tab 键在网卡之间切换。
  • 常用参数:
    • -a:全部数据的刷新时间周期(单位为秒,默认为 300s)。
    • -i:进入网卡流量图的显示比例最大值设置(默认为 10240 kBit/s)。
    • -m:不显示流量图,只显示统计数据。
    • -o:出去网卡流量图的显示比例最大值设置(默认为 10240 kBit/s)。
    • -t:显示数据的刷新时间间隔(单位为毫秒,默认为 500ms)。
    • -u:设置右边 Curr、Avg、Min、Max 的数据单位(默认为自动变更,注意大小写)。
# 以自动变更单位显示流量信息
nload -u h  # 自动变更单位,单位为 Bit/s
nload -u H  # 自动变更单位,单位为 Byte/s
# 不显示流量图
nload -m
nload -m -H ens33  # 不显示流量图,以 Byte 为单位查看 ens33 网卡流量情况
# 设置显示数据的刷新时间间隔为 1000ms
nload -t 1000

14. nmap 命令

  • nmap(“Network Mapper”)是一款开放源代码的网络探测和安全审核工具。
  • 它可以快速扫描大型网络,也可以用于扫描单个主机。
  • nmap 使用原始 IP 报文来发现网络上的主机、服务、操作系统、防火墙等信息。
  • 常用参数:
    • --traceroute:扫描主机端口并跟踪路由。
    • -p:扫描指定端口或端口范围。
    • -sP:对目标主机进行 ping 扫描。
    • -sV:探测服务版本信息。
# 检查 nmap 是否已安装
[root@rivers ~]# nmap -p 4430 www.baidu.com
-bash: nmap: command not found
# 安装 nmap
[root@rivers ~]# yum -y provides nmap
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirrors.aliyun.com
 * extras: mirrors.aliyun.com
 * updates: mirrors.aliyun.com
2:nmap-6.40-19.el7.x86_64 : Network exploration tool and security
                          : scanner
Repo        : base
# 扫描主机并跟踪路由
[root@rivers ~]# nmap --traceroute www.baidu.com
Starting Nmap 6.40 ( http://nmap.org  ) at 2022-11-16 06:18 CST
Stats: 0:00:42 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan
# 使用 -p 参数探测 80 和 443 端口
[root@rivers ~]# nmap -p80,443 www.baidu.com
# 探测服务器的 1-10000 端口范围
[root@rivers ~]# nmap -p1-10000 www.baidu.com
# 使用 -A 参数进行高级扫描
[root@rivers ~]# nmap -A www.baidu.com

15. uptime 命令

  • uptime 命令用于显示系统已运行的时间。
  • 它还会显示当前登录用户数以及系统在过去 1 分钟、5 分钟和 15 分钟内的平均负载。
  • 常用参数:
    • -p:以漂亮格式显示系统运行时间。
    • -s:显示系统开始运行的时间(格式为 yyyy-mm-dd hh:mm:ss)。
    • -h:显示帮助信息。
# 以漂亮格式显示系统运行时间
[root@rivers ~]# uptime -p
up 2 days, 4 hours, 36 minutes
# 显示帮助信息
[root@rivers ~]# uptime -h
Usage:
 uptime [options]

Options:
 -p, --pretty   show uptime in pretty format
 -h, --help     display this help and exit
 -s, --since    system up since
 -V, --version  output version information and exit

For more details see uptime(1).
# 显示系统开始运行的时间
[root@rivers ~]# uptime -s
2022-11-15 01:33:07

16. netstat 命令

  • netstat 命令用于显示各种网络相关信息,如网络连接状态、路由表信息、接口状态等。
  • 它不仅应用于 Linux 系统,Windows 系统也支持该命令。
  • 常用参数:
    • -a:显示所有连接中的 Socket。
    • -p:显示正在使用 Socket 的程序识别码和程序名称。
    • -l:仅列出在监听的服务状态。
    • -t:显示 TCP 传输协议的连接状态。
    • -u:显示 UDP 传输协议的连接状态。
    • -i:显示网卡信息。
    • -r:显示路由表信息。
    • -n:直接使用 IP 地址,不通过域名服务器。
# 显示系统网络状态中的所有连接信息
[root@rivers ~]# netstat -a
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:ssh             0.0.0.0:*               LISTEN   
# 显示系统网络状态中的 UDP 连接信息
[root@rivers ~]# netstat -nu
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
udp        0      0 172.19.226.238:68       172.19.239.253:67       ESTABLISHED    
# 显示系统网络状态中的 UDP 连接端口号使用信息
[root@rivers ~]# netstat -apu
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address    Foreign Address       State    PID/Program name    
udp        0      0 linuxcool:bootpc _gateway:bootps  ESTABLISHED   1024/NetworkManager 
udp        0      0 localhost:323           0.0.0.0:*               875/chronyd      
# 显示网卡当前状态信息
[root@rivers ~]# netstat -i 
Kernel Interface table
Iface             MTU    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg
ens33            1500    74054      0      0 0         34905      0      0      0 BMRU
lo              65536      851      0      0 0           851      0      0      0 LRU
# 显示网络路由表状态信息
[root@rivers ~]# netstat -r
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
default         gateway         0.0.0.0         UG        0 0          0 ens33
192.168.10.0    0.0.0.0         255.255.255.0   U         0 0          0 ens33
# 找到某个服务所对应的连接信息
[root@rivers ~]# netstat -lantup | grep sshd
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      9388/sshd           
tcp        0     36 192.168.10.102:22       192.168.10.1:62844      ESTABLISHED 12028/sshd: root@pt 
tcp6       0      0 :::22                   :::*                    LISTEN      9388/sshd           

17. nmtui 命令

  • nmtui 提供了一个基于文本的图形界面,用于编辑连接、激活连接和设置主机名。
  • 常用功能:
    • Edit a connection:编辑连接。
    • Activate a connection:激活连接。
    • Set system hostname:设置主机名。
# 查看 nmtui 是否已安装
[root@rivers ~]# yum provides nmtui
Loaded plugins: fastestmirror
Determining fastest mirrors
 * base: mirrors.aliyun.com
 * extras: mirrors.aliyun.com
 * updates: mirrors.aliyun.com
updates/7/x86_64/filelists_db  |  10 MB     00:00     
1:NetworkManager-tui-1.18.8-1.el7.x86_64 :
     ...: NetworkManager curses-based UI
# 安装 nmtui 软件
yum install NetworkManager-tui
# 进入图形界面
nmtui

Edit a connection      # 编辑连接
Activate a connection  # 激活连接
Set system hostname    # 设置主机名
# 修改完成后需要手动重启相应的服务

# 重载网卡
[root@rivers ~]# nmcli connection reload ens33
# 启动网卡
[root@rivers ~]# nmcli con up ens33

19. nmcli 命令

  • nmcli 是 “NetworkManager command-line” 的缩写,用于基于命令行配置网卡参数。
  • 它与 nmtui 命令工具配置的参数会直接写入网卡服务配置文件中,永久生效。
  • 常用参数:
    • -c:监控和管理网络设备的连接。
    • -d:监控和管理网络设备的接口。

nmcli 查看命令

# 查看所有网络连接
[root@rivers ~]# nmcli connection show
NAME   UUID                                  TYPE      DEVICE 
ens33  c96bc909-188e-ec64-3a96-6a90982b08ad  ethernet  ens33  
# 查看活动的网络连接
[root@rivers ~]# nmcli connection show -active
NAME   UUID                                  TYPE      DEVICE 
ens33  c96bc909-188e-ec64-3a96-6a90982b08ad  ethernet  ens33  
# 查看网卡地址信息
[root@rivers ~]# nmcli device show ens33 | grep "ADDRESS"
IP4.ADDRESS[1]:                         192.168.10.102/24
IP6.ADDRESS[1]:                         fe80::313d:5ec5:2360:b413/64
# 查看指定网卡的详细信息
[root@rivers ~]# nmcli con show ens33
connection.id:                          ens33
connection.uuid:                        c96bc909-188e-ec64-3a96-6a90982b08
connection.stable-id:                   --
connection.type:                        802-3-ethernet
connection.interface-name:              ens33
connection.autoconnect:                 yes
# 显示指定网络设备的详细信息
[root@rivers ~]# nmcli device show
GENERAL.DEVICE:                         ens33
GENERAL.TYPE:                           ethernet
GENERAL.HWADDR:                         00:0C:29:1A:8B:6F
GENERAL.MTU:                            1500

网络管理

# 查看网络状态
[root@rivers ~]# nmcli networking
enabled
# 启用网络
[root@rivers ~]# nmcli networking on
# 关闭网络
[root@rivers ~]# nmcli networking off
# 启用网络连接
[root@rivers ~]# nmcli connection up ens33
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)
# 停用网络连接(可以被自动激活)
[root@rivers ~]# nmcli con down ens33
# 禁用网卡,防止自动被激活
[root@rivers ~]# nmcli device disconnect ens33
# 删除网络连接的配置文件
[root@rivers ~]# nmcli con delete ens33
# 重新加载网络配置文件
[root@rivers ~]# nmcli connection reload ens33

新增网卡配置文件

# 动态获取 IP 的网络连接配置
nmcli con add con-name dynamic ifname ens36 type ethernet
# 启用动态配置文件
nmcli con up dynamic

修改配置文件

# 修改连接配置
nmcli connection modify Con-Name [+|-]setting.property value
  • 设置网卡自启动(实际修改的是网卡配置文件中的 ONBOOT=yes):

    nmcli con mod CON-NAME connection.autoconnect yes
    
  • 修改 IP 获取方式(静态:manual,动态:auto):

    nmcli con mod CON-NAME ipv4.method manual|static
    nmcli con mod CON-NAME ipv4.method auto
    
  • 修改 IP 配置及网关

    nmcli con mod CON-NAME ipv4.addresses "10.10.10.10/24 10.10.10.1"
    
  • 修改默认网关

    nmcli con mod CON-NAME ipv4.gateway 10.10.10.1
    
  • 添加第二个 IP 地址

    nmcli con mod CON-NAME +ipv4.addresses 10.10.10.10/16
    
  • 删除第二个 IP 地址

    nmcli con mod CON-NAME -ipv4.addresses 10.10.10.10/16
    
  • 添加 DNS1

    nmcli con mod CON-NAME ipv4.dns 114.114.114.114
    
  • 添加 DNS2

    nmcli con mod CON-NAME +ipv4.dns 8.8.8.8
    

配置文件参数

  • IP 获取方式

    ipv4.method manual|static   # BOOTPROTO=none
    ipv4.method auto            # BOOTPROTO=dhcp
    
  • 连接名称

    connection.id eth0          # NAME=eth0
    
  • IP 地址信息

    ipv4.addresses
    "192.0.2.1/24               # IPADDR0=192.0.2.1 PREFIX0=24
    192.0.2.254"                # GATEWAY0=192.0.2.254
    
  • DNS

    ipv4.dns 8.8.8.8            # DNS0=8.8.8.8
    
  • DNS 搜索域

    ipv4.dns-search example.com # DOMAIN=example.com
    ipv4.ignore-auto-dns true   # PEERDNS=no
    connection.autoconnect yes  # ONBOOT=yes
    connection.interface-name eth0 # DEVICE=eth0
    802-3-ethernet.mac-address... # HWADDR=...
    

20. ethtool 命令

  • ethtool 命令用于显示某个网络适配器的驱动信息。
  • 它适用于查询软件兼容性的情况。
  • ethtool 命令用于查询网口基本设置及设置网卡参数。
  • 常用参数:
    • -i:显示网卡驱动的信息。
    • -E:修改网卡只读存储器字节。
    • -K:修改网卡 Offload 的状态。
    • -s:修改网卡的部分配置。
    • -t:让网卡执行自我检测。
# 显示网卡驱动信息
ethtool -i eth0
# 显示网络数据
ethtool -S eth0
# 设置适配器连接速度(Mbps)
ethtool speed <10|100|1000>
# 设置网口工作方式
ethtool -s eth0 autoneg off speed 100 duplex full

使用 Shell 创建文本菜单和窗口部件

诗翔 发表于 2017-11-29

创建文本菜单

创建交互式 Shell 脚本最常用的方法是使用菜单,它提供了各种选项,帮助脚本用户了解脚本的功能。

Shell 脚本菜单的核心是 case 命令,该命令会根据用户在菜单上的选择来执行特定命令。

以下是创建基于菜单的 Shell 脚本的步骤:

创建菜单布局

第一步:决定在菜单上显示哪些元素以及布局方式。

在创建菜单前,通常先清空显示器上的内容,以便在干净的环境中显示菜单。

clear
echo
echo -e "\t\t\tSys Admin Menu\n"
echo -e "\t1. Display disk space"
echo -e "\t2. Display logged on users"
echo -e "\t3. Display memory usage"
echo -e "\t0. Exit menu\n\n"
echo -en "\t\tEnter an option: "

最后一行的 -en 选项去掉末尾换行符,使菜单更专业,光标会在行尾等待用户输入。

创建菜单的最后一步是获取用户输入。这一步用 read 命令。因为只期望用户输入单字符,所以加入 -n 选项进行限定。这样用户只需输入一个数字,无需按回车键。

read -n 1 option

创建菜单函数

Shell 脚本菜单选项作为一组独立的函数实现起来更为容易。要做到这一点,需要为每个菜单项创建独立的 Shell 函数。

第一步:决定希望脚本执行哪些功能,然后将这些功能以函数的形式放在代码中。

通常会为还没有实现的函数先创建一个“桩函数”,它是一个空函数,或者只有一个 echo 语句,说明最终这里需要什么内容。

function diskspace {
  clear
  echo "This is where the diskspace commands will go"
}

这允许菜单在实现某个函数之前仍然能正常操作。不需要写出所有函数之后才能让菜单投入使用。

另外,将菜单布局本身作为一个函数来创建有利于菜单制作。

function menu {
  clear
  echo
  echo -e "\t\t\tSys Admin Menu\n"
  echo -e "\t1. Display disk space"
  echo -e "\t2. Display logged on users"
  echo -e "\t3. Display memory usage"
  echo -e "\t0. Exit menu\n\n"
  echo -en "\t\tEnter an option: "
  read -n 1 option
}

这样可以在任何时候调用该函数以重现菜单。

添加菜单逻辑

下一步需要创建程序逻辑,将菜单布局和函数结合起来。这需要使用 case 命令。

case 命令应该根据菜单中输入的字符来调用相应的函数,用 case 命令的星号模式来处理所有不正确的菜单项。

以下是典型菜单的 case 用法:

menu
case $option in
0)
  break ;;
1)
  diskspace ;;
2)
  whoseon ;;
3)
  memusage ;;
*)
  clear
  echo "Sorry, wrong selection";;
esac

这里首先调用 menu 函数清空屏幕并显示菜单。menu 函数中的 read 命令会一直等待,直到用户在键盘上键入一个字符。然后 case 命令会接管余下的处理过程,基于字符调用相应的函数。

整合 Shell 脚本菜单

现在将前面的步骤全部组合起来,看看它们是如何协作的。

这是一个完整的菜单脚本示例:

#!/bin/bash
# Simple script menu

function diskspace {
  clear
  df -k
}

function whoseon {
  clear
  who
}

function memusage {
  clear
  cat /proc/meminfo
}

function menu {
  clear
  echo
  echo -e "\t\t\tSys Admin Menu\n"
  echo -e "\t1. Display disk space"
  echo -e "\t2. Display logged on users"
  echo -e "\t3. Display memory usage"
  echo -e "\t0. Exit menu\n\n"
  echo -en "\t\tEnter an option: "
  read -n 1 option
}

while [ 1 ]
do
  menu
  case $option in
    0)
      break ;;
    1)
      diskspace ;;
    2)
      whoseon ;;
    3)
      memusage ;;
    *)
      clear
      echo "Sorry, wrong selection" ;;
  esac
  echo -en "\n\n\t\t\tHit any key to continue"
  read -n 1 line
done
clear

使用示例:

            Sys Admin Menu

    1. Display disk space
    2. Display logged on users
    3. Display memory usage
    0. Exit menu

        Enter an option:

输入 1

Filesystem           1K-blocks      Used Available Use% Mounted on
udev             4006080         0   4006080   0% /dev
tmpfs             807220     81004    726216  11% /run
/dev/sda4      305650672 14226064 275828680    5% /
tmpfs            4036100      1724   4034376   1% /dev/shm
tmpfs               5120         4      5116   1% /run/lock
tmpfs            4036100         0   4036100   0% /sys/fs/cgroup
/dev/sda3         524272      4684    519588   1% /boot/efi
tmpfs             807220        52    807168   1% /run/user/1000
tmpfs             807220        16    807204   1% /run/user/125
/dev/sda2      421886972 23340376 398546596    6% /media/wsx/存储

            Hit any key to continue

其他选项可以自行测试。

使用 select 命令

select 命令只需要一条命令就可以创建出菜单,然后获取输入的答案并自动处理。

命令格式如下:

select variable in list
do
  commands
done

list 参数是由空格分隔的文本选项列表,这些列表构成了整个菜单。 select 命令会将每个列表项显示成一个带编号的选项,然后为选项显示一个由 PS3 环境变量定义的特殊提示符。

#!/bin/bash
# Using select in the menu

function diskspace {
  clear
  df -k
}

function whoseon {
  clear
  who
}

function memusage {
  clear
  cat /proc/meminfo
}

PS3="Enter an option: "
select option in "Display disk space" "Display logged on users" "Display memory usage" "Exit program"
do
  case $option in
    "Exit program")
      break ;;
    "Display disk space")
      diskspace ;;
    "Display logged on users")
      whoseon ;;
    "Display memory usage")
      memusage ;;
    *)
      clear
      echo "Sorry, wrong selection";;
  esac
done
clear

运行会自动生成如下菜单项:

1) Display disk space            3) Display memory usage
2) Display logged on users       4) Exit program
Enter an option:

在使用 select 命令时,存储在变量中的结果值是整个文本字符串而不是与菜单项相关联的数字。文本字符串是要在 case 语句中比较的内容。

制作窗口

dialog 包能够用 ANSI 转义控制字符在文本环境中创建标准的窗口对话框。可以将这些对话框融入自己的 Shell 脚本中,借此与用户进行交互。接下来学习如何使用 dialog 包。

安装

sudo apt-get install dialog

dialog 包

dialog 包使用命令行参数来决定生成哪种窗口部件(widget)。部件是 dialog 包中窗口元素的术语。

部件描述
calendar提供选择日期的日历
checklist显示多个选项(其中每个选项都能打开或关闭)
form构建一个带有标签以及文本字段(可以填写内容)的表单
fselect提供一个文件选择窗口来浏览选择文件
gauge显示完成的百分比进度条
infobox显示一条消息,但不用等待回应
inputbox提供一个输入文本用的文本表单
inputmenu提供一个可编辑的菜单
menu显示可选择的一系列选项
msgbox显示一条消息,并要求用户选择 OK 按钮
pause显示一个进度条来显示暂定期间的状态
passwordbox显示一个文本框,但会隐藏输入的文本
passwordform显示一个带标签的隐藏文本字段的表单
radiolist提供一组菜单选项,但只能选择其中一个
tailboxtail 命令在滚动窗口中显示文件的内容
tailboxbgtailbox 一样,但在后台模式中运行
textbox在滚动窗口中显示文件的内容
timebox提供一个选择小时、分钟和秒数的窗口
yesno提供一条带有 Yes 和 No 按钮的简单消息

如上表所见,可以选择很多不同的部件。只需要多花点功夫就可以让脚本看起来更专业。

要在命令行上指定某个特定的部件,需要使用双破折线格式

dialog --widget parameters

其中 widget 是上表中某个特定的部件,parameters 定义了部件窗口的大小以及部件需要的文本。

每个 dialog 部件都提供了两种形式的输出

  • 使用 STDERR
  • 使用退出状态码

可以通过 dialog 命令的退出状态码来确定用户选择的按钮。如果选择了 Yes 或 OK 按钮,命令会返回状态码 0。如果选择了 Cancel 或 No 按钮,命令会返回状态码 1。可以用标准的 $? 变量来确定 dialog 部件具体选择了哪个按钮。

如果部件返回了数据,dialog 命令会将数据发送到 STDERR。可以用标准的 Bash Shell 方法将其重定向到另一个文件或文件描述符中。

dialog --inputbox "Enter your age:" 10 20 2>age.txt

这条命令将文本框输入的文本重定向到 age.txt 文件中。

msgbox 部件

msgbox 部件是对话框中最常见的类型。它会在窗口中显示一条简单的信息,直到用户点击 OK 后消失。

使用格式:

dialog --msgbox text height width

text 参数是要在窗口中显示的字符串,heightwidth 参数设定自动换行的窗口大小。如果想要在窗口中添加标题,可以使用 --title 参数,后接作为标题的文本。

示例:

dialog --title "Testing" --msgbox "This is a test" 10 20

输入命令后,消息框会显示在终端上。如果终端仿真器支持鼠标,可以单击 OK 来关闭对话框,也可以按下回车键。

yesno 部件

该部件在窗口底部生成两个按钮:一个是 Yes,一个是 No。用户可以用鼠标、制表符或者键盘方向键来切换按钮。选择按钮则使用空格或者回车键。

示例:

dialog --title "Please answer" --yesno "Is this thing on?" 10 20
echo $?

dialog 命令的退出状态码会根据用户选择的按钮来设置。选择 No 返回 1,选择 Yes 返回 0

inputbox 部件

inputbox 部件提供了一个简单的文本框区域来输入文本字符串,dialog 会将它传到 STDERR,需要重定向以获取输入。inputbox 提供了两个按钮:OK 和 Cancel。如果选择了 OK,命令退出状态码为 0,否则为 1

示例:

dialog --inputbox "Enter your age:" 10 20 2>age.txt
cat age.txt

如果自己运行过的话就会注意到该值后面没有换行符,这可以让您轻松地将文本内容重定向到脚本变量中,以获取用户输入的值。

textbox 部件

textbox 部件是在窗口中显示大量信息的极佳办法。它会生成一个滚动窗口来显示由参数所指定的文件中的文本。

示例:

dialog --textbox /etc/passwd 15 45

/etc/passwd 文件内容显示在可滚动的文本窗口中,可以用方向键来左右或上下滚动显示文件的内容。窗口底部的行会显示当前查看文本处于文件中的哪个位置(百分比)。文本框只包含一个用来选择退出部件的 Exit 按钮。

menu 部件

可以用这个部件来创建之前(上一篇笔记)中制作的文本菜单的窗口版本。只要为每个选项提供一个选择标号和文本就行。

示例:

dialog --menu "Sys Admin Menu" 20 30 10 1 "Display disk space" 2 "Display users" 3 "Display memory usage" 4 "Exit" 2>test.txt

第一个参数定义了菜单的标题,之后的两个参数定义了菜单窗口的高和宽,而第四个参数则定义了在窗口中一次显示的菜单项总数。如果存在更多选择,则有滚动条。

菜单项必须使用菜单对:第一个元素是用来选择菜单项的标号(必须唯一);第二个元素是菜单中使用的文本。

dialog 命令会将选定(鼠标点击或回车键或选择 OK)的菜单项文本发送到 STDERR。

fselect 部件

该部件在处理文件名时非常方便。不用强制用户键入文件名,就可以用 fselect 部件来浏览文件的位置并选择文件。

使用格式:

dialog --title "Select a file" --fselect $HOME/ 10 50 2>file.txt

第一个参数是窗口使用的初始目录位置。fselect 部件窗口由左侧的目录列表、右侧的文件列表和含有当前选定的文件或目录的简单文本框组成。可以手动在文本框键入文件名,或者用目录和文件列表来选定(使用空格键选定)。

dialog 选项

除了标准部件,dialog 还有大量定制的选项。前面使用的 title 就是一个。

以下是命令可用的选项:

选项描述
--add-widget继续下一个对话框直到按下 Esc 或 Cancel 选项
--aspect ratio设置窗口宽度和高度的宽高比
--backtitle title设置显示在屏幕顶部背景上的标题
--begin x y指定窗口左上角的起始位置
--cancel-label label指定 Cancel 按钮的替代标签
--clear用默认的对话背景色来清空屏幕内容
--colors在对话文本中嵌入 ANSI 色彩编码
--cr-wrap在对话文本中允许使用换行符并强制换行
--create-rc file将示例配置文件的内容复制到指定的 file 文件中
--defaultno将 yes/no 对话框的默认答案设为 no
--default-item string设定复选列表、表单或菜单对话中的默认项
--exit-label label指定 Exit 按钮的替代标签
--extra-button在 OK 按钮和 Cancel 按钮之间显示一个额外按钮
--extra-label label指定额外按钮的替换标签
--help显示 dialog 命令的帮助信息
--help-button在 OK 按钮和 Cancel 按钮后显示一个 Help 按钮
--help-label label指定 Help 按钮的替换标签
--help-status当选定 Help 按钮后,在帮助信息后写入多选列表、单选列表或表单信息
--ignore忽略 dialog 不能识别的选项
--input-fd fd指定 STDIN 之外的另一个文件描述符
--insecurepasswd 部件中键入内容时显示星号
--item-help为多选列表、单选列表或菜单中的每个标号在屏幕底部添加一个帮助栏
--keep-window不要清除屏幕上显示过的部件
--max-input size指定输入的最大字符串长度。默认为 2048
--nocancel隐藏 Cancel 按钮
--no-collapse不要将对话文本中的制表符转换为空格
--no-killtailboxbg 对话放到后台,并禁止该进程的 SIGHUP 信号
--no-label label为 No 按钮指定替换标签
--no-shadow不要显示对话窗口的阴影效果
--ok-label label指定 OK 按钮的替换标签
--output-fd fd指定除 STDERR 之外的另一个输出文件描述符
--print-maxsize将对话窗口的最大尺寸打印到输出中
--print-size将每个对话窗口的大小打印到输出中
--print-versiondialog 的版本号打印到输出中
--separate-output一次一行地输出 checklist 部件的结果,不使用引号
--separator string指定用于分隔部件输出的字符串
--separate-widget string指定用于分隔部件输出的字符串
--shadow在每个窗口右下角绘制阴影
--single-quoted需要时对多选列表的输出采用单引号
--sleep sec在处理完对话窗口后延迟指定的秒数
--stderr将输出发送到 STDERR(默认)
--stdout将输出发送到 STDOUT
--tab-correct将制表符转换为空格
--tab-len n指定一个制表符占用的空格数(默认为 8)
--timeout sec指定无用户输入时,sec 秒后退出并返回错误代码
--title title指定对话窗口的标题
--trim从对话文本中删除前导空格和换行符
--visit-times修改对话窗口制表符的停留位置,使其包括选项列表
--yes-label label为 Yes 按钮指定替换标签

--backtitle 选项是为脚本中的菜单创建公共标题的简便办法。 上表提供的强大特性允许创建任何需要的窗口。


dialog 配置文件

dialog 命令支持运行时配置。该命令会根据配置文件模板创建一份配置文件。dialog 启动时会先检查是否设置了 DIALOGRC 环境变量,该变量会保存配置文件名信息。如果未设置该变量或未找到该文件,它会将 $HOME/.dialogrc 作为配置文件。如果这个文件还不存在的话就尝试查找编译时指定的 GLOBALRC 文件,也就是 /etc/dialogrc。如果还不存在就用编译时的默认值。


在脚本中使用 dialog 命令

必须记住两件事:

  1. 如果有 Cancel 或 No 按钮,检查 dialog 命令的退出状态码。
  2. 重定向 STDERR 来获得输出值。

接下来是一个简单的实例,使用 dialog 部件生成之前(上一篇笔记)所创建的系统管理菜单。

#!/bin/bash
# Using dialog to create a menu

temp=$(mktemp -t test.XXXXXX)
temp2=$(mktemp -t test2.XXXXXX)

function diskspace {
  df -k > $temp
  dialog --textbox $temp 20 60
}

function whoseon {
  who > $temp
  dialog --textbox $temp 20 50
}

function memusage {
  cat /proc/meminfo > $temp
  dialog --textbox $temp 20 50
}

while [ 1 ]
do
  dialog --menu "Sys Admin Menu" 20 30 10 1 "Display disk space" 2 "Display users" 3 "Display memory usage" 0 "Exit" 2> $temp2
  if [ $? -eq 1 ]
  then
    break
  fi

  selection=$(cat $temp2)

  case $selection in
    1)
      diskspace ;;
    2)
      whoseon ;;
    3)
      memusage ;;
    0)
      break ;;
    *)
      dialog --msgbox "Sorry, invalid selection" 10 30
  esac
done

rm -f $temp 2> /dev/null
rm -f $temp2 2> /dev/null

使用 while 循环加一个真值常量创建了一个无限循环来显示菜单对话。当执行完每个函数后,脚本会返回继续显示菜单。

脚本使用了 mktemp 命令创建两个临时文件来保存 dialog 命令的数据。


via:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值