SRE 第四次作业

网络配置

net-tools软件包

比较早出现的网络配置软件包,非内置,一般需要手动安装

ifconfig

介绍

用于查看网络接口的相关信息,可以临时对接口进行操作,比如修改IP地址、添加/删除IP地址、禁用/启用等

常用命令形式

ifconfig

显示启用的网络接口信息

lxh@ubuntu:~$ ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.150  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fe80::20c:29ff:fe08:c787  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:08:c7:87  txqueuelen 1000  (Ethernet)
        RX packets 460  bytes 262209 (262.2 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 389  bytes 77518 (77.5 KB)
        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 100  bytes 9342 (9.3 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 100  bytes 9342 (9.3 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
ifconfig -a

显示所有网络接口的信息(包括处于down状态)

lxh@ubuntu:~$ ifconfig -a
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.150  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fe80::20c:29ff:fe08:c787  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:08:c7:87  txqueuelen 1000  (Ethernet)
        RX packets 497  bytes 264919 (264.9 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 418  bytes 84302 (84.3 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens38: flags=4098<BROADCAST,MULTICAST>  mtu 1500
        ether 00:0c:29:08:c7:91  txqueuelen 1000  (Ethernet)
        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

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 100  bytes 9342 (9.3 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 100  bytes 9342 (9.3 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
ifconfig 设备名

仅仅查看指定接口的信息

lxh@ubuntu:~$ ifconfig ens33
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.150  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fe80::20c:29ff:fe08:c787  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:08:c7:87  txqueuelen 1000  (Ethernet)
        RX packets 534  bytes 267741 (267.7 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 442  bytes 88210 (88.2 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
ifconfig 设备名 down/up

禁用或者启用指定网络接口

lxh@ubuntu:/etc/netplan$ ifconfig ens38 
ens38: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.159  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fe80::20c:29ff:fe08:c791  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:08:c7:91  txqueuelen 1000  (Ethernet)
        RX packets 17  bytes 2980 (2.9 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 14  bytes 2136 (2.1 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ sudo ifconfig ens38 down					# 禁用接口
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ ifconfig ens38 
ens38: flags=4098<BROADCAST,MULTICAST>  mtu 1500
        ether 00:0c:29:08:c7:91  txqueuelen 1000  (Ethernet)
        RX packets 17  bytes 2980 (2.9 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 14  bytes 2136 (2.1 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ sudo ifconfig ens38 up						# 启用接口
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ ifconfig ens38 
ens38: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.159  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fe80::20c:29ff:fe08:c791  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:08:c7:91  txqueuelen 1000  (Ethernet)
        RX packets 18  bytes 3322 (3.3 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 19  bytes 2831 (2.8 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
ipconfig 设备名 IP地址 netmask 子网掩码

对指定接口的IP地址临时修改

lxh@ubuntu:/etc/netplan$ ifconfig ens38 
ens38: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.159  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fe80::20c:29ff:fe08:c791  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:08:c7:91  txqueuelen 1000  (Ethernet)
        RX packets 18  bytes 3322 (3.3 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 26  bytes 3341 (3.3 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ sudo ifconfig ens38 172.29.65.11 netmask 255.255.255.0
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ ifconfig ens38 
ens38: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.29.65.11  netmask 255.255.255.0  broadcast 172.29.65.255		# IP地址修改为172.29.65.11/24
        inet6 fe80::20c:29ff:fe08:c791  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:08:c7:91  txqueuelen 1000  (Ethernet)
        RX packets 18  bytes 3322 (3.3 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 26  bytes 3341 (3.3 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
ipconfig 设备名 add/del IP地址 netmask 子网掩码

为指定接口添加或者删除IP地址

lxh@ubuntu:/etc/netplan$ ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.150  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fe80::20c:29ff:fe08:c787  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:08:c7:87  txqueuelen 1000  (Ethernet)
        RX packets 2147  bytes 399119 (399.1 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1615  bytes 271381 (271.3 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens38: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.159  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fe80::20c:29ff:fe08:c791  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:08:c7:91  txqueuelen 1000  (Ethernet)
        RX packets 23  bytes 4011 (4.0 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 31  bytes 3689 (3.6 KB)
        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 106  bytes 9813 (9.8 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 106  bytes 9813 (9.8 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lxh@ubuntu:/etc/netplan$ # 添加IP地址172.29.65.1/24到网卡ens38
lxh@ubuntu:/etc/netplan$ sudo ifconfig ens38 add 172.29.65.1 netmask 255.255.255.0
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.150  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fe80::20c:29ff:fe08:c787  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:08:c7:87  txqueuelen 1000  (Ethernet)
        RX packets 2168  bytes 400727 (400.7 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1630  bytes 274861 (274.8 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens38: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.159  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fe80::20c:29ff:fe08:c791  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:08:c7:91  txqueuelen 1000  (Ethernet)
        RX packets 23  bytes 4011 (4.0 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 31  bytes 3689 (3.6 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens38:0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.29.65.1  netmask 255.255.255.0  broadcast 10.0.0.255
        ether 00:0c:29:08:c7:91  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 106  bytes 9813 (9.8 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 106  bytes 9813 (9.8 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lxh@ubuntu:/etc/netplan$ # 删除IP地址172.29.65.1/24到网卡ens38
lxh@ubuntu:/etc/netplan$ sudo ifconfig ens38 del 172.29.65.1 netmask 255.255.255.0
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.150  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fe80::20c:29ff:fe08:c787  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:08:c7:87  txqueuelen 1000  (Ethernet)
        RX packets 2189  bytes 402335 (402.3 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1644  bytes 278445 (278.4 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens38: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.159  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fe80::20c:29ff:fe08:c791  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:08:c7:91  txqueuelen 1000  (Ethernet)
        RX packets 23  bytes 4011 (4.0 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 31  bytes 3689 (3.6 KB)
        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 106  bytes 9813 (9.8 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 106  bytes 9813 (9.8 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lxh@ubuntu:/etc/netplan$ 

ifconfig输出中提取IP(扩展)

# 方法1
lxh@ubuntu:~$ ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.150  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fe80::20c:29ff:fe08:c787  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:08:c7:87  txqueuelen 1000  (Ethernet)
        RX packets 62  bytes 9627 (9.6 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 26  bytes 3015 (3.0 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens38: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.159  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fe80::20c:29ff:fe08:c791  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:08:c7:91  txqueuelen 1000  (Ethernet)
        RX packets 51  bytes 15228 (15.2 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 75  bytes 11415 (11.4 KB)
        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 24  bytes 3636 (3.6 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 24  bytes 3636 (3.6 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lxh@ubuntu:~$ 
lxh@ubuntu:~$ ifconfig | grep "inet "						# 获取到ipv4地址所在行
        inet 10.0.0.150  netmask 255.255.255.0  broadcast 10.0.0.255
        inet 10.0.0.159  netmask 255.255.255.0  broadcast 10.0.0.255
        inet 127.0.0.1  netmask 255.0.0.0
lxh@ubuntu:~$ 
lxh@ubuntu:~$ ifconfig | grep "inet " | tr -s " "			# 对连续多个空格进行压缩
 inet 10.0.0.150 netmask 255.255.255.0 broadcast 10.0.0.255
 inet 10.0.0.159 netmask 255.255.255.0 broadcast 10.0.0.255
 inet 127.0.0.1 netmask 255.0.0.0
lxh@ubuntu:~$ 
lxh@ubuntu:~$ ifconfig | grep "inet " | tr -s " " | cut -d " " -f 3		# 根据空格进行切割,获取第三列的内容
10.0.0.150
10.0.0.159
127.0.0.1
lxh@ubuntu:~$ 

#方法2
lxh@ubuntu:~$ ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.150  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fe80::20c:29ff:fe08:c787  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:08:c7:87  txqueuelen 1000  (Ethernet)
        RX packets 96  bytes 10526 (10.5 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 58  bytes 6943 (6.9 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens38: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.159  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fe80::20c:29ff:fe08:c791  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:08:c7:91  txqueuelen 1000  (Ethernet)
        RX packets 6163  bytes 517263 (517.2 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 4110  bytes 424170 (424.1 KB)
        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 92  bytes 8308 (8.3 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 92  bytes 8308 (8.3 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lxh@ubuntu:~$ 	# 指定分隔符为[ ]+,匹配一个或多个空格,匹配存在"inet "的行,打印第三列内容
lxh@ubuntu:~$ ifconfig | awk -F "[ ]+" '/inet /{print $3}'	
10.0.0.150
10.0.0.159
127.0.0.1
lxh@ubuntu:~$ 

route

介绍

查看并管理主机上的路由信息

常用命令形式

route -n

以数字方式显示主机上的路由表

lxh@ubuntu:/etc/netplan$ route 
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         _gateway        0.0.0.0         UG    100    0        0 ens33
10.0.0.0        0.0.0.0         255.255.255.0   U     100    0        0 ens33
10.0.0.0        0.0.0.0         255.255.255.0   U     100    0        0 ens38
_gateway        0.0.0.0         255.255.255.255 UH    100    0        0 ens33
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ route -n		# 将default、_gateway转换为IP地址显示,更明了
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.0.2        0.0.0.0         UG    100    0        0 ens33
10.0.0.0        0.0.0.0         255.255.255.0   U     100    0        0 ens33
10.0.0.0        0.0.0.0         255.255.255.0   U     100    0        0 ens38
10.0.0.2        0.0.0.0         255.255.255.255 UH    100    0        0 ens33
lxh@ubuntu:/etc/netplan$ 
route add/del -net 目标网段 gw 网关地址 dev 出接口

临时添加或删除路由信息

lxh@ubuntu:/etc/netplan$ route -n | grep 172.29.65.0
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ sudo route add -net 172.29.65.0/24 gw 10.0.0.2 dev ens38	# 添加路由信息
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ route -n | grep 172.29.65.0
172.29.65.0     10.0.0.2        255.255.255.0   UG    0      0        0 ens38
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ sudo route del -net 172.29.65.0/24			# 删除路由信息
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ route -n | grep 172.29.65.0
lxh@ubuntu:/etc/netplan$ 

路由表字段解析

lxh@ubuntu:/etc/netplan$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.0.2        0.0.0.0         UG    100    0        0 ens33
0.0.0.0         10.0.0.2        0.0.0.0         UG    100    0        0 ens38
10.0.0.0        0.0.0.0         255.255.255.0   U     100    0        0 ens33
10.0.0.0        0.0.0.0         255.255.255.0   U     100    0        0 ens38
10.0.0.2        0.0.0.0         255.255.255.255 UH    100    0        0 ens33
10.0.0.2        0.0.0.0         255.255.255.255 UH    100    0        0 ens38
  • Destination
    • 目标网络ID,0.0.0.0/0 表示所有未知网络,又称为默认路由,优先级最低
  • Gateway
    • 网关,下一跳地址
  • Genmask
    • 目标网络对应的子网掩码
  • Flags
    • 标记位 U(启用)| H(目标是主机) G(使用网关)| R(动态路由)| D(动态安装)| M(动态修改)|A(addrconf)| C(缓存)|!(拒绝)
  • Metric
    • 开销cost,值越小,路由记录被使用的优先级越高
  • Ref
    • 引用此路由的次数
  • Use
    • 使用次数
  • Iface
    • 出接口,到达对应网络,应该从当前主机哪个网卡发送出来

netstat

介绍

一般用于查看监听端口,可以查看各种UDP/TCP会话信息

常用命令形式

netstat -nltp

以纯数字方式(-n)显示,处于监听状态(-l)的tcp连接(-t),同时显示进程相关信息(-p)

lxh@ubuntu:/etc/netplan$ netstat -nplt
(No info could be read for "-p": geteuid()=1000 but you should be root.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 127.0.0.54:53           0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
tcp6       0      0 :::22                   :::*                    LISTEN      -                   
lxh@ubuntu:/etc/netplan$ 

iproute2软件包

较新出现的网络配置软件包,用于替代net-tools软件包中的相关信息,一般系统已经内置

ip

介绍

可以用于查看、管理网卡信息,查看管理路由信息,是 ifconfig 和 route 命令的结合

常用命令形式

ip a

完整命令为 ip address,查看所有网络接口相关信息(包括处于down状态)

lxh@ubuntu:/etc/netplan$ 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 noprefixroute 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:08:c7:87 brd ff:ff:ff:ff:ff:ff
    altname enp2s1
    inet 10.0.0.150/24 metric 100 brd 10.0.0.255 scope global dynamic ens33
       valid_lft 1120sec preferred_lft 1120sec
    inet6 fe80::20c:29ff:fe08:c787/64 scope link 
       valid_lft forever preferred_lft forever
3: ens38: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
    link/ether 00:0c:29:08:c7:91 brd ff:ff:ff:ff:ff:ff
    altname enp2s6
lxh@ubuntu:/etc/netplan$ 
ip addr show 设备名

查看指定网卡的相关信息

lxh@ubuntu:/etc/netplan$ ip addr show ens38
3: ens38: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:08:c7:91 brd ff:ff:ff:ff:ff:ff
    altname enp2s6
    inet 10.0.0.159/24 metric 100 brd 10.0.0.255 scope global dynamic ens38
       valid_lft 1792sec preferred_lft 1792sec
    inet6 fe80::20c:29ff:fe08:c791/64 scope link 
       valid_lft forever preferred_lft forever
lxh@ubuntu:/etc/netplan$ 
ip route

查看本机的路由表,个人感觉不如 route -n 显示得更加清楚

lxh@ubuntu:/etc/netplan$ ip route
default via 10.0.0.2 dev ens33 proto dhcp src 10.0.0.150 metric 100 
10.0.0.0/24 dev ens33 proto kernel scope link src 10.0.0.150 metric 100 
10.0.0.2 dev ens33 proto dhcp scope link src 10.0.0.150 metric 100 
lxh@ubuntu:/etc/netplan$ 

禁用或者启用指定的网络接口

lxh@ubuntu:/etc/netplan$ ip addr show ens38
3: ens38: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:08:c7:91 brd ff:ff:ff:ff:ff:ff
    altname enp2s6
    inet 10.0.0.159/24 metric 100 brd 10.0.0.255 scope global dynamic ens38
       valid_lft 1726sec preferred_lft 1726sec
    inet6 fe80::20c:29ff:fe08:c791/64 scope link 
       valid_lft forever preferred_lft forever
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ sudo ip link set ens38 down 				# 禁用网卡
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ ip addr show ens38
3: ens38: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
    link/ether 00:0c:29:08:c7:91 brd ff:ff:ff:ff:ff:ff
    altname enp2s6
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ sudo ip link set ens38 up					# 启用网卡
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ ip addr show ens38
3: ens38: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:08:c7:91 brd ff:ff:ff:ff:ff:ff
    altname enp2s6
    inet 10.0.0.159/24 metric 100 brd 10.0.0.255 scope global dynamic ens38
       valid_lft 1799sec preferred_lft 1799sec
    inet6 fe80::20c:29ff:fe08:c791/64 scope link 
       valid_lft forever preferred_lft forever
lxh@ubuntu:/etc/netplan$ 
ip addr add/del IP/掩码长度 dev 设备名

为指定网络接口添加或删除IP地址

lxh@ubuntu:/etc/netplan$ ip addr show ens38
3: ens38: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:08:c7:91 brd ff:ff:ff:ff:ff:ff
    altname enp2s6
    inet 10.0.0.159/24 metric 100 brd 10.0.0.255 scope global dynamic ens38
       valid_lft 1650sec preferred_lft 1650sec
    inet6 fe80::20c:29ff:fe08:c791/64 scope link 
       valid_lft forever preferred_lft forever
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ sudo ip addr add 172.29.65.11/24 dev ens38
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ ip addr show ens38
3: ens38: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:08:c7:91 brd ff:ff:ff:ff:ff:ff
    altname enp2s6
    inet 10.0.0.159/24 metric 100 brd 10.0.0.255 scope global dynamic ens38
       valid_lft 1641sec preferred_lft 1641sec
    inet 172.29.65.11/24 scope global ens38
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe08:c791/64 scope link 
       valid_lft forever preferred_lft forever
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ sudo ip addr del 172.29.65.11/24 dev ens38
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ ip addr show ens38
3: ens38: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:08:c7:91 brd ff:ff:ff:ff:ff:ff
    altname enp2s6
    inet 10.0.0.159/24 metric 100 brd 10.0.0.255 scope global dynamic ens38
       valid_lft 1630sec preferred_lft 1630sec
    inet6 fe80::20c:29ff:fe08:c791/64 scope link 
       valid_lft forever preferred_lft forever
lxh@ubuntu:/etc/netplan$ 
ip route add/del 目标网段 via 网关地址 dev 出接口

为本机添加或删除路由信息

lxh@ubuntu:/etc/netplan$ ip route | grep 172.29.65.0
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ sudo ip route add 172.29.65.0/24 via  10.0.0.2 dev ens38
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ ip route | grep 172.29.65.0
172.29.65.0/24 via 10.0.0.2 dev ens38 
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ sudo ip route del 172.29.65.0/24 via  10.0.0.2 dev ens38
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ ip route | grep 172.29.65.0
lxh@ubuntu:/etc/netplan$ 

ss

介绍

一般用于查看监听端口,可以查看各种UDP/TCP会话信息,用于替代 netstat 命令

常用命令形式

ss -nltp

以纯数字方式(-n)显示,处于监听状态(-l)的tcp连接(-t),同时显示进程相关信息(-p)

lxh@ubuntu:/etc/netplan$ ss -nltp
State             Recv-Q            Send-Q                       Local Address:Port                         Peer Address:Port            Process            
LISTEN            0                 4096                            127.0.0.54:53                                0.0.0.0:*                                  
LISTEN            0                 4096                         127.0.0.53%lo:53                                0.0.0.0:*                                  
LISTEN            0                 4096                               0.0.0.0:22                                0.0.0.0:*                                  
LISTEN            0                 4096                                  [::]:22                                   [::]:*     

网卡配置文件格式解析

Ubuntu

lxh@ubuntu:/etc/netplan$ vim /etc/netplan/50-cloud-init.yaml
network:
  version: 2  # 必须,Netplan 版本
  renderer: networkd  # 可选,networkd 或 NetworkManager
  ethernets:  # 网络接口配置
    eth33:  # 接口名称
      # 地址配置
      addresses:  # IP地址列表
        - 10.0.0.150/24
        - 172.29.65.11/64
      
      # 路由
      routes:
        - to: 0.0.0.0/0	 # 默认路由
          via: 10.0.0.2
      
      # DNS
      nameservers:
        addresses:  # DNS服务器
          - 8.8.8.8

RedHat

[lxh@Rocky network-scripts]$ vim ifcfg-ens33
# 基本参数
TYPE=Ethernet              # 接口类型
BOOTPROTO=none           # 协议: none/static/dhcp

# 标识参数
UUID=xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx  # 设备UUID
DEVICE=eth0              # 设备名称
NAME=System eth0         # 连接名称
ONBOOT=yes              # 开机启动

# IP地址配置
IPADDR=192.168.1.100    # IPv4地址
PREFIX=24               # 子网前缀长度
NETMASK=255.255.255.0    # 子网掩码 (PREFIX替代)
GATEWAY=192.168.1.1     # 网关
DNS1=8.8.8.8            # 主DNS
DNS2=8.8.4.4            # 备DNS

# 多个IP地址
IPADDR0=192.168.1.100
PREFIX0=24
IPADDR1=10.0.0.100
PREFIX1=24
GATEWAY0=192.168.1.1
GATEWAY1=10.0.0.1

上网案例

环境说明

使用双网卡,一个NAT网卡用于主机上网,一个仅主机网卡用于ssh远程配置主机

image-20251208162540873

NAT网络中的网关地址为10.0.0.2

image-20251209004751212

查看主机的网卡信息,其中NAT网卡的地址为10.2.0.150/24,仅主机网卡的地址为192.168.132.138/24

lxh@ubuntu:/etc/netplan$ 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 noprefixroute 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:c9:3a:a4 brd ff:ff:ff:ff:ff:ff
    altname enp2s1
    inet 10.2.0.150/24 brd 10.2.0.255 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fec9:3aa4/64 scope link 
       valid_lft forever preferred_lft forever
3: ens38: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:c9:3a:ae brd ff:ff:ff:ff:ff:ff
    altname enp2s6
    inet 192.168.132.138/24 metric 100 brd 192.168.132.255 scope global dynamic ens38
       valid_lft 1798sec preferred_lft 1798sec
    inet6 fe80::20c:29ff:fec9:3aae/64 scope link 
       valid_lft forever preferred_lft forever
lxh@ubuntu:/etc/netplan$ 

实现上网

通过 ping 命令检查与网关是否可通

lxh@ubuntu:/etc/netplan$ ping 10.0.0.2
ping: connect: Network is unreachable
lxh@ubuntu:/etc/netplan$ 

网关不可达,检查子网掩码和网关地址,判定不在同一网段

lxh@ubuntu:/etc/netplan$ ip addr show ens33
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:c9:3a:a4 brd ff:ff:ff:ff:ff:ff
    altname enp2s1
    inet 10.2.0.150/24 brd 10.2.0.255 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fec9:3aa4/64 scope link 
       valid_lft forever preferred_lft forever
lxh@ubuntu:/etc/netplan$ 

手动配置静态IP地址,实现网关可达

lxh@ubuntu:/etc/netplan$ sudo vim 50-cloud-init.yaml 
network:
  version: 2
  ethernets:
    ens33:
      addresses: [10.0.0.150/24]
    ens38:
      dhcp4: true
lxh@ubuntu:/etc/netplan$ sudo netplan apply
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ ping 10.0.0.2
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=128 time=0.706 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=128 time=0.486 ms
64 bytes from 10.0.0.2: icmp_seq=3 ttl=128 time=0.287 ms
64 bytes from 10.0.0.2: icmp_seq=4 ttl=128 time=0.257 ms
^C
--- 10.0.0.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3033ms
rtt min/avg/max/mdev = 0.257/0.434/0.706/0.180 ms
lxh@ubuntu:/etc/netplan$ 

添加默认路由,指向网关地址

lxh@ubuntu:/etc/netplan$ ip route
10.0.0.0/24 dev ens33 proto kernel scope link src 10.0.0.150 
192.168.132.0/24 dev ens38 proto kernel scope link src 192.168.132.138 metric 100 
192.168.132.1 dev ens38 proto dhcp scope link src 192.168.132.138 metric 100 
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ sudo ip route add default via 10.0.0.2 dev ens33
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ ip route
default via 10.0.0.2 dev ens33 
10.0.0.0/24 dev ens33 proto kernel scope link src 10.0.0.150 
192.168.132.0/24 dev ens38 proto kernel scope link src 192.168.132.138 metric 100 
192.168.132.1 dev ens38 proto dhcp scope link src 192.168.132.138 metric 100 
lxh@ubuntu:/etc/netplan$ 

可以通过指定IP地址访问外网,但是无法通过域名访问

lxh@ubuntu:/etc/netplan$ ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=128 time=68.2 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=128 time=47.0 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=128 time=47.9 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=128 time=47.9 ms
^C
--- 8.8.8.8 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 46.972/52.774/68.233/8.934 ms
lxh@ubuntu:/etc/netplan$ 
lxh@ubuntu:/etc/netplan$ ping www.baidu.com
ping: www.baidu.com: Temporary failure in name resolution
lxh@ubuntu:/etc/netplan$ 

修改网卡配置文件,指定域名解析服务器(这里生效后可能需要重新配置一下默认路由,因为临时生效)

lxh@ubuntu:/etc/netplan$ vim 50-cloud-init.yaml 
network:
  version: 2
  ethernets:
    ens33:
      addresses: [10.0.0.150/24]
      nameservers:
        addresses: [8.8.8.8]
    ens38:
      dhcp4: true
lxh@ubuntu:/etc/netplan$ sudo netplan apply
lxh@ubuntu:/etc/netplan$ 

最终实现访问外网

lxh@ubuntu:/etc/netplan$ ping www.baidu.com
PING www.wshifen.com (103.235.46.115) 56(84) bytes of data.
64 bytes from 103.235.46.115: icmp_seq=1 ttl=128 time=55.0 ms
64 bytes from 103.235.46.115: icmp_seq=2 ttl=128 time=46.9 ms
64 bytes from 103.235.46.115: icmp_seq=3 ttl=128 time=45.7 ms
64 bytes from 103.235.46.115: icmp_seq=4 ttl=128 time=157 ms
^C
--- www.wshifen.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 7066ms
rtt min/avg/max/mdev = 45.739/76.071/156.604/46.631 ms
lxh@ubuntu:/etc/netplan$ 

多网卡绑定 Bonding(扩展)

mod=0,即:Round-robin policy (轮询) 为例进行配置演示

Ubuntu

环境说明

演示主机具备三个网卡

  • 其中两个网卡处于同一个虚拟网络,对网卡所处的虚拟网络类型没有特别要求,用于演示多网卡绑定
  • 最后一个网卡用于远程控制主机
root@ubuntu:~# 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 noprefixroute 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:c9:3a:a4 brd ff:ff:ff:ff:ff:ff
    altname enp2s1
    inet 192.168.132.136/24 metric 100 brd 192.168.132.255 scope global dynamic ens33
       valid_lft 1798sec preferred_lft 1798sec
    inet6 fe80::20c:29ff:fec9:3aa4/64 scope link 
       valid_lft forever preferred_lft forever
3: ens38: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:c9:3a:ae brd ff:ff:ff:ff:ff:ff
    altname enp2s6
    inet 192.168.132.138/24 metric 100 brd 192.168.132.255 scope global dynamic ens38
       valid_lft 1798sec preferred_lft 1798sec
    inet6 fe80::20c:29ff:fec9:3aae/64 scope link 
       valid_lft forever preferred_lft forever
4: ens39: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:c9:3a:b8 brd ff:ff:ff:ff:ff:ff
    altname enp2s7
    inet 10.0.0.160/24 metric 100 brd 10.0.0.255 scope global dynamic ens39
       valid_lft 1798sec preferred_lft 1798sec
    inet6 fe80::20c:29ff:fec9:3ab8/64 scope link 
       valid_lft forever preferred_lft forever
root@ubuntu:~# 

配置演示

创建配置文件,将两个网卡绑定到bond0上,并设置为轮询模式

root@ubuntu:~# vim /etc/netplan/50-cloud-init.yaml 
network:
  version: 2
  ethernets:
    ens38:
      dhcp4: true
    ens33:
      addresses: []
      dhcp4: false
    ens39:
      addresses: []
      dhcp4: false

  bonds:
    bond0:
      addresses: [192.168.132.140/24]		# 虚拟接口的IP地址为192.168.132.140/24
      interfaces: [ens33,ens39]				# 配置ens33,ens39进行网卡绑定
      parameters:
        mode: balance-rr					# 轮询模式
root@ubuntu:~# netplan apply
root@ubuntu:~# 

此时通过ip a命令可以查看到虚拟出来的bond0

root@ubuntu:~# 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 noprefixroute 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc fq_codel master bond0 state UP group default qlen 1000
    link/ether 56:c1:ad:74:fe:53 brd ff:ff:ff:ff:ff:ff permaddr 00:0c:29:c9:3a:a4
    altname enp2s1
3: ens38: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:c9:3a:ae brd ff:ff:ff:ff:ff:ff
    altname enp2s6
    inet 192.168.132.138/24 metric 100 brd 192.168.132.255 scope global dynamic ens38
       valid_lft 1710sec preferred_lft 1710sec
    inet6 fe80::20c:29ff:fec9:3aae/64 scope link 
       valid_lft forever preferred_lft forever
4: ens39: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc fq_codel master bond0 state UP group default qlen 1000
    link/ether 56:c1:ad:74:fe:53 brd ff:ff:ff:ff:ff:ff permaddr 00:0c:29:c9:3a:b8
    altname enp2s7
5: bond0: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 56:c1:ad:74:fe:53 brd ff:ff:ff:ff:ff:ff
    inet 192.168.132.140/24 brd 192.168.132.255 scope global bond0
       valid_lft forever preferred_lft forever
    inet6 fe80::54c1:adff:fe74:fe53/64 scope link 
       valid_lft forever preferred_lft forever

通过查看内存中的映射出来的文件,可以获取当前聚合接口bond0的状态信息

root@ubuntu:~# cat /proc/net/bonding/bond0
Ethernet Channel Bonding Driver: v6.8.0-79-generic

Bonding Mode: load balancing (round-robin)
MII Status: up
MII Polling Interval (ms): 0
Up Delay (ms): 0
Down Delay (ms): 0
Peer Notification Delay (ms): 0

Slave Interface: ens33
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
Permanent HW addr: 00:0c:29:c9:3a:a4
Slave queue ID: 0

Slave Interface: ens39
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
Permanent HW addr: 00:0c:29:c9:3a:b8
Slave queue ID: 0
root@ubuntu:~# 

RedHat

环境说明

演示主机具备三个网卡

  • 其中两个网卡处于同一个虚拟网络,对网卡所处的虚拟网络类型没有特别要求,用于演示多网卡绑定
  • 最后一个网卡用于远程控制主机
[root@rocky lxh]# 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: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:bc:ee:db brd ff:ff:ff:ff:ff:ff
    inet 192.168.132.140/24 brd 192.168.132.255 scope global dynamic noprefixroute ens33
       valid_lft 1532sec preferred_lft 1532sec
    inet6 fe80::20c:29ff:febc:eedb/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: ens37: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:bc:ee:e5 brd ff:ff:ff:ff:ff:ff
4: ens38: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:bc:ee:ef brd ff:ff:ff:ff:ff:ff
5: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:42:2c:8d brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever
[root@rocky lxh]# 

配置演示

首先创建聚合接口bond0

[root@rocky lxh]# nmcli connection add type bond con-name bond0 ifname bond0 bond.options "mode=balance-rr"
Connection 'bond0' (fc258b39-983f-43d6-a9cf-a4534e3b6531) successfully added.
[root@rocky lxh]# 

然后将两个网卡加入聚合

[root@rocky lxh]# nmcli connection add type ethernet slave-type bond con-name bond0-port1 ifname ens37 master bond0
Connection 'bond0-port1' (57b29d3e-a5bd-4f7a-8d3e-882b4996dee6) successfully added.
[root@rocky lxh]# 
[root@rocky lxh]# nmcli connection add type ethernet slave-type bond con-name bond0-port2 ifname ens38 master bond0
Connection 'bond0-port2' (719b51df-230d-4d49-8e8e-82ca5204631f) successfully added.
[root@rocky lxh]# 

看到所有接口均为绿色启用状态

[root@rocky lxh]# nmcli connection 
NAME         UUID                                  TYPE      DEVICE 
bond0        fc258b39-983f-43d6-a9cf-a4534e3b6531  bond      bond0  
ens33        f4f634e2-d3a8-4569-bee8-51ffdbb8c4e5  ethernet  ens33  
virbr0       8f19b442-d110-4203-9cd5-5305013d2671  bridge    virbr0 
bond0-port1  57b29d3e-a5bd-4f7a-8d3e-882b4996dee6  ethernet  ens37  
bond0-port2  719b51df-230d-4d49-8e8e-82ca5204631f  ethernet  ens38  
[root@rocky lxh]# 

查看聚合接口bond0的状态

[root@rocky lxh]# cat /proc/net/bonding/bond0
Ethernet Channel Bonding Driver: v3.7.1 (April 27, 2011)

Bonding Mode: load balancing (round-robin)
MII Status: up
MII Polling Interval (ms): 100
Up Delay (ms): 0
Down Delay (ms): 0
Peer Notification Delay (ms): 0

Slave Interface: ens37
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
Permanent HW addr: 00:0c:29:bc:ee:e5
Slave queue ID: 0

Slave Interface: ens38
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
Permanent HW addr: 00:0c:29:bc:ee:ef
Slave queue ID: 0
[root@rocky lxh]# 

数组

索引数组

数组定义与查看

可以单行、多行、按索引进行数组定义,和变量一样通过unset进行删除

索引数组通过 declare -a 命令查看

# 单行定义
lxh@ubuntu:~$ arry=( 1 2 3 4 5 6 )
lxh@ubuntu:~$ 
lxh@ubuntu:~$ declare -a | tail -n 1
declare -a arry=([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6")
lxh@ubuntu:~$ 

# 多行定义
lxh@ubuntu:~$ arry=(
> 1
> 2
> 3
> 4
> 5
> 6
> )
lxh@ubuntu:~$ 
lxh@ubuntu:~$ declare -a | tail -n 1
declare -a arry=([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6")
lxh@ubuntu:~$ 

# 按索引不连续定义
lxh@ubuntu:~$ arry[1]=2
lxh@ubuntu:~$ arry[4]=5
lxh@ubuntu:~$ arry[0]=1
lxh@ubuntu:~$ 
lxh@ubuntu:~$ declare -a | tail -n 1
declare -a arry=([0]="1" [1]="2" [4]="5")
lxh@ubuntu:~$ 

# 定义一个空的索引数组
lxh@ubuntu:~$ declare -a arry
lxh@ubuntu:~$ 
lxh@ubuntu:~$ declare -a | tail -n 1
declare -a arry
lxh@ubuntu:~$ 

数组使用

可以对索引数组获取所有元素值、获取指定索引的元素值、获取索引、获取部分元素值、获取数组长度

环境准备

lxh@ubuntu:~$ arry=("apple" "orange" "banana" "grape​")
lxh@ubuntu:~$ 
lxh@ubuntu:~$ declare -a
declare -a BASH_ARGC=([0]="0")
declare -a BASH_ARGV=()
declare -a BASH_COMPLETION_VERSINFO=([0]="2" [1]="11")
declare -a BASH_LINENO=()
declare -a BASH_REMATCH=()
declare -a BASH_SOURCE=()
declare -ar BASH_VERSINFO=([0]="5" [1]="2" [2]="21" [3]="1" [4]="release" [5]="x86_64-pc-linux-gnu")
declare -a DIRSTACK=()
declare -a FUNCNAME
declare -a GROUPS=()
declare -a PIPESTATUS=([0]="0")
declare -a arry=([0]="apple" [1]="orange" [2]="banana" [3]="grape​")
lxh@ubuntu:~$ 

命令演示

# 获取指定元素值
lxh@ubuntu:~$ echo ${arry[1]}
orange
lxh@ubuntu:~$ 
lxh@ubuntu:~$ echo ${arry[2]}
banana

# 获取所有元素值
lxh@ubuntu:~$ echo ${arry[*]}
apple orange banana grape​
lxh@ubuntu:~$ 

# 获取索引
lxh@ubuntu:~$ echo ${!arry[*]}
0 1 2 3
lxh@ubuntu:~$ 

# 获取数组长度
lxh@ubuntu:~$ echo ${#arry[*]}
4
lxh@ubuntu:~$ 

# 获取数组部分元素
# 这里的格式为 数组所有元素:起始索引:元素获取个数
lxh@ubuntu:~$ echo ${arry[*]:1:1}
orange
lxh@ubuntu:~$ 
lxh@ubuntu:~$ echo ${arry[*]:2:1}
banana
lxh@ubuntu:~$ 
lxh@ubuntu:~$ echo ${arry[*]:2:2}
banana grape​
lxh@ubuntu:~$

关联数组

关联数组相对于索引数组,特点是索引可以是指定的字符串

数组定义与查看

关联数组需要在定义时指定索引

关联数组定义时,必须使用命令 declare -A arry

# 单行定义
lxh@ubuntu:~$ declare -A arry
lxh@ubuntu:~$
lxh@ubuntu:~$ arry=("first" "apple" "second" "orange")
lxh@ubuntu:~$ 
lxh@ubuntu:~$ declare -A | grep arry
declare -A arry=([second]="orange" [first]="apple" )
lxh@ubuntu:~$

# 按索引进行定义
lxh@ubuntu:~$ declare -A arry
lxh@ubuntu:~$ 
lxh@ubuntu:~$ arry["first"]="apple"
lxh@ubuntu:~$ arry["second"]="orange"
lxh@ubuntu:~$ 
lxh@ubuntu:~$ declare -A | grep arry
declare -A arry=([second]="orange" [first]="apple" )
lxh@ubuntu:~$ 

数组使用

关联数组与索引数组的使用别无二致

环境准备

lxh@ubuntu:~$ declare -A arry
lxh@ubuntu:~$ 
lxh@ubuntu:~$ arry["first"]="apple"
lxh@ubuntu:~$ arry["second"]="orange"
lxh@ubuntu:~$ arry["third"]="banana"
lxh@ubuntu:~$ arry["fourth"]="grape"
lxh@ubuntu:~$ 
lxh@ubuntu:~$ declare -A | grep arry
declare -A arry=([second]="orange" [first]="apple" [fourth]="grape" [third]="banana" )
lxh@ubuntu:~$ 

命令演示

# 获取指定元素值
lxh@ubuntu:~$ echo ${arry["first"]}
apple
lxh@ubuntu:~$ 
lxh@ubuntu:~$ echo ${arry["fourth"]}
grape
lxh@ubuntu:~$

# 获取所有元素值
lxh@ubuntu:~$ echo ${arry[*]}
orange apple grape banana
lxh@ubuntu:~$ 

# 获取索引
lxh@ubuntu:~$ echo ${!arry[*]}
second first fourth third
lxh@ubuntu:~$ 

# 获取数组长度
lxh@ubuntu:~$ echo ${#arry[*]}
4
lxh@ubuntu:~$ 

# 获取数组部分元素(这里的索引是根据排列顺序,需要通过echo ${!arry[*]}查看)
lxh@ubuntu:~$ echo ${arry[*]:2:1}
apple
lxh@ubuntu:~$ 
lxh@ubuntu:~$ echo ${arry[*]:3:1}
grape
lxh@ubuntu:~$ 
lxh@ubuntu:~$ echo ${arry[*]:0:1}
orange
lxh@ubuntu:~$ 

字符串

字符串截取

可以对字符串截取一部分字串

表示从头部开始匹配,且最短匹配,将通配符匹配部分删除

lxh@ubuntu:~$ fullpath="/var/www/html/index.html"
lxh@ubuntu:~$ echo ${fullpath#*.}
html
lxh@ubuntu:~$ 
lxh@ubuntu:~$ ip_address="192.168.1.100:8080"
lxh@ubuntu:~$ echo ${ip_address#*:}
8080
lxh@ubuntu:~$ 

表示从头部开始匹配,且最长匹配,将通配符匹配部分删除

lxh@ubuntu:~$ fullpath="/var/www/html/index.html"
lxh@ubuntu:~$ echo ${fullpath##*/}
index.html
lxh@ubuntu:~$ 

%

表示从尾部开始匹配,且最短匹配,将通配符匹配部分删除

lxh@ubuntu:~$ fullpath="/var/www/html/index.html"
lxh@ubuntu:~$ echo ${fullpath%/*}
/var/www/html
lxh@ubuntu:~$ 
lxh@ubuntu:~$ ip_address="192.168.1.100:8080"
lxh@ubuntu:~$ echo ${ip_address%:*}
192.168.1.100
lxh@ubuntu:~$ 

%%

表示从尾部开始匹配,且最长匹配,将通配符匹配部分删除

lxh@ubuntu:~$ fullpath="/var/www/html/index.html"
lxh@ubuntu:~$ echo ${fullpath%%.*}
/var/www/html/index
lxh@ubuntu:~$ echo ${fullpath%%*}

lxh@ubuntu:~$ 

字符串替换

/target/replace

表示将通配符匹配到的第一个字符串target,替换为replace

lxh@ubuntu:~$ file="document.backup.txt.gz"
lxh@ubuntu:~$ echo ${file/txt/log}
document.backup.log.gz
lxh@ubuntu:~$ 

//target/replace

表示将通配符匹配到的所有字符串target,替换为replace

lxh@ubuntu:~$ var_name=hello_world_example
lxh@ubuntu:~$ echo ${var_name//_/}
helloworldexample
lxh@ubuntu:~$ 
lxh@ubuntu:~$ file="document.backup.txt.gz"
lxh@ubuntu:~$ echo ${file//./_}
document_backup_txt_gz
lxh@ubuntu:~$ 

/#target/replace

表示从头部开始匹配,将通配符匹配到的字符串target,替换为replace

lxh@ubuntu:~$ file="document.backup.txt.gz"
lxh@ubuntu:~$ echo ${file/#/archive_}
archive_document.backup.txt.gz
lxh@ubuntu:~$ 

/%target/replace

表示从尾部开始匹配,将通配符匹配到的字符串target,替换为replace

lxh@ubuntu:~$ file="document.backup.txt.gz"
lxh@ubuntu:~$ echo ${file/%/.backup}
document.backup.txt.gz.backup
lxh@ubuntu:~$ 

字符串转换

^^

表示将小写字母全部转换为大写字母

lxh@ubuntu:~$ string="abcd_Helloworld"
lxh@ubuntu:~$ echo ${string^^}
ABCD_HELLOWORLD
lxh@ubuntu:~$ 

,,

表示将大写字母全部转换为小写字母

lxh@ubuntu:~$ string="abcd_Helloworld"
lxh@ubuntu:~$ echo ${string,,}
abcd_helloworld
lxh@ubuntu:~$ 

流程控制

条件语句

if语句

if语句分为单分支、双分支、多分支语句

# 单分支
read -p "请输入数字:" num

if [[ $num -eq 1 ]]
then
    echo "数字为1"
fi


# 双分支
read -p "请输入数字:" num

if [[ $num -eq 1 ]]
then
    echo "数字为1"
else
    echo "数字不为1"
fi


# 多分支
read -p "请输入数字:" num

if [[ $num -eq 1 ]]
then
    echo "数字为1"
elif [[ $num -lt 1 ]]
then
    echo "数字小于1"
else
    echo "数字大于1"
fi

case语句

在条件过多时,可以使用case语句来简化if语句

# 多分支(使用case)
read -p "请输入数字:" num

case $num in
    1)
        echo "数字为1"
    ;;
    2)
        echo "数字为2"
    ;;
    3)
        echo "数字为3"
    ;;
    4)
        echo "数字为4"
    ;;
    *)
        echo "其他数字"
    ;;
esac


# 多分支(使用if)
read -p "请输入数字:" num

if [[ $num -eq 1 ]]
then
    echo "数字为1"
elif [[ $num -eq 2 ]]
then
    echo "数字为2"
elif [[ $num -eq 3 ]]
then
    echo "数字为3"
elif [[ $num -eq 4 ]]
then
    echo "数字为4"
else
    echo "其他数字"
fi

循环语句

while语句

while语句的特点是当条件不满足时,跳出循环

# 写法1
num=1
while [[ $num -le 10 ]]
do
    echo $num
    let num+=1
done

# 写法2
num=1
while true
do
   if [[ $num -eq 11 ]]
   then
       break
   fi

   echo $num
   let num+=1
done


# 无限循环
while true
do
   date "+%F_%T"
   sleep 1
done

while语句可以按行读取指定文件的内容

# while遍历文件 /etc/passwd 的所有行
while read line
do
    echo $line
done < /etc/passwd

until语句

until语句的特点是当条件满足时,跳出循环

# 写法1
num=1
until [[ $num -gt 10 ]]
do
    echo $num
    let num+=1
done

# 写法2
num=1
until false
do
    if [[ $num -eq 11 ]]
    then
        break
    fi

    echo $num
    let num+=1
done


# 无限循环
num=1
until false
do
    date "+%F_%T"
    sleep 1
done

for语句

for语句可以用于遍历列表中的每个元素

练习题

计算用户id之和

脚本内容:

#!/bin/bash

sum=""

while read fline	# 获取文件中每一行
do
    let sum+=$( cut -d ":" -f 3 <<< $fline )	# 提取每一行的id数字,并进行累加
done < /etc/passwd

echo "id之和为$sum"

实现效果:

lxh@ubuntu:~$ /bin/bash sum.sh
id之和为72800
lxh@ubuntu:~$ 

10个随机数的最大最小值

脚本内容:

#!/bin/bash

for i in {1..10}
do
    random_arry[$i]=$RANDOM
done

echo -e "生成的四个随机数为 \e[31m${random_arry[*]}\e[0m"

maxnum=${random_arry[1]}
minnum=${random_arry[1]}

for num in ${random_arry[*]}
do
    if [[ $num -gt $maxnum ]]
    then
        maxnum=$num
    fi

    if [[ $num -lt $minnum ]]
    then
        minnum=$num
    fi
done

echo -e "最大值为\e[33m${maxnum}\e[0m"
echo -e "最小值为\e[33m${minnum}\e[0m"

实现效果:

lxh@ubuntu:~$ /bin/bash random.sh 
生成的十个随机数为 26406 17427 1222 138 26518 11640 32331 16155 5777 19759
最大值为32331
最小值为138
lxh@ubuntu:~$ /bin/bash random.sh 
生成的十个随机数为 21047 9291 11779 17513 31484 1950 4423 8543 14098 17262
最大值为31484
最小值为1950
lxh@ubuntu:~$ /bin/bash random.sh 
生成的十个随机数为 10483 30702 27150 30241 21979 3275 32037 32007 12235 24799
最大值为32037
最小值为3275
lxh@ubuntu:~$ 

使用递归实现阶乘算法

脚本内容:

#!/bin/bash

recursion(){
    num1=$1
    num2=$( expr $num1 - 1 )

    if [[ $num1 -gt 1 ]]
    then
        echo $[ $num1 * $(recursion $num2) ]
    else
        echo 1
    fi
}

read -p "请输入数字:" inputnum

echo -e "阶乘结果为 \e[31m$(recursion $inputnum)\e[0m"

实现效果:

lxh@ubuntu:~$ /bin/bash recursion.sh
请输入数字:3
阶乘结果为 6
lxh@ubuntu:~$ /bin/bash recursion.sh
请输入数字:4
阶乘结果为 24
lxh@ubuntu:~$ /bin/bash recursion.sh
请输入数字:5
阶乘结果为 120

鸡兔同笼

脚本内容:

#!/bin/bash

head_num=30
leg_num=80

for rabbit_num in {1..30}
do
    if [[ ${leg_num} == $[ ${rabbit_num} * 4 + (${head_num} - ${rabbit_num}) * 2 ] ]]
    then
        echo "兔子的数量为 ${rabbit_num}; 鸡的数量为 $[${head_num} - ${rabbit_num}]"
    fi
done

实现效果:

lxh@ubuntu:~$ /bin/bash cr.sh
兔子的数量为 10; 鸡的数量为 20

批量创建100个用户

用户列表(AI生成):

lxh@ubuntu:~$ cat userlist.txt 
username,uid,full_name,home_dir,shell,password
user001,1001,张三 001,/home/user001,/bin/bash,Passw0rd001
user002,1002,李四 002,/home/user002,/bin/bash,Passw0rd002
user003,1003,王五 003,/home/user003,/bin/bash,Passw0rd003
user004,1004,赵六 004,/home/user004,/bin/bash,Passw0rd004
user005,1005,钱七 005,/home/user005,/bin/bash,Passw0rd005
user006,1006,孙八 006,/home/user006,/bin/bash,Passw0rd006
user007,1007,周九 007,/home/user007,/bin/bash,Passw0rd007
user008,1008,吴十 008,/home/user008,/bin/bash,Passw0rd008
user009,1009,郑十一 009,/home/user009,/bin/bash,Passw0rd009
user010,1010,王十二 010,/home/user010,/bin/bash,Passw0rd010
user011,1011,刘十三 011,/home/user011,/bin/bash,Passw0rd011
user012,1012,陈十四 012,/home/user012,/bin/bash,Passw0rd012
user013,1013,杨十五 013,/home/user013,/bin/bash,Passw0rd013
user014,1014,黄十六 014,/home/user014,/bin/bash,Passw0rd014
user015,1015,赵十七 015,/home/user015,/bin/bash,Passw0rd015
user016,1016,周十八 016,/home/user016,/bin/bash,Passw0rd016
user017,1017,吴十九 017,/home/user017,/bin/bash,Passw0rd017
user018,1018,郑二十 018,/home/user018,/bin/bash,Passw0rd018
user019,1019,王二一 019,/home/user019,/bin/bash,Passw0rd019
user020,1020,刘二二 020,/home/user020,/bin/bash,Passw0rd020
...

脚本内容:

#!/bin/bash

msg1_color="\e[33m"
msg2_color="\e[31m"
data_color="\e[32m"
end_color="\e[0m"

while read line
do
    username=$( cut -d "," -f 1 <<<$line)
    userid=$( cut -d "," -f 2 <<<$line)
    fullname=$( cut -d "," -f 3 <<<$line)
    homedir=$( cut -d "," -f 4 <<<$line)
    shell=$( cut -d "," -f 5 <<<$line)
    passwd=$( cut -d "," -f 6 <<<$line)

    if cut -d ":" -f 3 /etc/passwd | grep -q "^${userid}$"
    then
        echo ;echo -e "${msg2_color}id为${userid}的目标用户已经存在${end_color}";echo 
        continue
    fi

    useradd ${username} -u ${userid} -c "${fullname}" -m -d "${homedir}" -s "${shell}" -p ${passwd}

    echo -e "${msg1_color}已添加用户${end_color}"
    echo -e "${msg1_color}========================${end_color}"
    echo -e "${msg_color}username:${end_color}${data_color}${username}${end_color}"
    echo -e "${msg_color}userid:${end_color}${data_color}${userid}${end_color}"
    echo -e "${msg_color}fullname:${end_color}${data_color}${fullname}${end_color}"
    echo -e "${msg_color}homedir:${end_color}${data_color}${homedir}${end_color}"
    echo -e "${msg_color}shell:${end_color}${data_color}${shell}${end_color}"
    echo -e "${msg_color}passwd:${end_color}${data_color}${passwd}${end_color}"
    echo -e "${msg1_color}========================${end_color}"

done < /home/lxh/userlist.txt

实现效果:

lxh@ubuntu:~$ /bin/bash adduser.sh 
已添加用户
========================
username:user001
userid:1001
fullname:张三 001
homedir:/home/user001
shell:/bin/bash
passwd:Passw0rd001
========================
已添加用户
========================
username:user002
userid:1002
fullname:李四 002
homedir:/home/user002
shell:/bin/bash
passwd:Passw0rd002
========================
已添加用户
========================
username:user003
userid:1003
fullname:王五 003
homedir:/home/user003
shell:/bin/bash
passwd:Passw0rd003
========================
已添加用户
========================
username:user004
userid:1004
fullname:赵六 004
homedir:/home/user004
shell:/bin/bash
passwd:Passw0rd004
========================
已添加用户
========================
username:user005
userid:1005
fullname:钱七 005
homedir:/home/user005
shell:/bin/bash
passwd:Passw0rd005
========================

id为1006的目标用户已经存在

已添加用户
========================
username:user007
userid:1007
fullname:周九 007
homedir:/home/user007
shell:/bin/bash
passwd:Passw0rd007
========================
...

root@ubuntu:/home/lxh# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:998:998:systemd Network Management:/:/usr/sbin/nologin
systemd-timesync:x:997:997:systemd Time Synchronization:/:/usr/sbin/nologin
dhcpcd:x:100:65534:DHCP Client Daemon,,,:/usr/lib/dhcpcd:/bin/false
messagebus:x:101:102::/nonexistent:/usr/sbin/nologin
systemd-resolve:x:992:992:systemd Resolver:/:/usr/sbin/nologin
pollinate:x:102:1::/var/cache/pollinate:/bin/false
polkitd:x:991:991:User for polkitd:/:/usr/sbin/nologin
syslog:x:103:104::/nonexistent:/usr/sbin/nologin
uuidd:x:104:105::/run/uuidd:/usr/sbin/nologin
tcpdump:x:105:107::/nonexistent:/usr/sbin/nologin
tss:x:106:108:TPM software stack,,,:/var/lib/tpm:/bin/false
landscape:x:107:109::/var/lib/landscape:/usr/sbin/nologin
fwupd-refresh:x:989:989:Firmware update daemon:/var/lib/fwupd:/usr/sbin/nologin
usbmux:x:108:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
sshd:x:109:65534::/run/sshd:/usr/sbin/nologin
lxh:x:1000:1000:LXH:/home/lxh:/bin/bash
testuser:x:1006:1006::/home/testuser:/bin/sh
user001:x:1001:1001:张三 001:/home/user001:/bin/bash
user002:x:1002:1002:李四 002:/home/user002:/bin/bash
user003:x:1003:1003:王五 003:/home/user003:/bin/bash
user004:x:1004:1004:赵六 004:/home/user004:/bin/bash
user005:x:1005:1005:钱七 005:/home/user005:/bin/bash
user007:x:1007:1007:周九 007:/home/user007:/bin/bash
user008:x:1008:1008:吴十 008:/home/user008:/bin/bash
user009:x:1009:1009:郑十一 009:/home/user009:/bin/bash
user010:x:1010:1010:王十二 010:/home/user010:/bin/bash
user011:x:1011:1011:刘十三 011:/home/user011:/bin/bash
user012:x:1012:1012:陈十四 012:/home/user012:/bin/bash
user013:x:1013:1013:杨十五 013:/home/user013:/bin/bash
...

扫描所在网络的在线主机(扩展)

脚本内容:

lxh@ubuntu:~$ cat test.sh 
#!/bin/bash

num_to_addr(){		# 用于将数字转换为ip地址的函数
    num=$1
    b_num=$(echo "obase=2;$num" | bc)
    let add_len=32-${#b_num}
    for j in $(eval echo {1..$add_len})
    do
        b_num=0$b_num

    done

    addr=""
    local num_part=""
    for j in {0..31}
    do
        bit=${b_num:$j:1}
        num_part=${num_part}${bit}

        if [[ ${#num_part} -eq 8 ]]
        then
           addr=${addr}$(echo "ibase=2;${num_part}" | bc )\. 
           num_part=""
        fi
    done

    echo ${addr:0:$[${#addr}-1]}

}

# 从ip addr中获取所有接口的IP地址以及掩码信息
ip_mask_list=$(ip addr | grep "inet " | tr -s " " | cut -d " " -f 3)

# 针对每个接口,获取IP地址对应的网段,扫描网段中所有IP
for ip_mask in $ip_mask_list
do 
	# 提取IP地址和掩码长度
    ip=$(echo $ip_mask | cut -d "/" -f 1)
    masklen=$(echo $ip_mask | cut -d "/" -f 2)
    echo "扫描$ip所在网段"
    # echo $[32-$masklen]

    ip_num=""
    for i in {1..4}
    do
    	# 将IP地址转换为二进制数
        num_part=$(printf "%08d" $(echo "obase=2;$(echo $ip | cut -d "." -f $i)" | bc))
        # echo $num_part
        ip_num=$ip_num$num_part
    
    done

    # echo $ip_num

	# 构造32位子网掩码的二进制形式,0对应网络位,1对应主机位
    part1=""
    for i in $( eval echo {1..$[32-$masklen]})
    do
        part1=${part1}1

    done

    part2=""
    for i in $( eval echo {1..$masklen})
    do 
        part2=${part2}0
    done

    mask=$part2$part1
    # echo $mask

	# 获取扫描网段的网段IP地址对应的二进制数字
    begin_ip=""
    for i in {0..31}
    do
        if [[ ${mask:$i:1} -eq 1 ]]
        then
            begin_ip=${begin_ip}0
        else
            begin_ip=${begin_ip}${ip_num:$i:1}
        fi
    done

    # echo $begin_ip

	# 获取扫描网段的广播IP地址对应的二进制数字
    end_ip=""
    for i in {0..31}
    do
        if [[ ${mask:$i:1} -eq 1 ]]
        then
            end_ip=${end_ip}1
        else
            end_ip=${end_ip}${ip_num:$i:1}
        fi
    done
    # echo $end_ip

	# 获取扫描网段的第一个地址和最后地址对应的十进制数字
    let begin_num=$(echo "ibase=2;$begin_ip" | bc)+1
    let end_num=$(echo "ibase=2;$end_ip" | bc)-1
    # echo $begin_num
    # echo $end_num

	# 如果扫描网段的第一个地址为"2130706433",那么表示回环地址,直接跳过扫描
    if [[ $begin_num -eq "2130706433" ]]
    then
         echo "回环地址,跳过扫描"
         continue
    fi

	# 遍历所有IP地址对应的十进制数字,如果能够成功ping通,那么输出"IP地址 online"
    for i in $(eval echo {$begin_num..$end_num})
    do
        ping -c 1 $i > /dev/null 2>&1
        if [[ $? -eq 0 ]]
        then 
            echo "$(num_to_addr $i) online"
        fi
    done
done

实现效果:

lxh@ubuntu:~$ /bin/bash test.sh
扫描127.0.0.1所在网段
回环地址,跳过扫描
扫描10.0.0.150所在网段
10.0.0.1 online
10.0.0.2 online
10.0.0.150 online
10.0.0.159 online
扫描10.0.0.159所在网段
10.0.0.1 online
10.0.0.2 online
10.0.0.150 online
10.0.0.159 online
...

AWK

介绍

awk全称 Aho Weinberger Kernighan报告生成器,awk的三个字母是来自于三个作者的首字母。它是一个功能非常强大的文档编辑工具,它不仅能以行为单位还能以列为单位处理文件,并且还具有格式化文本输出功能

awk的工作方式是逐行读取文本数据,将每一行数据视为一条记录(record)每条记录以字段分隔符分成若干字段,然后输出各个字段的值,然后以查找匹配某个特定模式的文本行,并对这些文本执行制定动作

格式

常用格式为

awk '匹配条件{打印语句}'

更加一般的格式为

awk 'BEGIN{变量定义}匹配条件{对指定行的动作}END{结束操作}'

值得注意的是,BEGIN块先被执行,然后是中间的匹配条件与动作,最后执行END块

常用变量

案例文件内容

lxh@ubuntu:~$ cat awk.txt 
nihao awk1 awk2 awk3
nihao awk4 awk5 awk6
nihao awk7 awk8 awk9
lxh@ubuntu:~$
lxh@ubuntu:~$ cat passwd_part 
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
lxh@ubuntu:~$ 

$0

$0表示一整个记录内容

lxh@ubuntu:~$ awk '{print $0}' awk.txt 
nihao awk1 awk2 awk3
nihao awk4 awk5 awk6
nihao awk7 awk8 awk9
lxh@ubuntu:~$ 

$N

$N表示记录的第N个字段内容

lxh@ubuntu:~$ awk '{print $NF}' awk.txt 
awk3
awk6
awk9
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk '{print $(NF-1)}' awk.txt 
awk2
awk5
awk8
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk '{print $(NF-2)}' awk.txt 
awk1
awk4
awk7
lxh@ubuntu:~$ 

NF

N表示number,F表示field,NR表示字段个数

lxh@ubuntu:~$ awk '{print NR,NF}' awk.txt 
1 4
2 4
3 4
lxh@ubuntu:~$ 

NR

N表示number,R表示record,NR表示记录编号,即行号

lxh@ubuntu:~$ awk '{print NR": "$0}' awk.txt 
1: nihao awk1 awk2 awk3
2: nihao awk4 awk5 awk6
3: nihao awk7 awk8 awk9
lxh@ubuntu:~$ 

FS

F表示field,S表示Separator,FS表示字段分隔符

lxh@ubuntu:~$ awk '{print $1}' passwd_part
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{FS=":"}{print $1}' passwd_part
root
daemon
bin
sys
sync
games
man
lp
mail
news
lxh@ubuntu:~$ 

OFS

O表示output,F表示field,S表示Separator,OFS表示输出字段分隔符

lxh@ubuntu:~$ awk 'BEGIN{FS=":"}{print $1,$3}' passwd_part
root 0
daemon 1
bin 2
sys 3
sync 4
games 5
man 6
lp 7
mail 8
news 9
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{FS=":";OFS="\t"}{print $1,$3}' passwd_part
root    0
daemon  1
bin     2
sys     3
sync    4
games   5
man     6
lp      7
mail    8
news    9
lxh@ubuntu:~$ 

ORS

O表示output,R表示record,S表示Separator,ORS表示输出记录分隔符

lxh@ubuntu:~$ awk 'BEGIN{FS=":"}{print $1}' passwd_part
root
daemon
bin
sys
sync
games
man
lp
mail
news
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{FS=":";ORS="、"}{print $1}' passwd_part
root、daemon、bin、sys、sync、games、man、lp、mail、news、lxh@ubuntu:~$ 
lxh@ubuntu:~$ 

数组

数组定义

lxh@ubuntu:~$ awk 'BEGIN{arry["first"]="apple";arry["second"]="orange"}'
lxh@ubuntu:~$ 

遍历数组

所谓遍历数组,就是将数组的每一个元素依次获取并打印

需要通过流程控制的for循环来遍历数组

lxh@ubuntu:~$ awk 'BEGIN{arry["first"]="apple";arry["second"]="orange"; for(i in arry){print i": "arry[i]}}'
first: apple
second: orange
lxh@ubuntu:~$ 

内置函数

数值类内置函数

int

格式:int(expr)

作用:截断为整数返回

lxh@ubuntu:~$ awk 'BEGIN{print int(123.33)}'
123
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{print int(123abc)}'
123
lxh@ubuntu:~$

sqrt

格式:sqrt(expr)

作用:返回平方根

lxh@ubuntu:~$ awk 'BEGIN{print sqrt(4)}'
2
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{print sqrt(5)}'
2.23607
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{print sqrt(16)}'
4
lxh@ubuntu:~$ 

rand 以及 srand

格式: rand()

​ srand([expr])

作用:rand 返回[0,1)之间的随机数,默认使用srand(1)作为种子值

​ srand 设置rand()种子值,省略参数时将取当前时间的epoch值(精确到秒的epoch)作为种子值

lxh@ubuntu:~$ awk 'BEGIN{srand();num=rand();print num}'
0.494666
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{srand();num=rand();print num}'
0.847979
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{srand();num=rand();print num}'
0.131395
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{srand();num=rand();print num}'
0.0568878
lxh@ubuntu:~$ 

字符串类内置函数

sprintf

格式: sprintf(format, expression1, ...)

作用:格式化显示数据

lxh@ubuntu:~$ awk 'BEGIN{outstr=sprintf("%d\t%s",123,"abc");print outstr}'
123     abc
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{outstr=sprintf("%d--%s",123,"abc");print outstr}'
123--abc
lxh@ubuntu:~$ 

length

格式:length(str)

作用:获取字符串长度

lxh@ubuntu:~$ awk 'BEGIN{len=length("abc");print len}'
3
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{len=length("abc___   ");print len}'
9
lxh@ubuntu:~$ 

strtonum

格式:strtonum(str)

作用:将字符串转换为十进制数值,如果str以0开头,则将其识别为8进制,如果str以0x或0X开头,则将其识别为16进制

lxh@ubuntu:~$ awk 'BEGIN{str="0x11";print strtonum(str)}'
17
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{str="011";print strtonum(str)}'
9
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{str="11";print strtonum(str)}'
11
lxh@ubuntu:~$ 

tolower

格式:tolower(str)

作用:将字母全部转换为小写

lxh@ubuntu:~$ awk 'BEGIN{str="ABCdef";print tolower(str)}'
abcdef
lxh@ubuntu:~$ 

toupper

格式:toupper(str)

作用:将字母全部转换为大写

lxh@ubuntu:~$ awk 'BEGIN{str="ABCdef";print toupper(str)}'
ABCDEF
lxh@ubuntu:~$ 

index

格式:index(str,substr)

作用:从str中搜索substr(子串),返回搜索到的索引位置,搜索不到则返回0

lxh@ubuntu:~$ awk 'BEGIN{str="abcDEF";subs="cD";print index(str,subs)}'
3
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{str="abcDEF";subs="ab";print index(str,subs)}'
1
lxh@ubuntu:~$ 

数据操作内置函数

substr

格式:substr(string,start[,length])

作用:指定起始索引和长度,从string中截取子串

lxh@ubuntu:~$ awk 'BEGIN{str="abcDEF";print substr(str, 1, 3)}'
abc
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{str="abcDEF";print substr(str, 4, 3)}'
DEF
lxh@ubuntu:~$ 

split

格式:split(string, array [, fieldsep [, seps ] ])

作用:将字符串分割后保存到数组array中

lxh@ubuntu:~$ awk 'BEGIN{str="abc:DEF";split(str, arry, ":");for(i in arry){print arry[i]}}'
abc
DEF
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{str="abc:DEF";split(str, arry, "bc");for(i in arry){print arry[i]}}'
a
:DEF
lxh@ubuntu:~$ 

match

格式:match(string,reg[,arr])

作用:使用reg正则规则匹配string信息,默认返回匹配的索引,仅仅匹配一次

​ 可以将内容存到数组,索引0对应整个正则表达式匹配到的字符串,索引1、2、3....对应分组1、2、3匹配到的子串

lxh@ubuntu:~$ awk 'BEGIN{str="172.29.65.11";match(str, "([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3})", arry);print arry[0]}'
172.29.65.11
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{str="172.29.65.11";match(str, "([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3})", arry);print arry[1]}'
172
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{str="172.29.65.11";match(str, "([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3})", arry);print arry[2]}'
29
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{str="172.29.65.11";match(str, "([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3})", arry);print arry[3]}'
65
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{str="172.29.65.11";match(str, "([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3})", arry);print arry[4]}'
11
lxh@ubuntu:~$ 

时间类内置函数

mktime

格式:mktime("YYYY MM DD HH mm SS [DST]")

作用:将指定时间转换为时间戳

lxh@ubuntu:~$ awk 'BEGIN{print mktime("2025 12 17 01 16 11 24")}'
1765930571
lxh@ubuntu:~$ 

systime

格式:systime()

作用:获取当前系统时间戳

lxh@ubuntu:~$ awk 'BEGIN{print systime()}'
1765905450
lxh@ubuntu:~$ 

strftime

格式:strftime([format [, timestamp [, utc-flag] ] ])

作用:获取格式化日期

lxh@ubuntu:~$ awk 'BEGIN{print strftime()}'
Tue Dec 16 17:18:11 UTC 2025
lxh@ubuntu:~$ 

数据类型相关内置函数

isarray

格式:isarray(var)

作用:判断变量是否为数组

lxh@ubuntu:~$ awk 'BEGIN{var[0]="0";print isarray(var)}'
1
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{var="0";print isarray(var)}'
0
lxh@ubuntu:~$ 

typeof

格式:typeof(var)

作用:获取变量的类型

lxh@ubuntu:~$ awk 'BEGIN{var[0]="0";print typeof(var)}'
array
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{var="0";print typeof(var)}'
string
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{var=0;print typeof(var)}'
number
lxh@ubuntu:~$ 

流程控制

流程控制在语法上与C语言差不多,学习过shell编程的流程控制后,学习awk的流程控制应该是手到擒来

所以这里不再赘述,直接给出一些案例

条件

if语句

单分支

lxh@ubuntu:~$ awk 'NR==1{print $0}' awk.txt 
nihao awk1 awk2 awk3
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk '{if(NR==1){print $0}}' awk.txt 
nihao awk1 awk2 awk3
lxh@ubuntu:~$ 

双分支

lxh@ubuntu:~$ awk '{print $0}' awk.txt 
nihao awk1 awk2 awk3
nihao awk4 awk5 awk6
nihao awk7 awk8 awk9
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk '{if(NR==2){print $2}else{print $1}}' awk.txt 
nihao
awk4
nihao
lxh@ubuntu:~$ 

多分支

lxh@ubuntu:~$ awk '{print $0}' awk.txt 
nihao awk1 awk2 awk3
nihao awk4 awk5 awk6
nihao awk7 awk8 awk9
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk '{if(NR==1){print $1}else if(NR==2){print $2}else{print $3}}' awk.txt 
nihao
awk4
awk8
lxh@ubuntu:~$ 

switch语句

lxh@ubuntu:~$ awk 'BEGIN{num=1;switch (num){
> case 0:
> print "这是0"
> break
> case 1:
> print "这是1"
> break
> case 2:
> print "这是2"
> break
> }}'
这是1
lxh@ubuntu:~$ 

循环

for语句

lxh@ubuntu:~$ awk 'BEGIN{for(i=0;i<10;i++){print i}}'
0
1
2
3
4
5
6
7
8
9
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{arry[1]="A";arry[2]="B";arry[3]="C";for(i in arry){print i": "arry[i]}}'
1: A
2: B
3: C
lxh@ubuntu:~$ 

while语句

lxh@ubuntu:~$ awk 'BEGIN{i=0;while(i<10){print i;i++}}'
0
1
2
3
4
5
6
7
8
9
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'BEGIN{i=0;do{print i;i++}while(i<10)}'
0
1
2
3
4
5
6
7
8
9
lxh@ubuntu:~$ 

自定义函数

函数定义

一般函数定义在BEGIN块的前面

函数名不能使用awk关键字,会导致报错

lxh@ubuntu:~$ awk 'function f(){print 123}'
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'function if(){print 123}'
awk: cmd. line:1: function if(){print 123}
awk: cmd. line:1:          ^ syntax error
lxh@ubuntu:~$ 
lxh@ubuntu:~$ awk 'function case(){print 123}'
awk: cmd. line:1: function case(){print 123}
awk: cmd. line:1:          ^ syntax error
lxh@ubuntu:~$ 

函数使用

lxh@ubuntu:~$ awk '
> function add_f(a,b){
>   return a+b
> }
> function sub_f(a,b){
>   if(a>b){
>   return a-b
>   }
>   return b-a
> }
> BEGIN{print add_f(2,1), sub_f(2,1)}'
3 1
lxh@ubuntu:~$ 

进程管理

进程与线程的区别

  • 进程
    • 在早期的操作系统中并没有线程的概念,进程是能拥有资源和独立运行的最小单位,也是程序执行的最小单位
  • 线程
    • 随着计算机的发展,对CPU的要求越来越高,进程之间的切换开销较大,已经无法满足越来越复杂的程序的要求了。于是就发明了线程
    • 线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元
  • 进程与线程
    • 一个进程可以有一个或多个线程,同一进程下的各个线程之间共享程序的内存空间(包括代码段、数据集、堆等)及一些进程级的资源(如打开文件和信号)

image-20251218232610895

进程结构

进程一般由程序、数据集合和进程控制块三部分组成

  • 程序
    • 程序用于描述进程要完成的功能,是控制进程执行的指令集
  • 数据集合
    • 数据集合是程序在执行时所需要的数据和工作区
  • 进程控制块(PCB)
    • 进程控制块包含进程的描述信息和控制信息,是进程存在的唯一标志
    • 进程控制块的内容:
      • 进程id、用户id和组id
      • 程序计数器
      • 进程的状态(有就绪、运行、阻塞)
      • 进程切换时需要保存和恢复的CPU寄存器的值
      • 描述虚拟地址空间的信息
      • 描述控制终端的信息
      • 当前工作目录
      • 文件描述符表,包含很多指向file结构体的指针
      • 进程可以使用的资源上限(ulimit -a命令可以查看)
      • 输入输出状态:配置进程使用I/O设备

进程状态

常见的5种状态

  • 创建
    • 进程在创建时需要申请一个空白进程控制块,向其中填写控制和管理进程的信息,完成资源分配
    • 如果创建工作无法完成,比如资源无法满足,就无法被调度运行,把此时进程所处状态称为创建状态
  • 就绪
    • 进程已准备好,已分配到所需资源,只要分配到CPU就能够立即运行
  • 执行
    • 进程处于就绪状态被操作系统调度后,进程进入执行状态
  • 阻塞
    • 正在执行的进程由于某些事件(I/O请求,申请缓存区失败)而暂时无法运行,进程受到阻塞
    • 在满足请求时进入就绪状态等待系统调用
  • 终止
    • 进程结束,或出现错误,或被系统终止,进入终止状态。无法再执行

状态之间转换

  • 执行→就绪
    • 主要是由于进程占用CPU的时间过长,而系统分配给该进程占用CPU的时间是有限的,停止调度该进程以后,该进程进入就绪状态
  • 就绪→运行
    • 运行的进程的时间片用完,那个进程就会被调度就转到就绪队列中,然后会选择合适的进程分配CPU
  • 运行→阻塞
    • 正在执行的进程因发生某等待事件而无法执行,则进程由执行状态变为阻塞状态,如发生了I/O请求
  • 阻塞→就绪
    • 进程所需要进程等待的事件已经完成,该进程自然就进入就绪队列等待被操作系统调度

特殊的进程

  • 僵尸进程
    • 进程终止,但是其父进程由于某些原因尚未回收该子进程资源,导致子进程残留资源(PCB)存放于内核中,变成僵尸(zombie)进程
  • 孤儿进程
    • 如果在子进程在退出前,父进程先退出,这时子进程将成为孤儿进程,因为它的父进程已经死了。孤儿进程会被PID=1的systemd进程收养,成为systemd的子进程
    • 注意,孤儿进程还会继续运行,而不会随父进程退出而终止,只不过其父进程发生了改变

进程优先级

linux2.6内核将任务优先级进行了一个划分,分为实时优先级范围和非实时优先级,优先级数值越小越优先

注意,优先级越高,并不代表程序执行会更快,而是说在cpu调度时,给予更高的权重,最先执行优先级决定的是执行顺序靠前,而不决定其程序本身要执行多久

  • 实时优先级
    • 范围为0到99
  • 非实时优先级
    • 范围为100到139

进程管理命令

找到目标进程

ps

用途:显示进程的相关信息,默认显示当前终端中的进程

选项:

  • -a:显示所有终端相关进程
  • -u:显示进程的所有者
  • -x:显示与终端无关的其他进程信息

案例:

lxh@ubuntu:~$ ps
    PID TTY          TIME CMD
   1416 pts/0    00:00:00 bash
   1579 pts/0    00:00:00 ps
lxh@ubuntu:~$ 
lxh@ubuntu:~$ ps -a
    PID TTY          TIME CMD
   1569 tty1     00:00:00 bash
   1580 pts/0    00:00:00 ps
lxh@ubuntu:~$ 
lxh@ubuntu:~$ ps -au
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         937  0.0  0.2   6968  4608 tty1     Ss   17:18   0:00 /bin/login -p --
lxh         1416  0.0  0.2   8780  5504 pts/0    Ss   17:22   0:00 -bash
lxh         1505  0.0  0.2   8780  5504 pts/1    Ss+  17:26   0:00 -bash
lxh         1569  0.3  0.2   8784  5632 tty1     S+   17:26   0:00 -bash
lxh         1581  100  0.2  10884  4480 pts/0    R+   17:26   0:00 ps -au
lxh@ubuntu:~$ 
lxh@ubuntu:~$ ps -aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  1.1  0.6  22000 12860 ?        Ss   17:17   0:06 /sbin/init
root           2  0.0  0.0      0     0 ?        S    17:17   0:00 [kthreadd]
root           3  0.0  0.0      0     0 ?        S    17:17   0:00 [pool_workqueue_release]
root           4  0.0  0.0      0     0 ?        I<   17:17   0:00 [kworker/R-rcu_g]
root           5  0.0  0.0      0     0 ?        I<   17:17   0:00 [kworker/R-rcu_p]
root           6  0.0  0.0      0     0 ?        I<   17:17   0:00 [kworker/R-slub_]
root           7  0.0  0.0      0     0 ?        I<   17:17   0:00 [kworker/R-netns]
root           8  0.2  0.0      0     0 ?        I    17:17   0:01 [kworker/0:0-events]
root           9  0.5  0.0      0     0 ?        I    17:17   0:03 [kworker/0:1-events]
root          10  0.0  0.0      0     0 ?        I<   17:17   0:00 [kworker/0:0H-kblockd]
root          11  0.0  0.0      0     0 ?        I    17:17   0:00 [kworker/u256:0-ext4-rsv-conversion]
root          12  0.0  0.0      0     0 ?        I<   17:17   0:00 [kworker/R-mm_pe]
...

pstree

用途:以树状显示各个进程

提示:花括号对应的是线程,无括号对应的是进程

选项:

  • -p:显示进程号

案例:

lxh@ubuntu:~$ pstree -p
systemd(1)─┬─ModemManager(987)─┬─{ModemManager}(1188)
           │                   ├─{ModemManager}(1197)
           │                   └─{ModemManager}(1199)
           ├─VGAuthService(832)
           ├─agetty(937)
           ├─cron(897)
           ├─dbus-daemon(898)
           ├─multipathd(471)─┬─{multipathd}(505)
           │                 ├─{multipathd}(507)
           │                 ├─{multipathd}(508)
           │                 ├─{multipathd}(509)
           │                 ├─{multipathd}(510)
           │                 └─{multipathd}(511)
           ├─polkitd(909)─┬─{polkitd}(944)
           │              ├─{polkitd}(955)
           │              └─{polkitd}(966)
           ├─rsyslogd(929)─┬─{rsyslogd}(961)
           │               ├─{rsyslogd}(962)
           │               └─{rsyslogd}(963)
           ├─sshd(1298)───sshd(1300)───sshd(1415)───bash(1416)───pstree(1461)
           ├─systemd(1305)───(sd-pam)(1306)
           ├─systemd-journal(436)
           ├─systemd-logind(914)
           ├─systemd-network(711)
           ├─systemd-resolve(719)
           ├─systemd-timesyn(720)───{systemd-timesyn}(739)
           ├─systemd-udevd(503)
           ├─udisksd(916)─┬─{udisksd}(945)
           │              ├─{udisksd}(952)
           │              ├─{udisksd}(965)
           │              ├─{udisksd}(1200)
           │              └─{udisksd}(1201)
           ├─unattended-upgr(940)───{unattended-upgr}(1243)
           └─vmtoolsd(833)─┬─{vmtoolsd}(904)
                           ├─{vmtoolsd}(968)
                           └─{vmtoolsd}(969)
lxh@ubuntu:~$ 

pidof

用途:根据进程名称来获取进程号PID

提示:通常用于脚本中,以确定特定的程序是否正在运行

案例:

lxh@ubuntu:~$ pidof sshd
1415 1300 1298
lxh@ubuntu:~$ 
lxh@ubuntu:~$ ps aux | grep sshd
root        1298  0.0  0.4  12020  8064 ?        Ss   17:21   0:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
root        1300  0.0  0.5  14972 10240 ?        Ss   17:21   0:00 sshd: lxh [priv]
lxh         1415  0.0  0.3  15132  6968 ?        S    17:22   0:00 sshd: lxh@pts/0,pts/1
lxh         1743  0.0  0.1   6544  2304 pts/0    S+   17:58   0:00 grep --color=auto sshd
lxh@ubuntu:~$ 

top

用途:用于实时显示系统的运行状况,特别是各个进程的资源和性能使用情况

选项:

  • -n:显示次数
  • -d:刷新间隔
  • -u:指定用户的进程

字段解读:

image-20251219222705429

交互命令:

  • P:按照CPU使用率排序
  • M:按照内存使用率排序
  • T:按照CPU使用时长排序
  • s:设置刷新间隔
  • k:杀掉指定进程
  • 1:将各个CPU分开显示

案例:

lxh@ubuntu:~$ top -n 1 >> top.txt
lxh@ubuntu:~$ top -n 1 >> top.txt
lxh@ubuntu:~$ cat top.txt 
top - 14:25:59 up 37 min,  1 user,  load average: 0.00, 0.00, 0.06
Tasks: 212 total,   2 running, 210 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st 
MiB Mem :   1919.9 total,   1324.9 free,    371.0 used,    377.4 buff/cache     
MiB Swap:   2048.0 total,   2048.0 free,      0.0 used.   1548.9 avail Mem 

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND  
      1 root      20   0   22008  13004   9292 S   0.0   0.7   0:03.07 systemd  
      2 root      20   0       0      0      0 S   0.0   0.0   0:00.02 kthreadd 
      3 root      20   0       0      0      0 S   0.0   0.0   0:00.00 pool_wo+ 
      4 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 kworker+ 
      5 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 kworker+ 
      6 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 kworker+ 
      7 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 kworker+ 
     10 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 kworker+ 
     11 root      20   0       0      0      0 I   0.0   0.0   0:00.00 kworker+ 
     12 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 kworker+ 
     13 root      20   0       0      0      0 I   0.0   0.0   0:00.00 rcu_tas+ 
     14 root      20   0       0      0      0 I   0.0   0.0   0:00.00 rcu_tas+ 
     15 root      20   0       0      0      0 I   0.0   0.0   0:00.00 rcu_tas+ 
     16 root      20   0       0      0      0 S   0.0   0.0   0:00.08 ksoftir+ 
     17 root      20   0       0      0      0 I   0.0   0.0   0:00.35 rcu_pre+ 
     18 root      rt   0       0      0      0 S   0.0   0.0   0:00.12 migrati+ 
     19 root     -51   0       0      0      0 S   0.0   0.0   0:00.00 idle_in+ 
top - 14:26:01 up 37 min,  1 user,  load average: 0.00, 0.00, 0.06
Tasks: 212 total,   2 running, 210 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  4.2 sy,  0.0 ni, 95.8 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st 
MiB Mem :   1919.9 total,   1324.9 free,    371.0 used,    377.4 buff/cache     
MiB Swap:   2048.0 total,   2048.0 free,      0.0 used.   1548.9 avail Mem 

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND  
    829 root      20   0  242184   9216   7808 S   8.3   0.5   0:07.95 vmtoolsd 
   1728 lxh       20   0   11936   5632   3456 R   8.3   0.3   0:00.02 top      
      1 root      20   0   22008  13004   9292 S   0.0   0.7   0:03.07 systemd  
      2 root      20   0       0      0      0 S   0.0   0.0   0:00.02 kthreadd 
      3 root      20   0       0      0      0 S   0.0   0.0   0:00.00 pool_wo+ 
      4 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 kworker+ 
      5 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 kworker+ 
      6 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 kworker+ 
      7 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 kworker+ 
     10 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 kworker+ 
     11 root      20   0       0      0      0 I   0.0   0.0   0:00.00 kworker+ 
     12 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 kworker+ 
     13 root      20   0       0      0      0 I   0.0   0.0   0:00.00 rcu_tas+ 
     14 root      20   0       0      0      0 I   0.0   0.0   0:00.00 rcu_tas+ 
     15 root      20   0       0      0      0 I   0.0   0.0   0:00.00 rcu_tas+ 
     16 root      20   0       0      0      0 S   0.0   0.0   0:00.08 ksoftir+ 
     17 root      20   0       0      0      0 I   0.0   0.0   0:00.35 rcu_pre+ 

lxh@ubuntu:~$ 

lsof

用途:显示进程打开的文件

选项:

  • -P:以数字方式显示端口
  • -t:仅仅显示PID
  • -i:筛选条件

案例:

lxh@ubuntu:~$ ps aux | grep nginx
root        2160  0.0  0.3  11196  6784 ?        S    15:55   0:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
www-data    2162  0.0  0.2  12884  4404 ?        S    15:55   0:00 nginx: worker process
www-data    2163  0.0  0.2  12884  4404 ?        S    15:55   0:00 nginx: worker process
lxh         2262  0.0  0.1   6544  2304 pts/0    S+   16:01   0:00 grep --color=auto nginx
lxh@ubuntu:~$ 
lxh@ubuntu:~$ sudo lsof -Pti :80
2160
2162
2163
lxh@ubuntu:~$ 

操作目标进程

nice

用途:设置进程优先级

选项:

  • -n:指定优先级

案例:

lxh@ubuntu:~$ ps ax -o pid,nice,command | grep ping
   1651   0 grep --color=auto ping
lxh@ubuntu:~$ 
lxh@ubuntu:~$ 
lxh@ubuntu:~$ ping 8.8.8.8 &> /dev/null &				# 默认的ping进程,优先级为0
[1] 1656
lxh@ubuntu:~$ ps ax -o pid,nice,command | grep ping
   1656   0 ping 8.8.8.8
   1658   0 grep --color=auto ping
lxh@ubuntu:~$ 
lxh@ubuntu:~$ 
lxh@ubuntu:~$ nice -n 10 ping 8.8.8.8 &> /dev/null &	# 指定ping进程的优先级为10
[2] 1660
lxh@ubuntu:~$ ps ax -o pid,nice,command | grep ping
   1656   0 ping 8.8.8.8
   1660  10 ping 8.8.8.8
   1662   0 grep --color=auto ping
lxh@ubuntu:~$ 

renice

用途:重新设置进程优先级

选项:

  • -n:指定优先级

案例:

lxh@ubuntu:~$ nice -n 10 ping 8.8.8.8 &> /dev/null &
[1] 1673
lxh@ubuntu:~$ ps ax -o pid,nice,command | grep ping
   1673  10 ping 8.8.8.8
   1675   0 grep --color=auto ping
lxh@ubuntu:~$ 
lxh@ubuntu:~$ renice -n 20  1673
1673 (process ID) old priority 10, new priority 19			# 非实时优先级的调整范围为-20到19
lxh@ubuntu:~$ 
lxh@ubuntu:~$ ps ax -o pid,nice,command | grep ping
   1673  19 ping 8.8.8.8
   1678   0 grep --color=auto ping
lxh@ubuntu:~$ 

kill

用途:向指定进程发送信号,通常用于终止进程,通过"进程ID”(PID)来指定进程

选项:

  • -l:显示所有信号
  • -9:强制杀死指定进程
  • -0:隐藏信号,判定进程是否存在

案例:

lxh@ubuntu:~$ ping 8.8.8.8 > /dev/null &
[1] 2284
lxh@ubuntu:~$ 
lxh@ubuntu:~$ sudo kill -0 2284			# 判断指定进程是否存在
lxh@ubuntu:~$ echo $?
0
lxh@ubuntu:~$ 
lxh@ubuntu:~$ sudo kill -9 2284			# 强制杀死指定进程
[1]+  Killed                  ping 8.8.8.8 > /dev/null
lxh@ubuntu:~$ 
lxh@ubuntu:~$ sudo kill -0 2284
kill: (2284): No such process
lxh@ubuntu:~$ echo $?
1
lxh@ubuntu:~$ 

killall

用途:与kill命令一样,可以发送多种信号到指定进程,通过"进程名称"来匹配进程,而不是进程ID

选项:

  • -l:显示所有信号
  • -9:强制杀死指定进程

案例:

lxh@ubuntu:~$ ps aux | grep nginx
root        2358  0.0  0.0  11156  1588 ?        Ss   16:32   0:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
www-data    2359  0.0  0.2  12880  4404 ?        S    16:32   0:00 nginx: worker process
www-data    2360  0.0  0.2  12880  4276 ?        S    16:32   0:00 nginx: worker process
lxh         2368  0.0  0.1   6544  2176 pts/0    S+   16:32   0:00 grep --color=auto nginx
lxh@ubuntu:~$ 
lxh@ubuntu:~$ sudo killall -9 nginx
lxh@ubuntu:~$ 
lxh@ubuntu:~$ ps aux | grep nginx
lxh         2380  0.0  0.1   6544  2304 pts/0    S+   16:32   0:00 grep --color=auto nginx
lxh@ubuntu:~$ 

IPC与RPC(扩展)

  • IPC

    • Inter-Process Communication,进程间通信
    • IPC 是指在同一台计算机上运行的多个进程之间进行数据交换和同步的机制
    • 主要用于操作系统内部的不同进程间的通信,如共享内存、管道、消息队列、信号量等。这些机制允许进程之间高效地传递数据和同步操作
  • RPC

    • Remote Procedure Call,远程过程调用
    • RPC 是一种通过网络从远程计算机程序上请求服务的协议。它允许一个程序调用另一个地址空间(通常是另一台机器上的程序)的过程或服务,就像调用本地服务一样
    • 广泛应用于分布式系统中,使得不同的服务和应用可以跨网络进行无缝的交互和协作。例如,微服务架构中的服务调用通常通过 RPC 实现

IPC实现方式

  • 管道,单向传输
    • 无名管道:是UNIX系统IPC最古老的形式,它是半双工的(即数据只能在一个方向上流动),具有固定的读端和写端,只能用于具有亲缘关系的进程之间的通信(如父子进程或兄弟进程之间)
    • 命名管道(FIFO):可以在无关的进程之间交换数据,与无名管道不同,FIFO有路径名与之相关联,以一种特殊设备文件形式存在于文件系统中
  • 共享内存
    • 指两个或多个进程共享一个给定的存储区,这是最快的一种IPC方式,因为进程是直接对内存进行存取。由于多个进程可以同时操作共享内存,因此需要进行同步,通常结合信号量使用
  • 套接字文件,双工通信
    • 同一台主机上,可以通过套接字文件【ip:port】来实现双工通信
  • 信号
    • 是一个计数器,用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。信号量基于操作系统的PV操作,程序对信号量的操作都是原子操作
  • 消息队列
    • 是消息的链接表,存放在内核中
    • 一个消息队列由一个标识符(即队列ID)来标识,消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级
    • 消息队列独立于发送与接收进程,进程终止时,消息队列及其内容并不会被删除

RPC实现方式

  • 典型的 RPC 系统包括以下几个组件
    • 客户端存根(Stub):负责将本地调用的参数打包成适合网络传输的格式,并发送到服务端
    • 服务端存根(Stub):接收来自客户端的请求,解包参数后调用相应的本地方法,然后将结果打包返回给客户端
    • 通信协议:定义了数据的格式和传输的规则,以确保客户端和服务端能够正确地解析和处理数据
    • 传输层:负责数据的实际传输,可以是基于 TCP/IP 的套接字编程,也可以是基于 HTTP 的 RESTful API

作业管理

前台与后台进程

前台进程:通过终端启动,且启动后一直占据终端

# 终端1
lxh@ubuntu:~$ ping 8.8.8.8 
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=128 time=195 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=128 time=196 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=128 time=192 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=128 time=202 ms
64 bytes from 8.8.8.8: icmp_seq=5 ttl=128 time=195 ms
...
# 终端2
lxh@ubuntu:~$ ps aux | grep ping	# + 表示这是前台进程
lxh        13328  0.0  0.1   7672  2688 pts/0    S+   05:40   0:00 ping 8.8.8.8
lxh        13330  0.0  0.1   6544  2304 pts/1    S+   05:40   0:00 grep --color=auto ping
lxh@ubuntu:~$ 

后台进程:可通过终端启动,但启动后即转入后台运行(释放终端)

lxh@ubuntu:~$ ping 8.8.8.8 &>/dev/null &
[1] 13337
lxh@ubuntu:~$ 
lxh@ubuntu:~$ ps aux | grep ping	# 没有 + 表示这是后台进程
lxh        13337  0.0  0.1   7672  2688 pts/0    S    05:45   0:00 ping 8.8.8.8
lxh        13339  0.0  0.1   6544  2304 pts/0    S+   05:45   0:00 grep --color=auto ping
lxh@ubuntu:~$ 

通过 & 创建的后台进程,如果终端关闭,那么进程可能会随之停止

建议使用nohup命令确保在终端关闭以后,进程不会终止,默认输出重定向到nohup.out文件中

lxh@ubuntu:~$ nohup ping 8.8.8.8 &
[1] 13695
lxh@ubuntu:~$ nohup: ignoring input and appending output to 'nohup.out'

lxh@ubuntu:~$ 
lxh@ubuntu:~$ cat nohup.out 
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=128 time=195 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=128 time=192 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=128 time=193 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=128 time=250 ms
64 bytes from 8.8.8.8: icmp_seq=5 ttl=128 time=192 ms
64 bytes from 8.8.8.8: icmp_seq=6 ttl=128 time=193 ms
64 bytes from 8.8.8.8: icmp_seq=7 ttl=128 time=195 ms
64 bytes from 8.8.8.8: icmp_seq=8 ttl=128 time=196 ms
64 bytes from 8.8.8.8: icmp_seq=9 ttl=128 time=195 ms
64 bytes from 8.8.8.8: icmp_seq=10 ttl=128 time=192 ms
64 bytes from 8.8.8.8: icmp_seq=11 ttl=128 time=195 ms
64 bytes from 8.8.8.8: icmp_seq=12 ttl=128 time=193 ms
64 bytes from 8.8.8.8: icmp_seq=13 ttl=128 time=193 ms
64 bytes from 8.8.8.8: icmp_seq=14 ttl=128 time=202 ms
lxh@ubuntu:~$ 

前台与后台进程的切换

后台进程(运行中)转换为前台进程,通过命令 fg jobnumber 实现,后台任务的jobnumber通过jobs命令查看

lxh@ubuntu:~$ ping 8.8.8.8 &>/dev/null &		# 创建后台进程
[1] 13720
lxh@ubuntu:~$ 
lxh@ubuntu:~$ ps aux | grep ping
lxh        13720  0.0  0.1   7672  2688 pts/1    S    06:18   0:00 ping 8.8.8.8
lxh        13722  0.0  0.1   6544  2304 pts/1    S+   06:18   0:00 grep --color=auto ping
lxh@ubuntu:~$ 
lxh@ubuntu:~$ jobs			# 查看后台进程的jobnumbedr
[1]+  Running                 ping 8.8.8.8 &> /dev/null &
lxh@ubuntu:~$ 
lxh@ubuntu:~$ fg 1			# 将后台进程转换到前台
ping 8.8.8.8 &> /dev/null
^Clxh@ubuntu:~$ 
lxh@ubuntu:~$ 
lxh@ubuntu:~$ ps aux | grep ping
lxh        13724  0.0  0.1   6544  2304 pts/1    S+   06:19   0:00 grep --color=auto ping
lxh@ubuntu:~$ 

前台进程转换为后台进程(停止运行),通过快捷键 Ctrl + Z 实现

lxh@ubuntu:~$ jobs		# 当前不存在后台进程
lxh@ubuntu:~$ 
lxh@ubuntu:~$ ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=128 time=273 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=128 time=289 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=128 time=298 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=128 time=192 ms
^Z
[1]+  Stopped                 ping 8.8.8.8
lxh@ubuntu:~$ 
lxh@ubuntu:~$ jobs		# 一个处于停止状态的后台进程
[1]+  Stopped                 ping 8.8.8.8
lxh@ubuntu:~$ 
lxh@ubuntu:~$ ps aux  | grep ping
lxh        13733  0.0  0.1   7672  2688 pts/1    T    06:23   0:00 ping 8.8.8.8
lxh        13735  0.0  0.1   6544  2304 pts/1    S+   06:23   0:00 grep --color=auto ping
lxh@ubuntu:~$ 

后台进程(停止运行)转化为后台进程(运行中),通过命令 bg jobnumber 实现

lxh@ubuntu:~$ jobs		# 一个处于停止状态的后台进程
[1]+  Stopped                 ping 8.8.8.8 > /dev/null
lxh@ubuntu:~$ 
lxh@ubuntu:~$ ps aux | grep ping
lxh        13836  0.0  0.1   7672  2688 pts/1    T    06:33   0:00 ping 8.8.8.8
lxh        13838  0.0  0.1   6544  2304 pts/1    S+   06:34   0:00 grep --color=auto ping
lxh@ubuntu:~$ 
lxh@ubuntu:~$ bg 1		# 启动后台进程
[1]+ ping 8.8.8.8 > /dev/null &
lxh@ubuntu:~$ 
lxh@ubuntu:~$ jobs		# 一个处于运行状态的后台进程
[1]+  Running                 ping 8.8.8.8 > /dev/null &
lxh@ubuntu:~$ 
lxh@ubuntu:~$ ps aux | grep ping
lxh        13836  0.0  0.1   7672  2688 pts/1    S    06:33   0:00 ping 8.8.8.8
lxh        13840  0.0  0.1   6544  2176 pts/1    S+   06:34   0:00 grep --color=auto ping
lxh@ubuntu:~$ 

后台进程(停止运行)转化为后台进程(运行中),也可以通过 kill -18 % jobnumber 实现

lxh@ubuntu:~$ ps aux | grep ping
lxh        13836  0.0  0.1   7672  2688 pts/1    T    06:33   0:00 ping 8.8.8.8
lxh        13851  0.0  0.1   6544  2304 pts/1    S+   06:38   0:00 grep --color=auto ping
lxh@ubuntu:~$ 
lxh@ubuntu:~$ jobs			# 一个处于停止状态的后台进程
[1]+  Stopped                 ping 8.8.8.8 > /dev/null
lxh@ubuntu:~$ 
lxh@ubuntu:~$ kill -18 %1	# 启动后台进程
lxh@ubuntu:~$ 
lxh@ubuntu:~$ ps aux | grep ping
lxh        13836  0.0  0.1   7672  2688 pts/1    S    06:33   0:00 ping 8.8.8.8
lxh        13853  0.0  0.1   6544  2304 pts/1    S+   06:39   0:00 grep --color=auto ping
lxh@ubuntu:~$ 
lxh@ubuntu:~$ jobs			# 一个处于运行状态的后台进程
[1]+  Running                 ping 8.8.8.8 > /dev/null &
lxh@ubuntu:~$

后台进程(运行中)转化为后台进程(停止运行),通过命令 kill -19 % jobnumber 实现

lxh@ubuntu:~$ ps aux | grep ping
lxh        13836  0.0  0.1   7672  2688 pts/1    S    06:33   0:00 ping 8.8.8.8
lxh        13853  0.0  0.1   6544  2304 pts/1    S+   06:39   0:00 grep --color=auto ping
lxh@ubuntu:~$ 
lxh@ubuntu:~$ jobs			# 一个处于运行状态的后台进程
[1]+  Running                 ping 8.8.8.8 > /dev/null &
lxh@ubuntu:~$ 
lxh@ubuntu:~$ kill -19 %1	# 启动后台进程
lxh@ubuntu:~$ 

[1]+  Stopped                 ping 8.8.8.8 > /dev/null
lxh@ubuntu:~$ 
lxh@ubuntu:~$ ps aux | grep ping
lxh        13836  0.0  0.1   7672  2688 pts/1    T    06:33   0:00 ping 8.8.8.8
lxh        13860  0.0  0.1   6544  2304 pts/1    S+   06:42   0:00 grep --color=auto ping
lxh@ubuntu:~$ 
lxh@ubuntu:~$ jobs			# 一个处于停止状态的后台进程
[1]+  Stopped                 ping 8.8.8.8 > /dev/null
lxh@ubuntu:~$

计划任务

at

  • at为一次性计划任务,即仅仅在指定时间点执行一次任务

  • at依赖于atd服务

  • 通过at命令添加、查看或编辑计划任务

  • at的任务文件路径

    • ubuntu:/var/spool/cron/atjobs/
    • rocky:/var/spool/at
  • at是需要安装软件包的

lxh@ubuntu:~$ ls test.txt
ls: cannot access 'test.txt': No such file or directory
lxh@ubuntu:~$ 
lxh@ubuntu:~$ ls time.txt
ls: cannot access 'time.txt': No such file or directory
lxh@ubuntu:~$ 
lxh@ubuntu:~$ at 15:27		# 通过交互式方式创建at一次性计划任务
warning: commands will be executed using /bin/sh
at Sat Dec 20 15:27:00 2025
at> echo "test at" > test.txt
at> echo `date` > time.txt
at> <EOT>
job 4 at Sat Dec 20 15:27:00 2025
lxh@ubuntu:~$ 
lxh@ubuntu:~$ sudo ls /var/spool/cron/atjobs/		# 自动创建任务文件
a0000401c12bff
lxh@ubuntu:~$ 
lxh@ubuntu:~$ sudo cat /var/spool/cron/atjobs/a0000401c12bff
#!/bin/sh
# atrun uid=1000 gid=1000
# mail lxh 0
umask 2
PWD=/home/lxh; export PWD
LOGNAME=lxh; export LOGNAME
XDG_SESSION_TYPE=tty; export XDG_SESSION_TYPE
HOME=/home/lxh; export HOME
LANG=en_US.UTF-8; export LANG
LS_COLORS=rs=0:di=01\;34:ln=01\;36:mh=00:pi=40\;33:so=01\;35:do=01\;35:bd=40\;33\;01:cd=40\;33\;01:or=40\;31\;01:mi=00:su=37\;41:sg=30\;43:ca=00:tw=30\;42:ow=34\;42:st=37\;44:ex=01\;32:\*.tar=01\;31:\*.tgz=01\;31:\*.arc=01\;31:\*.arj=01\;31:\*.taz=01\;31:\*.lha=01\;31:\*.lz4=01\;31:\*.lzh=01\;31:\*.lzma=01\;31:\*.tlz=01\;31:\*.txz=01\;31:\*.tzo=01\;31:\*.t7z=01\;31:\*.zip=01\;31:\*.z=01\;31:\*.dz=01\;31:\*.gz=01\;31:\*.lrz=01\;31:\*.lz=01\;31:\*.lzo=01\;31:\*.xz=01\;31:\*.zst=01\;31:\*.tzst=01\;31:\*.bz2=01\;31:\*.bz=01\;31:\*.tbz=01\;31:\*.tbz2=01\;31:\*.tz=01\;31:\*.deb=01\;31:\*.rpm=01\;31:\*.jar=01\;31:\*.war=01\;31:\*.ear=01\;31:\*.sar=01\;31:\*.rar=01\;31:\*.alz=01\;31:\*.ace=01\;31:\*.zoo=01\;31:\*.cpio=01\;31:\*.7z=01\;31:\*.rz=01\;31:\*.cab=01\;31:\*.wim=01\;31:\*.swm=01\;31:\*.dwm=01\;31:\*.esd=01\;31:\*.avif=01\;35:\*.jpg=01\;35:\*.jpeg=01\;35:\*.mjpg=01\;35:\*.mjpeg=01\;35:\*.gif=01\;35:\*.bmp=01\;35:\*.pbm=01\;35:\*.pgm=01\;35:\*.ppm=01\;35:\*.tga=01\;35:\*.xbm=01\;35:\*.xpm=01\;35:\*.tif=01\;35:\*.tiff=01\;35:\*.png=01\;35:\*.svg=01\;35:\*.svgz=01\;35:\*.mng=01\;35:\*.pcx=01\;35:\*.mov=01\;35:\*.mpg=01\;35:\*.mpeg=01\;35:\*.m2v=01\;35:\*.mkv=01\;35:\*.webm=01\;35:\*.webp=01\;35:\*.ogm=01\;35:\*.mp4=01\;35:\*.m4v=01\;35:\*.mp4v=01\;35:\*.vob=01\;35:\*.qt=01\;35:\*.nuv=01\;35:\*.wmv=01\;35:\*.asf=01\;35:\*.rm=01\;35:\*.rmvb=01\;35:\*.flc=01\;35:\*.avi=01\;35:\*.fli=01\;35:\*.flv=01\;35:\*.gl=01\;35:\*.dl=01\;35:\*.xcf=01\;35:\*.xwd=01\;35:\*.yuv=01\;35:\*.cgm=01\;35:\*.emf=01\;35:\*.ogv=01\;35:\*.ogx=01\;35:\*.aac=00\;36:\*.au=00\;36:\*.flac=00\;36:\*.m4a=00\;36:\*.mid=00\;36:\*.midi=00\;36:\*.mka=00\;36:\*.mp3=00\;36:\*.mpc=00\;36:\*.ogg=00\;36:\*.ra=00\;36:\*.wav=00\;36:\*.oga=00\;36:\*.opus=00\;36:\*.spx=00\;36:\*.xspf=00\;36:\*\~=00\;90:\*#=00\;90:\*.bak=00\;90:\*.crdownload=00\;90:\*.dpkg-dist=00\;90:\*.dpkg-new=00\;90:\*.dpkg-old=00\;90:\*.dpkg-tmp=00\;90:\*.old=00\;90:\*.orig=00\;90:\*.part=00\;90:\*.rej=00\;90:\*.rpmnew=00\;90:\*.rpmorig=00\;90:\*.rpmsave=00\;90:\*.swp=00\;90:\*.tmp=00\;90:\*.ucf-dist=00\;90:\*.ucf-new=00\;90:\*.ucf-old=00\;90:; export LS_COLORS
SSH_CONNECTION=10.0.0.1\ 58424\ 10.0.0.150\ 22; export SSH_CONNECTION
LESSCLOSE=/usr/bin/lesspipe\ %s\ %s; export LESSCLOSE
XDG_SESSION_CLASS=user; export XDG_SESSION_CLASS
LESSOPEN=\|\ /usr/bin/lesspipe\ %s; export LESSOPEN
USER=lxh; export USER
SHLVL=1; export SHLVL
XDG_SESSION_ID=19; export XDG_SESSION_ID
XDG_RUNTIME_DIR=/run/user/1000; export XDG_RUNTIME_DIR
SSH_CLIENT=10.0.0.1\ 58424\ 22; export SSH_CLIENT
XDG_DATA_DIRS=/usr/local/share:/usr/share:/var/lib/snapd/desktop; export XDG_DATA_DIRS
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin; export PATH
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus; export DBUS_SESSION_BUS_ADDRESS
SSH_TTY=/dev/pts/1; export SSH_TTY
cd /home/lxh || {
         echo 'Execution directory inaccessible' >&2
         exit 1
}
echo "test at" > test.txt
echo `date` > time.txt

lxh@ubuntu:~$ 
lxh@ubuntu:~$ date					# 来到at一次性计划任务的指定时间点
Sat Dec 20 03:27:12 PM CST 2025
lxh@ubuntu:~$ 
lxh@ubuntu:~$ sudo ls /var/spool/cron/atjobs/	# 由于是一次性任务,所以执行成功后,任务文件消失
lxh@ubuntu:~$ 
lxh@ubuntu:~$ cat test.txt			# 按照任务内容创建了test.txt
test at
lxh@ubuntu:~$ 
lxh@ubuntu:~$ cat time.txt 			# 按照任务内容创建了time.txt
Sat Dec 20 03:27:00 PM CST 2025
lxh@ubuntu:~$ 

cron

  • cron为周期性计划任务,用于在指定的时间段或周期执行重复性的任务
  • cron依赖于crond服务
  • 通过crontab命令添加、查看或编辑计划任务
  • cron的系统任务文件路径
    • /etc/crontab
    • /etc/cron.d/
  • cron的任务文件路径
    • ubuntu:/var/spool/cron/crontabs/USERNAME
    • rokcy:/var/spool/cron/USERNAME

cron周期任务格式

周期格式

从左到右依次是分、时、日、月、周

日 和 周 会取两条件同时满足的交集

  • 分:设置第几分,范围为0到59
  • 时:设置第几时,范围为0到23
  • 日:设置第几日,范围为1到31
  • 月:设置第几月,范围为1到12
  • 周:设置第几周,范围为0到6,这里0对应的是周日,6对应的是周六

image-20251220231131164

  • 如果在系统任务文件中添加周期任务
    • 格式为:任务周期 用户名 执行的命令
# *  *  *  *  * user-name command to be executed
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.daily; }
47 6    * * 7   root    test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.weekly; }
52 6    1 * *   root    test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.monthly; }
  • 如果通过crontab -e添加用户自身的周期任务
    • 格式为:任务周期 执行的命令
# m h  dom mon dow   command
0 1 * * * rm /path/to/target.txt
0 0 1 * * tar zip.tar.gz /path/to/target.txt

cron周期任务练习

每日凌晨1点,删除指定文件

0 1 * * * rm /path/to/target.txt

每月月初对指定文件进行压缩

0 0 1 * * tar zip.tar.gz /path/to/target.txt

每天上午9点到下午6点,每30分钟输出时间到指定文件中

*/30 9-17 * * * echo `date` > /path/to/target.txt

每周六和周日执行指定文件的备份

0 0 * * 0,6 cp /path/to/target.txt /path/to/target.txt.`date "+%F"`.bak

工作日上午9点到下午5点,每2小时执行一次指定脚本

0 9-17/2 * * 1-5 /path/to/target.sh
posted @ 2025-12-28 23:51  林浩233  阅读(0)  评论(0)    收藏  举报