补充

思考

  1. RAID 0 实现的原理是什么?有什么特点?

    • 实现原理:将数据条带化(Stripe) 均匀拆分到多块硬盘上并行读写,没有校验盘、没有冗余,数据分段同时写入多块盘。

    • 特点:

      • 读写速度极快,性能随硬盘数量线性提升

      • 无冗余,任意一块盘损坏,所有数据全部丢失

      • 无容量损耗,总容量 = 所有硬盘容量之和

      • 成本低,适合对速度要求高、但数据不重要的场景

  2. RAID 1 实现的原理是什么?有什么特点?

    • 实现原理:采用镜像(Mirror) 方式,数据同时完整写入两块硬盘,两块盘内容完全一致。
    • 特点:
      • 高可靠性,一块盘坏了另一块可继续工作,数据不丢
      • 读性能较好,写性能略有下降
      • 容量利用率低,总容量 = 单块硬盘容量
      • 至少需要 2 块盘
  3. RAID 5 实现的原理是什么?有什么特点?

    • 实现原理:数据条带化分布,同时将奇偶校验数据均匀分布在所有硬盘上,不单独使用校验盘。
    • 特点:
      • 兼顾性能与安全性,允许坏 1 块盘不丢数据
      • 读性能好,写性能一般(需计算校验)
      • 容量利用率高,总容量 = (硬盘数 − 1) × 单盘容量
      • 至少需要 3 块盘
      • 坏盘后重建压力大,重建期间容易二次损坏
  4. 假设你有6块2T硬盘,现需要为web应用提供4T存储空间,为db应用也提供4T存储空间。如何使用raid技术实现?讲述实现过程。

  5. LVM 技术有哪些优点?

  6. 概述使用LVM技术为web应用提供存储过程。

  7. 如果web应用使用的存储空间不足,如何扩容?

分区扩容

准备分区sdb1,容量10G,准备扩容5G。

[root@centos7 ~ 09:22:08]# df -hT /webapp
文件系统        类型     容量  已用  可用 已用% 挂载点
/dev/sdb1      xfs    10G   33M   10G    1% /webapp
[root@centos7 ~ 09:26:23]# ls /webapp/
host.conf  hostname  hosts  hosts.allow  hosts.deny

扩容的前提是分区后紧邻的物理空间要有足够的空间扩容。

[root@centos7 ~ 09:23:42]# parted /dev/sdb unit MiB print
Model: VMware, VMware Virtual S (scsi)
Disk /dev/sdb: 20480MiB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags: 

Number  Start    End       Size      Type     File system  标志
 1      1.00MiB  10241MiB  10240MiB  primary  xfs

使用parted扩容

# 先卸载
[root@centos7 ~ 09:26:42]# umount /webapp

# 在扩容分区
[root@centos7 ~ 09:27:13]# parted /dev/sdb unit MiB resizepart 1 15000
信息: You may need to update /etc/fstab.

[root@centos7 ~ 09:27:15]# lsblk /dev/sdb1                                
NAME MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sdb1   8:17   0 14.7G  0 part

# 挂载测试文件系统是否可用
[root@centos7 ~ 09:27:56]# mount /dev/sdb1 /webapp

# 扩容文件系统
[root@centos7 ~ 09:28:19]# xfs_growfs /webapp

# 验证文件系统容量
[root@centos7 ~ 09:28:30]# df -hT /webapp/
文件系统        类型    容量  已用  可用 已用% 挂载点
/dev/sdb1      xfs    15G   33M   15G    1% /webapp

# 文件也在
[root@centos7 ~ 09:28:45]# ls /webapp/
host.conf  hostname  hosts  hosts.allow  hosts.deny

使用本地ISO仓库安装图形化

  1. 关联ISO镜像

在这里插入图片描述

  1. 挂载光盘。
[root@centos7 ~ 10:40:58]# lsblk /dev/sr0
NAME MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sr0   11:0    1  4.4G  0 rom 

[root@centos7 ~ 10:43:52]# mkdir /dvd
[root@centos7 ~ 10:44:07]# mount /dev/sr0 /dvd
mount: /dev/sr0 写保护,将以只读方式挂载

[root@centos7 ~ 10:44:10]# ls /dvd
CentOS_BuildTag  EULA  images    LiveOS    repodata          RPM-GPG-KEY-CentOS-Testing-7
EFI              GPL   isolinux  Packages  RPM-GPG-KEY-CentOS-7  TRANS.TBL
  1. 配置仓库指向本地/dvd目录
# 备份原有仓库
[root@centos7 ~ 10:47:24]# mkdir /etc/yum.repos.d/bak
[root@centos7 ~ 10:47:58]# mv /etc/yum.repos.d/*repo /etc/yum.repos.d/bak

# 创建本地仓库
[root@centos7 ~ 10:44:12]# vim /etc/yum.repos.d/dvd.repo
[dvd]
name=CentOS-7 dvd
baseurl=file:///dvd 
gpgcheck=0
enabled=1
  1. 安装图形化环境组
[root@centos7 ~ 10:52:01]# yum group install '带 GUI 的服务器'

系统启动原理

系统启动过程

从接通电源到系统呈现登录提示符,需硬件初始化、固件引导、内核加载、系统初始化等多环节配合。

以下从宏观层面梳理 CentOS 7 完整启动流程:

在这里插入图片描述

  1. 计算机接通电源后,系统固件(UEFI 或传统 BIOS)首先执行开机自检(POST),检测 CPU、内存、硬盘等核心硬件是否正常。
    - 配置说明:启动早期按特定快捷键(如 F2)可进入固件配置界面,调整启动顺序、硬件参数等。
  2. 固件按配置的启动顺序搜索启动设备,读取磁盘主启动记录(MBR)中的引导加载器(CentOS 7 默认为 GRUB2),并将系统控制权移交 GRUB2。
    - 配置说明:通过 grub2-install 命令可将 GRUB2 安装为磁盘默认启动加载器。
  3. GRUB2 读取 /boot/grub2/grub.cfg 配置文件,显示操作系统选择菜单。
    - 配置说明:不可直接编辑 grub.cfg,需通过修改 /etc/grub.d/ 目录下的脚本、/etc/default/grub 配置文件,再执行 grub2-mkconfig 命令生成新的 grub.cfg
  4. 引导加载器根据选中的启动项,从磁盘加载内核(vmlinuz)和 initramfs 到内存,并将内核参数、initramfs 内存地址传递给内核。
    - initramfs 是临时内存文件系统,包含启动所需的硬件驱动、初始化脚本等,内核通过它完成硬件初始化。
    - 配置说明:通过 /etc/dracut.conf.d/ 目录、dracut 命令生成 initramfs,lsinitrd 命令可查看 initramfs 内容。
  5. initramfs 执行 /sbin/init(CentOS 7 中该文件为 systemd 的软链接),作为系统首个进程(PID 1)。
    - 配置说明:可通过内核参数 init=command 指定自定义初始化程序。
  6. systemd 加载内核命令行指定的 target,或系统默认的 default.target(通常为文本/图形登录界面)。
    - 配置说明:通过 systemctl 命令设置默认 target(如 systemctl set-default multi-user.target)。
  7. default.target 依赖 sysinit.target,该 target 完成系统基础初始化:读取 /etc/fstab 挂载文件系统、激活日志服务(systemd-journald)等。
    - 配置说明:通过 /etc/fstab 配置文件设置文件系统开机自动挂载规则。
  8. default.target 激活所有配置为开机自启的 systemd 单元(如服务、定时器等)。
    - 配置说明:通过 systemctl enable <服务名> 设置服务开机自启。
  9. default.target 激活 getty.target,打开 tty1 终端,提供用户登录入口。

系统 target 机制

目录和子目录、子文件之间关系:目录包含子目录和子文件。

  • service一个服务,例如sshd,提供远程执行命令、复制文件。
  • target 是一个可以包含service、time等对象的特殊unit。systemctl start target,激活该target包含的所有对象。

systemd 以 target 类型单元对各类系统单元(服务、挂载、设备等)进行分组管理,target 可嵌套依赖,形成层级化的启动逻辑。

# 查看 graphical.target 的直接/间接依赖
[root@centos7 ~]# systemctl list-dependencies graphical.target
graphical.target
● ├─accounts-daemon.service
● ├─gdm.service
● ├─initial-setup-reconfiguration.service
● ├─network.service
● ├─rtkit-daemon.service
● ├─systemd-readahead-collect.service
● ├─systemd-readahead-replay.service
● ├─systemd-update-utmp-runlevel.service
● ├─udisks2.service
● └─multi-user.target
......

[root@centos7 ~]# systemctl list-dependencies multi-user.target 
multi-user.target
● ├─abrt-ccpp.service
● ├─abrt-oops.service
● ├─abrt-vmcore.service
● ├─abrt-xorg.service
● ├─abrtd.service
● ├─atd.service
......

# 查看 sshd.service 的反向依赖(哪些 target 依赖该服务)
[root@centos7 ~]# systemctl list-dependencies sshd.service --reverse 
sshd.service
● └─multi-user.target
●   └─graphical.target

传统 SysVinit 定义 7 个运行级别(0-6),CentOS 7 虽使用 systemd,但仍保留对运行级别的兼容映射,具体如下:

运行级别 对应 systemd target 作用描述
0 - 关机(halt):终止所有进程并关闭电源,对应命令 shutdown -h now
1 emergency.target/rescue.target 单用户模式:仅 root 可登录,无网络服务,用于系统修复(如密码找回)。
2 - 多用户模式(无 NFS):支持多用户登录,但不启动网络文件系统,部分发行版与级别 3 功能一致。
3 multi-user.target 完全多用户模式(文本界面):启动所有网络服务,命令行登录,无图形界面。
4 - 预留级别:默认未使用,可自定义用途。
5 graphical.target 图形化多用户模式:在级别 3 基础上启动图形界面(GNOME/KDE),图形登录。
6 - 重启(reboot):终止所有进程并重启,对应命令 shutdown -r now

系统运行目标配置

切换当前系统的运行 target:

# 切换为文本界面(multi-user.target)
[root@centos7 ~]# systemctl isolate multi-user.target

# 切换为图形界面(graphical.target)
[root@centos7 ~]# systemctl isolate graphical.target 

设置系统启动默认 target:

# 查看当前默认 target
[root@centos7 ~]# systemctl get-default 
graphical.target

# 设置默认 target 为 multi-user.target(文本界面)
[root@centos7 ~]# systemctl set-default multi-user.target

# 重启系统验证配置
[root@centos7 ~]# reboot

思考:如何划分gdm.service归属multi-user.target?

ROOT 密码重置

  1. 重启系统,中断 GRUB2 菜单倒计时,选中第一个内核条目并按 e 编辑。
    在这里插入图片描述

  2. 定位到 linux16 开头的行,行尾添加 rd.break(rd.break前有空格)(在 initramfs 移交控制权前中断),按 Ctrl+x 启动。
    在这里插入图片描述

  3. 系统进入 root shell,此时根文件系统(/sysroot)为只读挂载,重新挂载为读写:

bash switch_root:/# mount -o remount,rw /sysroot
  1. 切换根目录到 /sysroot(实际系统根目录):
bash switch_root:/# chroot /sysroot
  1. 设置新 root 密码(将 password 替换为自定义密码):
bash sh-4.2# echo password | passwd --stdin root
  1. 若启用 SELinux,则需触发文件重新打标(否则密码修改可能失效):
bash sh-4.2# touch /.autorelabel
  1. 退出 chroot 环境并继续启动:
bash sh-4.2# exit switch_root:/# exit
  1. 系统重启后,使用新密码登录 root 验证。

/etc/fstab 配置故障排查

/etc/fstab 用于定义文件系统开机自动挂载规则,配置错误会导致系统启动异常,以下为常见故障及修复方法。

环境准备(模拟故障前的正常配置)

# 为 /dev/sdb 创建 MBR 分区表
[root@centos7 ~]# parted /dev/sdb mklabel msdos

# 创建 10GB 主分区
[root@centos7 ~]# parted /dev/sdb unit MiB mkpart primary 1 10241

# 格式化为 XFS 文件系统
[root@centos7 ~]# mkfs.xfs /dev/sdb1

# 创建挂载点
[root@centos7 ~]# mkdir /data01

# 添加 fstab 持久化挂载规则
[root@centos7 ~]# echo '/dev/sdb1 /data01 xfs defaults 0 0' >> /etc/fstab

# 挂载并验证
[root@centos7 ~]# mount -a
[root@centos7 ~]# df -h /data01
文件系统        容量  已用  可用 已用% 挂载点
/dev/sdb1        10G   33M   10G    1% /data01

故障 1:挂载点不存在

模拟故障

[root@centos7 ~]# umount /data01
[root@centos7 ~]# rmdir /data01

故障现象:重启后系统可正常进入,挂载点 /data01 会被自动创建,分区正常挂载。

说明:CentOS 7 会自动创建 fstab 中定义的不存在的挂载点,此故障无实际影响。

故障 2:设备名称错误/设备不存在

模拟故障:修改 fstab 中设备名(如 sdb1 → sdb2):

[root@centos7 ~]# vim /etc/fstab
/dev/sdb2 /data01 xfs defaults 0 0

故障现象:启动时无法找到 /dev/sdb2,超时(90秒)后进入 emergency 模式。

修复方法:在 emergency 模式下,编辑 /etc/fstab 修正设备名或注释错误条目,输入 exit 继续启动。

SELinux

firewalld 管理网络数据包。

Secure Enhance Linux:给每个文件都贴上一个标签。

应用程序 httpd 打标签A,提供/usr/share/nginx/html目录给客户端,/usr/share/nginx/html目录也打上标签A。

生活场景:门禁卡 702 打标签 A - 702 打标签A。

会验证身份?

Shell 特殊变量

Shell 位置参数变量

在 Shell 中存在一些特殊且重要的变量,例如:$0$1,我们称之为位置参数变量。要从命令行、函数或脚本执行等处传递参数时,就需要在 Shell 脚本中使用位置参数变量。

部分位置参数变量如下:

  1. $0,获取当前执行的 Shell 脚本的文件名,如果执行脚本包含了路径,那么就包括脚本路径。
  2. **n∗∗,获取当前执行的Shell脚本的∗∗第n个参数值∗∗。如果n大于9,则用大括号括起来,例如n**,获取当前执行的 Shell 脚本的**第n个参数值**。如果n大于9,则用大括号括起来,例如n,获取当前执行的Shell脚本的n个参数值。如果n大于9,则用大括号括起来,例如{10},接的参数以空格隔开。
  3. $#,获取当前执行的 Shell 脚本后面接的参数数量
  4. **∗∗∗,获取当前Shell脚本所有传参的参数,不加引号和‘***,获取当前 Shell 脚本所有传参的参数,不加引号和`,获取当前Shell脚本所有传参的参数,不加引号和@相同;如果给∗‘加上双引号,例如:‘"*`加上双引号,例如:`"加上双引号,例如:‘"*",则表示将所有的参数视为单个字符串,相当于$1 $2 $3`。
  5. **@∗∗,获取当前Shell脚本所有传参的参数,不加引号和@**,获取当前 Shell 脚本所有传参的参数,不加引号和@,获取当前Shell脚本所有传参的参数,不加引号和*相同;如果给@加上双引号,例如:‘@加上双引号,例如:`@加上双引号,例如:@,则表示将所有的参数视为不同的独立字符串,相当于"$1"、“$2”、“$3”…`,这是将多参数传递给其他程序的最佳方式,因为它会保留所有的内嵌在每个参数里的任何空白。

示例1:showargs.sh 内容如下

#!/bin/bash
echo $0
echo $1
echo $2
echo $10
echo ${10}
echo $#
echo $*
echo $@
echo "$@"
[root@centos7 ~]$ bash showargs.sh {a..z}
showargs.sh
a
b
a0
j
26
a b c d e f g h i j k l m n o p q r s t u v w x y z
a b c d e f g h i j k l m n o p q r s t u v w x y z
a b c d e f g h i j k l m n o p q r s t u v w x y z

示例2:sshd_ctl 内容如下

#!/bin/bash
systemctl $1 sshd

执行效果如下:

[root@centos7 ~]$ [root@centos7 ~] sshd_ctl stop
[root@centos7 ~]$ [root@centos7 ~] sshd_ctl status
[root@centos7 ~]$ [root@centos7 ~] sshd_ctl start

Shell 进程中的特殊状态变量

$?

作用:获取执行上一个指令的执行状态返回值:0为成功,非零为失败,这个变量最常用。

[root@centos7 ~]$ ls
hello  script.sh  showargs.sh
[root@centos7 ~]$ echo $?
0
[root@centos7 ~]$ ls /root
ls: 无法打开目录/root: 权限不够
[root@centos7 ~]$ echo $?
2

# man ls查看,退出码含义
[root@centos7 ~]$ man ls
......
   Exit status:
       0      if OK,
       1      if minor problems (e.g., cannot access subdirectory),
       2      if serious trouble (e.g., cannot access command-line argument).

$$(不重要)

作用:获取当前执行的 Shell 脚本的进程号(PID),这个变量不常用,了解即可。

[root@centos7 ~]$ echo $$
2447
[root@centos7 ~]$ kill -9 $$

Connection closed by foreign host.

Disconnected from remote host(10.1.8.88) at 21:00:36.

Type `help' to learn how to use Xshell prompt.

$!(不重要)

作用:获取上一个在后台工作的进程的进程号(PID),这个变量不常用,了解即可。

[root@centos7 ~]$ md5sum /dev/zero &
[1] 2611
[root@centos7 ~]$ echo $!
2611
[root@centos7 ~]$ ps o pid,%cpu,%mem,command $!
   PID %CPU %MEM COMMAND
  2611 99.1  0.0 md5sum /dev/zero
[root@centos7 ~]$ kill $!
[1]+  Terminated              md5sum /dev/zero

$_(不重要)

作用:获取在此之前执行的命令或脚本的最后一个参数,这个变量不常用,了解即可。

[root@centos7 ~]$ ls /etc/hosts /etc/fstab /etc/hostname
/etc/fstab  /etc/hostname  /etc/hosts
[root@centos7 ~]$ cat $_
sjw-shell
[root@centos7 ~]$ cat /etc/hostname
sjw-shell

Shell 内置变量命令

echo

echo命令参数选项:

  • -n,不换行输出内容。
  • -e,解析转义字符(见下面的字符)

转义字符:

  • \n,换行。
  • \t,制表符(tab)。
  • \b,退格。
  • \r,退格到开头。
[root@centos7 ~]$ echo -n "sjw ";echo laowang
sjw laowang
[root@centos7 ~]$ echo -e "sjw\nlaowang"
sjw
laowang
[root@centos7 ~]$ echo -e "sjw\tlaowang"
sjw   laowang

[root@centos7 ~]$ echo -e "1\b23"
23

[root@centos7 ~]$ echo -e "123\b"
123

# 后面有东西才会覆盖
[root@centos7 ~]$ echo -ne "123\b";echo haha
12haha

# 覆盖 hello,从头打印
[root@centos7 ~]$ echo -n "hello" ;echo -e "\rworld"
world

# 覆盖 hello,从头打印,最后o没有覆盖
[root@centos7 ~ 15:58:34]# echo -n "hello" ;echo -e "\rword"
wordo

read

从标准输入读取字符串等信息, 传给 Shell 程序内部定义的变量。

[root@centos7 ~]$ cat read.sh 
#!/bin/sh
read -p "输入你想要说的话:" str
echo "你想要说的话是:$str"

[root@centos7 ~]$ bash read.sh 
输入你想要说的话:`hello world`
你想要说的话是:hello world

# 不显示输入的内容
[root@centos7 ~]$ read -s -p "请设置用户密码: " password 
请设置用户密码: 

[root@centos7 ~]$ echo $password
redhat

案例:开发set_pass设置密码,例如set_pass sjw,提示用户输入密码,然后设置为相应密码。

[root@centos7 ~]$ vim set_pass 
#!/bin/bash
# -s 代表不显示输入的内容
read -sp "请输入用户 $1 新密码:" password
echo
echo $password | passwd --stdin $1

[root@centos7 ~]$ [root@centos7 ~] ./set_pass sjw
请输入用户 sjw 新密码:123 # 密码是不显示的
更改用户 sjw 的密码 。
passwd:所有的身份验证令牌已经成功更新。

复习:查看帮助信息。

  • –help(或者-h),例如date --help
  • man man_page,例如 man echo
  • help command,例如help read

案例:开发工具my_select,模拟tzselect,不需要实际判断。

#!/bin/bash
echo 'Please identify a location so that time zone rules can be set correctly.
Please select a continent or ocean.
 1) Africa
 2) Americas
 3) Antarctica
 4) Arctic Ocean
 5) Asia
 6) Atlantic Ocean
 7) Australia
 8) Europe
 9) Indian Ocean
10) Pacific Ocean
11) none - I want to specify the time zone using the Posix TZ format.'

read -p "#? " choice_1

echo '
Please select a country.
 1) Afghanistan       18) Israel            35) Palestine
 2) Armenia       19) Japan         36) Philippines
 3) Azerbaijan        20) Jordan            37) Qatar
 4) Bahrain       21) Kazakhstan        38) Russia
 5) Bangladesh        22) Korea (North)     39) Saudi Arabia
 6) Bhutan        23) Korea (South)     40) Singapore
 7) Brunei        24) Kuwait            41) Sri Lanka
 8) Cambodia          25) Kyrgyzstan        42) Syria
 9) China         26) Laos          43) Taiwan
10) Cyprus        27) Lebanon           44) Tajikistan
11) East Timor        28) Macau         45) Thailand
12) Georgia       29) Malaysia          46) Turkmenistan
13) Hong Kong         30) Mongolia          47) United Arab Emirates
14) India         31) Myanmar (Burma)       48) Uzbekistan
15) Indonesia         32) Nepal         49) Vietnam
16) Iran          33) Oman          50) Yemen
17) Iraq          34) Pakistan'

read -p "#? " choice_2

echo '
Please select one of the following time zone regions.
1) Beijing Time
2) Xinjiang Time'

read -p "#? " choice_3

echo '
The following information has been given:

    China
    Beijing Time

Therefore TZ='Asia/Shanghai' will be used.
Local time is now:  Fri Apr 10 16:16:09 CST 2026.
Universal Time is now:  Fri Apr 10 08:16:09 UTC 2026.
Is the above information OK?
1) Yes
2) No'

read -p "#? " choice_4

echo '
You can make this change permanent for yourself by appending the line
    TZ='Asia/Shanghai'; export TZ
to the file '.profile' in your home directory; then log out and log in again.

Here is that TZ value again, this time on standard output so that you
can use the /usr/bin/tzselect command in shell scripts:
Asia/Shanghai'

数值计算

下面就给大家介绍一下常见的 Shell 算术运算符:

  • +、-一元正号和负号。
  • +、-,加法和减法。
  • *、/、%,乘法、除法、取余(取模)。
  • **,幂运算。
  • ++、–,增加及减少,可前置也可放在变量结尾。
  • !、&&、||,逻辑非(取反)、逻辑与(and)、逻辑或(or)。
  • <、<=、>、>=,比较符号(小于、小于等于、大于、大于等于)。
  • ==、!=、=,比较符号(相等、不相等,对于字符串也可以表示相当于)。
  • <<、>>,向左移位、向右移位。
  • ~、|、&、^,按位取反、按位异或、按位与、按位。
  • =、+=、-=、*=、/=、%=,赋值运算符,例如 a+=1 相当于 a=a+1a-=1 相当于 a=a-1

Shell 中常见的算术运算命令:

  • $(()),用于整数运算的常用运算符,效率很高。
  • $[],用于整数运算。
  • bc,Linux下的一个计算器程序(适合整数及小数运算)。

(()) 双小括号数值运算命令

双小括号 (()) 的作用是进行数值运算与数值比较,它的效率很高,用法灵活,是企业场景运维人员经常采用的运算操作符。

1 (()) 双小括号数值运算的基础语法

双小括号 (()) 的操作方法:

  • ((i=i+1)),此种书写方法为运算后赋值法,即将i+1的运算结果赋值给变量i。

注意:不能用 echo ((i=i+l))输出表达式的值,可以用echo $((i=i+l))输出其值。

  • **i=((i+1))∗∗,可以在‘(())‘前加‘((i+1))**,可以在 `(())` 前加 `((i+1)),可以在(())前加` 符,表示将表达式运算后赋值给i。
  • (( 8>7 && 5==5)),可以进行比较操作,还可以加入逻辑与和逻辑或,用于条件判断。
  • **echo ((2+1))∗∗,需要直接输出运算表达式的运算结果时,可以在‘(())‘前加‘((2+1))**,需要直接输出运算表达式的运算结果时,可以在 `(())` 前加 `((2+1)),需要直接输出运算表达式的运算结果时,可以在(())前加` 符。

2 (()) 双小括号数运算实践

**示例1:**简单的数值计算。

[root@centos7 ~]$ echo $((1+1))
2
[root@centos7 ~]$ echo $((6*3))
18
[root@centos7 ~]$ ((i=5))
[root@centos7 ~]$ ((i=i*2))
[root@centos7 ~]$ echo $i
10

**示例2:**复杂的数值计算。

[root@centos7 ~]$ ((a=1+2**3-4%3))
[root@centos7 ~]$ echo $a
8

[root@centos7 ~]$ b=$((a=1+2**3-4%3))
[root@centos7 ~]$ echo $b
8
[root@centos7 ~]$ echo $((a=1+2**3-4%3))
8

[root@centos7 ~]$ a=$((100*(100+1)/2))
[root@centos7 ~]$ echo $a
5050
[root@centos7 ~]$ echo $((100*(100+1)/2))
5050

**示例3:**特殊运算符号

[root@centos7 ~]$ a=8;echo $((a+=1))
9
[root@centos7 ~]$ echo $((a**2))
81

**示例4:**比较和判断

[root@centos7 ~]$ ((3<8))
[root@centos7 ~]$ echo $?
0
[root@centos7 ~]$ echo $((3<8))
1

[root@centos7 ~]$ ((3>8))
[root@centos7 ~]$ echo $?
1
[root@centos7 ~]$ echo $((3>8))
0

[root@centos7 ~]$ echo $((3==3))
1

[root@centos7 ~]$ if ((8>7 && 5==5));then echo yes;fi
yes

**示例5:**变量前后使用–和++特殊运算符的表达式

[root@centos7 ~]$ a=10
[root@centos7 ~]$ echo $((a++))
10
[root@centos7 ~]$ echo $a
11

[root@centos7 ~]$ echo $((--a))
10
[root@centos7 ~]$ echo $a
10

总结:

  • 执行 echo $((a++))echo $((a--)) 命令输出整个表达式时,输出的值即为 a 的值,表达式执行完毕后,会对a进行++--的运算
  • 执行 echo $((++a))echo $((--a)) 命令输出整个表达式时,会先对a进行++--的运算,然后再输出表达式的值,即为a运算后的值。

**示例6:**通过 (())运算后赋值给变量

[root@centos7 ~]$ num=99
[root@centos7 ~]$ echo $((num+1))
100
[root@centos7 ~]$ num=$((num+1))
[root@centos7 ~]$ echo $num
100

let 命令

let运算命令的语法格式为:let 表达式

let表达式的功能等同于:((表达式))

示例:

[root@centos7 ~]$ i=2
[root@centos7 ~]$ i=i+8
[root@centos7 ~]$ echo $i
i+8

[root@centos7 ~]$ i=2
[root@centos7 ~]$ let i=i+8
[root@centos7 ~]$ echo $i
10

bc 命令

bc 是UNIX/Linux下的计算器,因此,除了可以作为计算器来使用,还可以作为命令行计算工具使用。

示例:

[root@centos7 ~]$ bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
1+3*4-6/3^3%4
13
# 设置小数点位数
scale=4
1/3
.3333
quit

[root@centos7 ~]$ echo '1+3*4-6/3^3%4' | bc
13
[root@centos7 ~]$ echo 'scale=4;1/3' | bc
.3333

$[] 符号的运算

示例1:

[root@centos7 ~]$ echo $[1+1]
2
[root@centos7 ~]$ echo $[4-2]
2
[root@centos7 ~]$ echo $[2*2]
4
[root@centos7 ~]$ echo $[4/2]
2
[root@centos7 ~]$ echo $[5/2]
2
[root@centos7 ~]$ echo $[5%2]
1
[root@centos7 ~]$ count=3;echo $[(count+1)*3]
12
[root@centos7 ~]$ count=3;echo $[ ++count + 3 ]
7
[root@centos7 ~]$ count=3;echo $[ count++ + 3 ]
6
[root@centos7 ~]$ count=3;echo $[ --count + 3 ]
5
[root@centos7 ~]$ count=3;echo $[ count-- + 3 ]
6

综合案例

通过一条命令计算输出 1+2+3+...+10 的表达式,并计算出结果,请使用bc命令计算。输出内容如1+2+3+4+5+6+7+8+9+10=55

[root@centos7 ~]# echo {1..10}
1 2 3 4 5 6 7 8 9 10

[root@centos7 ~]# echo {1..10} | tr ' ' '+'
1+2+3+4+5+6+7+8+9+10

[root@centos7 ~]# echo "Today is $(date +%A)"
Today is Friday

[root@centos7 ~]# echo $[ 1+2+3 ]
6

[root@centos7 ~]# echo $[ $(echo {1..10} | tr ' ' '+') ]
55

[root@centos7 ~]# echo $(echo {1..10} | tr ' ' '+')=$[ $(echo {1..10} | tr ' ' '+') ]
1+2+3+4+5+6+7+8+9+10=55
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐