数值运算

主要讨论一下Shell编程的基本数值运算,包括:

  • 数值(包括整数和浮点数)间的加、减、乘、除、求幂、求模等
  • 产生指定范围的随机数
  • 产生指定范围的数列

Shell 本身可以做整数运算,复杂一些的运算要通过外部命令实现,比如 exprbcawk 等。另外,可通过 RANDOM 环境变量产生一个从 0 到 32767 的随机数,一些外部工具,比如 awk 可以通过 rand() 函数产生随机数。而 seq 命令可以用来产生一个数列。

整数运算

  1. 对一个数+1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#自加,效率最高
i=0
((i++))
echo $i

#使用let,其次
let i++
echo $i

#使用expr(注意要空格分开,乘法运算要转义)
expr $i + 1

#awk
echo $i 1 | awk '{printf $1+$2}'
  1. 从1加到某个数
1
2
3
4
5
6
7
8
#!/bin/bash

i=0;
while [ $i -lt 10000 ]
do
((i++))
done
echo $i

(()) 的运算效率最高。而 let 作为 Shell 内置命令,效率也很高,但是 exprbcawk 的计算效率就比较低。

  1. 求模

letexprbc 都可以用来求模,运算符都是 %,而 letbc 可以用来求幂,运算符不一样,前者是 **,后者是 ^

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
expr 5 % 2
#ans: 1

let i=5%2
#ans:1

echo 5 %2 | bc
#ans: 1

((i=5%2))
echo $i
#ans:1




  1. 求幂
1
2
3
4
5
6
7
8
9
let i=5**2
echo $i

((i=5**2))
echo $i

echo "5^2" | bc

#ans:25
  1. 进制转换
1
2
3
4
5
6
7
# 八进制的11转换成十进制

# bash内置
echo $((8#11))

# 用bc
echo "obase=10;ibase=8;11"

浮点运算

  1. 求 1 除以 13,保留 3 位有效数字
1
2
3
4
echo "scale=3;1/13" | bc
#bc 在进行浮点运算时需指定精度,否则默认为 0,即进行浮点运算时,默认结果只保留整数

# ans:.076
1
2
3
$ echo "1 13" | awk '{printf("%0.3f\n",$1/$2)}'

#ans:0.077

随机数

  1. 有一组数据,求人均收入最高的家庭

在这里随机产生了一组测试数据,文件名为 income.txt

1
2
3
4
5
6
7
8
9
10
1 3 4490
2 5 3896
3 4 3112
4 4 4716
5 4 4578
6 6 5399
7 3 5089
8 6 3029
9 4 6195
10 5 5145

说明:上面的三列数据分别是家庭编号、家庭人数、家庭月总收入。

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash

[ $# -lt 1 ] && echo "请输入收入文件" && exit -1
# $#是Shell中传入的个数

[ ! -f $1 ] && echo "$1不是一个文件" && exit -1

income=$1

awk '{
printf("%d %0.2f\n",$1,$3/$2);
}' $income | sort -k 2 -n -r
# 保留两位小数,-k 2是awk结果的第二列,-n是按照数字排序,-r是递减顺序
  1. 随机数

环境变量 RANDOM 产生从 0 到 32767 的随机数,而 awkrand() 函数可以产生 0 到 1 之间的随机数。

1
2
3
echo $RANDOM

echo "" | awk '{srand();printf("%f",rand());}'

随机生成0-255之间的数字

可以通过 RANDOM 变量的缩放和 awkrand() 的放大来实现。

1
2
3
echo $RANDOM / 128

echo "" | awk '{srand();printf("%f",rand()*255);}'

文件系统的操作

硬件管理和设备驱动

Linux 系统通过设备驱动管理硬件设备。如果添加了新的硬件设备,那么需要编写相应的硬件驱动来管理它。对于一些常见的硬件设备,系统已经自带了相应的驱动,编译内核时,选中它们,然后编译成内核的一部分或者以模块的方式编译。如果以模块的方式编译,那么可以在系统的 /lib/modules/$(uname -r)目录下找到对应的模块文件。

查找驱动文件

更新文件索引数据库:updatedb

查找scsi相关驱动:locate scsi*.ko

查找usb相关驱动:locate usb*.ko

查看内核中已加载的各个模块的状态:

lsmod或者cat /proc/modules

加载驱动

insmod 模块

卸载驱动

rmmod 模块

Linux下的网络”实战”

通过dhclient获取IP地址

如果所在的局域网有DHCP服务器,可用使用dhclient,N是设备名称

1
2
dhclient ethN
# 我的centos 7.9是ens33

静态配置IP

ip_address 是本地主机的 IP 地址,gw_ip_address 是接入网络的网关的 IP 地址。

1
2
ifconfig ens33 192.168.31.87 on
route add default gw 192.168.31.1

如果上面不工作,记得通过 ifconfig/mii-tool/ethtool 等工具检查网卡是否有被驱动起来,然后通过 lspci/dmesg 等检查网卡类型(或者通过主板手册和独立网卡自带的手册查看),接着安装或者编译相关驱动,最后把驱动通过 insmod/modprobe 等工具加载到内核中

用 Linux 搭建网桥

网桥工作在 OSI 模型的第二层,即数据链路层,它只需要知道目标主机的 MAC 地址就可以工作。 Linux 内核在 2.2 开始就已经支持了这个功能,具体怎么配置看看后续参考资料吧。如果要把 Linux 主机配置成一个网桥,至少需要两个网卡。

网桥的作用相当于一根网线,用户无须关心里头有什么东西,把它的两个网口连接到两个主机上就可以让这两个主机支持相互通信。不过它比网线更厉害,如果配上防火墙,就可以隔离连接在它两端的网段(注意这里是网络,因为它不识别 IP),另外,如果这个网桥有多个网口,那么可以实现一个功能复杂的交换机,而如果有效组合多个网桥,则有可能实现一个复杂的可实现流量控制和负载平衡的防火墙系统。

用 Linux 做路由

路由工作在 OSI 模型的第三层,即网络层,通过 router 可以配置 Linux 的路由,当然,Linux 下也有很多工具支持动态路由的。相关的资料在网路中铺天盖地,由于时间关系,这里不做介绍。

用 Linux 搭建各种常规的网络服务

需要什么网络服务呢?

  • 给局域网弄个 DHCP 服务器,那就弄个 dhcpd,看看参考资料
  • 如果想弄个邮件发送服务器,那就安装个 sendmail 或者 exim4
  • 如果再想弄个邮件列表服务器呢,那就装个 mailman
  • 如果想弄个接收邮件的服务器呢,那就安装个 pop3 服务器;
  • 如果想弄个 web 站点,那就弄个 apache 或者 nginx 服务器;
  • 如果想弄上防火墙服务,那么通过 iptables 工具配置 netfilter 就可以

Linux 下网络问题诊断与维护

如果出现网络问题,不要惊慌,逐步检查网络的各个层次:物理链接、链路层、网络层直到应用层,熟悉使用各种如下的工具,包括 ethereal/tcpdumphpingnmapnetstatnetpipenetperfvnstatntop 等。