1、Ubuntu系统网络配置总结

1.1 主机名

修改主机名

root@ubuntu20:/home/dong# hostnameubuntu20root@ubuntu20:/home/dong# hostnamectl set-hostname ubuntu20.magedu.cnroot@ubuntu20:/home/dong# hostnameubuntu20.magedu.cnroot@ubuntu20:/home/dong# cat /etc/hostnameubuntu20.magedu.cnroot@ubuntu20:/home/dong# echo $HOSTNAME        #不能立即生效,重新登录后生效ubuntu20root@ubuntu20:/home/dong# logoutbash: logout: not login shell: use `exit'root@ubuntu20:/home/dong# exitexitdong@ubuntu20:~$ suPassword:root@ubuntu20:/home/dong# echo $HOSTNAMEubuntu20.magedu.cn

1.2 网卡名称

默认ubuntu的网卡名称和 CentOS 7 类似,如:ens33,ens38等

修改网卡名称为传统命名方式:

#查看网卡默认名称为ens系列root@ubuntu20:~# ip a |grep ens2: 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/grubGRUB_DEFAULT=0GRUB_TIMEOUT_STYLE=hiddenGRUB_TIMEOUT=0GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`GRUB_CMDLINE_LINUX_DEFAULT="maybe-ubiquity"GRUB_CMDLINE_LINUX=""1)修改配置文件GRUB_CMDLINE_LINUXroot@ubuntu20:~# sed -i.bak '/^GRUB_CMDLINE_LINUX=/s#"$#net.ifnames=0"#' /etc/default/grub2)生成新的grub.cfg文件root@ubuntu20:~# grub-mkconfig -o /boot/grub/grub.cfgSourcing 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-genericFound initrd image: /boot/initrd.img-5.4.0-42-genericdone#或者root@ubuntu20:~# update-grubroot@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=0dong@ubuntu20:~$#重启后生效root@ubuntu20:~# reboot3)重启后,eth0无ip地址,替换原配置的接口名称root@ubuntu20:~# sed -i 's/ens33/eth0' /etc/netplan/00-installer-config.yamlroot@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: 2root@ubuntu20:~# ip a |grep eth02: 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 Ubuntu网卡配置

官网文档:
帮助文档:https://help.ubuntu.com/
https://help.ubuntu.com/lts/serverguide/network-configuration.html.zh-CN
网络配置文档:https://ubuntu.com/server/docs/network-configuration

网络配置文件:yaml格式
1)- 列表:表示多个成员或[ ]
2)键(变量名):值
3)不同层级有缩进,而且统一

1.3.1 配置自动获取IP

范例:

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 applyroot@ubuntu20:~# ip a|grep eth02: 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 配置静态IP

范例:

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/24root@ubuntu20:~# ip a|grep eth02: 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

查看ip和gateway

root@ubuntu20:/etc/apt# ip a1: 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 forever2: 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

查看路由表route

#1)执行route -nroot@ubuntu20:~# route -n   #route没有安装,需安装net-tools文件Command 'route' not found, but can be installed with:apt install net-toolsroot@ubuntu20:~# apt install net-toolsReading package lists... DoneBuilding dependency treeReading state information... DoneThe following NEW packages will be installed:  net-tools0 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/aptroot@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 multiversedeb 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 multiversedeb 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 multiversedeb 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 -nKernel IP routing tableDestination     Gateway         Genmask         Flags Metric Ref    Use Iface0.0.0.0         192.168.100.2   0.0.0.0         UG    0      0        0 eth0192.168.100.0   0.0.0.0         255.255.255.0   U     0      0        0 eth0

查看DNS

dong@ubuntu20:~$ ll /etc/resolv.conflrwxrwxrwx 1 root root 39 Jul 31  2020 /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.confdong@ubuntu20:~$ systemd-resolve --statusGlobal       LLMNR setting: noMulticastDNS 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                      testLink 2 (eth0)      Current Scopes: DNSDefaultRoute setting: yes       LLMNR setting: yesMulticastDNS 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 配置多⽹卡静态IP和静态路由

1、多个网卡配置都在一个文件

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.1root@ubuntu20:~# netplan applyroot@ubuntu20:~# ip a|grep eth2: 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 eth03: 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 eth1root@ubuntu20:~# route -nKernel IP routing tableDestination     Gateway         Genmask         Flags Metric Ref    Use Iface0.0.0.0         192.168.100.2   0.0.0.0         UG    0      0        0 eth010.10.100.0     172.16.100.1    255.255.255.0   UG    0      0        0 eth1172.16.100.0    0.0.0.0         255.255.255.0   U     0      0        0 eth1172.18.100.0    172.16.100.1    255.255.255.0   UG    0      0        0 eth1172.19.100.0    172.16.100.1    255.255.255.0   UG    0      0        0 eth1192.168.100.0   0.0.0.0         255.255.255.0   U     0      0        0 eth0

2、每个网卡各自一个配置文件

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: 2root@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.1root@ubuntu20:~# netplan applyroot@ubuntu20:~# ip a1: 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 forever2: 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 forever3: 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 foreverroot@ubuntu20:~# route -nKernel IP routing tableDestination     Gateway         Genmask         Flags Metric Ref    Use Iface0.0.0.0         192.168.100.2   0.0.0.0         UG    0      0        0 eth010.10.100.0     172.16.100.1    255.255.255.0   UG    0      0        0 eth1172.16.100.0    0.0.0.0         255.255.255.0   U     0      0        0 eth1172.18.100.0    172.16.100.1    255.255.255.0   UG    0      0        0 eth1172.19.100.0    172.16.100.1    255.255.255.0   UG    0      0        0 eth1192.168.100.0   0.0.0.0         255.255.255.0   U     0      0        0 eth0root@ubuntu20:~#

2 函数介绍

  • 函数function是由若干条shell命令组成的语句块,实现代码重用和模块化编程
  • 它与shell程序形式上是相似的,不同的是它不是一个单独的进程,不能独立运行,而是shell程序的一部分

函数和shell程序比较相似,区别在于

==Shell程序在子Shell中运行,而Shell函数在当前Shell中运行==。因此在当前Shell中,函数可对shell中的变量进行修改

2.1 管理函数

函数由两部分组成:函数名和函数体

帮助参看:help function

2.1.1 定义函数

格式:

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

定义函数范例:函数定义和调用在一个脚本中

1)创建一个关闭防火墙和selinux的函数[root@repo-client scripts]# cat all_functionsdisable_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/configSELINUX=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/configSELINUX=disabled2)创建centos7统一的repo[root@repo-client scripts]# cat all_functionsyum_repo () {    cd /etc/yum.repos.d/    mkdir backup -p    mv *.repo backup    cat > base.repo <<EOF[BaseOS-aliyun]name=centos7 repo-server BaseOS by aliyunbaseurl=https://mirrors.aliyun.com/centos/7/os/x86_64/gpgcheck=0[epel]name=centos7 repo-server epelbaseurl=https://mirrors.aliyun.com/epel/7/x86_64/gpgcheck=0[extras]name=centos7 repo-server extrasbaseurl=https://mirrors.aliyun.com/centos/7/extras/x86_64/gpgcheck=0EOF}yum_repo#查看原来的yum.repos.d目录中的文件[root@repo-client yum.repos.d]# lsbackup  centos7-client.repo  Centos-7.repo  CentOS-Base.repo[root@repo-client scripts]# . all_functionsmv: overwrite ‘backup/CentOS-Base.repo’? y[root@repo-client yum.repos.d]# lltotal 4drwxr-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 repolistrepo id               repo name                                     statusBaseOS-aliyun         centos7 repo-server BaseOS by aliyun          10,072epel                  centos7 repo-server epel                      13,564extras                centos7 repo-server extras                    460repolist: 24,096

范例:函数定义和调用分开

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#关闭防火墙和selinuxdisable_firewall_selinux3)测试执行[root@repo-client scripts]# . dis_firewall_selinux.sh

范例:安装常用软件的函数

1)该函数也定义在统一的脚本文件all_functions中[root@repo-client scripts]# cat all_functions#1)关闭防火墙和selinuxdisable_firewall_selinux () {...省略...}#2)统一yum源仓库yum_repo () {...省略...}#3)安装常用软件工具install_packages () {PACKAGES="vimtreeautofsnet-toolsgccmakeautoconfpcrepcre-developensslopenssl-develvimlrzsztmuxlsoftcpdumpwgetiotop"for i in $PACKAGES; do        rpm -q $i &> /dev/null || yum -q -y install $idone}2、编写安装脚本,测试[root@repo-client scripts]# rpm -q vim lrzsz lsof gccpackage vim is not installedpackage lrzsz is not installedpackage lsof is not installedpackage gcc is not installed[root@repo-client scripts]# . install_packages.sh...安装过程省略...[root@repo-client scripts]# rpm -q vim lrzsz lsof gccpackage vim is not installedlrzsz-0.12.20-36.el7.x86_64lsof-4.87-6.el7.x86_64gcc-4.8.5-44.el7.x86_64

范例:调用函数的简易运维菜单脚本

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

2.1.2 查看函数

#查看当前已定义的函数名declare -F#查看当前已定义的函数定义declare -f#查看指定当前已定义的函数名declare -f func_name#查看当前已定义的函数名定义declare -F func_name[root@repo-client scripts]# declare -fdisable_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 -Fdeclare -f disable_firewall_selinuxdeclare -f yum_repo

2.1.3 删除函数

unset func_name     #删除函数

2.2 函数调用

范例1:函数体内执行的变量赋值,影响外面的变量值

[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

范例2:避免同名变量的冲突,local

若函数内定义的变量只在函数内有效,需要定义成本地变量,即使用local定义,只在函数体内或子进程有效。

[root@repo-client scripts]# type locallocal is a shell builtin[root@repo-client scripts]# help locallocal: 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#变量赋值为localtest () {        local NAME        NAME=mage       #这两条可以合并为local NAME=mage        echo NAME=$NAME}[root@repo-client scripts]# . test1[root@repo-client scripts]# testNAME=mage[root@repo-client scripts]# NAME=wang[root@repo-client scripts]# echo $NAMEwang[root@repo-client scripts]# test            #函数内变量NAME=mage[root@repo-client scripts]# echo $NAME      #函数外同名变量,不冲突了wang

函数的调用方式

  • 可在交互式环境下定义函数

  • 可将函数放在脚本文件中作为它的一部分

  • 可放在只包含函数的单独文件中

调用:函数只有被调用才会执行,通过给定函数名调用函数,函数名出现的地方,会被自动替换为函数代码

函数的生命周期:被调用时创建,返回时终止

#系统自带的函数文件,可以在脚本中直接调用[root@repo-client scripts]# grep  -E -A10 "^(action|success)" /etc/init.d/functionssuccess() {    [ "$BOOTUP" != "verbose" -a -z "${LSB:-}" ] && echo_success    return 0}# Log that something failedfailure() {    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 flejlfldsfe -bash: flejlf: command not found                     [FAILED]

2.3 函数返回值

1、函数的执行结果返回值:

  • 使用echo等命令进行输出

  • 函数体中调用命令的输出结果

2、函数的退出状态码:

默认取决于函数中执行的最后一条命令的退出状态码

3、自定义退出状态码,其格式为:

  • return 从函数中返回,用最后状态命令决定返回值

  • return 0 无错误返回

  • return 1-255 有错误返回
#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函数. test1test#返回值echo statue=$?[root@repo-client scripts]# bash test1.shNAME=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 statueNAME=magestatue=100

2.4 交互式转化批处理工具 expect

expect 是由Don Libes基于 Tcl( Tool Command Language )语言开发的,主要应用于自动化交互式操作的场景,借助 expect 处理交互的命令,可以将交互过程如:ssh登录,ftp登录等写在一个脚本上,使之自动化完成。尤其适用于需要对多台服务器执行相同操作的环境中,可以大大提高系统管理人员的工作效率。最小化安装系统中没有这个命令,yum安装即可。

expect 语法:

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

常见选项:

-c:从命令行执行expect脚本,默认expect是交互地执行的
-d:可以输出调试信息

示例:

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

expect中相关命令

  • spawn 启动新的进程
  • expect 从进程接收字符串
  • send 用于向进程发送字符串
  • interact 允许用户交互

  • exp_continue 匹配多个字符串在执行动作后加此命令

expect最常用的语法(tcl语言:模式-动作)

单一分支模式语法:匹配到hi后,会输出“you said hi”,并换行

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

多分支模式语法:匹配hi,hello,bye任意字符串时,执行相应输出。不过是一次性的,等同如下

[root@centos8 test]#expectexpect1.1> expect "hi" { send "You said hi\n" } "hehe" { send "Hehe yourself\n"} "bye" { send "Good bye\n" }heheHehe yourselfexpect1.2> expect "hi" { send "You said hi\n" } "hehe" { send "Hehe yourself\n"} "bye" { send "Good bye\n" }byeGood byeexpect1.3> expect "hi" { send "You said hi\n" } "hehe" { send "Hehe yourself\n"} "bye" { send "Good bye\n" }hiYou said hiexpect1.4> exit[root@centos7 expect]# expectexpect1.1> expect {+> "hi" { send "You said hi\n"}+> "hehe" { send "Hehe yourself\n"}+> "bye" { send " Good bye\n"}+> }bye Good byeexpect1.2>

范例1:从10.0.0.8主机,非交互式复制fstab文件到7主机的data目录下

[root@centos7 expect]# cat expect1#!/usr/bin/expectspawn scp /etc/fstab 192.168.100.11:/dataexpect {    "yes/no" { send "yes\n";exp_continue }    "password" { send "dongdong\n" }}expect eof[root@centos7 expect]# chmod +x expect1[root@centos7 expect]# ./expect1spawn scp /etc/fstab 192.168.100.11:/dataThe 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)? yesWarning: Permanently added '192.168.100.11' (ECDSA) to the list of known hosts.root@192.168.100.11'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

范例2:自动登录

[root@centos7 expect]# cat expect2#!/usr/bin/expectspawn ssh 192.168.100.11expect {    "yes/no" { send "yes\n";exp_continue }    "password" { send "dongdong\n" }}interact[root@centos7 expect]# chmod +x expect2[root@centos7 expect]# ./expect2spawn ssh 192.168.100.11root@192.168.100.11's password:Last login: Thu Mar 25 21:53:35 2021 from 192.168.100.1[root@c7-test ~]# exitlogoutConnection to 192.168.100.11 closed.[root@centos7 expect]#

范例3:定义expect 变量实现非交互式登录

[root@centos7 expect]# cat expect3#!/usr/bin/expectset ip 192.168.100.11set user rootset password dongdongset timeout 10spawn ssh $user@$ipexpect {    "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]# ./expect3spawn ssh root@192.168.100.11root@192.168.100.11's password:Last login: Thu Mar 25 21:56:36 2021 from 192.168.100.12[root@c7-test ~]# exitlogoutConnection to 192.168.100.11 closed.[root@centos7 expect]#

范例4:expect 位置参数,相当于$1 $2等

[root@centos7 expect]# cat expect4#!/usr/bin/expectset ip [lindex $argv 0]set user [lindex $argv 1]set password [lindex $argv 2]spawn ssh $user@$ipexpect {    "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 dongdongspawn ssh root@192.168.100.11root@192.168.100.11's password:Last login: Thu Mar 25 22:08:21 2021 from 192.168.100.12[root@c7-test ~]# exitlogoutConnection to 192.168.100.11 closed.[root@centos7 expect]#

范例5:expect 非交互登录到对方主机,执行多个命令

[root@centos7 expect]# cat expect5#!/usr/bin/expectset ip [lindex $argv 0]set user [lindex $argv 1]set password [lindex $argv 2]set timeout 10#非交互登录到对方主机spawn ssh $user@$ipexpect {        "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 dongdongspawn ssh root@192.168.100.11root@192.168.100.11'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 hahaChanging password for user haha.passwd: all authentication tokens updated successfully.[root@c7-test ~]# exitlogoutConnection to 192.168.100.11 closed.[root@centos7 expect]#[root@c7-test ~]# getent passwd|grep hahahaha:x:2011:2011::/home/haha:/bin/bash

范例6:shell脚本调用expect,登录到对方主机,并创建用户

[root@centos7 expect]# cat expect6.sh#!/bin/baship=$1user=$2password=$3expect <<EOFset timeout 20spawn ssh $user@$ipexpect {    "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 eofEOF[root@centos7 expect]# chmod +x expect6.sh[root@centos7 expect]# ./expect6.sh 192.168.100.11 root dongdongspawn ssh root@192.168.100.11root@192.168.100.11'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 heheChanging password for user hehe.passwd: all authentication tokens updated successfully.[root@c7-test ~]# exitlogoutConnection to 192.168.100.11 closed.[root@centos7 expect]#[root@c7-test ~]# getent passwd|grep hehehehe:x:2012:2012::/home/hehe:/bin/bash

3 数组array

3.1 数组介绍

变量:存储单个元素的内存空间

数组:存储多个元素的连续的内存空间,相当于多个变量的集合

数组名和索引

  • 索引的编号从0开始,属于数值索引
  • 索引可支持使用自定义的格式,而不仅是数值格式,即为关联索引,bash4.0版本之后开始支持(centos6之后)
  • bash的数组支持稀疏格式(索引不连续)

3.2 声明数组

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

注意:两者不可相互转换

范例:数组不能相互转换

#关联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 filedeclare -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 数组赋值

数组元素的赋值

(1) 一次只赋值一个元素

ARRAY_NAME[INDEX]=VALUE

范例:

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

范例:单个元素赋值

[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 titledeclare -a title='([0]="ceo" [1]="cto")'

(2) 一次赋值全部元素

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

范例:

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

范例:一次赋值全部元素

[root@centos7 ~]# name=(mage wang li zhao)[root@centos7 ~]# declare -a name[root@centos7 ~]# declare -a |grep namedeclare -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 numdeclare -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]# lsargsnum.sh     dir.sh         expect    for_99.sh      for_continue.sh  for_prename.sh   guess_number.sh  menu.sh   shift_doit.sh     trap.shcolor.sh       disk_check.sh  file.sh   for_break2.sh  for_mkdir.sh     for_scanhost.sh  hostping.sh      per.sh    shift_useradd.shcreateuser.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 filedeclare -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) 只赋值特定元素

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

(4) 交互式数组值对赋值

read -a ARRAY

范例:

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

3.4 显示所有数组

显示所有数组:

declare -a

范例:

[root@centos7 ~]# declare -adeclare -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 引用数组

引用数组元素

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

范例:

[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 ~]#

引用数组所有元素

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

范例:

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

数组的长度,即数组中元素的个数

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

范例:

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

3.6 删除数组

删除数组中的某元素,会导致稀疏格式,数组不连续

[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

删除整个数组

unset ARRAY

范例:

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

3.7 关联数组

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

注意:关联数组必须先声明再调用,下标随意定义。一个数组中可以存放多个变量(key)和值(value)。

范例:未定义关联数组

#如果默认创建关联数组,会当成普通索引数组,下标不合理,会合并成一个下标,即0[root@centos7 ~]# magedu[ceo]=mage[root@centos7 ~]# declare -a |grep magedu   #第一次定义的下标是ceo,但识别出来的只是0declare -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")'

范例:定义关联数组

[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 magedudeclare -A magedu='([ceo]="mage" [cto]="wang" )'[root@centos7 ~]#

范例:定义一个数组多个元素

[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 studentdeclare -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]}; donestudent[name1]=lijunstudent[name2]=ziqingstudent[name3]=student[name4]=student[name5]=student[name6]=student[name7]=student[name8]=student[name9]=student[name10]=[root@centos7 ~]#

3.8 范例

范例1:生成10个随机数保存于数组中,并找出其最大值和最小值

[root@centos7 scripts]# cat min_max.sh#!/bin/bashdeclare -i min maxdeclare -a numsfor ((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]}doneecho "All numbers are ${nums[*]}"echo Max is $maxecho Min is $min[root@centos7 scripts]# bash min_max.shAll numbers are 19010 26392 30183 6597 25443 9142 1734 14084 1773 19250The max numbers is 30183The min numbers is 1734[root@centos7 scripts]# bash min_max.shAll numbers are 29778 25987 3225 6644 4313 14984 14970 9396 19655 18413The max numbers is 29778The min numbers is 3225

范例2:输入若干个数值存入数组中,采用冒泡算法进行升序或降序排序

[root@centos7 scripts]# bash maopao.sh#!/bin/bashecho "请输入任意数量的数值,空格隔开:"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[*]}"doneecho "排序结果为:${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
©著作权归作者所有:来自51CTO博客作者puppydong的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. 串与数组,广义表
  2. 函数的嵌套调用和链式访问
  3. 函数的形参和实参
  4. 函数的声明和定义
  5. C语言函数功能的强大和入坑体会
  6. C语言中的函数概念
  7. C语言中的择中,二分查找算法解析
  8. C语言指针的理解
  9. 使用C语言判断密码是否正确,三次失败就退出,超详细教程!!

随机推荐

  1. php连接mssql两种方法(com &amp; pdo)
  2. 本机PHP函数将授予我直接访问字符串部分
  3. php多进程处理
  4. 基于MySQL查询的Laravel路由
  5. 【实战】如何通过html+css+mysql+php来快
  6. 在使用PHP编程时,使用存储过程还是硬编码S
  7. 如何在php / mysql中使用事务
  8. Zend Studio-8.0.0中文汉化教程及入门教
  9. 使用php codeigniter进行Mysql数据库同步
  10. 填充PHP数组:首先检查索引?