1、编写脚本

1.1、拓展:shell脚本语法

case语句:

  • 主要用于做选择的;
  • 多条件、多分支结构;

case语句注意事项

  • case行尾必须以单词“in”,每一模式必须以单个右括号")"结束
  • 双分号";;"表示命令序列的结束
  • 模式字符串中,可以用方括号表示一个连续的范围,如"[0-9]";还可以使用竖杠|表示或,比如A|B
  • 最后的“*)”表示默认模式,其中的星相当于通配符
#格式说明
case in 
模式1)
	命令1
	;;
模式2)
	命令2
	;;
.......
*)
	命令n
	;;
esac

1.2、编写一个case语句脚本

编写一个shell脚本

  • 让用户选择;并且输出对应的选择
[root@Node1 sh]# vim case_v1.sh
#!/bin/bash
#Author By LiangGaRy
#Time:2023年5月24日
#############################
read -p  "请输入你喜欢的数字【1-4】:" num
echo "你选择的号码是:$num"
case $num in
1)
        echo “这个是特等奖1”
;;
2)
        echo "这个是一等奖2"
;;
3)
        echo "这个是二等奖3"
;;
4)
        echo "这个是三等奖4"
;;
*)
        echo "请输入【1-4】的数字~!"
;;
esac

#测试脚本:
[root@Node1 sh]# bash case_v1.sh 
请输入你喜欢的数字【1-4】:1
你选择的号码是:1
“这个是特等奖1”

1.3、编写统计Linux进程脚本

[root@Node1 sh]# vim tj.sh
#!/bin/bash
#Author By LiangGaRy
#Time: 2023年5月24日
##########################
#定义四个状态值的初始值为0
running=0
sleepping=0
stopped=0
zombie=0
procs=0
#或者是自己统计/proc以数字开头的进程
#ls /proc/ | grep ^[0-9]

        #定义一个进程值,用于统计所有的进程,这里相当于让他循环一次就+1
        procs=$[procs+1]
        #这里就是截取进程的状态值S T Z 等等的状态
        stat=$(awk '{print $3}' $pid/stat)
        #再使用一个case循环
        case $stat in
        R)
                running=$[running+1]
        ;;
        S)
                sleepping=$[sleepping+1]
        ;;
        T)
                stopped=$[stopped+1]
        ;;
        Z)
                zombie=$[zombie+1]
        ;;
        esac
done
echo -e "进程信息统计如下:\n 进程总数为:$procs \n 运行中进程数为:$running \n 
休眠进程数为:$sleepping \n stopped 进程数为:$stopped \n zombie 进程数为:$zomb
ie \n"

#测试脚本
[root@Node1 sh]# bash tj.sh 
进程信息统计如下:
 进程总数为:103 
 运行中进程数为:0 
 休眠进程数为:103 
 stopped 进程数为:0 
 zombie 进程数为:0 

2、文件描述符

2.1、文件描述符定义

百度百科的定义:

  • 内核(kernel)利⽤⽂件描述符(file descriptor)来访问⽂件。
  • ⽂件描述符是⾮负整数。打开现存⽂件或新建⽂件时,内核会返回⼀个⽂件描述符。
  • 读写⽂件也需要使⽤⽂件描述符来指定待读写的⽂件。

理解:

  • 文件描述符(file descriptor)就是内核为了高效管理这些已经被打开的文件所创建的索引,其是一个非负整数(通常是小整数),用于指代被打开的文件,所有执行I/O操作的系统调用都通过文件描述符来实现。

通俗理解:

  • 进程运⾏的时候是打开了很多的⽂件,
  • 为了区分打开的⽂件,linux给每个⽂件分配编号,标号就是⼀个⾮零整数,
  • 这个⾮零的整数 就是⽂件描述符

PCB控制块:

  • 一个 Linux 进程启动后,会在内核空间中创建一个 PCB 控制块,
  • PCB 内部有一个文件描述符表(File descriptor table),记录着当前进程所有可用的文件描述符,也即当前进程所有打开的文件。
  • 进程级的描述符表的每一条记录了单个进程所使用的文件描述符的相关信息,
  • 进程之间相互独立,一个进程使用了文件描述符3,另一个进程也可以用3;

文件描述符表:

  • 当前文件偏移量(调用read()和write()时更新,或使用lseek()直接修改)
  • 打开文件时的标识(open()的flags参数)
  • 文件访问模式(如调用open()时所设置的只读模式、只写模式或读写模式)
  • 与信号驱动相关的设置
  • 对该文件i-node对象的引用,即i-node 表指针

i-node表:

  • 文件类型(例如:常规文件、套接字或FIFO)和访问权限
  • 一个指针,指向该文件所持有的锁列表
  • 文件的各种属性,包括文件大小以及与不同类型操作相关的时间戳
    • 文件的类型
    • 文件的字节数
    • 文件的USERID
    • 文件的GID
    • 文件读写权限
    • 文件的时间戳
    • 文件的链接数
    • 文件数据的block位置

案例:关于修改文件描述符

#获取系统打开文件描述符的数量
[root@Node1 sh]# cat /proc/sys/fs/file-nr 
992	0	197381
992:表示已经分配的FD的数量
0:表示已经分配但是没有使用的数量
197381:表示系统可用最大的FD的数量

已⽤FD数量=为已分配的FD数量 - 为已分配但尚未使⽤的FD数量 ,系统层⾯

#获取进程打开的文件描述符的数量
	#先使用vim 修改一个文件
[root@Node1 sh]# vim jincheng.sh 
	#然后打开一个终端-->查看vim进程的pid
[root@Node1 ~]# pidof vim
6786
	#然后去到/proc/目录下找出
[root@Node1 ~]# ll /proc/6786/fd/
total 0
lrwx------ 1 root root 64 Jun 23 22:44 0 -> /dev/pts/0
lrwx------ 1 root root 64 Jun 23 22:44 1 -> /dev/pts/0
lrwx------ 1 root root 64 Jun 23 22:44 2 -> /dev/pts/0
lrwx------ 1 root root 64 Jun 23 22:44 4 -> /sh/.jincheng.sh.swp
	#3-->存在的,不停的闪烁,红底白字,等待输入
#更改文件描述符限制:
	#明显的报错信息:“too many open files” 错误,提示你需要添加文件描述符限制数量
	#查看文件描述符限制数量
[root@Node1 ~]# ulimit -n
1024
	#一次性修改文件描述符
[root@Node1 ~]# ulimit -n 10240
[root@Node1 ~]# ulimit -n
10240
	#如果想要永久修改,需要修改配置文件
[root@Node1 ~]# vim /etc/security/limits.conf 
 59 #@student        -       maxlogins       4
 60 liangjiawei     hard    nofile  10240
	#用户名		硬件数		类型	文件描述符
	#切换用户访问
[root@Node1 ~]# su - liangjiawei
Last login: Thu Jun 22 14:16:15 CST 2023 on pts/1
[liangjiawei@Node1 ~]$ ulimit -n
10240

#直接修改对整个操作系统可以使用DF的数量,改为51200
[root@Node1 ~]# echo "51200" > /proc/sys/fs/file-max 
[root@Node1 ~]# cat /proc/sys/fs/file-nr 
992	0	51200
[root@Node1 ~]# echo "fs.file-max=51200" >> /etc/sysctl.conf 

案例:获取文件的打开数

#获取系统的打开文件数量
[root@Node1 ~]# lsof  | wc -l
2412

#获取某个用户打开文件数量
[root@Node1 ~]# lsof -u liangjiawei | wc -l
15

#获取某个服务打开文件数量
[root@Node1 ~]# pidof httpd
6806 6805 6804 6803 6802 6779
[root@Node1 ~]# lsof -p 6806 | wc -l
123

拓展:

  • 文件描述符缺点:不能够一直unix以外系统

2.2、重定向

输出重定向:

  • 讲文件的正常输出结果保存到指定的文件中,不显示在屏幕
  • 使用的符号:
    • “>”:覆盖文件
    • “>>”:追加内容
#正常命令echo会输出到屏幕
[root@Node1 ~]# echo " this is a boy"
 this is a boy

#如果使用输出重定向-->则改变输出路径-->如果没有aa.txt会自动创建
[root@Node1 ~]# echo " this is a boy" > aa.txt
[root@Node1 ~]# cat aa.txt 
 this is a boy

输入重定向:

  • 将米宁接收输入的路径有默认的键盘改为其他文件,而不是等待从键盘输入
  • 操作符号:“<”–>
  • 输入重定向可以理解为通过文件中的内容作为输入的数据
#给用户赋予密码
[root@Node1 ~]# echo 123456 > passwd.txt
[root@Node1 ~]# cat passwd.txt 
123456
[root@Node1 ~]# passwd --stdin zhangsan < passwd.txt 
Changing password for user zhangsan.
passwd: all authentication tokens updated successfully.

错误重定向

  • 将命令执⾏过程中出现的错误信息保存到指定⽂件当中,不直接显示在显示器上
  • 操作符号:“2>”–>
#如果命令错误会输出到屏幕
[root@Node1 ~]# ls llll 
ls: cannot access llll: No such file or directory

#如果错误重定向添加则会改变
[root@Node1 ~]# ls llll 2> /dev/null
[root@Node1 ~]# 

#把正确的执行放在一个文件,把错误的又放到另外一个文件
[root@Node1 ~]# ll sdfjdlsk 1> right.txt 2> error.txt
[root@Node1 ~]# cat right.txt 
[root@Node1 ~]# cat error.txt 
ls: cannot access sdfjdlsk: No such file or directory

混合使用:

  • 不管是正确与否都全部放到一个文件;
  • 操作符号:
    • “&>”
    • “>” /dev/null 2>&1
    • “1>& 2”
#不管是好的还是坏的都放到同一个文件里边
[root@Node1 ~]# ll sdfjdlsk &>  error.txt
[root@Node1 ~]# cat error.txt 
ls: cannot access sdfjdlsk: No such file or directory

案例说明

#追加重定向
[root@Node1 ~]# cat /proc/cpuinfo  > aa.txt 
[root@Node1 ~]# uname -a  >> aa.txt 
[root@Node1 ~]# tail -3 aa.txt 
power management:
Linux Node1 3.10.0-957.el7.x86_64 #1 SMP Thu Nov 8 23:39:32 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

#清空文件内容
[root@Node1 ~]# > aa.txt 
[root@Node1 ~]# cat aa.txt 

#输入重定向
[root@Node1 ~]# cat aa.txt 
[root@Node1 ~]# grep root < /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
	#统计passwd文件行数
[root@Node1 ~]# wc -l < /etc/passwd
21

#使用EOF来结合重定向
[root@Node1 ~]# cat >a.txt << EOF
> AA
> BB
> CC
> EOF
[root@Node1 ~]# cat a.txt 
AA
BB
CC
#追加
[root@Node1 ~]# cat >> a.txt << EOF
> aa
> bb
> cc
> EOF
[root@Node1 ~]# cat a.txt 
AA
BB
CC
aa
bb
cc

#错误重定向:
[root@Node1 ~]# ls sdfjsdkl 2> aa.txt 
[root@Node1 ~]# cat aa.txt 
ls: cannot access sdfjsdkl: No such file or directory

结合重定向;–>经常会见到两个文件

  • /dev/null:所有写⼊它的内容都会永远丢失. ⽽尝试从它那⼉读取内容则什么也读不 到
  • /dev/zero:当你读它的时候,它会提供⽆限的空字符

2.2、IO 概念

标准输入与标准输出

  • 文件描述符–>0–>标准输入,默认的就是设备键盘
  • 第二个文件–>1–>标准输出,默认的就是显示器
  • 标准错误–>2–>默认显示的就是显示器

重定向:重定向输出和重定向输入;

I/O概念:

  • I/O(input/output),即输入和输出端口,操作系统每一个设备都有一个专有的I/O地址用来处理输入输出信息。
  • CPU与外部设备之间的通信连接和数据交换都需要通过I/O地址来实现。
  • Linux内核将所有外部设备都看作一个文件来操作,应用程序通过调用文件操作的系统调用来与内核进行交互,来实现设备的访问和操作。

I/O模型:

  • 阻塞I/O
  • 非阻塞I/O
  • I/O多路复用
  • 信号驱动I/O
  • 异步I/O

2.3、dd命令

作用:指定大小的块拷贝一个文件;

语法:dd if=xxx of=ooo bs=n count=N

  • if:表示输入文件
  • of:表示输出的文件
  • bs:表示字节数
  • count:复制多少次
#创建一个10M的文件
[root@Node1 ~]# dd if=/dev/zero of=bb.txt bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 0.00423371 s, 2.5 GB/s
[root@Node1 ~]# ls -l bb.txt 
-rw-r--r-- 1 root root 10485760 Jun 24 14:24 bb.txt
[root@Node1 ~]# 

2.4、管道符“|”

作用:管道符主要用于多重命令处理,前面命令的打印结果作为后面命令的输入。

命令格式:

  • 命令1 | 命令2
    • 命令1的输出作为命令2的参数
[root@Node1 ~]# cat /etc/passwd | grep liangjiawei
liangjiawei:x:1000:1000:liangjiawei:/home/liangjiawei:/bin/bash

2.5、tee命令

作用:从标准输入读取,再写入标准输出和文件

语法:tee + 选项 + 文件名

选项:

  • -a:追加
  • –help:获取帮助
#把磁盘情况追加到一个文件中
[root@Node1 ~]# df -h  | tee -a disk.log
[root@Node1 ~]# cat disk.log 
Filesystem               Size  Used Avail Use% Mounted on
/dev/mapper/centos-root   19G  1.2G   18G   7% /
..........

3、查找相关的命令

3.1、which命令

作用:用于查找命令的绝对路径

语法:which + 选项 + 命令

#查看ls命令
[root@Node1 ~]# which ls
alias ls='ls --color=auto'
	/usr/bin/ls

3.2、whereis命令

作用:查找命令的路径以及相关信息

语法:whereis + 选项 + 命令

选项:

  • -b:只搜索二进制文件
  • -m:搜索手册文件
  • -s:搜索源文件
#查找ls命令
[root@Node1 ~]# whereis  ls
ls: /usr/bin/ls /usr/share/man/man1/ls.1.gz

3.3、locate命令

作用:查找文件的路径

  • 这个命令是基于/var/lib/mlocate/mlocate.db库来搜索的
  • 其中/etc/updatedb.conf这个文件制定了更新时间
  • /etc/con.daily/mlocate:这里指定了更新得频率

语法:locate+ 选项 + 文件

#更新库
[root@Node1 ~]# updatedb
[root@Node1 ~]# locate passwd
/etc/passwd
/etc/passwd-
/etc/pam.d/passwd
.........
05-25 19:55