09 网络管理和shell进阶

09 网络管理和shell进阶

1 网络管理和工具命令解读

1.1 常见命令

1.1.1hostname

hostname										#临时设置主机名,需要退出终端后或使用exec /bin/bash后生效
hostnamectl hostname [name]						#永久设置主机名
hostname -A										#可从/etc/hosts文件中提取主机名
[root@localhost ~]# hostname -I					#可从网卡中提取IP地址
10.0.2.15 fd17:625c:f037:2:a00:27ff:fe78:e15e 

1.1.2 ifconfig

老牌 系统默认
软件名 net-tools iproute
网卡ip地址 ifconifg ip address
路由配置 route ip route
端口信息 netstat ss
安装 手工 默认
#需要前置使用net-tools来安装
[root@localhost ~]# ifconfig enp0s3
enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.2.15  netmask 255.255.255.0  broadcast 10.0.2.255
        inet6 fd17:625c:f037:2:a00:27ff:fe78:e15e  prefixlen 64  scopeid 0x0<global>
        inet6 fe80::a00:27ff:fe78:e15e  prefixlen 64  scopeid 0x20<link>
        ether 08:00:27:78:e1:5e  txqueuelen 1000  (Ethernet)
        RX packets 440  bytes 73679 (71.9 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 390  bytes 47153 (46.0 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@localhost ~]# ifconfig enp0s3 | grep netmask
        inet 10.0.2.15  netmask 255.255.255.0  broadcast 10.0.2.255
[root@localhost ~]# ifconfig enp0s3 | grep netmask |awk '{print $2}'
10.0.2.15

#临时修改IP地址
[root@localhost ~]# ifconfig enp0s3 10.0.2.16

#创建网卡别名
[root@localhost ~]# ifconfig enp0s3:1 10.0.2.20 up									#注意,up是默认项,可不写
[root@localhost ~]# ifconfig
enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.2.15  netmask 255.0.0.0  broadcast 10.255.255.255
        inet6 fd17:625c:f037:2:a00:27ff:fe78:e15e  prefixlen 64  scopeid 0x0<global>
        inet6 fe80::a00:27ff:fe78:e15e  prefixlen 64  scopeid 0x20<link>
        ether 08:00:27:78:e1:5e  txqueuelen 1000  (Ethernet)
        RX packets 814  bytes 103229 (100.8 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 654  bytes 72119 (70.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

enp0s3:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500						#网卡别名,本质上使用的还是一个物理网卡
        inet 10.0.2.20  netmask 255.0.0.0  broadcast 10.255.255.255
        ether 08:00:27:78:e1:5e  txqueuelen 1000  (Ethernet)

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

#关闭网卡别名
[root@localhost ~]# ifconfig enp0s3:1 10.0.2.20 down
[root@localhost ~]# ifconfig
enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.2.15  netmask 255.0.0.0  broadcast 10.255.255.255
        inet6 fd17:625c:f037:2:a00:27ff:fe78:e15e  prefixlen 64  scopeid 0x0<global>
        inet6 fe80::a00:27ff:fe78:e15e  prefixlen 64  scopeid 0x20<link>
        ether 08:00:27:78:e1:5e  txqueuelen 1000  (Ethernet)
        RX packets 876  bytes 108017 (105.4 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 692  bytes 77023 (75.2 KiB)
        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

1.1.3 route

动态路由:自动生成

静态路由:手工编写写死的

默认路由:default

网关:距离目标网段最近的一个本网段的IP地址,相当于是本网段的出口

#添加一个具体的网段,通过网关10.0.0.2去访问
route add -net 10.0.1.0/24 gw 10.0.0.2
#添加一个具体的主机地址,通过网关10.0.0.2去访问
route add -host 10.0.0.13/24 gw 10.0.0.2
#同理,删除则将add更换为del即可

1.1.4 netstat

#用来查看正在使用且在监听的端口
[root@localhost ~]# netstat -tunlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      821/sshd: /usr/sbin 
tcp6       0      0 :::22                   :::*                    LISTEN      821/sshd: /usr/sbin 
udp        0      0 127.0.0.1:323           0.0.0.0:*                           779/chronyd         
udp6       0      0 ::1:323                 :::*                                779/chronyd         

#查看某个网卡上的数据传输信息
[root@localhost ~]# netstat -I=enp0s3
Kernel Interface table
Iface             MTU    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg
enp0s3           1500     1281      0      0 0          1012      0      0      0 BMRU

1.1.5 ip

#ip link命令用于修改网卡本身的内容
[root@localhost ~]# ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 08:00:27:78:e1:5e brd ff:ff:ff:ff:ff:ff
    altname enx08002778e15e
[root@localhost ~]# ip link show enp0s3
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 08:00:27:78:e1:5e brd ff:ff:ff:ff:ff:ff
    altname enx08002778e15e

#ip addr相关命令
ip a
#ip a a 等同于ip addr add
ip addr add [IP地址]/[子网掩码] dev [设备名称]					#为指定网卡添加IP地址
ip addr del [IP地址]/[子网掩码] dev [设备名称]					#为指定网卡删除IP地址

#ip r路由添加用add,删除用del
ip route add TARGET via GW dev IFACE src SOURCE_IP
ip route add 11.0.0.0/24 via 10.0.0.2
ip route add 11.0.0.1 via 10.0.0.2
ip route add default via 10.0.0.2

1.1.6 ss

[root@localhost ~]# netstat -tunlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      821/sshd: /usr/sbin 
tcp6       0      0 :::22                   :::*                    LISTEN      821/sshd: /usr/sbin 
udp        0      0 127.0.0.1:323           0.0.0.0:*                           779/chronyd         
udp6       0      0 ::1:323                 :::*                                779/chronyd         
[root@localhost ~]# ss -tunlp
Netid State  Recv-Q Send-Q  Local Address:Port   Peer Address:Port Process                           
udp   UNCONN 0      0           127.0.0.1:323         0.0.0.0:*     users:(("chronyd",pid=779,fd=5)) 
udp   UNCONN 0      0               [::1]:323            [::]:*     users:(("chronyd",pid=779,fd=6)) 
tcp   LISTEN 0      128           0.0.0.0:22          0.0.0.0:*     users:(("sshd",pid=821,fd=7))    
tcp   LISTEN 0      128              [::]:22             [::]:*     users:(("sshd",pid=821,fd=8))    

1.2 nmcli

NetworkManager
	是2004年由RedHat开始启动的项目
该项目提供了丰富的管理工具:
	- 图形工具:nm-connection-editor
	- 字符配置工具:nmtui nmtui-connect nmtui-edit nmtui-hostname
	- 命令行工具:nmcli
[root@localhost ~]# systemctl status NetworkManager
● NetworkManager.service - Network Manager
     Loaded: loaded (/usr/lib/systemd/system/NetworkManager.service; enabled; preset: enabled)
     Active: active (running) since Wed 2026-01-28 12:33:10 CST; 1h 37min ago
 Invocation: a0fb6af2ca0e46bd9449c5ae3e363fa9
       Docs: man:NetworkManager(8)
   Main PID: 812 (NetworkManager)
      Tasks: 4 (limit: 10643)
     Memory: 9.1M (peak: 9.7M)
        CPU: 341ms
     CGroup: /system.slice/NetworkManager.service
             └─812 /usr/sbin/NetworkManager --no-daemon

1月 28 12:33:11 localhost.localdomain NetworkManager[812]: <info>  [1769574791.0065] device (enp0s3)>
1月 28 12:33:11 localhost.localdomain NetworkManager[812]: <info>  [1769574791.0078] manager: Networ>
1月 28 12:33:11 localhost.localdomain NetworkManager[812]: <info>  [1769574791.0085] manager: startu>
1月 28 12:33:12 localhost.localdomain NetworkManager[812]: <info>  [1769574792.8559] policy: set-hos>
1月 28 12:33:13 localhost.localdomain NetworkManager[812]: <info>  [1769574793.0501] policy: set en>
1月 28 12:33:13 localhost.localdomain NetworkManager[812]: <info>  [1769574793.0502] policy: set-hos>
1月 28 12:33:13 localhost.localdomain NetworkManager[812]: <info>  [1769574793.0577] policy: set-hos>
1月 28 12:33:14 localhost.localdomain NetworkManager[812]: <info>  [1769574794.7643] policy: set-hos>
1月 28 12:33:32 localhost.localdomain NetworkManager[812]: <info>  [1769574812.6790] policy: set-hos>
1月 28 12:34:02 localhost.localdomain NetworkManager[812]: <info>  [1769574842.6660] policy: set-hos>


[root@localhost ~]# nmcli conn
NAME    UUID                                  TYPE      DEVICE 
enp0s3  c602f455-8fba-37c7-9875-c6021ae19ebe  ethernet  enp0s3 
lo      a5c4c4a7-a2db-44fd-86f2-1daa5ccaaffa  loopback  lo     

#状态管理
nmcli conn down 网卡名
nmcli conn up  网卡名

#设备管理
nmcli deivce up 网卡名			#新网卡,没有配置文件的时候需要UP,后续还需要执行down,也可用cp命令拷贝旧的网卡配置直接更改

1.3 网卡高可用

在Linux操作系统中,网卡绑定(Bonding,也叫链路聚合)和网络组(Network Teaming,常称Team)都用于多网卡聚合,实现冗余、负载均衡,但在实现方式、功能特性、适用场景等方面有区别。

  • 网卡绑定:Linux传统的多网卡聚合技术,依赖内核bonding驱动实现
  • 网络组:较新的多网卡聚合方案,将多网卡聚合为逻辑组,提供更灵活的模型和扩展性,由teamd守护进程+内核驱动共同实现
维度 网卡绑定(Bonding) 网络组(Network Teaming)
依赖组件 仅内核bonding驱动,无需额外守护进程 依赖teamd守护进程(用户态)+内核驱动配合
配置复杂度 配置相对简单,通过/etc/sysconfig/network-scripts/(传统方式或nmcli等工具设置) 配置更灵活(支持json定义模式),但需熟悉teamd语法,学习成本稍高
管理工具 用ifconfig|ip link等传统命令,或nmcli管理 依赖teamdctl工具(如teamctl team0 state查状态),也可结合nmcli
网卡绑定的常见模式
0				#轮询模式,按顺序在多网卡发数据包,实现负载均衡+冗余
1				#主备模式,仅1个网卡工作,故障时切换到备份网卡
4				#基于LACP协议的聚合,需交换机配合,动态协商链路聚合。

网络组常见模式
activebackup	#类似bonding的主备模式
roundrobin		#轮询发包,负载均衡+冗余
lacp			#对接802.3ad协议,需交换机支持,动态聚合链路
loadbalance		#基于BPD(Berkeley包过滤器)的智能负载均衡,更灵活分配流量

#新系统,优先网络组,老系统,优先bonding

2 网络综合实践

2.1 软路由

2.1.1 简介

软路由是一种基于软件实现的路由器技术,它利用标准的计算机硬件作为路由器,并通过安装特定的软件来达成路由器的功能。

2.1.2 原理

软路由主要依赖软件的设置来实现路由器的功能。这些软件通常被称为“固件”,可以运行在多种操作系统上。用户通过安装和配置这些固件,使普通的计算机具备路由器的功能,从而为用户提供网络接入、数据转发等服务。

2.1.3 特点

  • 成本低廉

    • 标准计算机硬件,成本较低
  • 灵活定制

    • 软路由的固件可以根据用户的需求进行定制和优化,以满足不同的网络环境和应用场景。打造专属于自己的网络环境。
  • 易维护

    • 由于软路由使用的是标准计算机硬件和软件,因此维护方便
  • 强大的功能

    • 软路由通常支持多种高级路由功能,如:静态路由,动态路由,多拨功能,VPN支持,此外,还可以实现网络防火墙,QoS,网络存储,网络监控等功能

2.1.4 软路由实践

使用Linux虚拟机,模拟路由器的能力-->转发的能力

要求能做到数据转发【ip_forwarded】

拓扑图如下所示:

img

10.0.0.12定制路由:

#Rocky Linux
echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf			#开启IP转发
route -net 192.168.8.0/24 gw 10.0.0.15
ip route add 192.168.8.0/24 via 10.0.0.15
#上述两条命令看命令支持的情况二选一

10.0.0.15定制路由:

#Rocky Linux
echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf			#开启IP转发
route -net 172.24.100.0/24 gw 10.0.0.12
ip route add 172.24.100.0/24 via 10.0.0.12
#上述两条命令看命令支持的情况二选一

2.1.5 网桥

Linux服务器模拟交换机,传递数据即可

#ubuntu下创建网桥,没有命令可安装
brctl addbr br0
brctl addif br0 ens33
brctl addif br0 ens37

#网桥创建完成之后需要将网桥和网卡全部启用
ip link set br0 up
ip link set ens33 up
ip link set ens37 up

3 诊断工具

作用分类 工具/命令
测试网络连通性 fping
显示正确的路由表 ip route,route
跟踪路由 traceroute,tracepath,mtr
确定名称服务器使用 nslookup,host,dig
抓包工具 tcpdump,wireshark
安全扫描工具 nmap,netcat(nc)
流量控制工具 tc

网络测试场景举例:

  1. 主机联通

    1. ping
    2. fping
  2. 排障

    1. 内部联通异常排障

      1. route
      2. ip route
    2. 外部联通异常排障

      1. traceroute
      2. tracepath
      3. mtr
    3. 正常远程连接,访问服务异常

      tcpdump

  3. 心态不正常,想要搞破坏

    1. nmap
    2. nc

3.1 fping

#针对某一范围的主机进行ping
fping -g 10.0.0.0/24
#检查该网段IP是否在使用

3.2 tcpdump

#环境部署之后,测试客户端和服务端数据传输是否正常
tcpdump -nn 							#所有的IP、port都以数字样式展示
tcpdump -i								#设备名
tcpdump host							#ip层首部包含的信息
tcpdump port							#tcp层首部包含的端口信息
tcpdump -w ./target.cap					#抓来的包全部丢到某个文件里面

#示例如下
#抓包专门的网卡
root@test-VirtualBox:~# tcpdump -nn -i enp0s3
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on enp0s3, link-type EN10MB (Ethernet), snapshot length 262144 bytes
12:40:44.536263 IP 10.0.2.15.22 > 10.0.2.2.19786: Flags [P.], seq 4037735665:4037735861, ack 6596384, win 65535, length 196
12:40:44.536501 IP 10.0.2.2.19786 > 10.0.2.15.22: Flags [.], ack 196, win 65535, length 0
12:40:44.678854 IP 10.0.2.15.22 > 10.0.2.2.19786: Flags [P.], seq 196:360, ack 1, win 65535, length 164
12:40:44.679092 IP 10.0.2.2.19786 > 10.0.2.15.22: Flags [.], ack 360, win 65535, length 0
12:40:44.679255 IP 10.0.2.15.22 > 10.0.2.2.19786: Flags [P.], seq 360:492, ack 1, win 65535, length 132
12:40:44.679477 IP 10.0.2.2.19786 > 10.0.2.15.22: Flags [.], ack 492, win 65535, length 0
12:40:44.869531 IP 10.0.2.15.22 > 10.0.2.2.19786: Flags [P.], seq 492:928, ack 1, win 65535, length 436
12:40:44.869779 IP 10.0.2.2.19786 > 10.0.2.15.22: Flags [.], ack 928, win 65535, length 0
12:40:44.995636 IP 10.0.2.15.22 > 10.0.2.2.19786: Flags [P.], seq 928:1172, ack 1, win 65535, length 244
12:40:44.995883 IP 10.0.2.2.19786 > 10.0.2.15.22: Flags [.], ack 1172, win 65535, length 0
12:40:45.580225 IP 10.0.2.15.22 > 10.0.2.2.19786: Flags [P.], seq 1172:1416, ack 1, win 65535, length 244
12:40:45.580522 IP 10.0.2.2.19786 > 10.0.2.15.22: Flags [.], ack 1416, win 65535, length 0
12:40:46.260131 IP 10.0.2.15.22 > 10.0.2.2.19786: Flags [P.], seq 1416:1660, ack 1, win 65535, length 244
12:40:46.260672 IP 10.0.2.2.19786 > 10.0.2.15.22: Flags [.], ack 1660, win 65535, length 0
12:40:47.166080 IP 10.0.2.15.22 > 10.0.2.2.19786: Flags [P.], seq 1660:1904, ack 1, win 65535, length 244
12:40:47.166631 IP 10.0.2.2.19786 > 10.0.2.15.22: Flags [.], ack 1904, win 65535, length 0
^C
16 packets captured
25 packets received by filter
0 packets dropped by kernel

#监听特定主机之间的通信
tcpdump ip host 10.0.0.12 adn 10.0.0.13

3.3 nmap

#针对网段端口等进行扫描|渗透方面专用的工具
#使用-h来查看nmap相关的信息,这里只做一些基础展示
[root@localhost ~]# nmap -h
Nmap 7.92 ( https://nmap.org )
Usage: nmap [Scan Type(s)] [Options] {target specification}
TARGET SPECIFICATION:
  Can pass hostnames, IP addresses, networks, etc.
  Ex: scanme.nmap.org, microsoft.com/24, 192.168.0.1; 10.0.0-255.1-254
  -iL <inputfilename>: Input from list of hosts/networks
  -iR <num hosts>: Choose random targets
  --exclude <host1[,host2][,host3],...>: Exclude hosts/networks
  --excludefile <exclude_file>: Exclude list from file
.
.
.
.
.
.
EXAMPLES:
  nmap -v -A scanme.nmap.org
  nmap -v -sn 192.168.0.0/16 10.0.0.0/8
  nmap -v -iR 10000 -Pn -p 80
SEE THE MAN PAGE (https://nmap.org/book/man.html) FOR MORE OPTIONS AND EXAMPLES

3.4 traceroute

[root@localhost ~]# ping www.baidu.com
PING www.a.shifen.com (223.109.82.212) 56(84) 字节的数据。
64 字节,来自 223.109.82.212: icmp_seq=1 ttl=255 时间=19.3 毫秒
64 字节,来自 223.109.82.212: icmp_seq=2 ttl=255 时间=18.9 毫秒
64 字节,来自 223.109.82.212: icmp_seq=3 ttl=255 时间=18.6 毫秒
64 字节,来自 223.109.82.212: icmp_seq=4 ttl=255 时间=18.7 毫秒
64 字节,来自 223.109.82.212: icmp_seq=5 ttl=255 时间=18.7 毫秒
64 字节,来自 223.109.82.212: icmp_seq=6 ttl=255 时间=18.6 毫秒
64 字节,来自 223.109.82.212: icmp_seq=7 ttl=255 时间=18.6 毫秒
^C
--- www.a.shifen.com ping 统计 ---
已发送 7 个包, 已接收 7 个包, 0% packet loss, time 7030ms
rtt min/avg/max/mdev = 18.550/18.768/19.294/0.235 ms

[root@localhost ~]# traceroute www.baidu.com
traceroute to www.baidu.com (223.109.82.212), 30 hops max, 60 byte packets
 1  _gateway (10.0.2.2)  4.691 ms  4.210 ms  3.819 ms
 2  * * *
 3  * * *
 4  * * *
 5  * * *
 6  * * *
 7  * * *
.
.
.
.
28  * * *
29  * * *
30  * * *

#该信息可被防火墙拦截,也可不显示

3.5 tracepath

[root@localhost ~]# tracepath www.baidu.com
 1?: [本地主机]                   PMTU 1500
 1:  _gateway                                              0.570 毫秒 
 1:  _gateway                                              2.054 毫秒 
 2:  无应答
 3:  无应答
 4:  无应答
^C

[root@localhost ~]# tracepath -n www.baidu.com
 1?: [本地主机]                   PMTU 1500
 1:  10.0.2.2                                              0.517 毫秒 
 1:  10.0.2.2                                              0.625 毫秒 
 2:  无应答
 3:  无应答

3.6 mtr

mtr是traceroute和ping的结合

4 shell编程进阶

4.1 循环语句

while --等到XXX的时候,我才执行YYY动作

	--达到条件要求,执行

until --在没有XXX的时候,我就执行YYY动作

	--达不到条件要求,执行
num = 1
while [条件判断]
do
	循环执行的语句
done

num = 1
until [条件判断]
do
	循环执行的语句
done
#上述两个可以实现死循环

for i in 列表
do
	循坏执行的语句
done
#上述实现的是有限个数的

#生成列表的方式
{1..6}
seq 起始值 步长 边界值

4.2 循环控制

continue		#满足条件的情况下,临时停止当前的循环,直接进入到下一循环

break			#满足条件的情况下,提前退出当前的循环

exit			#直接退出当前循环的程序

while  XXX
do
	判断-----continue		#跳过当前循环
	判断-----break			#终止当前循环
	判断-----exit			#退出程序
	zzz
done

4.3 函数

函数:功能代码块

如何定义函数|使用函数是重点

函数名(){
执行语句
}

4.3.1 函数传参

函数的使用必须先定义再调用

#!/bin/bash
#定义函数
say_hello(){
	echo "你好啊,张三"
}
#调用函数
say_hello

从简单函数定义和调用优化到通用场景下,进行传参

#!/bin/bash
#定义函数
say_hello(){
	echo "你好啊,$1"
}
#调用函数
say_hello "lisi"			#将lisi传参给$1

大通用场景下,脚本传参,函数调用--环境变量的灵活使用

#!/bin/bash
#定义脚本变量
name = "$1"
#定义函数
say_hello(){
	xingming="$1"
	echo "你好啊,$xingming"
}
#调用函数
say_hello "$name"

4.3.2 函数变量

#!/bin/bash
#定制普通的全局变量
message ="helloworld"

#定制一个函数,提示脚本的使用方式
function Usage {
	echo "直接调用脚本的message: ${message}"
	message="function-message"
	echo "函数体重置后的message: ${message}"
}

#定制脚本使用逻辑
while true
do
	read -p "查看变量的方式[ 1-脚本内| 2-函数内 ]: " type
	if[ ${type} == "1" ];then
		#直接在脚本环境使用全局变量
		echo ${message}
	elif [ ${type} == "2" ];then
		#函数内部使用全局变量
		Usage
	fi
done

4.3.3 函数退出

$?		系统默认的
		函数体内部 -- 最后一条命令的执行结果状态返回值

return	自定义状态返回值
		0~255
		后面只能跟数字

echo	可传递字符串数据

4.4 脚本自动化

4.4.1 脚本外执行自动化

4.4.1.1 信号相关

信号 描述
1 SIGHUP 挂起进程
2 SIGINT 终止进程
3 SIGQUIT 停止进程
9 SIGKILL 无条件终止进程
15 SIGTERM 优雅的终止进程
17 SIGSTOP 无条件停止进程,不终止进程
18 SIGSTP 停止或暂停进程,不终止进程
19 SIGCONT 继续运行停止的进程

4.4.1.2 trap

用于捕捉终止信号,也可用于自定义信号用于退出相关的进程

4.4.2 脚本内容执行自动化-可干预【read -p】

4.4.2.1 expect

免费的编程工具,实现自动的交互式任务,无需人工操作

4.4.2.1.1 基础命令
set			设定环境变量
				格式:set 变量名 变量值
				样式:set host "192.168.1.12"

spawn		启动新的进程,模拟手工在命令行启动服务
				格式:spawn 手工执行命令
				样式:spawn ssh python@$host

expect		接收一个新进程的反馈信息,我们根据进程的反馈,再发送对应的交互命令
				格式:expect "交互界面用户输入出的关键字"
				样式:expect "*password*"

send		接收一个字符串参数,并将该参数发送到新进程
				格式:send "用户输入的信息"
				样式:send "$password\r"

interact	退出自动化交互界面,进入用户交互状态,如果需要用户交互的话,这条命令必须在最后一行
				格式:interact
				样式:interact
其它命令
	expect eof		expect执行内容的结束标识符,退出当前脚本,与interact只能存在一个
	exp_continue	expect获取期望后,还会有另外的期望,那么我们就把多个期望连续执行
4.4.2.2.2 自动登录脚本
#!/bin/bash
#定义指定参数
host="$1"
username="$2"
password="$3"

/usr/bin/expect <<-EOF
spawn ssh ${username}@${host}

expect {
	"yes/no*" {send "yes\n";exp_continue  }
	"password:" {send "${password}\n";}
}
puts "测试完毕!!!"
expect eof
EOF
4.4.2.2.3 定制脚本文件 remotehost_sshkey_auth.sh
#!/bin/bash
# 功能:设置ssh跨主机免密码认证
# 版本:v0.1
# 作者:王树森
# 联系:sswang.magedu.com
# 定制普通变量
user_dir="/root"
login_uesr='root'
login_pass='123456'
# 定制数组变量
target_type=(部署 免密 退出)
# 定制安装软件的函数
expect_install(){
    yum install expect -y >> /dev/null
    echo "软件安装完毕"
}
# 定制ssh秘钥对的生成
sshkey_create(){
    # 清理历史秘钥
    [ -d ${user_dir}/.ssh ] && rm -rf ${user_dir}/.ssh
    # 生成新的秘钥
    ssh-keygen -t rsa -P "" -f ${user_dir}/.ssh/id_rsa >> /dev/null
    echo "秘钥生成完毕"
}
# 定制expect的认证逻辑
expect_process(){
    # 注意:这里不要乱用$1,可以参考函数和脚本间的数组传参
    command="$@"
    expect -c "
        spawn ${command}
        expect {
            \"*yes/no*\" {send \"yes\r\"; exp_continue}
            \"*password*\" {send \"${login_pass}\r\"; exp_continue}
            \"*Password*\" {send \"${login_pass}\r\";}
        }"
}
# 跨主机密码认证
sshkey_auth(){
    local host_list="$1"
    for i in ${host_list}
    do
        command="/usr/bin/ssh-copy-id -i /root/.ssh/id_rsa.pub"
        remote="${login_uesr}@$i"
        expect_process ${command} ${remote}
    done
}
# 定制服务的操作提示功能函数
menu(){
    echo -e "\e[31m---------------管理平台操作界面---------------"
    echo -e " 1: 秘钥准备 2: 免密认证 3: 退出操作"
    echo -e "-------------------------------------------\033[0m"
}
# 定制脚本帮助信息
Usage(){
    echo "请输入有效的操作标识!!!"
}
# 定制业务逻辑
while true
do
    menu
    read -p "> 请输入要操作的目标类型: " target_id
    if [ ${target_type[$target_id-1]} == "部署" ];then
        echo "开始部署秘钥环境..."
        expect_install
        sshkey_create
    elif [ ${target_type[$target_id-1]} == "免密" ];then
        read -p "> 请输入免密10.0.0网段主机的范围,示例{12..19}: " num_list
        # eval的隐藏命令解析,仅接收{12..13} 格式,不接受 12 13 风格
        ip_list=$(eval echo 10.0.0.${num_list})
        sshkey_auth ${ip_list}
    elif [ ${target_type[$target_id-1]} == "退出" ];then
        echo "准备退出管理操作界面..."
        exit
    else
        Usage
    fi
done
posted @ 2026-01-30 13:44  小茗同学study  阅读(37)  评论(0)    收藏  举报