关于 linux中 shell等知识的一些笔记

傍晚时分,你坐在屋檐下,看着天慢慢地黑下去,心里寂寞而凄凉,感到自己的生命被剥夺了。当时我是个年轻人,但我害怕这样生活下去,衰老下去。在我看来,这是比死亡更可怕的事。——–王小波

写在前面


  • 笔记是上课后整理的笔记,适合温习,不适合新手,希望对小伙伴有帮助
  • 笔记内容包括:Shell一些常见情境

傍晚时分,你坐在屋檐下,看着天慢慢地黑下去,心里寂寞而凄凉,感到自己的生命被剥夺了。当时我是个年轻人,但我害怕这样生活下去,衰老下去。在我看来,这是比死亡更可怕的事。——–王小波


一、Shell 基础知识

1.1 什么是 Shell

shell 是用户 与 Linux 内核之间的解释器

区分 shell 和 bash:shell是解释器的总称,bash是一类解释器。

Bash基本特性

查看当前在使用得解释器,不会显示临时切换的解释器,查看当前系统支持得解释器类型

1
2
3
4
5
6
7
8
9
10
11
[root@liruilong ~]$ echo $SHELL #查看当前在使用得解释器,不会显示临时切换的解释器
/bin/bash
[root@liruilong ~]$ cat /etc/shells #查看当前系统支持得解释器类型
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh

临时使用其他的解释器,查看设置用户得解释器类型

1
2
3
4
5
6
7
8
9
10
11
[root@liruilong ~]$ sh #临时使用其他的解释器
[root@liruilong ~]$ useradd zhangsan #创建用户
[root@liruilong ~]$ cat /etc/passwd | grep zhangsan #查看用户得解释器类型
zhangsan:x:1002:1002::/home/zhangsan:/bin/bash
[root@liruilong ~]$ usermod -s /bin/tcsh zhangsan #修改zhangsan得解释器
[root@liruilong ~]$ cat /etc/passwd | grep zhangsan
zhangsan:x:1002:1002::/home/zhangsan:/bin/tcsh
[root@liruilong ~]$ su - zhangsan #切换用户,验证用户得解释器类型
[zhangsan@liruilong ~]$ echo $SHELL
/bin/tcsh
[zhangsan@liruilong ~]$

在这里插入图片描述

Bash的优点

  • 快捷键、Tab键补齐
    • Ctrl + A #将光标移动到命令行首
    • Ctrl + E #将光标移动到命令行尾
    • Ctrl + C #中断正在执行的命令
    • Ctrl + L #清屏
    • Ctrl + W #从光标位置,往回删一个单词
    • Ctrl + U #从光标位置,往回删到开头
  • 命令历史 ( history )
    1
    2
    3
    4
    [root@liruilong ~]$ history #查看历史记录
    [root@liruilong ~]$ history -c #清空历史记录
    [root@liruilong ~]$ vim /etc/profile #修改历史记录的数量
    46 HISTSIZE=1000
  • 命令别名 (alias)
    1
    [root@liruilong ~]$ alias #查看当前用户可以使用的别名

在这里插入图片描述

1
2
3
4
[root@liruilong ~]$ vim /root/.bashrc #重开一个终端生效,针对root用户生效
alias ens33='cat /etc/sysconfig/network-scripts/ifcfg-ens33'
[root@liruilong ~]$ vim /etc/bashrc #重开一个终端生效,针对所有用户生效
alias ens33='cat /etc/sysconfig/network-scripts/ifcfg-ens33'

标准输入与输出的重定向 ( >、>>、2>、2>>、&> )

正确输出重定向覆盖,> 等同于 1>

1
2
3
4
##正确输出重定向覆盖,> 等同于 1>
[root@liruilong ~]$ ls /etc/passwd > /root/1.txt
[root@liruilong ~]$ cat /root/1.txt
/etc/passwd

正确输出重定向追加, 1>> 等同于 1>>

1
2
3
4
5
##正确输出重定向追加, 1>> 等同于 1>>
[root@liruilong ~]$ ls /etc/passwd >> /root/1.txt
[root@liruilong ~]$ cat /root/1.txt
/etc/passwd
/etc/passwd

错误输出重定向覆盖追加

1
2
3
4
5
6
7
8
9
10
11
12
##错误输出重定向覆盖
[root@liruilong ~]$ ls --helps 2> /root/2.txt
[root@liruilong ~]$ cat /root/2.txt
ls:无法识别的选项“--helps”
Try 'ls --help' for more information.
##错误输出重定向追加
[root@liruilong ~]$ ls --helps 2>> /root/2.txt
[root@liruilong ~]$ cat 2.txt
ls:无法识别的选项“--helps”
Try 'ls --help' for more information.
ls:无法识别的选项“--helps”
Try 'ls --help' for more information.

错误或正确的输出重定向覆盖追加

1
2
3
4
5
6
7
8
9
10
11
12
##错误或正确的输出重定向覆盖
[root@liruilong ~]$ ls /etc/shadow /root/fsdfs &> /root/3.txt
[root@liruilong ~]$ cat /root/3.txt
ls: 无法访问/root/fsdfs: 没有那个文件或目录
##错误或正确的输出重定向追加
[root@liruilong ~]$ ls /etc/shadow /root/fsdfs &>> /root/3.txt
[root@liruilong ~]$ cat /root/3.txt
ls: 无法访问/root/fsdfs: 没有那个文件或目录
/etc/shadow
[root@liruilong ~]$ cat /root/3.txt
ls: 无法访问/root/fsdfs: 没有那个文件或目录
/etc/shadow

管道 ( | )

1
2
3
##管道的应用
[root@liruilong ~]$ cat /etc/passwd | less
[root@liruilong ~]$ echo "123" | passwd --stdin zhangsan

Shell 执行命令的方式

  • 交互式 (命令行)
    • 人工干预
    • 逐条解释执行、效率低
  • 非交换式(脚本)
    • 需要提前设计
    • 批量执行、效率高
    • 修改用户的 Shell 解释器:/etc/shadow

二、脚本设计与运行

2.1 编写Shell 脚本

什么是 Shell 脚本
提前将可执行的命令语句写入一个文件
顺序执行
解释器逐行解释代码

第一个 Shell 脚本

编写一个 Hello Word脚本
新建文件
添加可执行语句 (命令)
给文件添加 x 执行权限
1
2
3
4
[root@liruilong ~]$ mkdir -p /root/shell/day01
[root@liruilong ~]$ vim /root/shell/day01/first.sh
echo "Hello World"

规范脚本的构成

一个合格规范的脚本应该包含以下这些内容
#! 脚本声明 (使用哪种解释器解释代码)
注释信息 (步骤、思路、用途等),以 #
可执行的语句
1
2
3
4
[root@liruilong ~]$ vim /root/shell/day01/first.sh
#!/bin/bash
#A test program for Shell.
echo "Hello World"

2.2 执行 Shell 脚本

方法一:需要为文件赋予可执行的权限
绝对路径执行
相对路径执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@liruilong ~]$ chmod +x /root/shell/day01/first.sh #赋予执行权限
[root@liruilong ~]$ /root/shell/day01/first.sh #以绝对路径的方式运行脚本
Hello World
[root@liruilong ~]$ cd /root/shell/day01
[root@liruilong day01]# ./first.sh #以相对路径运行脚本,【.】只得是当前目录
Hello World
```
|**<font color=camel>方法二:不需要文件有可执行的权限</font>**|
|--|
|sh 脚本文件名|
|source 脚本文件名 <font color=red>#不会启动子进程,通过pstree 查看进程树</font>|

![在这里插入图片描述](https://img-blog.csdnimg.cn/4a91b49b11234548a52250efffa28b27.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3Nhbmhld3V5YW5n,size_16,color_FFFFFF,t_70)
```bash
[root@liruilong ~]$ chmod -x /root/shell/day01/first.sh #取消脚本的执行权限
[root@liruilong ~]$ ls -l /root/shell/day01/first.sh
-rw-r--r-- 1 root root 58 7月 4 11:03 /root/shell/day01/first.sh
[root@liruilong ~]$ sh /root/shell/day01/first.sh #用开启子进程的方式运行脚本
Hello World

![在这里插入图片描述](https://img-blog.csdnimg.cn/0ed77c927305454dbe40ae57e34b93

1
2
[root@liruilong ~]$ source /root/shell/day01/first.sh #运行脚本时不会开启子进程
Hello World
1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
echo "Hello World"
sleep 100 #休眠100秒
[root@liruilong ~]$ yum -y install psmisc #pstree的软件包
[root@liruilong ~]$ sh /root/hello.sh #终端A上运行脚本
[root@liruilong ~]$ pstree #终端B验证,查看进程树
├─sshd─┬─sshd───bash───sh───sleep
└─sshd───bash───pstree
[root@liruilong ~]$ source /root/hello.sh #终端A上运行脚本
[root@liruilong ~]$ pstree #终端B验证,查看进程树
├─sshd─┬─sshd───bash───sleep
└─sshd───bash───pstree

三、变量

3.1 自定义变量

以固定的名称,存放可以能有变化的值

定义变量

  • 定义变量的格式:变量名=变量值
  • 取消变量的格式:unset 变量名
注意事项:
= 两边不能有空格,不要使用关键字做变量名,如:ls、cd等;
如果变量名已经存在则覆盖之前的变量值;
变量名称有:字母/数字/下划线,不能以数字开始;

查看变量

  • 查看变量的语法格式: $变量名 ${变量名}
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    ###脚本中得变量并不需要回收,运行完成后系统会自动回收变量
    [root@liruilong ~]$ x=12 #给变量x赋值为12
    [root@liruilong ~]$ var1=centos #给变量var1赋值为centos
    [root@liruilong ~]$ _a=12 #变量名以下划线开头
    [root@liruilong ~]$ a_0="hello world" #变量的值可以是字符串
    [root@liruilong ~]$ echo $x #输出变量x的值
    12
    [root@liruilong ~]$ echo $_a #输出变量$_a的值
    12
    [root@liruilong ~]$ echo $a_0 #输出变量$_0的值
    hello world
    [root@liruilong ~]$ echo ${var1}6.5 #输出变量 var1的值,为了区分,用{var1}表示
    centos6.5
    [root@liruilong ~]$ unset x #取消定义的变量x
    [root@liruilong ~]$ echo $x #再次输出结果为空

3.2系统预设变量

变量类型
环境变量(变量名通常大写,有操作系统维护);
位置变量(bash内置变量,存储脚本执行时的参数);
预定义变量(bash内置变量,可以调用但是不能赋值或修改);
自定义变量(用户自主设置)

环境变量

环境变量
存储在 /etc/profile ~/.bash_profile
命令 env 可以列出所有环境变量
常见环境变量:PATH、PWD、USER、UID、HOME、SHELL
1
2
3
4
5
6
7
8
9
10
11
12
13
[root@liruilong ~]$ echo $PATH #默认搜索路径
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@liruilong ~]$ echo $UID #当前用户对应得UID号
0
[root@liruilong ~]$ echo $USER #当前系统得登录用户
root
[root@liruilong ~]$ echo $HOME #当前登录用户得家目录
/root
[root@liruilong ~]$ cd /etc/sysconfig/network-scripts/
[root@liruilong network-scripts]# echo $PWD #显示当前用户得所在路径
/etc/sysconfig/network-scripts
[root@liruilong ~]$ [root@liruilong ~]$ echo $SHELL #显示当前用户使用得解释器
/bin/bash

位置变量

位置变量
存储脚本执行时的参数:
使用 $n 表示,n 为数字序列号
$1、$2、... 、${10}、${11}、...
1
2
3
4
5
6
7
8
9
10
[root@liruilong ~]$ vim /root/shell/day01/user.sh
#!/bin/bash
#test positional parameters.
echo $1
echo $2
echo $3
[root@liruilong ~]$ bash /root/shell/day01/user.sh aa 99 cc
aa
99
cc
  • 通过位置变量创建系统账户,配置密码
    1
    2
    3
    4
    5
    6
    7
    8
    [root@liruilong ~]$ vim /root/shell/day01/user02.sh
    #!/bin/bash
    #read username and pass from positional parameters.
    useradd "$1" #创建用户
    echo "$2" | passwd --stdin "$1" #给用户设置密码
    [root@liruilong ~]$ sh /root/shell/day01/user02.sh tom 123
    更改用户 tom 的密码 。
    passwd:所有的身份验证令牌已经成功更新。

预定义变量

预定义变量
用来保存脚本程序的执行信息
直接使用这些变量
不能直接为这些变量赋值

在这里插入图片描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@liruilong ~]$ ls /tmp/
[root@liruilong ~]$ echo $? #返回上一条命令的执行状态:0 为正确,非0 为错误
0
[root@liruilong ~]$ cat /root/sfsfsd
cat: /root/sfsfsd: 没有那个文件或目录
[root@liruilong ~]$ echo $? #上一条命令执行失败,返回一个非0值
1
[root@liruilong ~]$ vim /root/shell/day01/pre.sh
#!/bin/bash
echo $0 #输出当前得脚本名
echo $* #输出所有得位置变量
echo $# #输出位置变量得数量
echo $$ #输出脚本的进程号,每次运行脚本进程号不同
[root@liruilong ~]$ bash /root/shell/day01/pre.sh aa bb 88 qq
/root/shell/day01/pre.sh # $0执行结果
aa bb 88 qq # $*执行结果
4 # $#执行结果
3255 # $$脚本进程号
[root@liruilong ~]$

四、变量的扩展应用

4.1 各种引号

多种引号的区别

区别三种定界符
双引号 “ “ 允许扩展,以 $ 引用其他变量;
单引号 ‘ ‘ 禁用扩展,即便 $ 也视为普通符号;
反引号 `` 将命令的执行输出作为变量值,$() 与反引号等效;
1
2
3
4
5
6
7
8
9
10
11
[root@liruilong ~]# touch a b c #创建的是三个文件
[root@liruilong ~]# touch "a b c" #双引号让其代表一个文件
[root@liruilong ~]# touch 'b c d' #单引号作用这里是与双引号相同
[root@liruilong ~]# ls -l #查看
-rw-r--r-- 1 root root 0 7月 6 09:36 a
-rw-r--r-- 1 root root 0 7月 6 09:36 b
-rw-r--r-- 1 root root 0 7月 6 09:36 c
-rw-r--r-- 1 root root 0 7月 6 09:48 a b c
-rw-r--r-- 1 root root 0 7月 6 09:48 b c d
[root@liruilong ~]# rm -rf "a b c" #删除时要引号引起来
[root@liruilong ~]# rm -rf 'b c d'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@liruilong ~]# echo $HOME #输出家目录路径
/root
[root@liruilong ~]# echo '$HOME' #只输出 $HOME 字符串,''屏蔽特殊符号的含义
$HOME
[root@liruilong ~]# echo '$USER id is $UID'
$USER id is $UID
[root@liruilong ~]# echo $USER id is $UID
root id is 0
[root@liruilong ~]# test=`grep root /etc/shadow`
[root@liruilong ~]# test01=$(grep root /etc/shadow)
[root@liruilong ~]# echo $test
root:$6$Uebh9/WEzEaQfT$8b0B6oBgWUTEmYojDW9.6PHOw0.jD7A.SENsHFD/YPwh/L9jRJK0yWAtRF4BEteYZETeMiInp72dTviSKmLZf.:18501:0:99999:7::: dockerroot:!!:18691::::::
[root@liruilong ~]# echo $test01
root:$6$Uebh9/WEzEaQfT$8b0B6oBgWUTEmYojDW9.6PHOw0.jD7A.SENsHFD/YPwh/L9jRJK0yWAtRF4BEteYZETeMiInp72dTviSKmLZf.:18501:0:99999:7::: dockerroot:!!:18691::::::
[root@liruilong ~]#

4.2 read 命令定义变量

read 标准输入取值

read 标准输入取值
read 从键盘读入变量值完成赋值
格式:read [-p "提示信息"] 变量名
-p 可选-t 可指定超时秒数-s 设置是否在终端显示输入的内容

交互式定义变量

1
2
3
4
[root@liruilong ~]# read name #交互式定义变量
haha #输入名字
[root@liruilong ~]# echo $name #查看变量
haha
1
2
3
4
5
[root@liruilong ~]# read -p "请输入用户名:" name #交互式定义变量
请输入用户名:xixi
[root@liruilong ~]# echo $name #查看变量
xixi

从键盘读取用户名密码,创建用户并设置密码

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@liruilong ~]# vim /root/shell/day01/user03.sh
#!/bin/bash
##read 从键盘读取用户名密码,创建用户并设置密码
read -p "请输入一个用户名:" name
read -p "请输入密码:" pass
useradd $name
echo "$pass" | passwd --stdin $name
##脚本测试
[root@liruilong ~]# source /root/shell/day01/user03.sh
请输入一个用户名:nana
请输入密码:123456
更改用户 nana 的密码 。
passwd:所有的身份验证令牌已经成功更新。

read 从键盘读取用户名密码,创建用户并设置密码,要求不显示输入密码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@liruilong ~]# vim /root/shell/day01/user03.sh
#!/bin/bash
##read 从键盘读取用户名密码,创建用户并设置密码,要求不显示输入密码
read -p "请输入一个用户名:" name
read -p "请输入密码:" -s pass
useradd $name
echo "$pass" | passwd --stdin $name
##脚本测试
[root@liruilong ~]# source /root/shell/day01/user03.sh
请输入一个用户名:haha
请输入密码:更改用户 haha 的密码 。
passwd:所有的身份验证令牌已经成功更新。
[root@liruilong ~]# vim /root/shell/day01/user03.sh
#!/bin/bash

不输入就会自动退出:如果后面不加秒数,则不会自动退出

1
2
3
4
5
6
7
8
9
10
11
##read 从键盘读取用户名密码,创建用户并设置密码,要求不显示输入密码
##-t 多少秒不输入就会自动退出:如果后面不加秒数,则不会自动退出
read -p "请输入一个用户名:" name
read -p "请输入密码:" -s -t 3 pass
useradd $name
echo "$pass" | passwd --stdin $name
##脚本测试
[root@liruilong ~]# source /root/shell/day01/user03.sh
请输入一个用户名:lisi
请输入密码:更改用户 lisi 的密码 。 #超过3秒退出
passwd: 鉴定令牌操作错误

4.3 全局变量 or 局部变量

变量的作用范围

变量的作用范围
局部变量 新定义的变量默认只是在当前 Shell 环境中有效,无法在子 Shell 环境中使用
全局变量 系统中的任何 Shell 环境中都有效
1
2
3
4
5
6
7
8
9
10
11
####开启两个终端,A和B来测试
#终端A上操作
[root@liruilong ~]# x=11 #定义局部变量
[root@liruilong ~]# sh #进入sh子进程
sh-4.2# echo $x #无此变量,输出为空
#终端B上操作
[root@liruilong ~]# pstree #查看进程树
......
├─sshd─┬─sshd───bash───sh
│ └─sshd───bash───pstree
......

使用 export 定义全局变量

1
2
3
4
5
6
7
8
9
10
11
12
13
#终端A上操作
[root@liruilong ~]# export x=12 #定义全局变量
[root@liruilong ~]# sh #开启sh子进程
sh-4.2# echo $x #新的解释器里变量也生效
12
sh-4.2# bash #开启bash子进程
[root@liruilong ~]# echo $x #新的解释器里变量也生效
12
[root@liruilong ~]# pstree #查看进程树
......
├─sshd─┬─sshd───bash───sh───bash
└─sshd───bash───pstree
......

五、Shell 中的运算

5.1 整数运算

基本运算法则

基本运算法则
四则运算
加法:num1 + num2
减法:num1 - num2
乘法:num1 * num2
整除:num1 / num2
取余数运算
求模:num1 % num2

$[] 算式替换

  • 使用 $[ ]$(( )) 表达式
    • 格式:$[整数1 运算符 整数2……]
    • 计算结果替换表达式本身,可结合 echo 命令输出
      1
      2
      3
      4
      [root@liruilong ~]# echo $[1+2]
      3
      [root@liruilong ~]# echo $[2*3]
      6
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      [root@liruilong ~]# x=15;y=3 #定义两个临时变量x,y
      [root@liruilong ~]# echo $[x+y] #加法运算
      18
      [root@liruilong ~]# echo $[x-y] #减法运算
      12
      [root@liruilong ~]# echo $[x*y] #乘法运算
      45
      [root@liruilong ~]# echo $[x/3] #除法运算
      5
      [root@liruilong ~]# echo $[x%3] #取余运算(除尽)
      0
      [root@liruilong ~]# echo $[x%2] #取余运算(未除尽)
      1
      [root@liruilong ~]# x=15;y=3 #定义两个临时变量x,y
      [root@liruilong ~]# echo $((x+y)) #加法运算
      18
      [root@liruilong ~]# echo $((x-y)) #减法运算
      12
      [root@liruilong ~]# echo $((x*y)) #乘法运算
      45
      [root@liruilong ~]# echo $((x/y)) #除法运算
      5
      [root@liruilong ~]# echo $((x%y)) #取余运算(除尽)
      0
      [root@liruilong ~]# echo $((x%y)) #取余运算(未除尽)
      1
      [root@liruilong ~]# x=2 #定义变量x=2
      [root@liruilong ~]# echo $[x+=4] #输出x值,x=x+4
      6
      [root@liruilong ~]# echo $x #输出x值
      6

变量的自增/减等操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@liruilong ~]# echo $[x+=1] #输出x值,x=x+1
7
[root@liruilong ~]# echo $x #输出x值
7
[root@liruilong ~]# echo $[x*=3] #输出x值,x=x*3
21
[root@liruilong ~]# echo $x #输出x值
21
[root@liruilong ~]# echo $[x++] #输出x+1前的值
21
[root@liruilong ~]# echo $x #这是x+1后的值
22
[root@liruilong ~]# echo $[x--] #输出x-1前的值
22
[root@liruilong ~]# echo $x #输出x-1后的值
21

let 指定算术运算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
####let 用于指定算术运算
[root@liruilong ~]# let i=2*3 #将算术运算 2*3 赋予变量 i
[root@liruilong ~]# echo $i
6
[root@liruilong ~]# let i=3*6 #将算术运算 3*6 赋予变量 i
[root@liruilong ~]# echo $i
18
[root@liruilong ~]# b=2 #定义变量
[root@liruilong ~]# let b+=2 #变量赋值,b=b+2
[root@liruilong ~]# echo $b
4
[root@liruilong ~]# let b*=3 #变量赋值,b=b*3
[root@liruilong ~]# echo $b
12
[root@liruilong ~]# x=2
[root@liruilong ~]# let x++;echo $x # ;用来区分两条命令
3
[root@liruilong ~]# let x++;echo $x # ;用来区分两条命令
4
[root@liruilong ~]# let x+=3;echo $x # ;用来区分两条命令
7

5.2 小数运算

bc计算器

Bash 内建机制仅支持整数运算,不支持小数运算

1
2
[root@liruilong ~]# echo $[12.2+23]
-bash: 12.2+23: 语法错误: 无效的算术运算符 (错误符号是 ".2+23")

我们可以通过计算器软件 bc 实现小数运算

我们没有该软件则需要使用yum安装; bc支持交换式和非交换式两种计算scale=n 可以约束小数位,quit 退出交互式计算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@liruilong ~]# yum -y install bc #安装bc软件包
###使用bc进行交互运算
[root@liruilong ~]# bc
12+23 #加法运算
35
23.43*1.243 #乘法运算
29.123
23/2 #除法运算
11
23%3 #取余运算
2
quit #退出命令
[root@liruilong ~]# echo "1.2+3.3" | bc
4.5
[root@liruilong ~]# echo "1.2+3.3;3.8*2.7" | bc #同时进行多个运算
4.5
10.2
[root@liruilong ~]# echo "scale=2;10/2" |bc #scale=2 结果小数位保留两位
5.00
[root@liruilong ~]# echo "scale=2;17/2" |bc
8.50
[root@liruilong ~]# echo "scale=2;17.34/2" |bc #scale=2 结果小数位保留两位

小数的比较

  • bc 支持的比较操作符:>、>=、<、<=、==、!=
  • 表达式成立则返回1,否则返回0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@liruilong ~]# echo "1>2" | bc #比较错误,1小于2,结果为0
0
[root@liruilong ~]# echo "5>2" | bc #比较正确,5大于2,结果为1
1
[root@liruilong ~]# echo "2==2" | bc #比较正确,2等于2,结果为1
1
[root@liruilong ~]# echo "2!=2" | bc #比较错误,2等于2,结果为0
0
[root@liruilong ~]# echo "12.34 < 8.8" | bc #比较错误,12.34 大于 8.8,结果为0
0
[root@liruilong ~]# echo "12.34 != 8.8" | bc #比较正确,12.34不等于8.8
[root@liruilong ~]# echo "hello world" #echo 默认会换行
hello world
[root@liruilong ~]# echo -n "hello world" #-n 取消 echo 命令的默认换行
hello world
[root@liruilong ~]#

六、综合案例

6.1 监控脚本之显示硬件信息

echo回显

  • -n选项:不换行
  • -e选项:支持扩展属性

改变echo输出的文本颜色

  • echo -e “\033[文字颜色m 文字 \033[0m”
  • 文字颜色:30 ———– 37

30:黑 34:蓝色
31:红 35:紫色
32:绿 36:深绿
33:黄 37:白色

1
2
3
[root@liruilong ~]# echo -e "\033[32m天气预报\033[0m" #0m还原文字颜色,让颜色只作用
于当前字体
hello #32绿色字

监控硬件信息

显示服务器硬件信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
###最小化安装需要安装查看IP的软件包
[root@liruilong ~]# which ifconfig
/usr/sbin/ifconfig
[root@liruilong ~]# rpm -qf /usr/sbin/ifconfig
net-tools-2.0-0.22.20131004git.el7.x86_64
[root@liruilong ~]# vim /root/shell/day01/info.sh
#!/bin/bash
##显示服务器硬件信息
echo -e "\033[34m----------服务器硬件信息----------\033[0m"
echo -e "\033[32m网卡信息如下:\033[0m"
ifconfig ens33 | grep "inet"
echo -e "\033[32m剩余内容容量信息如下: \033[0m"
grep MemAvailable /proc/meminfo
echo -e "\033[32m磁盘容量信息如下: \033[0m"
df -h /
echo -e "\033[32mCPU信息如下:\033[0m"
grep "model name" /proc/cpuinfo
[root@liruilong ~]# sh /root/shell/day01/info.sh #运行脚本
----------服务器硬件信息----------
网卡信息如下:
inet 192.168.4.5 netmask 255.255.255.0 broadcast 192.168.4.255
inet6 fe80::452e:bf37:6ef7:c2fa prefixlen 64 scopeid 0x20<link>
剩余内容容量信息如下:
MemAvailable: 1238268 kB
磁盘容量信息如下:
文件系统 容量 已用 可用 已用% 挂载点
/dev/mapper/centos-root 50G 7.2G 43G 15% /
CPU信息如下:
model name : Intel(R) Core(TM) i7-1065G7 CPU @ 1.30GHz

在这里插入图片描述

计算例题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
[root@liruilong ~]# vim /root/shell/day01/calc.sh
#!/bin/bash
##计算1+2+3,...,+n的和,可以使用n*(n+1)/2公式快速计算结果
read -p "请输入一个正整数:" num
sum=$[num*(num+1)/2]
echo -e "\033[32m$num以内整数的总和是:$sum \033[0m"
[root@liruilong ~]# sh /root/shell/day01/calc.sh
请输入一个正整数:23
23以内整数的总和是:276
[root@liruilong ~]# vim /root/shell/day01/area.sh
#!/bin/bash
##使用三角形的底边和高计算面积:A=1/2底高
read -p "请输入三角形底边长度:" bottom
read -p "请输入三角形的高度:" hight
A=$(echo "scale=2;1/2*$bottom*$hight" | bc)
echo -e "\033[32m三角形的面积是:$A\033[0m"
[root@liruilong ~]# sh /root/shell/day01/area.sh
请输入三角形底边长度:23
请输入三角形的高度:5
三角形的面积是:57.50
[root@liruilong ~]# vim /root/shell/day01/tixingmianhi.sh
#!/bin/bash
##梯形面积:(上底边长度+下底边长度)*高/2
read -p "请输入梯形上底边长度:" a
read -p "请输入梯形下底边长度:" b
read -p "请输入梯形高度:" h
A=$(echo "scale=2;($a+$b)*$h/2" | bc)
echo -e "\033[32m梯形面积是:$A\033[0m"
[root@liruilong ~]# sh -x /root/shell/day01/tixingmianhi.sh #-x执行时测试
+ read -p 请输入梯形上底边长度: a
请输入梯形上底边长度:32
+ read -p 请输入梯形下底边长度: b
请输入梯形下底边长度:45
+ read -p 请输入梯形高度: h
请输入梯形高度:7
++ echo 'scale=2;(32+45)*7/2'
++ bc
+ A=269.50
+ echo -e '\033[32m梯形面积是:269.50\033[0m'
梯形面积是:269.50
[root@liruilong ~]# vim /root/shell/day01/yuanmianji.sh
#!/bin/bash
###使用A=πr2 公式计算圆的面积,取2位小数点精度,π=3.14
read -p "请输入圆的半径:" r
A=`echo "scale=2;3.14*$r*2" | bc`
echo -e "\033[32m圆的面积是:$A\033[0m"
[root@liruilong ~]# sh -x /root/shell/day01/yuanmianji.sh #-x执行时测试
+ read -p 请输入圆的半径: r
请输入圆的半径:25
++ echo 'scale=2;3.14*25*2'
++ bc
+ A=157.00
+ echo -e '\033[32m圆的面积是:157.00\033[0m'
圆的面积是:157.00

配置 YUM 源脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@liruilong ~]# vim /root/shell/day01/yum.sh
#!/bin/bash
###配置本地yum仓库
#删除所有.repo文件
rm -rf /etc/yum.repos.d/*
#挂载本地光盘
mkdir /centos
mount /dev/cdrom /centos
chmod +x /etc/rc.d/rc.local
echo "mount /dev/cdrom /centos" >> /etc/rc.d/rc.local
#创建yum源配置文件
echo "[Centos]
name=centos7.5
baseurl=file:///centos
enabled=1
gpgcheck=0" > /etc/yum.repos.d/centos.repo
#yum 测试
yum clean all
yum repolist
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@liruilong ~]# sh -x /root/shell/day01/yum.sh
+ rm -rf /etc/yum.repos.d/centos.repo
+ mkdir /centos
+ mount /dev/cdrom /centos
mount: /dev/sr0 写保护,将以只读方式挂载
+ chmod +x /etc/rc.d/rc.local
+ echo 'mount /dev/cdrom /centos'
+ echo '[Centos]
name=centos7.5
baseurl=file:///centos
enabled=1
gpgcheck=0'
+ yum clean all
+ yum repolist

七、字符串处理与变量初始化

字符串处理机制

子串截取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
┌──(liruilong㉿Liruilong)-[/mnt/c/Users/lenovo]
└─$ name=liruilong
┌──(liruilong㉿Liruilong)-[/mnt/c/Users/lenovo]
└─$ echo $name
liruilong
┌──(liruilong㉿Liruilong)-[/mnt/c/Users/lenovo]
└─$ echo ${#name}
9
┌──(liruilong㉿Liruilong)-[/mnt/c/Users/lenovo]
└─$ echo ${name:0:3}
lir
┌──(liruilong㉿Liruilong)-[/mnt/c/Users/lenovo]
└─$ echo ${name:3:3}
uil
┌──(liruilong㉿Liruilong)-[/mnt/c/Users/lenovo]
└─$ echo ${name:3:-3}
uil

子串替换

  • 替换1个结果:${变量/旧字串/新字串}
  • 替换全部结果:${变量//旧字串/新字串}

子串替换时,变量本身的值并不会变化,只会把变化的值输出到屏幕

1
2
3
4
5
6
7
8
9
10
11
12
13
###子串替换时,变量本身的值并不会变化,只会把变化的值输出到屏幕
[root@liruilong ~]# phone=13812345678
[root@liruilong ~]# echo ${phone/3/X} # / 替换变量中的第一个3
1X812345678
[root@liruilong ~]# echo ${phone//3/X} # // 替换变量中所有3
1X812X45678
[root@liruilong ~]# info=$(head -1 /etc/passwd) #定义变量
[root@liruilong ~]# echo $info #查看变量的值
root:x:0:0:root:/root:/bin/bash
[root@liruilong ~]# echo ${info/root/ROOT} #替换单个root为大写
ROOT:x:0:0:root:/root:/bin/bash
[root@liruilong ~]# echo ${info//root/ROOT} #替换所有root为大写
ROOT:x:0:0:ROOT:/ROOT:/bin/bash

字串掐头

  • 从左向右: 最短匹配删除:${变量#关键词}
  • 从左向左:最长匹配删除:${变量##关键词}
1
2
3
4
5
6
7
8
9
[root@liruilong ~]# A=$(head -1 /etc/passwd) #定义变量
[root@liruilong ~]# echo $A #查看变量的值
root:x:0:0:root:/root:/bin/bash
[root@liruilong ~]# echo ${A#*:} #删除字串A中,第一个 : 前的所有字符
x:0:0:root:/root:/bin/bash
[root@liruilong ~]# echo ${A##*:} #删除字串A中,最后一个 : 前的所有字符
/bin/bash
[root@liruilong ~]# echo $A #变量A的值不会发生变化
root:x:0:0:root:/root:/bin/bash

字串去尾

  • 从右向左: 最短匹配删除:${变量%关键词}
  • 从右向左:最长匹配删除:${变量%%关键词}
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [root@liruilong ~]# A=$(head -1 /etc/passwd) #定义变量
    [root@liruilong ~]# echo $A #查看变量的值
    root:x:0:0:root:/root:/bin/bash
    [root@liruilong ~]# echo ${A%:*} #删除字串A中,最后一个 : 后的所有字符
    root:x:0:0:root:/root
    [root@liruilong ~]# echo ${A%%:*} #删除字串A中,第一个 : 后的所有字符
    root
    [root@liruilong ~]# echo $A #变量A的值不会发生变化
    root:x:0:0:root:/root:/bin/bash

    批量修改文件扩展名
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    [root@liruilong ~]# cd /root/shell/day03/
    [root@liruilong day03]# touch {a,b,c,d,e,f}.txt
    [root@liruilong day03]# vim /root/shell/day03/rename1.sh
    #!/bin/bash
    ####批量修改目录下的以.txt结尾的文件为.doc结尾
    for i in $(ls *.txt)
    do
    mv $i ${i%.*}.doc #通过字符串去尾的去做
    done
    ###脚本验证
    [root@liruilong day03]# sh ./rename1.sh
    [root@liruilong day03]# ls
    [root@liruilong day03]# vim /root/shell/day03/rename2.sh
    #!/bin/bash
    ###批量修改文件扩展名,$1为原扩展名,$2为新扩展名
    for i in $(ls *.$1)
    do
    mv $i ${i%.*}.$2
    done
    ###脚本验证
    [root@liruilong day03]# sh ./rename1.sh doc pdf
    [root@liruilong day03]# ls
    变量初始化::
变量初始化
变量有值,则返回该变量的值
变量无值,则返回初始值
格式:${变量:-关键字}
1
2
3
4
5
[root@liruilong ~]# X=123
[root@liruilong ~]# echo ${X:-xyz} #变量有值,输出该变量的值
123
[root@liruilong ~]# echo ${ABC:-xyz} #变量无值,输出该变量的初始值
xyz

创建系统用户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[root@liruilong ~]# vim /root/shell/day03/user03.sh
#!/bin/bash
##创建系统用户,未设置密码,会自动赋予用户初始密码12345
###定义函数,输出文字的颜色
color(){
echo -e "\033[32m$1\033[0m"
}
read -p "请输入用户名:" iname
if [ -z "$iname" ];then
color "未输入用户名,脚本将退出..."
exit
fi
###输入密码,不输入密码,则赋予初始密码123456
read -p "请输入密码:" ipass
ipass=${ipass:-123456}
useradd "$iname"
echo "$ipass" | passwd --stdin "$iname"
###测试脚本
[root@liruilong ~]# sh /root/shell/day03/user3.sh
请输入用户名:
未输入用户名,脚本将退出...
[root@liruilong ~]# sh /root/shell/day03/user3.sh
请输入用户名:zhang
请输入密码:
更改用户 zhang 的密码 。
passwd:所有的身份验证令牌已经成功更新。
1

一、使用sed修改配置

1.1 常用sed指令

常用sed指令
p(print): 打印行
d(delete): 删除行
c(replace): 替换行
s(substitution): 替换关键词
=:打印行号

1.2 过滤数据

Print 指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
##过滤网卡IP地址
[root@liruilong ~]# sed -n '/IPADDR/p' /etc/sysconfig/network-scripts/ifcfg-ens33
IPADDR=192.168.4.5
##过滤内存信息
[root@liruilong ~]# free | sed -n '/Mem/p'
Mem: 1865280 373344 1072176 10544 419760 1278920
##过滤磁盘根分区信息(根分区是以/ 结尾的分区)
[root@liruilong ~]# df -h | sed -n '/\/$/p'
/dev/mapper/centos-root 50G 3.4G 47G 7% /
##显示第1、3、6行内容
[root@liruilong ~]# sed -n '1p;3p;6p' /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
##打印第2行以外的所有其他行内容
[root@liruilong ~]# sed -n '2!p' /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4

1.3 删除数据

Delete 指令 (不使用-i 选项,源文件不会被修改)

1
2
3
4
5
6
7
8
9
10
11
12
##删除/etc/hosts全文,没有定位条件等于匹配所有行
[root@liruilong ~]# sed ‘d’ /etc/hosts
##删除/tmp/fstab 的1到3行
[root@liruilong ~]# cat /etc/fstab > /tmp/fstab
[root@liruilong ~]# sed "1,3d" /tmp/fstab
[root@liruilong ~]# vim /tmp/fstab
##删除不包含dev的行
[root@liruilong ~]# sed '/dev/!d' /tmp/fstab
##删除所有以 # 符号开头的行
[root@liruilong ~]# sed '/^#/d' /tmp/fstab
##删除空白行
[root@liruilong ~]# sed '/^$/d' /tmp/fstab

1.4 替换行

Replace 指令(不使用 -i 选项,源文件不会被修改)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
##所有行替换为 123456
[root@liruilong ~]# sed 'c 123456' /tmp/fstab
123456
123456
123456
123456
123456
123456
123456
123456
123456
123456
123456
123456
##替换IP地址为 1.1.1.1
[root@liruilong ~]# file=/etc/sysconfig/network-scripts/ifcfg-ens33
[root@liruilong ~]# sed '/IPADDR/c IPADDR=1.1.1.1' $file
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=none
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens33
UUID=314ef20c-394e-4ef6-ba3b-0c6aaf47d1fc
DEVICE=ens33
ONBOOT=yes
IPADDR=1.1.1.1
PREFIX=24
##替换/etc/hosts中包含127的行为 127.0.0.1
[root@liruilong ~]# cat /etc/hosts
[root@liruilong ~]# sed '/127/c 127.0.0.1' /etc/hosts
127.0.0.1
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
##替换文件的第四行为 xxxx
[root@liruilong ~]# sed '4c xxxx' /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
xxxx
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh

1.5 替换关键词

Substitution指令(不使用 -i 选项,源文件不会被修改)

1
2
3
4
##通过echo命令定义测试文件
[root@liruilong ~]# echo "2046 2048 2046 2046
> 1001 2046 2999 1888
> 2046 2046 2046 2046" > test.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
##查看测试文件的内容
[root@liruilong ~]# cat test.txt
2046 2048 2046 2046
1001 2046 2999 1888
2046 2046 2046 2046
##把每一行的第一个2046替换为xxxx
[root@liruilong ~]# sed 's/2046/xxxx/' test.txt
xxxx 2048 2046 2046
1001 xxxx 2999 1888
xxxx 2046 2046 2046
##把每行中的所有的2046替换为xxxx
[root@liruilong ~]# sed 's/2046/xxxx/g' test.txt
xxxx 2048 xxxx xxxx
1001 xxxx 2999 1888
xxxx xxxx xxxx xxxx
##把每行中的第2个2046替换为xxxx
[root@liruilong ~]# sed 's/2046/xxxx/2' test.txt
2046 2048 xxxx 2046
1001 2046 2999 1888
2046 xxxx 2046 2046
##把每行中的所有2046替换为(2046); &就代表被替换的参数
[root@liruilong ~]# sed 's/2046/(&)/g' test.txt
(2046) 2048 (2046) (2046)
1001 (2046) 2999 1888
(2046) (2046) (2046) (2046)
##把每行中的所有2046替换为2046-1111;&就代表被替换的参数
[root@liruilong ~]# sed 's/2046/&-1111/' test.txt
2046-1111 2048 2046 2046
1001 2046-1111 2999 1888
2046-1111 2046 2046 2046
##把第2行中的所有2046替换为xxxx
[root@liruilong ~]# sed '2s/2046/xxxx/g' test.txt
2046 2048 2046 2046
1001 xxxx 2999 1888
2046 2046 2046 2046
##把第2行中的所有2046替换为空,等同于删除操作
[root@liruilong ~]# sed '2s/2046//g' test.txt
2046 2048 2046 2046
1001 2999 1888
2046 2046 2046 2046
##只输出修改过的行
[root@liruilong ~]# sed -n '2s/2046/xxxx/p' test.txt
1001 xxxx 2999 1888

正则符号() 具有保留的功能

1
2
3
4
5
6
7
8
[root@liruilong ~]# echo "hello the world" | sed -r 's/^(.)(.*)(.)$/\3\2\1/'
dello the worlh
[root@liruilong ~]# echo "hello the world" | sed -r 's/^(.)(.*)(.)$/\3\1\2/'
dhello the worl
[root@liruilong ~]# echo "hello the world" | sed -r 's/^(.)(.*)(.)$/\3\3/'
dd
[root@liruilong ~]# echo "hello the world" | sed -r 's/^(.)(.*)(.)$/\3\3\2\1\1/'
ddello the worlhh

1.8 打印行号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
##打印第2行的行号
[root@liruilong ~]# sed -n '2=' /etc/passwd
2
##打印包含root的行号
[root@liruilong ~]# sed -n '/root/=' /etc/passwd
1
10
##打印bash结尾的行的行号
[root@liruilong ~]# sed -n '/bash$/=' /etc/passwd
1
42
##$代表最后一行,打印最后一行的行号
[root@liruilong ~]# sed -n '$=' /etc/passwd
42

二、sed 多行文本处理

2.1 文本块指令

文本块指令
i (insert): 插入
a (append): 追加
r (read): 读 取文件
w (write): 文件另存为

插入指令 Insert (插入,行前写入)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
##查看test.txt文件内容
[root@liruilong ~]# cat test.txt
2046 2048 2046 2046
1001 2046 2999 1888
2046 2046 2046 2046
##在第2行前插入 ABC_XYZ
[root@liruilong ~]# sed '2i ABC_XYZ' test.txt
2046 2048 2046 2046
ABC_XYZ
1001 2046 2999 1888
2046 2046 2046 2046
##在第3 行前插入 ABC_XYZ
[root@liruilong ~]# sed '3i ABC_XYZ' test.txt
2046 2048 2046 2046
1001 2046 2999 1888
ABC_XYZ
2046 2046 2046 2046
##在包含 2046的行前插入两行数据ABC\nXYZ,\n是换行符
[root@liruilong ~]# sed '/2046/i ABC\nXYZ' test.txt
ABC
XYZ
2046 2048 2046 2046
ABC
XYZ
1001 2046 2999 1888
ABC
XYZ
2046 2046 2046 2046
##在包含 1888 的行前插入两行数据ABC\nXYZ,\n是换行符
[root@liruilong ~]# sed '/1888/i ABC\nXYZ' test.txt
2046 2048 2046 2046
ABC
XYZ
1001 2046 2999 1888
2046 2046 2046 2046

Append(追加,行后写入)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
##在第2行后面插入 ABC_XYZ
[root@liruilong ~]# sed '2a ABC_XYZ' test.txt
2046 2048 2046 2046
1001 2046 2999 1888
ABC_XYZ
2046 2046 2046 2046
##在第3行后面插入 ABC_XYZ
[root@liruilong ~]# sed '3a ABC_XYZ' test.txt
2046 2048 2046 2046
1001 2046 2999 1888
2046 2046 2046 2046
ABC_XYZ
##在包含 2046的行后面插入两行数据ABC\nXYZ,\n是换行符
[root@liruilong ~]# sed '/2046/a ABC\nXYZ' test.txt
2046 2048 2046 2046
ABC
XYZ
1001 2046 2999 1888
ABC
XYZ
2046 2046 2046 2046
ABC
XYZ
##在包含 1888 的行后面插入两行数据ABC\nXYZ,\n是换行符
[root@liruilong ~]# sed '/1888/a ABC\nXYZ' test.txt
2046 2048 2046 2046
1001 2046 2999 1888
ABC
XYZ
2046 2046 2046 2046

导入指令:Read (将其他文件的内容导入)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
##将/etc/hosts中的内容读入到 test.txt 文件第2行的后面
[root@liruilong ~]# sed '2r /etc/hosts' test.txt
2046 2048 2046 2046
1001 2046 2999 1888
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
2046 2046 2046 2046
##将/etc/hosts中的内容读入到 test.txt 文件每一行数据的后面
[root@liruilong ~]# sed 'r /etc/hosts' test.txt
2046 2048 2046 2046
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
1001 2046 2999 1888
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
2046 2046 2046 2046
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
##将/etc/hosts中的内容读入到 test.txt 文件中包含 1888字串所在行的后面
[root@liruilong ~]# sed '/1888/r /etc/hosts' test.txt
2046 2048 2046 2046
1001 2046 2999 1888
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
2046 2046 2046 2046

导出指令:Write (将文件内容导出另存到其他文件)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
##将test.txt 文件的所有内容另存为一个新文件 copy_test.txt
[root@liruilong ~]# sed 'w copy_test.txt' test.txt
2046 2048 2046 2046
1001 2046 2999 1888
2046 2046 2046 2046
[root@liruilong ~]# cat copy_test.txt #查看文件的内容
2046 2048 2046 2046
1001 2046 2999 1888
2046 2046 2046 2046
##将test.txt 文件的 2到3行另存为新文件line.txt
[root@liruilong ~]# sed '2,3w line.txt' test.txt
2046 2048 2046 2046
1001 2046 2999 1888
2046 2046 2046 2046
[root@liruilong ~]# cat line.txt #查看新文件的内容
1001 2046 2999 1888
2046 2046 2046 2046
##将test.txt 文件中所有包含1888的行另存为新文件 1888.txt
[root@liruilong ~]# sed '/1888/w /opt/1888.txt' test.txt
2046 2048 2046 2046
1001 2046 2999 1888
2046 2046 2046 2046
[root@liruilong ~]# cat /opt/1888.txt #查看文件的内容
1001 2046 2999 1888

三、sed综合案例

点名器

1
2
3
4
5
6
7
[root@svr5 ~]# mkdir -p /root/shell/day04/
[root@svr5 ~]# vim /root/shell/day04/name.txt
李白
杜甫
白居易
孟浩然
苏轼

编写随机点名脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@svr5 ~]# cd /root/shell/day04
[root@svr5 day04]# vim roll.sh
#!/bin/bash
##功能描述(Description):随机点名抽奖器,按ctrl+c结束脚本.
name_file="name.txt"
# 获取最后一行行号
line_file=$(sed -n '$=' $name_file)
while :
do
clear
tmp=$(sed -n "$[RANDOM%$line_file+1]p" $name_file)
echo -e "\033[32m 随机点名器(按ctrl+c停止):\033[0m"
echo -e "\033[32m##############################\033[0m"
echo -e "\033[32m \033[0m"
echo -e "\033[32m $tmp \033[0m"
echo -e "\033[32m \033[0m"
echo -e "\033[32m##############################\033[0m"
sleep 0.1
done

一、awk基础语法

awk 编程语言/数据处理引擎,创造者:Aho、Weinberger、Kernighan,基于模式匹配检查输入文本,逐行处理并输出,通常用于在 Shell 脚本中,获取指定的数据,单独用时,可对文本数据做统计

awk 流程控制

格式1:前置命令| awk [选项] , [条件] (指令)’
格式2: awk [选项] ‘ [条件] {指令}, 文件….
格式3: awk ,BEGIN{} [条件]{} END{}’ 文件….

if语句

单分支if判断

1
awk '{指令}' 文件

-F: : awk 指定分割符为:

1
2
3
4
5
6
7
8
9
10
11
12
13
###if是指令必须放到{ if(){} }中
#如果UID大于等于1000时,i自加1;最后输出i的值,i作为变量默认值为0
[root@liruilong ~]# awk -F: '{if($3>=1000){i++}} END{print i}' /etc/passwd
2
###当$1 用户名为root时,打印用户名和UID
[root@liruilong ~]# awk -F: '{if($1=="root"){print $1,$3}}' /etc/passwd
root 0
###查看CPU的负载情况
[root@liruilong ~]# uptime
10:53:35 up 2 min, 1 user, load average: 0.33, 0.33, 0.14
###当cpu 15分钟的负载大于0.01时,打印15分钟的负载信息
[root@liruilong ~]# uptime | awk '{if($NF>0.01){print "CPUload:",$NF}}'
CPUload: 0.13

双分支if判断

1
awk '{指令}' 文件
1
2
3
4
5
6
7
8
9
10
####统计普通用户和系统用户的个数
##普通用户的UID号大于等于1000;系统用户的UID小于1000
[root@liruilong ~]# awk -F: '{if($3>=1000){i++} else{j++}} END{print "普通用户:"i,"系统用户:"j}' /etc/passwd
普通用户:3 系统用户:34
[root@liruilong ~]#

#### 统计普通文件和目录的个数
## 普通文件的属性以“-”开头,非“-”开头的也是目录也可以是快捷方式
[root@liruilong ~]# ls -l /etc/ | awk '{ if($1~/^-/){x++} else{y++} } END{print "普通文件个数:"x,"目录个数:"y}'
普通文件个数:122 目录个数:148

多分支if判断

awk '{ if(){} else if(){} else{} } END{}'

1
awk '{ if(){} else if(){} else{} } END{}' 文件
1
2
3
4
5
6
7
###awk '{ if(){} else if(){} else{} } END{}'
[root@liruilong ~]# ls -l /etc/ | awk '{ if($1~/^-/){x++} else if($1~/^d/){y++} else{z++} } END{print "普通文件:"x,"\n目录个数:",y,"\n其他:",z}'
普通文件:118
目录个数: 106
其他: 17
[root@liruilong ~]#

for循环

awk 的for 循环采用与C语言一样的语法格式: for(表达式1;表达式2;表达式3) {指令}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
##i=1,每循环一次i的值加1
[root@liruilong ~]# awk 'BEGIN{ for(i=1;i<=5;i++) {print i} }'
1
2
3
4
5
##i=5,每循环一次i的值减1
[root@liruilong ~]# awk 'BEGIN{ for(i=5;i>=1;i--){print i} }'
5
4
3
2

awk 数组与应用案例

awk 数组的定义及使用

数组的下标可以是数字,也可以是字符串

1
2
3
4
5
###给数组name添加两个值,并打印数值
[root@liruilong ~]# awk 'BEGIN{
> name[0]="jim";name[1]="tom";print name[1],name[0]
> }'
tom jim

给数组name添加两个值,调用数组中的值

1
2
3
4
[root@liruilong ~]# awk 'BEGIN{
> name[0]="jim";name[1]="tom";print name[1],name[1],name[0]
> }'
tom tom jim

定义数组age,age[tom]的值为22,age[jim]的值为18

1
2
3
4
[root@liruilong ~]# awk 'BEGIN{
> age["tom"]=22;age["jim"]=18;print age["tom"],age["jim"]
> }'
22 18

遍历数组的值

1
2
3
4
5
6
7
8
9
10
###定义数组x,赋值,用for循环取数组中的值
[root@liruilong ~]# awk 'BEGIN{ x[0]=0;x[1]=11;x[2]=12;x[3]=13;x[4]=14;
> for(i in x){print i,x[i]}
> }'
4 14
0 0
1 11
2 12
3 13

应用案例

分组统计

1
2
3
4
5
6
7
8
###IP为数组,数组的下表为access_log 第一列的ip地址; 数组对应的值为 ip地址出现的次数
[root@liruilong ~]# awk '{IP[$1]++} END{ for(i in IP){print i,IP[i]} }'
/root/access_log
172.40.1.14 1
172.40.1.1 1
172.40.1.16 4
172.40.1.17 6
172.40.1.18 3

统计每个系统账户登录的次数

1
2
3
[root@liruilong ~]#  who | awk '{wh[$1]++} END{for(i in wh){print i,wh[i]} }'
root 2
[root@liruilong ~]#

awk 综合案例

ss命令

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@liruilong ~]# ss -at
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 127.0.0.1:webcache *:*
LISTEN 0 128 *:ssh *:*
LISTEN 0 128
[root@liruilong ~]# ss -atu #查看tcp和udp协议
#查看tcp和udp协议,以数字显示,端口都变成了数字模式
[root@liruilong ~]# ss -atun
#查看tcp和udp协议,以数字显示,端口都变成了数字模式,显示进程名和PID号
[root@liruilong ~]# ss -atunp
#查看tcp和udp协议,以数字显示,端口都变成了数字模式,显示进程名和PID号,不显示标题行
[root@liruilong ~]# ss -atunpH
[root@liruilong ~]# ss -s ##汇总所有的结果

过滤连接状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[root@liruilong ~]# mkdir -p /root/shell/day05/
[root@liruilong ~]# vim /root/shell/day05/net.sh
#!/bin/bash
##所有TCP连接的个数
TCP_Total=$(ss -s | awk '$1=="TCP"{print $2}')
##所有UDP连接的个数
UDP_Total=$(ss -s | awk '$1=="UDP"{print $2}')
##所有处于 Listen 监听状态的 TCP 端口个数
TCP_Listen_Total=$(ss -antlpH | awk 'BEGIN{count=0} {count++} END{print count}')
##所有处于 ESTABLISHED 状态的TCP连接个数
TCP_Estab_Total=$(ss -antpH | awk 'BEGIN{count=0} /^ESTAB/{count++} END{print
count}')
##所有处于 TIME-WAIT 状态的 tcp 连接个数
TCP_TIME_WAIT_Total=$(ss -antpH | awk 'BEGIN{count=0} /^TIME-WAIT/{count++}
END{print count}')
##显示TCP连接总数
echo "TCP连接总数:$TCP_Total"
##显示UDP连接总数
echo "UDP连接总数:$UDP_Total"
##显示处于LISTEN状态的TCP端口个数
echo "处于LISTEN状态的TCP端口个数:$TCP_Listen_Total"
##显示处于ESTABLISHED状态的TCP连接个数
echo "处于ESTAB状态的TCP连接个数:$TCP_Estab_Total"
##显示处于TIME-WAIT状态的TCP连接个数
echo "处于TIME-WAIT状态的TCP连接个数:$TCP_TIME_WAIT_Total"
[root@liruilong ~]# sh /root/shell/day05/net.sh
TCP连接总数:15
UDP连接总数:10
处于LISTEN状态的TCP端口个数:15
处于ESTAB状态的TCP连接个数:2
处于TIME-WAIT状态的TCP连接个数:0

循环嵌套

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[root@liruilong ~]# mkdir /root/shell/day06
[root@liruilong ~]# vim /root/shell/day06/star.sh
#!/bin/bash
#######################
#此循环的作用是输出5个*在同一行
for i in {1..5}
do
echo -n "*"
done
echo
echo
########################
#内层for循环在一行输出5个*;外层for循环,将内层循环执行5遍
for i in {1..5}
do
for j in {1..5}
do
echo -n "*"
done
echo
done
#####执行脚本
[root@liruilong ~]# sh /root/shell/day06/star.sh
*****
*****
*****
*****
*****
*****

循环嵌套

打印星星矩阵

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@liruilong ~]# mkdir -p /root/shell/day06
[root@liruilong ~]# vim /root/shell/day06/star.sh
#!/bin/bash
#######################
#此循环的作用是输出5个*在同一行
for i in {1..5}
do
echo -n "*"
done
echo
echo
########################
#内层for循环在一行输出5个*;外层for循环,将内层循环执行5遍
for i in {1..5}
do
for j in {1..5}
do
echo -n "*"
done
echo
done
1
2
3
4
5
6
7
8
#####执行脚本
[root@liruilong ~]# sh /root/shell/day06/star.sh
*****
*****
*****
*****
*****
*****

排列与组合

1
2
3
4
5
6
7
8
9
10
[root@liruilong ~]# vim /root/shell/day06/compose.sh
#!/bin/bash
###打印1-3的所有两位数的排列组合方式
for i in {1..3}
do
for j in {1..3}
do
echo "${i}${j}"
done
done

打印形状

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@liruilong ~]# vim /root/shell/day06/sharp1.sh
#!/bin/bash
####打印出上述图片形状
for((i=1;i<=6;i++))
do
for((j=1;j<=i;j++))
do
echo -ne "\033[46m \033[0m"
done
echo
done
############
[root@liruilong ~]# vim /root/shell/day06/sharp2.sh
#!/bin/bash
####打印出上述图片形状
for((i=1;i<=6;i++))
do
for((j=6;j>=i;j--))
do
echo -ne "\033[46m \033[0m"
done
echo
done

带菜单的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[root@liruilong ~]# vim /root/shell/day06/menu.sh
#!/bin/bash
echo "1.查看剩余内存容量."
echo "2.查看根分区剩余容量."
echo "3.查看cpu十五分钟负载."
echo "4.查看系统进程数量."
echo "5.查看系统账户数量."
echo "6.退出."
###while死循环,查看过程不退出,不需要继续查看可以按6选择退出
while :
do
read -p "请输入选项[1-6]:" key
###case语句,对用户输入key进行判断给出相应的结果
case $key in
1)
free| awk '/Mem/{print $NF}';;
2)
df | awk '/\/$/{print $4}';;
3)
uptime | awk '{print $NF}';;
4)
ps -aux | wc -l;;
5)
sed -n '$=' /etc/passwd;;
6)
exit;;
esac
done

备份数据

备份日志

1
2
3
4
5
6
7
8
9
10
11
[root@liruilong ~]# vim /root/shell/day06/bak_log.sh
#!/bin/bash
###此脚本运用日期定义备份的文件名,方便与每天进行备份不重复
date=`date +"%Y%m%d"`
if [ ! -f /tmp/log-$date.tar.gz ];then
tar -zcPf /tmp/log-$date.tar.gz /var/log
fi
###执行脚本并检查输出结果
[root@liruilong ~]# sh /root/shell/day06/bak_log.sh
[root@liruilong ~]# ls /tmp/log-*
/tmp/log-20200718.tar.gz

备份数据库

逻辑备份

1
2
3
4
5
6
7
###安装mariadb数据库,重启服务
[root@liruilong ~]# yum -y install mariadb mariadb-server
[root@liruilong ~]# systemctl restart mariadb
####查看数据库服务的进程信息
[root@liruilong ~]# ss -ntulpa | grep mysql
tcp LISTEN 0 50 *:3306 *:*
users:(("mysqld",pid=9561,fd=14)
1
2
3
##mysqldump可以对数据库中的库进行备份
##格式: mysqldump -u"用户名" --password="" 数据库名 > 备份名.sql
[root@liruilong ~]# mysqldump mysql > mysql.sql
1
2
3
4
5
6
7
8
9
10
11
12
[root@liruilong ~]# vim /root/shell/day06/mysqldump.sh
#!/bin/bash
###date 指定备份数据名;iuser 指定登录数据库的用户
###ipass 指定登录密码,默认为空;db 指定要备份的数据库
date=$(date +"%Y%m%d")
iuser=root
ipass=
db=mysql
###文件在/tmp 下不存在时才会进行备份
if [ ! -f /tmp/$db-$date.sql ];then
mysqldump -u$iuser --password="$ipass" $db > /tmp/$db-$date.sql
fi
1
2
3
4
###运行脚本
[root@liruilong ~]# sh /root/shell/day06/mysqldump.sh
[root@liruilong ~]# ls -l /tmp/mysql-*
-rw-r--r-- 1 root root 514619 7月 18 12:54 /tmp/mysql-20200718.sql

物理备份(buttaidong)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@liruilong ~]# vim /root/shell/day06/bak_mysql.sh
#!/bin/bash
###对数据库中的mysql库下每一个表都进行打包备份;备份文件存放在/tmp/mysql目录下
date=$(date +"%Y%m%d")
db_dir="/var/lib/mysql"
db=mysql
[ ! -d /tmp/$db ] && mkdir /tmp/$db
for i in $(ls $db_dir/$db)
do
tar -zcf /tmp/$db/$i-$date.tar.gz $db_dir/$db/$i
done
###运行脚本
[root@liruilong ~]# sh /root/shell/day06/bak_mysql.sh
[root@liruilong ~]# ls /tmp/mysql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
mysql> show databases
-> ;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)

mysql> create databases liruilong;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'databases liruilong' at line 1
mysql> create database liruilong;
Query OK, 1 row affected (0.02 sec)

mysql> use liruilong;
Database changed
mysql> create table demo(id int(2),name varchar(20));
Query OK, 0 rows affected (0.04 sec)

mysql>

差异备份

嗯,这个有些复杂。。。

部署安装rsync同步软件、inotifywait 监听软件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
┌──[root@liruilongs.github.io]-[/var/www/html]
└─$ yum -y install rsync
┌──[root@liruilongs.github.io]-[/mysql]
└─$ yum search inotify-tools
已加载插件:fastestmirror
Loading mirror speeds from cached hostfile
============================================== N/S matched: inotify-tools ===============================================
inotify-tools.x86_64 : Command line utilities for inotify
inotify-tools-devel.x86_64 : Headers and libraries for building apps that use libinotifytools

名称和简介匹配 only,使用“search all”试试。
┌──[root@liruilongs.github.io]-[/mysql]
└─$ yum -y install inotify-tools
┌──[root@liruilongs.github.io]-[/mysql]
└─$ rpm -qal inotify-tools
/usr/bin/inotifywait
/usr/bin/inotifywatch
/usr/lib64/libinotifytools.so.0
/usr/lib64/libinotifytools.so.0.4.1
/usr/share/doc/inotify-tools-3.14
/usr/share/doc/inotify-tools-3.14/AUTHORS
/usr/share/doc/inotify-tools-3.14/COPYING
/usr/share/doc/inotify-tools-3.14/ChangeLog
/usr/share/doc/inotify-tools-3.14/NEWS
/usr/share/doc/inotify-tools-3.14/README
/usr/share/man/man1/inotifywait.1.gz
/usr/share/man/man1/inotifywatch.1.gz

差异备份【inotify+rsync】

所谓差异备份,即通过inotify 来监听文件变化,通rsync来增量同步数据。
这里我们本机模拟一下,一般是备份到远程机器上的,备份前一定做ssh免密 ssh-copy-id root@192.168.26.55

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
┌──[root@liruilongs.github.io]-[~]
└─$ mkdir rsync;cd rsync
┌──[root@liruilongs.github.io]-[~/rsync]
└─$ vim isync.sh
┌──[root@liruilongs.github.io]-[~/rsync]
└─$ mkdir /root/liruilong
┌──[root@liruilongs.github.io]-[~/rsync]
└─$ sh isync.sh &
[1] 17575
┌──[root@liruilongs.github.io]-[~/rsync]
└─$ cd /root/liruilong/
┌──[root@liruilongs.github.io]-[~/liruilong]
└─$ ls
┌──[root@liruilongs.github.io]-[~/liruilong]
└─$ cd /var/www/html/
┌──[root@liruilongs.github.io]-[/var/www/html]
└─$ echo "123456" > liruilong.txt
┌──[root@liruilongs.github.io]-[/var/www/html]
└─$ cat liruilong.txt
123456
┌──[root@liruilongs.github.io]-[/var/www/html]
└─$ cd /root/liruilong/
┌──[root@liruilongs.github.io]-[~/liruilong]
└─$ ls
liruilong.txt
┌──[root@liruilongs.github.io]-[~/liruilong]
└─$ cat liruilong.txt
123456
┌──[root@liruilongs.github.io]-[~/liruilong]
└─$ jobs
[1]+ 运行中 sh isync.sh &(工作目录:~/rsync)
┌──[root@liruilongs.github.io]-[~/liruilong]
└─$

备份脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌──[root@liruilongs.github.io]-[~/rsync]
└─$ ls
isync.sh
┌──[root@liruilongs.github.io]-[~/rsync]
└─$ cat isync.sh
#!/bin/bash
##from_dir 为要被同步的目录
from_dir="/var/www/html/"
##将$from_dir下的内容,同步到本机的/root/liruilong/目录下
rsync_cmd="rsync -az --delete $from_dir root@192.168.26.55:/root/liruilong"
##inotifywait监听 $from_dir 目录,目录下发生文件的变化时,执行同步操作,脚本后台运行
while inotifywait -rqq -e modify,move,create,delete,attrib $from_dir
do
$rsync_cmd
done
┌──[root@liruilongs.github.io]-[~/rsync]
└─$

安全脚本

HASH值

HASH值

  • HASH 值与文件名称、时间、大小等信息无关,仅与内容有关
  • MD5
  • SHA256
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
######文件的内容只要不发生变化,HASH值就是唯一的
##计算文件的hash值
[root@liruilong ~]# md5sum /etc/passwd
6218010e73619a856999d39590a533f8 /etc/passwd
##只要文件内容不变,hash值一样
[root@liruilong ~]# cp /etc/passwd /root/pass
[root@liruilong ~]# md5sum /root/pass
6218010e73619a856999d39590a533f8 /root/pass
##删除了文件第5行,内容发生变化,hash值改变
[root@liruilong ~]# sed -i '5d' /root/pass
[root@liruilong ~]# md5sum /root/pass
449a721dd0449390377ae5216922faa7 /root/pass
###sha256sum和sha512sum都是计算hash值的,区别是长度不同
[root@liruilong ~]# sha256sum /etc/passwd
db5560c8d21a9a4558272a2781ed1636eb40e7ebd709d5bca6751eb09db43383 /etc/passwd
[root@liruilong ~]# sha512sum /etc/passwd
c42b1c3531cd9d45c669845906f033c19cb40d626febdccd1e4834f1feb40730e4d52e0317dfd3f5
7f7406a23c10901be8d65787398beeae4513d71838f34803 /etc/passwd

数据安全检测脚本

1
2
3
4
5
6
7
[root@liruilong ~]# vim /root/shell/day06/data.sh
#!/bin/bash
###为/etc/下所有以 .conf 结尾的文件生成hash值,保存到/tmp/data.log文件中
for i in $(ls /etc/*.conf)
do
md5sum $i >> /tmp/data.log
done
1
2
3
##运行脚本,查看结果
[root@liruilong ~]# sh /root/shell/day06/data.sh
[root@liruilong ~]# cat /tmp/data.log

SSH配置

sshd配置

sshd主配置文件:
在这里插入图片描述

  • Port 3389 // 改用非标准端口
  • PermitRootLogin no // 禁止root登录
  • UseDNS no //不解析客户机地址
  • AllowUsers 账户名 //设置远程连接的白名单,多个用户空格分割
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
###拷贝远程服务 sshd 的主配置文件
[root@liruilong ~]# cp /etc/ssh/sshd_config /opt/
[root@liruilong ~]# ls -l /opt/sshd_config
-rw------- 1 root root 3907 7月 20 10:00 /opt/sshd_config
###过滤包含 port 的行
[root@liruilong ~]# grep -i "port" /opt/sshd_config
###使用sed删除对应行的注释
[root@liruilong ~]# sed -n '/^#Port/s/#//p' /opt/sshd_config
Port 22
###过滤包含 permitrootlogin 的行
[root@liruilong ~]# grep -i 'permitrootlogin' /opt/sshd_config
###使用sed删除对应行的注释
[root@liruilong ~]# sed -n '/^#PermitRootLogin/s/#//p' /opt/sshd_config
PermitRootLogin yes
###过滤包含 usedns 的行
[root@liruilong ~]# grep -i "usedns" /opt/sshd_config
###使用sed删除对应行的注释
[root@liruilong ~]# sed -n '/^#UseDNS/s/#//p' /opt/sshd_config
UseDNS yes
###上述操作只是打印出来,-i 直接修改配置文件
[root@liruilong ~]# sed -i '/^#Port/s/#//' /opt/sshd_config
[root@liruilong ~]# sed -i '/^#PermitRootLogin/s/#//' /opt/sshd_config
[root@liruilong ~]# sed -i '/^#UseDNS/s/#//' /opt/sshd_config

1
2
3
4
5
6
7
8
9
[root@liruilong ~]# vim /root/shell/day06/ssh_conf.sh
#!/bin/bash
####安全的远程配置脚本
conf="/opt/sshd_config"
sed -i '/^Port/s/22/1122/' $conf
sed -i '/^PermitRootLogin/s/yes/no/' $conf
sed -i '/^UseDNS/s/yes/no/' $conf
sed -i '$a AllowUsers tom' $conf
systemctl restart sshd
1
2
3
4
5
6
7
8
9
10
11
12
###运行脚本
[root@liruilong opt]# sh /root/shell/day06/ssh_conf.sh
###查看结果
[root@liruilong ~]# sed -n '/^Port/p' /opt/sshd_config
Port 1122
[root@liruilong ~]# sed -n '/^PermitRootLogin/p' /opt/sshd_config
PermitRootLogin no
[root@liruilong ~]# sed -n '/^UseDNS/p' /opt/sshd_config
UseDNS no
[root@liruilong ~]# sed -n '$p' /opt/sshd_config
AllowUsers tom

、格式化输出passwd

格式输出

格式化输出各式化输出/etc/passwd,效果如下 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
###打印 用户名,UID和家目录
[root@liruilong ~]# awk -F: 'BEGIN{print "用户名 UID 家目录"} {print $1,$3,$6}' /etc/passwd
用户名 UID 家目录
root 0 /root
bin 1 /bin
daemon 2 /sbin
......
###column -t 作用是对打印的内容进行排版
[root@liruilong ~]# awk -F: 'BEGIN{print "用户名 UID 家目录"} {print $1,$3,$6}'
/etc/passwd | column -t
用户名 UID 家目录
root 0 /root
bin 1 /bin
daemon 2 /sbin

过滤系统账户对应的密码

  • 在 awk中可以通过 -v 选项调用 shell 中的变量
    1
    2
    3
    4
    5
    ###定义变量 hello
    [root@liruilong ~]# hello="nihao"
    ### -v 选项,可以引用shell中的变量,将变量hello的值赋予tmp
    [root@liruilong ~]# awk -v tmp=$hello 'BEGIN{print tmp}'
    nihao
  • 从 /etc/passwd 中将所有能登陆的账户名提取出来
  • 从 /etc/shadow 中提取账户对应的密码
1
2
3
4
5
6
7
8
9
10
[root@liruilong ~]# sh /root/shell/day06/userpass.sh
#!/bin/bash
###过滤出以bash结尾的用户,赋予变量USER
USER=$(awk -F: '/bash$/{print $1}' /etc/passwd)
for i in $USER
do
awk -F: -v iuser=$i '$1==iuser{print $1,$2}' /etc/shadow
done
##注意单独使用时,$1=="root",要加双引号,代表字符串
## awk -F: '$1=="root"{print $1,$2}' /etc/shadow

在这里插入图片描述

1
2
3
4
5
6
7
8
###运行脚本
[root@liruilong ~]# sh /root/shell/day06/userpass.sh
root
$6$pAL3P7fovbgv4LEv$zwO6BZTMSfyfFcIZHO8S.TQc8RDuBtj4dj3wJ5CdH0clUue3G15.0C0PpytA
wh9Lo.Dcxl1q0j6.z09yOGH32/
zhangzhao
$6$mcBYSo/SxmOFm8l.$NxqB4us2UerMMPRPHn4u2v4BdFqkPBza/5NA1IV/Z3.knseF7sNS8.171OPx
KULoW7KBYY6qyM0VNxF2r6I.h0

、综合案例

一键PXE+kickstart

PXE:

  • PXE,全名Pre-boot Execution Environment,预启动执行环境;
  • 通过网络接口启动计算机,不依赖本地存储设备(如硬盘)或本地已安装的操作系统;由Intel和Systemsoft公司于1999年9月20日公布的技术;
  • lient/Server的工作模式;PXE客户端会调用网际协议(IP)、用户数据报协议(UDP)、动态主机设定协议(DHCP)、小型文件传输协议(TFTP)等网络协议;
  • PXE客户端(client)这个术语是指机器在PXE启动过程中的角色。一个PXE客户端可以是一台服务器、笔记本电脑或者其他装有PXE启动代码的机器(我们电脑的网卡)。

在这里插入图片描述

1、启动步骤详解

1、服务器加电启动,从DHCP服务器获取IP地址并加载(PXEClient)。
2、通过TFTP服务器获取网络引导程序(pxelinux.0)。
3、引导程序读取配置文件(pxelinux.cfg本例中文件名为:default)。
4、引导程序加载文件系统初始化(initrd)程序和内核初始镜像(vmlinuz)、自动应答程序(ks.cfg)。
5、按自动应答文件中指定的网络安装方式,以FTP方式安装linux系统。

一键PXE+kickstart

  • 部署 PXE+kickstart 环境
    • dhcp 服务
    • tftp 服务
    • http 服务
    • kickstart 配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
###输出多行文本
[root@liruilong ~]# cat << EOF
> hello world
> i am come here
> i love the world
> EOF
hello world
i am come here
i love the world
###将多行文本保存到文件/opt/password中
[root@liruilong ~]# cat > /opt/password << EOF
> hello world
> i am come here
> i love the world
> EOF
###查看文件内容跟
[root@liruilong ~]# cat /opt/password
hello world
i am come here
i love the world
[root@liruilong ~]# vim /root/shell/day06/pxe.sh
#!/bin/bash
##定义变量,让方便后面的调用,和提高适用性
DHCP_NET=192.168.4.0
DHCP_NETMASK=255.255.255.0
DHCP_MINIP=192.168.4.100
DHCP_MAXIP=192.168.4.200
DHCP_ROUTER=192.168.4.254
DHCP_NEXT_SERVER=192.168.4.5
HTTP_IP=192.168.4.5
##安装软件包
yum -y install httpd dhcp tftp-server syslinux
##临时停用SELinux
setenforce 0
##配置 DHCP 服务
cat > /etc/dhcp/dhcpd.conf << EOF
subnet $DHCP_NET netmask $DHCP_NETMASK {
range $DHCP_MINIP $DHCP_MAXIP;
option routers $DHCP_ROUTER;
default-lease-time 600;
max-lease-time 7200;
next-server $DHCP_NEXT_SERVER;
filename "pxelinux.0";
}
EOF
systemctl restart dhcpd
systemctl enable dhcpd
##配置httpd共享服务器
if [ ! -e /dev/cdrom ];then
echo "未检测到系统光盘/dev/cdrom,请插入光盘后再试"
exit
fi
[ -d /var/www/html/cdrom ] || mkdir /var/www/html/cdrom
mount /dev/cdrom /var/www/html/cdrom
systemctl start httpd
##配置kickstart 文件
cat > /var/www/html/ks.cfg << EOF
install
keyboard 'us'
rootpw --plaintext redhat
url --url="http://$HTTP_IP/cdrom"
lang en_US
firewall --disabled
auth --useshadow --passalgo=sha512
text
selinux --disabled
network --bootproto=dhcp --device=eth0
reboot
timezone Asia/Shanghai
bootloader --location=mbr
zerombr
clearpart --all --initlabel
part /boot --fstype="xfs" --size=500
part / --fstype="xfs" --grow --size=1
%packages
@base
%end
EOF
####配置tftp服务
cp /usr/share/syslinux/pxelinux.0 /var/lib/tftpboot/
cp /var/www/html/cdrom/isolinux/* /var/lib/tftpboot/
[ -d /var/lib/tftpboot/pxelinux.cfg ] || mkdir /var/lib/tftpboot/pxelinux.cfg
##部署菜单文件
cat > /var/lib/tftpboot/pxelinux.cfg/default << EOF
default vesamenu.c32
timeout 100
label linux
menu label ^Install CentOS 7
kernel vmlinuz
append initrd=initrd.img ks=http://$HTTP_IP/ks.cfg
EOF
systemctl start tftp
##临时清空防火墙规则
iptables -F
###执行脚本
[root@liruilong ~]# sh /root/shell/day06/pxe.sh
###检查三个服务【dhcpd,httpd,tftp】是否已经运行
[root@liruilong ~]# systemctl status dhcpd | grep Active
Active: active (running) since 一 2020-07-20 12:06:31 CST; 16min ago
[root@liruilong ~]# systemctl status tftp | grep Active
Active: active (running) since 一 2020-07-20 12:05:35 CST; 17min ago
[root@liruilong ~]# systemctl status httpd | grep Active
Active: active (running) since 一 2020-07-20 12:05:34 CST; 17min ago
发布于

2021-07-30

更新于

2023-06-21

许可协议

评论
加载中,最新评论有1分钟缓存...
Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×