Explicación detallada del uso de la matriz de funciones de la configuración de red del sistema Ubuntu y la programación del script de shell

1. Resumen de la configuración de red del sistema Ubuntu

1.1 Nombre de host

Modificar el nombre de host

root@ubuntu20:/home/dong# hostname
ubuntu20
root@ubuntu20:/home/dong# hostnamectl set-hostname ubuntu20.magedu.cn
root@ubuntu20:/home/dong# hostname
ubuntu20.magedu.cn
root@ubuntu20:/home/dong# cat /etc/hostname
ubuntu20.magedu.cn
root@ubuntu20:/home/dong# echo $HOSTNAME        #不能立即生效,重新登录后生效
ubuntu20
root@ubuntu20:/home/dong# logout
bash: logout: not login shell: use `exit'
root@ubuntu20:/home/dong# exit
exit
dong@ubuntu20:~$ su
Password:
root@ubuntu20:/home/dong# echo $HOSTNAME
ubuntu20.magedu.cn

1.2 Nombre NIC

El nombre predeterminado de la tarjeta de red de ubuntu es similar a CentOS 7, como: ens33, ens38, etc.

Modifique el nombre de la tarjeta de red al método de nomenclatura tradicional:

#查看网卡默认名称为ens系列
root@ubuntu20:~# ip a |grep ens
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 192.168.100.180/24 brd 192.168.100.255 scope global ens33
#查看配置文件
root@ubuntu20:~# cat /etc/default/grub
GRUB_DEFAULT=0
GRUB_TIMEOUT_STYLE=hidden
GRUB_TIMEOUT=0
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT="maybe-ubiquity"
GRUB_CMDLINE_LINUX=""

1)修改配置文件GRUB_CMDLINE_LINUX
root@ubuntu20:~# sed -i.bak '/^GRUB_CMDLINE_LINUX=/s#"$#net.ifnames=0"#' /etc/default/grub
2)生成新的grub.cfg文件
root@ubuntu20:~# grub-mkconfig -o /boot/grub/grub.cfg
Sourcing file `/etc/default/grub'
Sourcing file `/etc/default/grub.d/init-select.cfg'
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-5.4.0-42-generic
Found initrd image: /boot/initrd.img-5.4.0-42-generic
done
#或者
root@ubuntu20:~# update-grub
root@ubuntu20:~# grep net.ifnames /boot/grub/grub.cfg
        linux   /vmlinuz-5.4.0-42-generic root=/dev/mapper/ubuntu--vg-ubuntu--lv ro net.ifnames=0 maybe-ubiquity
                linux   /vmlinuz-5.4.0-42-generic root=/dev/mapper/ubuntu--vg-ubuntu--lv ro net.ifnames=0 maybe-ubiquity
                linux   /vmlinuz-5.4.0-42-generic root=/dev/mapper/ubuntu--vg-ubuntu--lv ro recovery nomodeset net.ifnames=0
dong@ubuntu20:~$

#重启后生效
root@ubuntu20:~# reboot

3)重启后,eth0无ip地址,替换原配置的接口名称
root@ubuntu20:~# sed -i 's/ens33/eth0' /etc/netplan/00-installer-config.yaml
root@ubuntu20:~# netplan apply  #生效
root@ubuntu20:~# cat /etc/netplan/00-installer-config.yaml
# This is the network config written by 'subiquity'
network:
  ethernets:
    eth0:
    # dhcp: no
      addresses: [192.168.100.180/24]
      optional: true
      gateway4: 192.168.100.2
      nameservers:
               addresses: [192.168.100.2]
  version: 2
root@ubuntu20:~# ip a |grep eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 192.168.100.180/24 brd 192.168.100.255 scope global eth0

1.3 Configuración de la tarjeta de red de Ubuntu

Documento del sitio web oficial: Documento de
ayuda: https://help.ubuntu.com/
https://help.ubuntu.com/lts/serverguide/network-configuration.html.zh-CN
Documento de configuración de red: https: // ubuntu. com / server / docs / network-configuration

Archivo de configuración de red: formato yaml
1) -Lista : indica varios miembros o []
2) Clave (nombre de la variable): valor
3) Los diferentes niveles están sangrados y unificados

1.3.1 Configurar para obtener IP automáticamente

ejemplo:

root@ubuntu20:~# cat /etc/netplan/00-installer-config.yaml
# This is the network config written by 'subiquity'
network:
  ethernets:
    eth0:
      dhcp4: yes
      #addresses: [192.168.100.180/24]
      #optional: true
      #gateway4: 192.168.100.2
      #nameservers:
      #         addresses: [192.168.100.2]
  version: 2

#修改网卡配置文件后需执行命令生效:
root@ubuntu20:~# netplan apply

root@ubuntu20:~# ip a|grep eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 192.168.100.128/24 brd 192.168.100.255 scope global dynamic eth0

1.3.2 Configurar IP estática

ejemplo:

root@ubuntu20:~# cat /etc/netplan/00-installer-config.yaml
# This is the network config written by 'subiquity'
network:
  ethernets:
    eth0:
      #dhcp4: yes
      addresses: [192.168.100.128/24,192.168.100.180/24]
      optional: true
      gateway4: 192.168.100.2
      nameservers:
              #search:[magedu.com,magedu.org]
        addresses: [192.168.100.2]
  version: 2
#或者用下面两行,两种格式不能混用
      addresses:
      - 192.168.100.128/24
      - 192.168.100.180/24
root@ubuntu20:~# ip a|grep eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:02:81:56 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.128/24 brd 192.168.100.255 scope global eth0
    inet 192.168.100.180/24 brd 192.168.100.255 scope global secondary eth0

Ver ip y puerta de enlace

root@ubuntu20:/etc/apt# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:02:81:56 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.128/24 brd 192.168.100.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet 192.168.100.180/24 brd 192.168.100.255 scope global secondary eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe02:8156/64 scope link
       valid_lft forever preferred_lft forever

Ver la ruta de la tabla de enrutamiento

#1)执行route -n
root@ubuntu20:~# route -n   #route没有安装,需安装net-tools文件
Command 'route' not found, but can be installed with:
apt install net-tools
root@ubuntu20:~# apt install net-tools
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  net-tools
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 196 kB of archives.
After this operation, 864 kB of additional disk space will be used.
Err:1 http://mirrors.aliyun.com focal/main amd64 net-tools amd64 1.60+git20180626.aebd88e-1ubuntu1
  404  Not Found [IP: 111.62.129.238 80]
E: Failed to fetch http://mirrors.aliyun.com/pool/main/n/net-tools/net-tools_1.60+git20180626.aebd88e-1ubuntu1_amd64.deb  404  Not Found [IP: 111.62.129.238 80]
E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?

#2)因aliyun源无法连通,更换为清华源
root@ubuntu20:/# cd /etc/apt
root@ubuntu20:/etc/apt# cp sources.list sources.list.bak
#编辑source.list,复制清华源
root@ubuntu20:/etc/apt# cat sources.list
# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-backports main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-backports main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security main restricted universe multiverse

#3)更新
root@ubuntu20:/etc/apt# apt update
#4)安装net-tools工具
root@ubuntu20:/etc/apt# apt install net-tools
#5)查看路由表
root@ubuntu20:/etc/apt# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.100.2   0.0.0.0         UG    0      0        0 eth0
192.168.100.0   0.0.0.0         255.255.255.0   U     0      0        0 eth0

Ver DNS

dong@ubuntu20:~$ ll /etc/resolv.conf
lrwxrwxrwx 1 root root 39 Jul 31  2020 /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf
dong@ubuntu20:~$ systemd-resolve --status
Global
       LLMNR setting: no
MulticastDNS setting: no
  DNSOverTLS setting: no
      DNSSEC setting: no
    DNSSEC supported: no
          DNSSEC NTA: 10.in-addr.arpa
                      16.172.in-addr.arpa
                      168.192.in-addr.arpa
                      17.172.in-addr.arpa
                      18.172.in-addr.arpa
                      19.172.in-addr.arpa
                      20.172.in-addr.arpa
                      21.172.in-addr.arpa
                      22.172.in-addr.arpa
                      23.172.in-addr.arpa
                      24.172.in-addr.arpa
                      25.172.in-addr.arpa
                      26.172.in-addr.arpa
                      27.172.in-addr.arpa
                      28.172.in-addr.arpa
                      29.172.in-addr.arpa
                      30.172.in-addr.arpa
                      31.172.in-addr.arpa
                      corp
                      d.f.ip6.arpa
                      home
                      internal
                      intranet
                      lan
                      local
                      private
                      test

Link 2 (eth0)
      Current Scopes: DNS
DefaultRoute setting: yes
       LLMNR setting: yes
MulticastDNS setting: no
  DNSOverTLS setting: no
      DNSSEC setting: no
    DNSSEC supported: no
  Current DNS Server: 192.168.100.2
         DNS Servers: 192.168.100.2

1.3.3 Configurar IP estática de múltiples tarjetas y enrutamiento estático

1. Varias configuraciones de tarjetas de red están en un archivo

root@ubuntu20:~# cat /etc/netplan/00-installer-config.yaml
# This is the network config written by 'subiquity'
network:
  ethernets:
    eth0:
      addresses:
      - 192.168.100.128/24
      optional: true
      gateway4: 192.168.100.2
      nameservers:
              #search:[magedu.com,magedu.org]
        addresses: [192.168.100.2]
  version: 2
  ethernets:
    eth1:
      addresses: [172.16.100.128/24]
      #gateway4: 172.16.100.1
      #nameservers:
      #  addresses: [223.5.5.5,180.76.76.76]
      routes:
      - to: 10.10.100.0/24
        via: 172.16.100.1
      - to: 172.18.100.0/24
        via: 172.16.100.1
      - to: 172.19.100.0/24
        via: 172.16.100.1

root@ubuntu20:~# netplan apply
root@ubuntu20:~# ip a|grep eth
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:02:81:56 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.128/24 brd 192.168.100.255 scope global eth0
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:02:81:60 brd ff:ff:ff:ff:ff:ff
    inet 172.16.100.128/24 brd 172.16.100.255 scope global eth1

root@ubuntu20:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.100.2   0.0.0.0         UG    0      0        0 eth0
10.10.100.0     172.16.100.1    255.255.255.0   UG    0      0        0 eth1
172.16.100.0    0.0.0.0         255.255.255.0   U     0      0        0 eth1
172.18.100.0    172.16.100.1    255.255.255.0   UG    0      0        0 eth1
172.19.100.0    172.16.100.1    255.255.255.0   UG    0      0        0 eth1
192.168.100.0   0.0.0.0         255.255.255.0   U     0      0        0 eth0

2. Cada tarjeta de red tiene su propio archivo de configuración.

root@ubuntu20:~# cat /etc/netplan/00-installer-config.yaml
# This is the network config written by 'subiquity'
network:
  ethernets:
    eth0:
      addresses:
      - 192.168.100.128/24
      optional: true
      gateway4: 192.168.100.2
      nameservers:
              #search:[magedu.com,magedu.org]
        addresses: [192.168.100.2]
  version: 2

root@ubuntu20:~# cat /etc/netplan/01-eth1-config.yaml
# This is the network config written by 'subiquity'
network:
  version: 2
  ethernets:
    eth1:
      addresses: [172.16.100.128/24]
      #gateway4: 172.16.100.1
      nameservers:
        addresses: [223.5.5.5,180.76.76.76]
      routes:
      - to: 10.10.100.0/24
        via: 172.16.100.1
      - to: 172.18.100.0/24
        via: 172.16.100.1
      - to: 172.19.100.0/24
        via: 172.16.100.1
root@ubuntu20:~# netplan apply
root@ubuntu20:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:02:81:56 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.128/24 brd 192.168.100.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe02:8156/64 scope link
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:02:81:60 brd ff:ff:ff:ff:ff:ff
    inet 172.16.100.128/24 brd 172.16.100.255 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe02:8160/64 scope link
       valid_lft forever preferred_lft forever
root@ubuntu20:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.100.2   0.0.0.0         UG    0      0        0 eth0
10.10.100.0     172.16.100.1    255.255.255.0   UG    0      0        0 eth1
172.16.100.0    0.0.0.0         255.255.255.0   U     0      0        0 eth1
172.18.100.0    172.16.100.1    255.255.255.0   UG    0      0        0 eth1
172.19.100.0    172.16.100.1    255.255.255.0   UG    0      0        0 eth1
192.168.100.0   0.0.0.0         255.255.255.0   U     0      0        0 eth0
root@ubuntu20:~#

2 Introducción a la función

  • La función de función es un bloque de instrucciones compuesto por varios comandos de shell para realizar la reutilización del código y la programación modular.
  • Es similar en forma al programa de shell, la diferencia es que no es un proceso separado, no se puede ejecutar de forma independiente, sino que forma parte del programa de shell.

Las funciones y los programas de shell son similares, la diferencia es

== El programa Shell se ejecuta en el sub Shell, y la función Shell se ejecuta en el Shell actual ==. Por lo tanto, en el Shell actual, la función puede modificar las variables en el shell

2.1 Funciones de gestión

La función consta de dos partes: nombre de la función y cuerpo de la función

Ayuda ver: función de ayuda

2.1.1 Definir función

formato:

#语法一:
func_name (){
...函数体...
}
#语法二:
function func_name {
...函数体...
}
#语法三:
function func_name () {
...函数体...
}

Ejemplo de definición de función: definición de función y llamada en un script

1)创建一个关闭防火墙和selinux的函数
[root@repo-client scripts]# cat all_functions
disable_firewall_selinux () {
        systemctl stop firewalld
        systemctl disable firewalld
        sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
        setenforce 0
}
disable_firewall_selinux        #调用函数
#原来的selinux和firewall状态
[root@repo-client scripts]# cat /etc/selinux/config
SELINUX=enforcing
[root@repo-client scripts]# systemctl status firewalld
   Active: active (running) since Tue 2021-03-23 13:52:58 CST; 9min ago
#执行函数,并查看结果
[root@repo-client scripts]# . all_functions
[root@repo-client scripts]# systemctl status firewalld
   Active: inactive (dead)
[root@repo-client scripts]# cat /etc/selinux/config
SELINUX=disabled

2)创建centos7统一的repo
[root@repo-client scripts]# cat all_functions
yum_repo () {
    cd /etc/yum.repos.d/
    mkdir backup -p
    mv *.repo backup
    cat > base.repo <<EOF

[BaseOS-aliyun]
name=centos7 repo-server BaseOS by aliyun
baseurl=https://mirrors.aliyun.com/centos/7/os/x86_64/
gpgcheck=0

[epel]
name=centos7 repo-server epel
baseurl=https://mirrors.aliyun.com/epel/7/x86_64/
gpgcheck=0

[extras]
name=centos7 repo-server extras
baseurl=https://mirrors.aliyun.com/centos/7/extras/x86_64/
gpgcheck=0
EOF
}
yum_repo

#查看原来的yum.repos.d目录中的文件
[root@repo-client yum.repos.d]# ls
backup  centos7-client.repo  Centos-7.repo  CentOS-Base.repo
[root@repo-client scripts]# . all_functions
mv: overwrite ‘backup/CentOS-Base.repo’? y
[root@repo-client yum.repos.d]# ll
total 4
drwxr-xr-x. 2 root root 235 Mar 23 14:20 backup
-rw-r--r--. 1 root root 512 Mar 23 14:20 base.repo

[root@repo-client yum.repos.d]# yum repolist
repo id               repo name                                     status
BaseOS-aliyun         centos7 repo-server BaseOS by aliyun          10,072
epel                  centos7 repo-server epel                      13,564
extras                centos7 repo-server extras                    460
repolist: 24,096

Ejemplo: definición de función separada y llamada

1)函数定义在一个统一的脚本文件中,如all_functions;
[root@repo-client scripts]# cat all_functions
#1)停止防火墙和selinux的函数
disable_firewall_selinux () {
        systemctl stop firewalld
        systemctl disable firewalld
        sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
        setenforce 0
}
#2)定义yum源的函数
yum_repo () {
...同上...省略
}
2)调用函数时,编写相应的sh脚本,如只需要关闭防火墙和selinux,就编写这样一个脚本,就不执行其他的函数了
[root@repo-client scripts]# cat dis_firewall_selinux.sh
#!/bin/bash
#调用函数库
. all_functions
#关闭防火墙和selinux
disable_firewall_selinux
3)测试执行
[root@repo-client scripts]# . dis_firewall_selinux.sh

Ejemplo: instalar funciones de software de uso común

1)该函数也定义在统一的脚本文件all_functions中
[root@repo-client scripts]# cat all_functions
#1)关闭防火墙和selinux
disable_firewall_selinux () {
...省略...
}
#2)统一yum源仓库
yum_repo () {
...省略...
}
#3)安装常用软件工具
install_packages () {
PACKAGES="
vim
tree
autofs
net-tools
gcc
make
autoconf
pcre
pcre-devel
openssl
openssl-devel
vim
lrzsz
tmux
lsof
tcpdump
wget
iotop
"
for i in $PACKAGES; do
        rpm -q $i &> /dev/null || yum -q -y install $i
done
}
2、编写安装脚本,测试
[root@repo-client scripts]# rpm -q vim lrzsz lsof gcc
package vim is not installed
package lrzsz is not installed
package lsof is not installed
package gcc is not installed
[root@repo-client scripts]# . install_packages.sh
...安装过程省略...
[root@repo-client scripts]# rpm -q vim lrzsz lsof gcc
package vim is not installed
lrzsz-0.12.20-36.el7.x86_64
lsof-4.87-6.el7.x86_64
gcc-4.8.5-44.el7.x86_64

Ejemplo: Script de menú de operación y mantenimiento simple para funciones de llamada

[root@centos7 scripts]# cat fun_menu.sh
#!/bin/bash
. all_functions
PS3="请选择运维编号(1-4):"
select MENU in 关闭防火墙和selinux 配置yum仓库 安装常用软件包 退出; do
    case $REPLY in
    1)
        disable_firewall_selinux
        ;;
    2)
        yum_repo
        ;;
    3)
        install_packages
        ;;
    4)
        exit
        ;;
    *)
        echo "输入错误,请重新输入"
        ;;
    esac
done

[root@centos7 scripts]# bash fun_menu.sh
1) 关闭防火墙和selinux  3) 安装常用软件包
2) 配置yum仓库          4) 退出
请选择运维编号(1-4):1
setenforce: SELinux is disabled
请选择运维编号(1-4):2
请选择运维编号(1-4):4
[root@centos7 scripts]#

2.1.2 Función de visualización

#查看当前已定义的函数名
declare -F
#查看当前已定义的函数定义
declare -f
#查看指定当前已定义的函数名
declare -f func_name
#查看当前已定义的函数名定义
declare -F func_name

[root@repo-client scripts]# declare -f
disable_firewall_selinux ()
{
    systemctl stop firewalld;
    systemctl disable firewalld;
    sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config;
    setenforce 0
}
yum_repo ()
{
    ...省略...
}
[root@repo-client scripts]# declare -F
declare -f disable_firewall_selinux
declare -f yum_repo

2.1.3 Función de eliminación

unset func_name     #删除函数

2.2 Llamada a función

Ejemplo 1: La asignación de variable realizada en el cuerpo de la función afecta el valor de la variable externa

[root@repo-client scripts]# cat test1
#变量赋值
test () {
        NAME=mage
        echo NAME=$NAME
}
[root@repo-client scripts]# . test1     #.或source是在当前shell中执行
[root@repo-client scripts]# test    #函数内的变量赋值
NAME=mage
[root@repo-client scripts]# NAME=wang       #重新赋值
[root@repo-client scripts]# echo $NAME      #显示
wang
[root@repo-client scripts]# test            #再次执行test函数
NAME=mage
[root@repo-client scripts]# echo $NAME      #再查看$NAME,是函数内的赋值;因函数内的变量和当前进程是同级关系,在同一个shell中,不是子进程。
mage

Ejemplo 2: Evite conflictos de variables con el mismo nombre, local

Si la variable definida en la función solo es válida en la función, es necesario definir la variable local, es decir, usar la definición local, que es válida solo en el cuerpo de la función o subproceso.

[root@repo-client scripts]# type local
local is a shell builtin
[root@repo-client scripts]# help local
local: local [option] name[=value] ...
    Define local variables.

    Create a local variable called NAME, and give it VALUE.  OPTION can
    be any option accepted by `declare'.

    Local variables can only be used within a function; they are visible
    only to the function where they are defined and its children.

    Exit Status:
    Returns success unless an invalid option is supplied, an error occurs,
    or the shell is not executing a function.

[root@repo-client scripts]# cat test1
#变量赋值为local
test () {
        local NAME
        NAME=mage       #这两条可以合并为local NAME=mage
        echo NAME=$NAME
}
[root@repo-client scripts]# . test1
[root@repo-client scripts]# test
NAME=mage
[root@repo-client scripts]# NAME=wang
[root@repo-client scripts]# echo $NAME
wang
[root@repo-client scripts]# test            #函数内变量
NAME=mage
[root@repo-client scripts]# echo $NAME      #函数外同名变量,不冲突了
wang

Cómo llamar a la función

  • Las funciones se pueden definir en un entorno interactivo

  • Las funciones se pueden colocar en archivos de script como parte de él.

  • Se puede colocar en un archivo separado que contiene solo funciones

Llamada: La función solo se ejecutará cuando se llame. La función es llamada por el nombre de función dado, y el código de función será reemplazado automáticamente donde aparezca el nombre de la función.

El ciclo de vida de la función: se crea cuando se llama y se termina cuando regresa

#系统自带的函数文件,可以在脚本中直接调用

[root@repo-client scripts]# grep  -E -A10 "^(action|success)" /etc/init.d/functions
success() {
    [ "$BOOTUP" != "verbose" -a -z "${LSB:-}" ] && echo_success
    return 0
}
# Log that something failed
failure() {
    local rc=$?
    [ "$BOOTUP" != "verbose" -a -z "${LSB:-}" ] && echo_failure
    [ -x /bin/plymouth ] && /bin/plymouth --details
    return $rc
}
action() {
    local STRING rc

    STRING=$1
    echo -n "$STRING "
    shift
    "$@" && success $"$STRING" || failure $"$STRING"
    rc=$?
    echo
    return $rc
}
#action函数里包含了success和failure两个函数,直接调用时,会显示成功和shi'bai
[root@repo-client scripts]# . /etc/init.d/functions
[root@repo-client scripts]# action "rm -rf /*"
rm -rf /*                                                  [  OK  ]
[root@repo-client scripts]# action ldsfe flejlf
ldsfe -bash: flejlf: command not found                     [FAILED]

2.3 Valor de retorno de la función

1. El valor de retorno del resultado de ejecución de la función:

  • Utilice comandos como echo para la salida

  • El resultado de salida del comando de llamada en el cuerpo de la función

2. El código de estado de salida de la función:

El valor predeterminado depende del código de estado de salida del último comando ejecutado en la función

3. Código de estado de salida personalizado, su formato es:

  • return Retorno de la función, use el comando de estado final para determinar el valor de retorno

  • devuelve 0 vuelve sin error

  • devuelve 1-255 vuelve con error
#1)使用exit退出,返回值100
[root@repo-client scripts]# cat test1
#5)变量赋值
test () {
        local NAME
        NAME=mage
        echo NAME=$NAME
        exit 100
}
[root@repo-client scripts]# cat test1.sh
#!/bin/bash
#调用test1函数
. test1
test
#返回值
echo statue=$?
[root@repo-client scripts]# bash test1.sh
NAME=mage           #只显示NAME,而无statue值,因为调用test1函数后,exit就退出整个脚本了,不会执行echo statue值

#2)使用return退出,返回值也是100
[root@repo-client scripts]# cat test1
#5)变量赋值
test () {
        local NAME
        NAME=mage
        echo NAME=$NAME
        #exit 100
        return 100
}
[root@centos7 scripts]# bash test1.sh       #执行后,只退出函数,还执行echo statue
NAME=mage
statue=100

2.4 Espera de la herramienta por lotes de conversión interactiva

Expect es desarrollado por Don Libes basado en el lenguaje Tcl (Tool Command Language). Se utiliza principalmente en escenarios de operación interactiva automatizada. Con la ayuda de esperar para procesar comandos interactivos, se pueden realizar procesos interactivos como ssh login, ftp login, etc. ser escrito en un guión, completarlo automáticamente. Es especialmente adecuado para entornos en los que se debe realizar la misma operación en varios servidores, lo que puede mejorar en gran medida la eficiencia del trabajo de los administradores del sistema. No existe tal comando en el sistema de instalación mínima, simplemente instálelo con yum.

esperar sintaxis:

expect [选项] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ]

Opciones comunes:

-c: ejecuta la secuencia de comandos de espera desde la línea de comandos, la espera predeterminada se ejecuta de forma interactiva
-d: se puede generar información de depuración

Ejemplo:

expect -c 'expect "\n" {send "pressed enter\n"}'
expect -d ssh.exp

[root@centos7 yum.repos.d]# expect -c 'expect "\n" {send "pressed enter\n"}'

pressed enter

Comandos relacionados en espera

  • spawn comienza un nuevo proceso
  • esperar recibir una cadena del proceso
  • enviar se usa para enviar una cadena al proceso
  • interactuar permite la interacción del usuario

  • exp_continue coincide con varias cadenas, agregue este comando después de realizar una acción

La gramática de esperar más utilizada (tcl language: mode-action)

Sintaxis de patrón de rama única: después de hacer coincidir hola, se mostrará "dijiste hola" y se ajustará

#捕获hi字符,出现后,打印you said hi
[root@centos7 expect]# expect
expect1.1> expect "hi" {send "You said hi\n"}
halefhiald
You said hi
expect1.2> exit

Sintaxis del modo de múltiples ramas: cuando haga coincidir cualquier cadena de hola, hola, adiós, ejecute la salida correspondiente. Pero es una única vez, equivalente a lo siguiente

[root@centos8 test]#expect
expect1.1> expect "hi" { send "You said hi\n" } "hehe" { send "Hehe yourself\n"
} "bye" { send "Good bye\n" }
hehe
Hehe yourself
expect1.2> expect "hi" { send "You said hi\n" } "hehe" { send "Hehe yourself\n"
} "bye" { send "Good bye\n" }
bye
Good bye
expect1.3> expect "hi" { send "You said hi\n" } "hehe" { send "Hehe yourself\n"
} "bye" { send "Good bye\n" }
hi
You said hi
expect1.4> exit

[root@centos7 expect]# expect
expect1.1> expect {
+> "hi" { send "You said hi\n"}
+> "hehe" { send "Hehe yourself\n"}
+> "bye" { send " Good bye\n"}
+> }
bye
 Good bye
expect1.2>

Ejemplo 1: Desde el host 10.0.0.8, copie de forma no interactiva el archivo fstab al directorio de datos del host 7

[root@centos7 expect]# cat expect1
#!/usr/bin/expect
spawn scp /etc/fstab 192.168.100.11:/data
expect {
    "yes/no" { send "yes\n";exp_continue }
    "password" { send "dongdong\n" }
}
expect eof
[root@centos7 expect]# chmod +x expect1
[root@centos7 expect]# ./expect1
spawn scp /etc/fstab 192.168.100.11:/data
The authenticity of host '192.168.100.11 (192.168.100.11)' can't be established.
ECDSA key fingerprint is SHA256:LsADkBrAATQSCqxKP9lZXDYm2WncbAvsH3M1Z0ubNpE.
ECDSA key fingerprint is MD5:5c:bf:b4:5d:6a:24:38:4e:1c:1e:47:d0:b9:92:c2:08.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.100.11' (ECDSA) to the list of known hosts.
[email protected]'s password:
fstab                                                                                                       100%  596   126.4KB/s   00:00

[root@c7-test ~]# ll /data/fstab
-rw-r--r-- 1 root root 596 Mar 25 21:52 /data/fstab

Ejemplo 2: inicio de sesión automático

[root@centos7 expect]# cat expect2
#!/usr/bin/expect
spawn ssh 192.168.100.11
expect {
    "yes/no" { send "yes\n";exp_continue }
    "password" { send "dongdong\n" }
}
interact

[root@centos7 expect]# chmod +x expect2
[root@centos7 expect]# ./expect2
spawn ssh 192.168.100.11
[email protected]'s password:
Last login: Thu Mar 25 21:53:35 2021 from 192.168.100.1
[root@c7-test ~]# exit
logout
Connection to 192.168.100.11 closed.
[root@centos7 expect]#

Ejemplo 3: definir la variable de espera para realizar un inicio de sesión no interactivo

[root@centos7 expect]# cat expect3
#!/usr/bin/expect
set ip 192.168.100.11
set user root
set password dongdong
set timeout 10
spawn ssh $user@$ip
expect {
    "yes/no" { send "yes\n";exp_continue }
    "password" { send "$password\n" }
}
interact

#测试,删除测试机上的.ssh文件后,执行
[root@c7-test ~]# rm /root/.ssh -rf
[root@centos7 expect]# chmod +x expect3
[root@centos7 expect]# ./expect3
spawn ssh [email protected]
[email protected]'s password:
Last login: Thu Mar 25 21:56:36 2021 from 192.168.100.12
[root@c7-test ~]# exit
logout
Connection to 192.168.100.11 closed.
[root@centos7 expect]#

Ejemplo 4: espere parámetros posicionales, equivalentes a $ 1 $ 2, etc.

[root@centos7 expect]# cat expect4
#!/usr/bin/expect
set ip [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
spawn ssh $user@$ip
expect {
    "yes/no" { send "yes\n";exp_continue }
    "password" { send "$password\n" }
}
interact

[root@c7-test ~]# rm /root/.ssh -rf
[root@centos7 expect]# chmod +x expect4
#命令后加位置参数
[root@centos7 expect]# ./expect4 192.168.100.11 root dongdong
spawn ssh [email protected]
[email protected]'s password:
Last login: Thu Mar 25 22:08:21 2021 from 192.168.100.12
[root@c7-test ~]# exit
logout
Connection to 192.168.100.11 closed.
[root@centos7 expect]#

Ejemplo 5: espere iniciar sesión en el host de la otra parte de forma no interactiva y ejecutar varios comandos

[root@centos7 expect]# cat expect5
#!/usr/bin/expect
set ip [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
set timeout 10
#非交互登录到对方主机
spawn ssh $user@$ip
expect {
        "yes/no" { send "yes\n";exp_continue }
        "password" { send "$password\n" }
}
#创建用户haha,并设置密码
expect "]#" { send "useradd haha\n" }
expect "]#" { send "echo $password |passwd --stdin haha\n" }
send "exit\n"
expect eof

[root@centos7 expect]# chmod +x expect5
[root@centos7 expect]# ./expect5 192.168.100.11 root dongdong
spawn ssh [email protected]
[email protected]'s password:
Last login: Thu Mar 25 22:11:25 2021 from 192.168.100.12
[root@c7-test ~]# useradd haha
[root@c7-test ~]# echo dongdong |passwd --stdin haha
Changing password for user haha.
passwd: all authentication tokens updated successfully.
[root@c7-test ~]# exit
logout
Connection to 192.168.100.11 closed.
[root@centos7 expect]#

[root@c7-test ~]# getent passwd|grep haha
haha:x:2011:2011::/home/haha:/bin/bash

Ejemplo 6: Las llamadas del script de shell esperan, inician sesión en el host de la otra parte y crean un usuario.

[root@centos7 expect]# cat expect6.sh
#!/bin/bash
ip=$1
user=$2
password=$3
expect <<EOF
set timeout 20
spawn ssh $user@$ip
expect {
    "yes/no" { send "yes\n";exp_continue }
    "password" { send "$password\n" }
}
expect "]#" { send "useradd hehe\n" }
expect "]#" { send "echo $passwordu |passwd --stdin hehe\n" }
expect "]#" { send "exit\n" }
expect eof
EOF
[root@centos7 expect]# chmod +x expect6.sh
[root@centos7 expect]# ./expect6.sh 192.168.100.11 root dongdong
spawn ssh [email protected]
[email protected]'s password:
Last login: Thu Mar 25 22:19:43 2021 from 192.168.100.12
[root@c7-test ~]# useradd hehe
[root@c7-test ~]# echo dongdong |passwd --stdin hehe
Changing password for user hehe.
passwd: all authentication tokens updated successfully.
[root@c7-test ~]# exit
logout
Connection to 192.168.100.11 closed.
[root@centos7 expect]#
[root@c7-test ~]# getent passwd|grep hehe
hehe:x:2012:2012::/home/hehe:/bin/bash

3 matriz

3.1 Introducción a las matrices

Variable: el espacio de memoria para almacenar un solo elemento.

Matriz: un espacio de memoria continuo que almacena múltiples elementos, lo que equivale a una colección de múltiples variables

Nombre e índice de matriz

  • El número de índice comienza en 0 y pertenece al índice numérico
  • El índice puede admitir el uso de un formato personalizado, no solo un formato numérico, es decir, un índice asociado, que se admite después de bash4.0 (después de centos6)
  • Las matrices bash admiten formato disperso (el índice no es continuo)

3.2 Declaración de una matriz

#普通数组可以不事先声明,直接使用
declare -a ARRAY_NAME
#关联数组必须先声明,再使用
declare -A ARRAY_NAME

Nota: los dos no se pueden convertir entre sí

Ejemplo: las matrices no se pueden convertir entre sí

#关联associative数组和索引index数组不能相互转换
[root@centos7 scripts]# declare -A course
[root@centos7 scripts]# declare -a course
-bash: declare: course: cannot convert associative to indexed array

[root@centos7 scripts]# file=(s*.sh)    #定义的是索引数组,不能转换成关联数组
[root@centos7 scripts]# declare -a |grep file
declare -a file='([0]="shift_doit.sh" [1]="shift_useradd.sh")'
[root@centos7 scripts]# declare -A file
-bash: declare: file: cannot convert indexed to associative array

3.3 Asignación de matrices

Asignación de elementos de matriz

(1) Asignar solo un elemento a la vez

ARRAY_NAME[INDEX]=VALUE

ejemplo:

weekdays[0]="Sunday"
weekdays[4]="Thursday"

Ejemplo: asignación de un solo elemento

[root@centos7 ~]# title[0]=ceo
[root@centos7 ~]# title[1]=cto
[root@centos7 ~]# echo ${title[0]}
ceo
[root@centos7 ~]# echo ${title[1]}
cto
[root@centos7 ~]# echo ${title}     #不加索引号,就默认第一个
ceo
[root@centos7 ~]# declare -a |grep title
declare -a title='([0]="ceo" [1]="cto")'

(2) Asignar todos los elementos a la vez

ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)

ejemplo:

title=("ceo" "coo" "cto")
num=({0..10})
alpha=({a..g})
file=( *.sh )

Ejemplo: asignar todos los elementos a la vez

[root@centos7 ~]# name=(mage wang li zhao)
[root@centos7 ~]# declare -a name
[root@centos7 ~]# declare -a |grep name
declare -a name='([0]="mage" [1]="wang" [2]="li" [3]="zhao")'
[root@centos7 ~]# echo ${name[2]}
li
[root@centos7 ~]# echo ${name[*]}
mage wang li zhao

#数值
[root@centos7 scripts]# num=({1..10})
[root@centos7 scripts]# declare -a |grep num
declare -a num='([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6" [6]="7" [7]="8" [8]="9" [9]="10")'
[root@centos7 scripts]# echo ${num[6]}
7

#目录中的文件为元素赋值
[root@centos7 scripts]# ls
argsnum.sh     dir.sh         expect    for_99.sh      for_continue.sh  for_prename.sh   guess_number.sh  menu.sh   shift_doit.sh     trap.sh
color.sh       disk_check.sh  file.sh   for_break2.sh  for_mkdir.sh     for_scanhost.sh  hostping.sh      per.sh    shift_useradd.sh
createuser.sh  excute.sh      file.txt  for_break.sh   for_movedir.sh   for_sum.sh       init.sh          rm_mv.sh  trap_exit.sh
[root@centos7 scripts]# file=(f*.sh)        #把f开头的sh文件当做元素赋值
[root@centos7 scripts]# declare -a |grep file
declare -a file='([0]="file.sh" [1]="for_99.sh" [2]="for_break2.sh" [3]="for_break.sh" [4]="for_continue.sh" [5]="for_mkdir.sh" [6]="for_movedir.sh" [7]="for_prename.sh" [8]="for_scanhost.sh" [9]="for_sum.sh")'
[root@centos7 scripts]# echo ${file[5]}
for_mkdir.sh

(3) Asignar solo elementos específicos

ARRAY_NAME=([0]="VAL1" [3]="VAL2" ...)

(4) Asignación de valor de matriz interactiva

read -a ARRAY

ejemplo:

[root@centos7 scripts]# read -a menu
lamian paomo huimian luzhu douzhi
[root@centos7 scripts]# echo ${menu[3]}
luzhu

3.4 Mostrar todas las matrices

Mostrar todas las matrices:

declare -a

ejemplo:

[root@centos7 ~]# declare -a
declare -a BASH_ARGC='()'
declare -a BASH_ARGV='()'
declare -a BASH_LINENO='()'
declare -a BASH_SOURCE='()'
declare -ar BASH_VERSINFO='([0]="4" [1]="2" [2]="46" [3]="2" [4]="release" [5]="x86_64-redhat-linux-gnu")'
declare -a DIRSTACK='()'
declare -a FUNCNAME='()'
declare -a GROUPS='()'
declare -a PIPESTATUS='([0]="0")'

3.5 Referenciar una matriz

Elemento de matriz de referencia

${ARRAY_NAME[INDEX]}
#如果省略[INDEX]表示引用下标为0的元素

ejemplo:

[root@centos7 ~]# declare -a title=([0]="ceo" [1]="coo" [2]="cto")
[root@centos7 ~]# echo ${title[1]}
coo
[root@centos7 ~]# echo ${title}
ceo
[root@centos7 ~]# echo ${title[2]}
cto
[root@centos7 ~]# echo ${title[3]}

[root@centos7 ~]#

Hacer referencia a todos los elementos de la matriz

${ARRAY_NAME[*]}
${ARRAY_NAME[@]}

ejemplo:

[root@centos7 ~]# echo ${title[@]}
ceo coo cto
[root@centos7 ~]# echo ${title[*]}
ceo coo cto

La longitud de la matriz, es decir, el número de elementos de la matriz.

${#ARRAY_NAME[*]}
${#ARRAY_NAME[@]}

ejemplo:

[root@centos7 ~]# echo ${#title[*]}
3
[root@centos7 ~]# alpha=({a..z})
[root@centos7 ~]# echo ${#alpha[@]}
26

3.6 Eliminar matriz

Eliminar un elemento en la matriz resultará en un formato disperso y la matriz no es continua

[root@centos7 ~]# echo ${title[*]}
ceo coo cto
[root@centos7 ~]# unset title[1]
[root@centos7 ~]# echo ${title[*]}
ceo cto

[root@centos7 ~]# unset alpha[3]
[root@centos7 ~]# echo ${#alpha[@]}
25
[root@centos7 ~]# echo ${alpha[2]}
c
[root@centos7 ~]# echo ${alpha[4]}
e
[root@centos7 ~]# echo ${alpha[3]}

[root@centos7 ~]# echo ${alpha[*]}
a b c e f g h i j k l m n o p q r s t u v w x y z

Eliminar toda la matriz

unset ARRAY

ejemplo:

[root@centos7 ~]# unset title
[root@centos7 ~]# echo ${title[*]}

[root@centos7 ~]# echo ${#title[*]}
0

3.7 Matriz asociativa

declare -A ARRAY_NAME
ARRAY_NAME=([idx_name1]='val1' [idx_name2]='val2'...)

Nota: Las matrices asociativas deben declararse antes de llamar y los subíndices se definen a voluntad. Se pueden almacenar múltiples variables (clave) y valores (valor) en una matriz.

Ejemplo: matriz asociativa indefinida

#如果默认创建关联数组,会当成普通索引数组,下标不合理,会合并成一个下标,即0
[root@centos7 ~]# magedu[ceo]=mage
[root@centos7 ~]# declare -a |grep magedu   #第一次定义的下标是ceo,但识别出来的只是0
declare -a magedu='([0]="mage")'
[root@centos7 ~]# magedu[cto]=wang      #第二次定义的下标是cto,也会当做0,所以替换之前的赋值
[root@centos7 ~]# echo ${magedu[ceo]}   
wang
[root@centos7 ~]# declare -a |grep magedu   #只保留最后一次的赋值
declare -a magedu='([0]="wang")'

Ejemplo: definir una matriz asociativa

[root@centos7 ~]# declare -A magedu
[root@centos7 ~]# magedu[ceo]=mage
[root@centos7 ~]# magedu[cto]=wang
[root@centos7 ~]# echo ${magedu[ceo]}
mage
[root@centos7 ~]# echo ${magedu[cto]}
wang
[root@centos7 ~]# declare -a |grep magedu
[root@centos7 ~]# declare -A |grep magedu
declare -A magedu='([ceo]="mage" [cto]="wang" )'
[root@centos7 ~]#

Ejemplo: definir varios elementos en una matriz

[root@centos7 ~]# declare -A student
[root@centos7 ~]# student[name1]=lijun
[root@centos7 ~]# student[name2]=ziqing
[root@centos7 ~]# student[age1]=18
[root@centos7 ~]# student[age2]=20
[root@centos7 ~]# student[age2]=16
[root@centos7 ~]# declare -A |grep student
declare -A student='([age2]="16" [age1]="18" [name2]="ziqing" [name1]="lijun" )'
[root@centos7 ~]# student[gender1]=m
[root@centos7 ~]# student[gender2]=f
[root@centos7 ~]# student[city1]=nanjing
[root@centos7 ~]# student[city2]=beijing

[root@centos7 ~]# for i in {1..10};do echo student[name$i]=${student[name$i]}; done
student[name1]=lijun
student[name2]=ziqing
student[name3]=
student[name4]=
student[name5]=
student[name6]=
student[name7]=
student[name8]=
student[name9]=
student[name10]=
[root@centos7 ~]#

3.8 Ejemplos

Ejemplo 1: Genere 10 números aleatorios y guárdelos en una matriz, y encuentre los valores máximo y mínimo

[root@centos7 scripts]# cat min_max.sh
#!/bin/bash
declare -i min max
declare -a nums
for ((i=0;i<10;i++));do
    nums[$i]=$RANDOM
    [ $i -eq 0 ] && min=${nums[0]} && max=${nums[0]} && continue
    [ ${nums[$i]} -gt $max ] && max=${nums[$i]}
    [ ${nums[$i]} -lt $min ] && min=${nums[$i]}
done
echo "All numbers are ${nums[*]}"
echo Max is $max
echo Min is $min

[root@centos7 scripts]# bash min_max.sh
All numbers are 19010 26392 30183 6597 25443 9142 1734 14084 1773 19250
The max numbers is 30183
The min numbers is 1734
[root@centos7 scripts]# bash min_max.sh
All numbers are 29778 25987 3225 6644 4313 14984 14970 9396 19655 18413
The max numbers is 29778
The min numbers is 3225

Ejemplo 2: Ingrese varios valores y guárdelos en la matriz, y use el algoritmo de burbuja para ordenar en orden ascendente o descendente

[root@centos7 scripts]# bash maopao.sh
#!/bin/bash
echo "请输入任意数量的数值,空格隔开:"
read -a array
    for((i=0;i<${#array[*]}-1;i++))
    do
        for((j=0;j<${#array[*]}-i-1;j++))
        do
            if [ ${array[j]} -gt ${array[j+1]} ];then
                temp=${array[j]}
                array[j]=${array[j+1]}
                array[j+1]=$temp
             fi
        done
        echo "第`expr $i + 1`次排序结果: ${array[*]}"
done
echo "排序结果为:${array[*]}"

[root@centos7 scripts]# bash maopao.sh
请输入任意数量的数值,空格隔开:
1 5 3 8 0 6
第1次排序结果: 1 3 5 0 6 8
第2次排序结果: 1 3 0 5 6 8
第3次排序结果: 1 0 3 5 6 8
第4次排序结果: 0 1 3 5 6 8
第5次排序结果: 0 1 3 5 6 8
排序结果为:0 1 3 5 6 8
[root@centos7 scripts]# bash maopao.sh
请输入任意数量的数值,空格隔开:
56 129 2 5 -3 12 0 35
第1次排序结果: 56 2 5 -3 12 0 35 129
第2次排序结果: 2 5 -3 12 0 35 56 129
第3次排序结果: 2 -3 5 0 12 35 56 129
第4次排序结果: -3 2 0 5 12 35 56 129
第5次排序结果: -3 0 2 5 12 35 56 129
第6次排序结果: -3 0 2 5 12 35 56 129
第7次排序结果: -3 0 2 5 12 35 56 129
排序结果为:-3 0 2 5 12 35 56 129

Supongo que te gusta

Origin blog.51cto.com/puppydong/2675635
Recomendado
Clasificación