ANSIBLE

## ansible

“`sh
[root@m01 ~]# yum install -y python3-pip
[root@m01 ~]# pip3 install -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple ansible

[root@m01 ~]# echo ‘export PATH=/usr/local/bin/:$PATH’ >>/etc/profile
[root@m01 ~]# source /etc/profile
[root@m01 ~]# ansible –version

[root@m01 /etc/ansible]# cat ansible.cfg
[defaults]
interpreter_python=/usr/bin/python3
host_key_checking = False
deprecation_warnings = False
[inventory]
[privilege_escalation]
[paramiko_connection]
[ssh_connection]
[persistent_connection]
[accelerate]
[selinux]
[colors]
[diff]
[root@m01 /etc/ansible]# cat hosts
[web]
172.16.1.[7:8]

[backup]
172.16.1.41

[nfs]
172.16.1.31

[data:children]
backup
nfs

“`

![image-20250107123925048](D:\Program Files (x86)\Typora\ansible\image-20250107123925048.png)

在主机清单中指定用户密码,

“`sh
172.16.1.9 ansible_user=root ansible_password=XZnh@95599 absible_port=22
“`

![image-20250107123941746](D:\Program Files (x86)\Typora\ansible\image-20250107123941746.png)

71:host_key_checking = False 这个配置没有关闭.关闭主机认证.

### 5.1 命令与脚本类模块

#### 1 command模块

“`sh
[root@m01 ~]# ansible all -m command -a ‘ip a s ens33’

-m command是默认的,可以省略
[root@m01 ~]# ansible all -a ‘ip a s ens33’

“`

#### 2 shell模块

与command模块相似,但是shell支持特殊符号

“`sh
[root@m01 ~]# ansible all -m shell -a ‘find /etc/sysconfig/network-scripts/ -name *ens33’

[root@m01 ~]# ansible all -m shell -a ip a show ens33 | awk -F ‘[ /]+’ ‘NRR==3{print \$3}'”

“`

#### 3 script模块

“`sh
ansible all -m script -a ‘/server/scripts/ansible/scripts.sh’
“`

文件相关模块

#### 4 file模块

案例05-创建/opt/ysl.txt

“`sh
[root@m01 ~]# ansible all -m file -a ‘path=/opt/ysl.txt state=touch’
“`

案例06-创建目录/app/

“`sh
[root@m01 ~]# ansible all -m file -a ‘path=/app/a/ state=directory’
“`

案例07-创建软连接,/etc/hosts创建软连接到/opt下

“`sh
[root@m01 ~]# ansible all -m file -a ‘src=/etc/hosts path=/opt/hosts state=link’
“`

案例08-创建/ans-backup目录,所有者是rsync,权限是700

“`sh
[root@m01 ~]# ansible all -m file -a ‘path=/ans-backup owner=rsync group=rsync mode=700 state=directory’

mode参数最好写4位0700,rsync必须存在,不然会报错
“`

案例09-删除/ans-backup

“`sh
[root@m01 ~]# ansible all -m file -a ‘path=/ans-backup state=absent’
“`

#### 5 copy模块

ansible-doc -s

案例10-分发属性好的/etc/hosts文件,如果文件存在则备份下

“`sh
[root@m01 ~]# ansible all -m copy -a ‘src=/etc/hosts dest=/etc/hosts backup=yes’

可以分发文件、压缩包,不推荐目录
copy是推送

fetch是拉取
[root@m01 ~]# ansible all -m fetch -a ‘src=/etc/hostname dest=/root/’
拉取后会在/root/目录下出现以所有主机清单的IP命名的目录,目录里有etc目录,hostnamectl在etc目录下

“`

#### 6 服务管理-systemd

systemd模块适用于目前大部分的Linux系统.

service模块适用于管理旧的Linux系统

案例11-开启crond服务并设置开机启动

案例12-关闭firewalld服务不让开机启动

案例13-重启sshd服务

“`sh
[root@m01 ~/172.16.1.31/etc]# ansible all -m systemd -a ‘name=crond enabled=yes state=started’

[root@m01 ~/172.16.1.31/etc]# ansible all -m systemd -a ‘name=firewalld enabled=no state=stopped’

[root@m01 ~]# ansible all -m systemd -a ‘name=sshd state=restarted’

“`

#### 7 软件管理

yum模块

“`sh
[root@m01 ~]# ansible all -m yum -a ‘name=htop,tree,lrzsz,sshpass’

[root@m01 ~]# ansible all -m yum -a ‘name=htop state=absent’

[root@m01 ~]# ansible all -m yum -a ‘name=rsync state=present’ 安装,默认可以不写

[root@m01 ~]# ansible all -m yum -a ‘name=rsync state=latest’ 安装或更新

“`

#### 8 get_url模块

相当于wget命令

推荐在管理节点下载好,再使用copy模块分发

“`sh
[root@m01 ~]# ansible all -m get_url -a ‘url=”https://nginx.org/download/nginx-1.26.1.tar.gz” dest=/root/’

“`

#### 9 yum_repository模块

推荐写好后,再使用copy模块分发

“`sh
ansible backup \
-m yum_repository \
-a ‘name=epel
description=”Extra Packages for Enterprise Linux 7 –
$basearch”
baseurl=”http://mirrors.aliyun.com/epel/7/$basearch”
enabled=yes
gpgcheck=no
“`

#### 10 用户管理

user用户管理 : useradd,userdel,passwd,usermod修改用户信息

案例15-创建www-ans用户,uid2000的虚拟用户

“`sh
[root@m01 ~]# ansible all -m user -a ‘name=www uid=2000 shell=/sbin/nologin create_home=no state=present’

“`

案例16-批量更新密码

方法1

“`sh
[root@m01 ~]# ansible all -m user -a “name=ysl password={{‘ysl’ | password_hash(‘sha512’ , ‘ysl’)}} state=present”

将密码ysl生成哈希值,再加入ysl生成哈希,使别人不能破解
{{ ‘1’ | password_hash(‘sha512’, ‘ysl’) }}
表示1是密码,经过管道,传递给了password_hash()插件, sha512加密算法,ysl
是随机字符用于生成随机加密后的密码
“`

方法2

“`sh
[root@m01 ~]# ansible all -m shell -a ‘echo ysl007 | passwd –stdin ysl’

“`

#### 11 group模块

添加组

“`sh
[root@m01 ~]# ansible all -m group -a ‘name=ysltest gid=2005 state=present’
“`

删除组

“`sh
[root@m01 ~]# ansible all -m group -a ‘name=ysltest state=absent’
“`

#### 12 cron模块

作用:用于管理系统的定时任务.

替代了crontab -e或vi /var/spool/cron/xxx用户功能

![image-20250107124106193](D:\Program Files (x86)\Typora\ansible\image-20250107124106193.png)

创建定时任务

“`sh
[root@m01 ~]# ansible all -m cron -a ‘name=”test” job=”echo ysl >> /tmp/ysl.txt” state=present’

name是注释,如果是ansible添加的,可以通过注释来删除定时任务
“`

删除定时任务

“`sh
[root@m01 ~]# ansible all -m cron -a ‘name=”test” state=absent’

“`

#### 13 mount模块

案例17-挂载nfs01已有的共享目录到web01上的/mnt下

“`sh
[root@m01 ~]# ansible web -m mount -a ‘fstype=nfs src=172.16.1.31:/data/ path=/mnt state=mounted’

“`

| state参数可使用的值 | 含义 |
| ——————- | ———————– |
| absent | 卸载并修改fstab |
| unmounted | 卸载不修改/etc/fstab |
| present | 仅修改/etc/fstab 不挂载 |
| mounted | 挂载并修改/etc/fstab |
| remounted | 重新挂载 |

卸载

“`sh
ansible 172.16.1.7 -m mount -a ‘path=/mnt/ state=absent’
“`

### 5.2 剧本与变量

yaml格式的文件:空格,冒号

“`sh

– hosts: all
tasks:
– name: 01 打开冰箱门
shell: echo 01 >> /tmp/bingxiang.log

– name: 02 放进冰箱
shell: echo 02 >> /tmp/bingxiang.log

– name: 03 关上冰箱
shell: echo 03 >> /tmp/bingxiang.log

“`

### 5.3 案例02-创建目录并分发

步骤:
1.创建目录/server/files
2.管理机的/etc/hosts文件发送过去

“`sh
[root@m01 /server/scripts/playbook]# cat 02.dist_file.yml

– hosts: all
tasks:
– name: 01 创建目录
file:
path: /server/files/
state: directory
– name: 02 分发文件
copy:
src: /etc/hosts
dest: /server/files/

“`

### 5.4 案例03-批量添加定时任务

定时同步时间ntp.aliyun.com

“`sh
[root@m01 /server/scripts/playbook]# cat 03.cron_ntp.yml

– hosts: all
tasks:
– name: 批量同步时间
cron:
name: “sync time”
job: “/sbin/ntpdate ntp.aliyun.com > /dev/null 2>&1”
state: present
[root@m01 /server/scripts/playbook]#

“`

### 5.5 案例04-nfs服务

nfs服务端:在xxx上部署nfs服务,共享/backup-nfs目录,all_squash,匿名用户:www-ans uid 2999 2999

nfs客户端:web挂载 /ans-upload目录挂载nfs服务端共享的/backup-nfs(永久挂载)

服务端流程:

\1. 部署nfs-utils

\2. 修改配置文件 /etc/exports

/backup-nfs 172.16.1.0/24(rw,all_squash)

\3. 创建共享目录,改所有者

\4. 启动服务rpcbind,nfs

客户端:

\1. 安装nfs-utils

\2. 挂载与永久挂载

“`yaml
[root@m01 /server/scripts/playbook]# cat 04.nfs_mount.yaml

– hosts: nfs
tasks:
– name: 01.部署nfs-utils
yum:
name: rpcbind,nfs-utils
state: present
– name: 02.修改配置文件
lineinfile:
path: /etc/exports
line: /nfs/ans 172.16.1.0/24(rw,anonuid=2999,all_squash)

– name: 03.创建组
group:
name: www-ans
gid: 2999
state: present

– name: 04.创建用户
user:
name: www-ans
group: www-ans
uid: 2999
create_home: no
shell: /sbin/nologin
state: present

– name: 05.创建并修改数组
file:
path: /nfs/ans
owner: www-ans
group: www-ans
mode: 0755
state: directory

– name: 06.启动rpc服务
systemd:
name: rpcbind
state: started
enabled: yes
– name: 07.启动nfs服务
systemd:
name: nfs
state: reloaded
enabled: yes

– hosts: web
tasks:
– name: 01.安装服务
yum:
name: nfs-utils,rpcbind
state: present
– name: 02.创建组
group:
name: www-ans
gid: 2999
state: present
– name: 04.创建用户
user:
name: www-ans
group: www-ans
uid: 2999
create_home: no
shell: /sbin/nologin
state: present
– name: 05.创建并修改数组
file:
path: /app/web/ansv2-upload/
owner: www-ans
group: www-ans
mode: 0755
state: directory

– name: 05.挂载
mount:
fstype: nfs
src: 172.16.1.31:/nfs/ans
path: /app/web/ansv2-upload/
state: mounted

“`

### 5.6 剧本里创建文件添加多行

“`yaml
– name: Insert multiple lines into a file
blockinfile:
path: /path/to/your/file
block: |
This is the first line
This is the second line
This is the third line
create: yes
“`

### 5.7 ansible变量

#### 1 vars

ansible 变量命名规则:

\1. 与shell类似,不能以数字开头.

\2. 变量中仅包含_下划线即可.不要包含其他特殊符号.

案例05-批量创建/ysl/ysl/upload

“`yaml
[root@m01 /server/scripts/playbook]# cat 05.mk_dir.yaml

– hosts: all
vars:
dir: /ysl/ysl/upload
file: ysl.txt
tasks:
– name: mkdir directory
file:
path: “{{ dir }}”
state: directory
– name: touch file
file:
path: “{{ dir }}/{{ file }}”
state: touch

“`

如果变量是某个选项的开头,则变量引用的时候需要加上双引号

如果不是开头,则可以不用添加引号

多个变量在一起的时候只需要一个引号,多添加引号会报错

“{{ dir }}/{{ file }}”这个是对的,”{{ dir }}”/”{{ file }}”这个是错的

vars局限性:

vars只能在当前剧本中生效

使用两个花括号包起来,花括号中间有空格

在hosts和tasks中间使用

#### 2 变量文件vars_files

在hosts和tasks中间使用

例:

“`yaml
– hosts: web
vars_files:
– ./vars.yml
tasks:

vars.yaml格式
可以顶格写
cat vars.yaml
dir: /server/ans-test-01/
file: test02.txt
“`

#### 3 组变量

在剧本目录下创建一个all目录,再创建vars.yml

或者根据主机清单的分组建多个目录,然后再各个目录创建vars.yaml

“`yaml
[root@m01 /server/scripts/playbook]# tree group_vars/
group_vars/
├── all
│ └── vars.yml
├── backup
│ ├── nfs
│ └── vars.yml
└── web
└── vars.yml

“`

“`yaml
案例07-测试组变量
vim 07.group_vars_test.yml

– hosts: all
tasks:
– name: 01.创建目录
file:
path: “{{ dir }}”
state: directory
– name: 02.创建用户
user:
name: “{{ user }}”
shell: /sbin/nologin
create_home: no
state: present
– hosts: web
tasks:
– name: 01.创建目录
file:
path: “{{ web_upload }}”
state: directory
– hosts: nfs
tasks:
– name: 01.创建目录
file:
path: “{{ nfs_dir }}”
state: directory

创建vars文件
[root@m01 /server/scripts/playbook]# cat group_vars/all/vars.yml
#1.all
dir: /server/scripts/
user: www

#2.nfs
nfs_dir: /ans-data/web/

#3.backup
backup_dir: /ans-backup/nfsbackup/

#4.web
web_upload: /app/ans/web/upload/

“`

#### 4 facts变量

facts变量相当于是ansible内置变量,存放被管理机器的基本信息

运行剧本的时候会运行:**Gathering Facts** task任务

**Gathering Facts** :ansible收集被管理端基本信息.cpu,内存,磁盘,网络,系统

我们在剧本中使用facts变量,未来如果不用可以关闭gather facts功能,加速剧本运行效果

“`sh
查看某个主机facts变量
[root@m01 /server/scripts/playbook]# ansible 172.16.1.61 -m setup

“`

常用facts变量

“`sh
ansible_hostname #主机名
ansible_memtotal_mb #内存大小
ansible_processor_vcpus #cpu总数
ansible_default_ipv4.address #默认网卡ip
ansible_distribution #系统版本

debian
ansible_distribution_version #系统版本
ansible_date_time.date #年月日
“`

##### 1 案例08-输出常用基本信息到屏幕,系统基本信息写入到/etc/motd中

“`sh
vim 08.test_facts_vars.yml

– hosts: all
tasks:
– name: 01.调试变量
debug:
msg: |
“主机名:{{ ansible_hostname }}”
“内存:{{ ansible_memtotal_mb }}”
“cpu:{{ ansible_processor_vcpus }}”
– name: 02.保存到文件中
lineinfile:
path: /etc/motd
state: present
backup: true
create: true
line: |
主机名:{{ ansible_hostname }}
内存:{{ ansible_memtotal_mb }}
cpu核数:{{ ansible_processor_vcpus }}
系统:{{ ansible_distribution }}
系统版本:{{ ansible_distribution_version }}

[root@m01 /server/scripts/playbook]# ansible all -m shell -a “cat /etc/motd”

“`

debug模块用于在剧本中输出与调试,一般用于输出变量内容.

|表示下面的内容是多行,用于输出或写入多行到文件中,注意索引对齐

debug:

msg:

相当于 echo,msg后面也要加引号

##### 2 案例09-ans-facts变量和判断

麒麟系统安装cowsay
ubt系统安装cmatrix

“`yaml
– hosts: all
tasks:
– name: 麒麟系统安装cowsay
yum:
name: cowsay
state: present
when: ansible_distribution is match(“Kylin”)

– name: ubt系统安装cmatrix
apt:
name: cmatrix
state: present
when: ansible_distribution is match(“Ubuntu”)

– name: 输出
debug:
msg:”{{ ansible_distribution }}”
“`

\1. 通过facts变量获取系统的基本信息

\2. 通过facts变量获取信息并进行判断

\3. 如果不需要可以进行关闭,加速剧本的运行( gather_facts: false )

\4. 修改ansible.cfg #gathering = implicit去掉注释,永久关闭,后期剧本中需要开启gather_facts: true

“`sh
yes or no 还是True or false
在使用上是一致的,表示的是真(开启,启动),假(关闭).
布尔类型的数据:真,假.
真:yes,True,true
假:no,False,false
根据每个模块选项的说明去使用即可
“`

##### 3 关闭facts变量,加速剧本运行

默认开启,不使用的时候临时关闭: gather_facts: false hosts: tasks之间

彻底关闭,使用的时候在剧本中临时开启 gather_facts: true

“`sh
cat>/etc/ansible/ansible.cfg<、<、>=、<=、==、!= | 大于、小于、大于等于、小于等于、等于、不等于 | | is match("正则") | 例:ansible_hostname is match("web\|backup") | | is not match("正则") | 取反排除 | ```sh 关闭掉麒麟系统中每次提示的: 自动发现的pyhont问题. group_vars/all/vars.yml加入即可 ansible_python_interpreter: /usr/bin/python3 关闭麒麟或其他系统,对python3.7不支持的警告提示. sed -i 's@#deprecation_warnings = True@deprecation_warnings = False@g' /etc/ansible/ansible.cfg ``` ### 5.14 剧本调试 debug流程 目标通过注释,等等方法定位问题 #### 1 检查语法与单步执行 ```sh -C --check 模拟运行,不作出改变,一些变量可能会提示报错,因为-C没有真正运行 剧本. register变量无法使用(目前使用pip安装的是OK的). --syntax-check 只做语法检查,不运行. 高级:--step 单步运行. y执行这个task,n忽略这个task,c自动运行 [root@m01 /server/scripts/playbook]# ansible-playbook -i hosts --step 15.test_hadnlers.yml PLAY [nfs] ********************************************************************* Perform task: TASK: 1.分发文件 (N)o/(y)es/(c)ontinue: y ``` #### 2 从指定任务开始运行 ```sh 一般先用--list-tasks查看剧本中tasks名字 然后--start-at-task "任务名字" 从指定任务开始运行. ansible-playbook -i inventory --list-tasks 16.nfs_server_client_v2_handlers.yml ansible-playbook -i inventory --start-at-task "3.创建挂载点" 16.nfs_server_clit_v2_handlers.yml [root@m01 /server/scripts/playbook]# ansible-playbook -i hsots --list-tasks 13.rsync_server_client_v1.yml [WARNING]: Unable to parse /server/scripts/playbook/hsots as an inventory source [WARNING]: No inventory was parsed, only implicit localhost is available [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all' [WARNING]: Could not match supplied host pattern, ignoring: backup playbook: 13.rsync_server_client_v1.yml play #1 (backup): backup TAGS: [] tasks: 1.部署rsync TAGS: [] 2.配置文件 TAGS: [] 3.用户组 TAGS: [] 4.目录,目录权限 TAGS: [] 5.服务端密码文件 TAGS: [] 6.启动服务端 TAGS: [] 7.查看端口 TAGS: [] 8.查看7的结果 TAGS: [] play #2 (all): all TAGS: [] tasks: 1.安装rsycn TAGS: [] 2.密码文件权限 TAGS: [] ``` #### 3 tag标签 ```sh 运行剧本的时候 --list-tasks 查看任务名字和标签名 -t --tags 运行的标签,如果多个标签通过","分割 --skip-tags 排除指定的tags,如果多个标签通过","分割 ``` ```sh [root@m01 /server/ans/playbooks]# cat 02.install_nfs.yml #nfs server服务端 - hosts: backup tasks: - name: 01. 安装nfs yum: name: nfs-utils,rpcbind state: present tags: - server_01_install - nfs_server - name: 02. 修改配置或分发 lineinfile: path: /etc/exports line: "/backup-nfs 172.16.1.0/24(rw,all_squash,anonuid=2999,anongid=2999)" #//backup-nfs 172.16.1.0/24(rw,all_squash,anonuid=2999,anongid=2999) tags: - server_02_conf - nfs_server - name: 03. 添加www-ans用户组 group: name: www-ans gid: 2999 state: present tags: - server_03_user - nfs_server - name: 03. 添加www-ans用户 user: name: www-ans shell: /sbin/nologin uid: 2999 ``` #### 4 忽略错误 运行剧本的时候,因为重复运行导致的错误提示,并不是真的错误. 比如:目录已经存在,用户已经存在. 在这种情况下,我们可以通过ignore_errors忽略错误,让剧本可以继续运行 ignore_errors: true ### 5.15 jinja2模版 #### 1 基本使用 ```sh [root@m01 /server/scripts/playbook]# cat 07.change_motd.yml - hosts: all gather_facts: no tasks: - name: 分发motd文件 template: src: templates/motd.j2 dest: /etc/motd backup: yes - name: 分发motd文件 copy: src: templates/motd.j2 dest: /tmp/motd backup: yes [root@m01 /server/scripts/playbook]# cat templates/motd.j2 ####################################### welcome to ysl elastic linux system 操作需谨慎,删根弹指间. 主机名: {{ ansible_hostname }} ip地址: {{ ansible_default_ipv4.address }} 内存大小: {{ ansible_memtotal_mb }} CPU数量: {{ ansible_processor_vcpus }} 核心总数: {{ ansible_processor_cores }} 发行版本: {{ ansible_distribution }} ``` #### 2 判断使用 ```sh [root@m01 /server/scripts/playbook]# cat 15.jinja2-if.yml - hosts: all tasks: - name: 分发配置文件 template: src: templates/keepalived.conf.j2 dest: /tmp/keepalived.conf [root@m01 /server/scripts/playbook]# tree templates/ templates/ ├── keepalived.conf.j2 └── motd.j2 0 directories, 2 files [root@m01 /server/scripts/playbook]# cat templates/keepalived.conf.j2 #this is keepalived.conf {% if ansible_hostname == "web01" %} state 主节点 {% elif ansible_hostname == "web02" %} state 备节点 {% endif %} 其他配置,都是相同的这里忽略 [root@m01 /server/scripts/playbook]# j2文件中判断 {% if ansible_hostname == "web02" %} state 备节点 {% elif ansible_hostname == "web01" %} state 主节点 {% endif %} ``` #### 3 循环 ```sh 配置文件 server.conf web服务器的/tmp/目录下 10.0.0.7 10.0.0.8 10.0.0.9 10.0.0.10 {% for ip in [1,2,3,4,5,6] %} 10.0.0.{{ ip }} {% endfor %} #range(2,11) 生成数字序列 2表示从2开始,到10结束 #顾头不顾腚 {% for ip in range(2,11) %} 10.0.0.{{ ip }} {%endfor%} {% for ip in ["ysl","oldwang"] %} 10.0.0.{{ ip }} {%endfor%} ``` ### 5.16 ansible进阶 #### 1 vault \#1.进行加密 ansible-vault encrypt 文件 #enable \#进行使用 ansible或ansible-playbook 加上--ask-vault-pass 即可 --ask-vault-pass 交互 --vault-password-file 密码文件 \#彻底解密 ansible-vault decrypt hosts# #### 2 roles Roles本质让我们书写剧本的时候有个目录规范. 把我们完整的剧本拆分若干部分,有的专门存放tasks部分(剧本),存放变量, 存放普通文件,存储变量文件,handlers内容 创建roles环境 ```sh [root@m01 /server/ans]# mkdir -p roles/{nfs-server,nfs-client}/{files,tasks,templates,handlers} [root@m01 /server/ans]# mkdir -p roles/group_vars/all [root@m01 /server/ans]# [root@m01 /server/ans]# tree -F roles/ roles/ ├── group_vars/ │ └── all/ ├── nfs-client/ │ ├── files/ │ ├── handlers/ │ ├── tasks/ │ └── templates/ └── nfs-server/ ├── files/ ├── handlers/ ├── tasks/ └── templates/ 12 directories, 0 files [root@m01 /server/ans]# 剧本安装nfs的yml文件 #nfs server服务端 - hosts: backup tasks: - name: 01. 安装nfs yum: name: nfs-utils,rpcbind state: present tags: - server_01_install - nfs_server - name: 02. 修改配置或分发 template: src: exports.j2 #文件里面可以放点变量 dest: /etc/exports backup: true notify: - restart_nfs tags: - server_02_conf - nfs_server - name: 03. 添加www-ans用户组 group: name: www-ans gid: 2999 state: present tags: - server_03_user - nfs_server - name: 03. 添加www-ans用户 剧本文件需要的文件内容 user: name: www-ans shell: /sbin/nologin uid: 2999 group: www-ans create_home: false state: present tags: - server_03_user - nfs_server - name: 04. 创建共享目录 file: path: /backup-nfs owner: www-ans group: www-ans state: directory tags: - server_04_dir - nfs_server - name: 05. 启动 rpc systemd: name: rpcbind enabled: true state: started tags: - server_05_start - nfs_server - name: 05. 启动 nfs systemd: name: nfs enabled: true state: started tags: - server_05_start - nfs_server handlers: - name: restart_nfs systemd: name: nfs state: restarted ```

SHELL

# 1.1 修改vim

当前用户家目录下 ~/.vimrc

放在/etc/vimrc (红帽系列) /etc/vim/vimrc(ubuntu debian)

追加

“`sh
set ignorecase

autocmd BufNewFile,BufRead *.py,*.cc,*.sh,*.java,*.bash exec “:call SetTitle()”

func SetTitle()
if expand(“%:e”) =~ ‘sh\|bash’
call setline(1, “#!/bin/bash”)
call setline(2, “##############################################################”)
call setline(3, “# File Name: ” . expand(“%”))
call setline(4, “# Version: V1.0”)
call setline(5, “# Author: ysl”)
call setline(6, “# Organization: www.ysledu.com”)
call setline(7, “# Date: ” . strftime(“%Y-%m-%d %H:%M:%S”))
call setline(8, “# Desc:”)
call setline(9, “##############################################################”)
endif
endfunc
“`

将脚本放入/etc/profile.d/目录下就是登录时显示

### 10.2 特殊变量-位置变量

位置的特殊变量 含义 应用场景

$n 脚本的第n个参数 命令行与脚本的内部桥梁

$0 脚本名字 用于错误提示输出帮助

$# 脚本参数的个数 一般与判断结合,检查脚本个数

$@ $* 取出脚本所有参数 数组或循环

-eq 等于

-ne 不等于

-lt 小于

-le 小于等于

-gt 大于

-ge 大于等于

### 10.3 案例2、检查用户是否存在

#!/bin/bash
#1.vars
user=$1

#2.判断参数个数是否为1,不是1就退出

if [ $# -ne 1 ]
then
echo “help :$0 用户名”
exit
fi

#3.判断用户是否存在
id $user >/dev/null 2>&1
if [ $? -eq 0 ]
then
echo “${user}存在”
else
echo “${user}不存在”
fi

[root@kylin shell]# sh user.sh test
test存在
[root@kylin shell]# sh user.sh mysql
mysql不存在

### 10.4 案例03-检查ip或域名是否可以访问的脚本

[root@kylin shell]# cat 03.check_ping.sh
#!/bin/bash

#1.vars
ip=$1

#2.检查参数个数是否为1,不是则退出
if [ $# -ne 1 ];then
echo “$0 ip或域名”
exit 1
fi

#3.检查输出
ping -c3 -w3 ${ip} > /dev/null 2>&1
if [ $? -eq 0 ];then
echo “${ip}可以ping通”
else
echo “${ip}不通”
fi
[root@kylin shell]# sh 03.check_ping.sh jd.com
jd.com可以ping通

案例04-$n n大于9会有什么问题?

$1…$9 ${10}

以后读取变量数据的时候都使用{}来括起来就不会有这个问题

案例05-通过$# 来完善02-03增加判断

if [ $# -ne 1 ];then

​ echo “使用说明:sh $0 username”

​ exit 1

fi

### 10.5 案例06-执行脚本输入1个或多个用户名,通过脚本进行输出

[root@kylin shell]# cat 06.check_multi_users.sh
#!/bin/bash

#1.vars
names=”$@”

#2.检查如果参数为0则退出
if [ $# -eq 0 ];then
echo “用法 bash $0 user1 user2 user3 user4”
exit 1
fi

#.for循环
for name in ${names}
do
id ${name} > /dev/null 2>&1
if [ $? -eq 0 ];then
id ${name}
else
echo “${name}” 不存在
fi
done

[root@kylin shell]# sh 06.check_multi_users.sh test ysl
用户id=1111(test) 组id=1111(test) 组=1111(test),1112(ceshi)
ysl 不存在
[root@kylin shell]# sh 06.check_multi_users.sh
用法 bash 06.check_multi_users.sh user1 user2 user3 user4
[root@kylin shell]#

### 10.6 for循环格式

for 变量 in 变量取值列表

do

命令,if等

done

状态的特殊符号 含义 应用场景

$? 上一个命令、脚本的返回值 一般与判断检查命令结果

\$$ 当前脚本的pid 一般写在脚本中获取脚本id

$! 上一个脚本的pid

$_ 取前一个命令的参数esc+点.

案例09-windows下书写的脚本复制到linux执行异常

现象:windows下书写的脚本,上传到Linux执行报错.

原因:windows下面的回车换行\r\n ,linux下面回车换行\n

解决:替换结束标记即可.dos2unix windows–>linux

或者进脚本set ff=unix

案例10:-通过脚本传参方式输入任何一个命令并执行,检查这个命令执行结果是否正确

[root@kylin shell]# cat 10.check_cmd.sh
#!/bin/bash
#1.检查是否为root
if [ $UID -ne 0 ];then
echo “请使用root用户运行”
exit 1
fi

#2.检查参数个数是否为0
if [ $# -eq 0 ];then
echo “Usage:$0 命令”
exit 2
fi

#3.执行
$* > /dev/null 2>&1

#4.检查
if [ $? -eq 0 ];then
echo “$* 运行成功”
else
echo “$* 运行失败”
fi
[root@kylin shell]# sh 10.check_cmd.sh cat 10.check_cmd.sh
cat 10.check_cmd.sh 运行成功
[root@kylin shell]#

### 10.7 特殊变量-变量子串

变量子串 parameter expension 变量扩展

格式${变量},写为$变量形式无法识别

作用:用于对变量处理加工()

应用:可以不用,如果使用效率高

变量子串parameter为变量名 含义

${parameter} $para 变量取值

${#parameter} 统计字符长度

${parameter#word} 从变量左边开始删除,按最短匹配删除

${parameter##word} 从变量左边开始删除,按最长开始匹配删除

${parameter%word} 从变量右边开始删除,按最短匹配删除

${parameter%%word} 从变量右边开始删除,按最长匹配删除

${var:5} 从下标是5字符开始向后截取字符

${var:5:2} 从下标是5字符开始向后截取2个字符

${para/word/replace} 把word替换为replace,仅替换第一个

${para//word/replace} 把所有word替换为replace

#### 1 统计字符长度

[root@kylin shell]# echo ${#ysl}
8
[root@kylin shell]# echo ${#LANG}
11
[root@kylin shell]# echo ${LANG}
zh_CN.UTF-8
[root@kylin shell]# ysl=”forest”
[root@kylin shell]# echo ${#ysl}
9

统计的时候空格也算一个字符

#### 2 删除变量中的内容(仅影响输出)

[root@kylin shell]# var=”yslforest”
[root@kylin shell]# echo ${var#ysl}
forest
[root@kylin shell]# echo ${var#o}
yslforest
[root@kylin shell]# echo ${var#l}
yslforest
[root@kylin shell]# echo ${var#l}
yslforest
[root@kylin shell]# echo ${var#*l}
dboyforest
[root@kylin shell]# echo ${var#*o}
yslforest
[root@kylin shell]# echo ${var##o}
forest
[root@kylin shell]# echo ${var##*o}

为什么要加*号

[root@kylin shell]# dir=/etc/sysconfig/network-scripts/ifcfg-ens33
[root@kylin shell]# echo ${dir##*/}
ifcfg-ens33
[root@kylin shell]# echo ${dir%/*}
/etc/sysconfig/network-scripts

#### 3 截取(切片)

[root@kylin shell]# var=ysl
[root@kylin shell]# echo ${var}
ysl
[root@kylin shell]# echo ${var:3}
boy
[root@kylin shell]# echo ${var:3:2}
bo
[root@kylin shell]# echo ${var}|cut -c1-3
old

cut也可以取字符串

#### 4 替换

[root@kylin shell]# var=yslforest
[root@kylin shell]# echo ${var/o/-}
-rest
[root@kylin shell]# echo ${var//o/-}
-ldb-ylida-996
[root@kylin shell]#

#### 5 案例 I am ysl teacher welcome to ysl training class

for循环打印上面这句话中字母数不大于6的单词

[root@kylin shell]# cat 09.calc_strings.sh
#!/bin/bash

#1.vars
str=” I am ysl teacher welcome to ysl training class”
num=6

#2.特殊符号替换成空格
str_space=`echo $str | sed ‘s#[,.]# #g’`

#4.for循环
for s in ${str_space}
do
if [ ${#s} -le ${num} ];then
echo “$s单词数小于6”
fi
done
[root@kylin shell]# sh 09.calc_strings.sh
I单词数小于6
am单词数小于6
ysl单词数小于6
to单词数小于6
ysl单词数小于6
class单词数小于6

awk书写

[root@kylin shell]# echo “I am ysl teacher welcome to ysl training class.” | awk -vRS=” ” ‘length()<=6' I am ysl to ysl #### 6 变量子串-小结 掌握计算变量字符串长度,替换 ### 10.8 变量赋值 向变量中写入内容 赋值方式 格式 直接赋值 ysl=forest 命令结果赋值 hostname=`hostname` 脚本传参 read交互方式赋值 通过read命令实现 读取文件内容赋值给变量 循环中使用 read通过交互式方式进行赋值 -p 交互的时候提示信息 -t 超时 -s 不显示用户的输入,记录密码时使用 read -t 40 -s -p "请输入密码:" pass pass是变量 ### 10.9 运算符 | shell运算符 | 含义 | | -------------- | ------------------------------------ | | +-*/ | 加减乘除 | | % | 取余 | | ^或** | 幂、指数 | | i=i+1或i++ | 计数 | | j=j+?? j+=? | 求和,累加 | | && | 前一个命令执行成功,再执行后面的命令 | | \|\| | 前一个命令执行失败,再执行后面的命令 | ### 10.10 对随机数取余 echo $RANDOM%5 | bc ### 10.11 运算方法 | 运算的命令 | 说明 | 应用场景 | | ---------- | ------------------------------------------------- | ------------------------------ | | awk | 可以进行计算,带小数,可以与shell脚本进行变量传递 | 一般计算都可以用awk | | bc | 带小数 | 一般计算都可以使用bc,需要安装 | | expr | 计算,整数 | 判断是否为数字 | | let | 进行计算,整数,变量直接使用即可 | 用于计算i++ | | $(()) | 进行计算,整数,变量直接使用即可 | | | $[] | 进行计算,整数,变量直接使用即可 | | #### 1 awk计算 ```sh root@ubt:~# awk 'BEGIN{print 1/3}' 0.333333 root@ubt:~# awk 'BEGIN{print 1/4*100}' 25 root@ubt:~# awk 'BEGIN{print 1/4*100 + 1/5*100}' 45 root@ubt:~# awk 'BEGIN{print 1/4*100 + 1+5*100}' 526 root@ubt:~# awk 'BEGIN{print 1/4*100 + (1+5)*100}' 625 root@ubt:~# awk -vn1=1 -vn2=3 'BEGIN{print n1/n2}' 0.333333 ``` awk -v选项用于创建或修改awk中的变量,-v是shell脚本与awk桥梁 在awk中各种变量直接使用即可,如果加上$n1,会被awk识别为取列 #### 2 案例13:计算器,传入脚本中2个参数,进行计算,输出结果 ```sh root@ubt:/ysl/shell# sh 13.num_calc_parameter.sh 10 20 10 是数字 20 是数字 10 + 20 结果是 30 10 - 20 结果是 -10 10 * 20 结果是 200 10 / 20 结果是 0.5 root@ubt:/ysl/shell# cat 13.num_calc_parameter.sh #!/bin/bash ############################################################## # File Name: 13.num_calc_parameter.sh # Version: V1.0 # Author: ysl # Organization: www.ysledu.com # Date: 2024-10-16 12:56:11 # Desc: ############################################################## #1、vars num1=$1 num2=$2 #2、判断是否为数字 if echo $num1 | grep -qE '^[0-9]+$';then echo "$num1 是数字" else echo "$num1 不是数字,请输入数字" fi if echo $num2 | grep -qE '^[0-9]+$';then echo "$num2 是数字" else echo "$num2 不是数字,请输入数字" fi #3、计算 jia=`awk -vn1=$num1 -vn2=$num2 BEGIN'{print n1+n2}'` jian=`awk -vn1=$num1 -vn2=$num2 BEGIN'{print n1-n2}'` cheng=`awk -vn1=$num1 -vn2=$num2 BEGIN'{print n1*n2}'` chu=`awk -vn1=$num1 -vn2=$num2 BEGIN'{print n1/n2}'` #4、结果 echo $num1 + $num2 结果是 $jia echo $num1 - $num2 结果是 $jian echo $num1 \* $num2 结果是 $cheng echo $num1 / $num2 结果是 $chu ``` #### 3 案例14:计算器,传入脚本中2个参数,进行计算,输出结果。(read) ```sh root@ubt:/ysl/shell# cat 14.num_calc_parameter.sh #!/bin/bash ############################################################## # File Name: 14.num_calc_parameter.sh # Version: V1.0 # Author: ysl # Organization: www.ysledu.com # Date: 2024-10-16 17:05:20 # Desc: ############################################################## #1/vars read -p "输入两个数字:" num1 num2 #2、判断是否为数字 if echo $num1 | grep -qE ^[0-9]+$;then echo "$num1 是数字" else echo "${num1} 不是数字" fi if echo $num1 | grep -qE ^[0-9]+$;then echo "$num1 是数字" else echo "${num1} 不是数字" fi #3/计算 jia=`awk -vn1=$num1 -vn2=$num2 BEGIN'{print n1+n2}'` jian=`awk -vn1=$num1 -vn2=$num2 BEGIN'{print n1-n2}'` cheng=`awk -vn1=$num1 -vn2=$num2 BEGIN'{print n1*n2}'` chu=`awk -vn1=$num1 -vn2=$num2 BEGIN'{print n1/n2}'` #4/结果 echo "$num1 + $num2 结果是$jia" echo "$num1 - $num2 结果是$jian" echo "$num1 \* $num2 结果是$cheng" echo "$num1 / $num2 结果是$chu" root@ubt:/ysl/shell# sh 14.num_calc_parameter.sh 输入两个数字:10 20 10 是数字 10 是数字 10 + 20 结果是30 10 - 20 结果是-10 10 \* 20 结果是200 10 / 20 结果是0.5 root@ubt:/ysl/shell# ``` #### 4 bc -l 显示小数 ```sh root@ubt:/ysl/shell# echo 1/3 1/3 root@ubt:/ysl/shell# echo 1/3 |bc -l .33333333333333333333 root@ubt:/ysl/shell# echo 1/3 | bc 0 root@ubt:/ysl/shell# echo 2^10 2^10 root@ubt:/ysl/shell# echo 2^10 | bc 1024 root@ubt:/ysl/shell# echo 2^10 | bc -l 1024 root@ubt:/ysl/shell# ``` #### 5 expr 使用注意事项:使用空格,对*号转义 小坑:了解:计算0 + 0 查看命令的返回值。 expr 进行计算的时候结果为0 ,返回值就是1. 可以判断返回值大于1即可.或者等于2也行. ```sh root@ubt:/ysl/shell# expr 1 + 1 2 root@ubt:/ysl/shell# expr 1 * 1 expr: syntax error: unexpected argument ‘01.show-v3.sh’ root@ubt:/ysl/shell# expr 1 \* 1 1 root@ubt:/ysl/shell# expr 1 - 1 0 root@ubt:/ysl/shell# $? 1: command not found root@ubt:/ysl/shell# echo $? 127 root@ubt:/ysl/shell# expr 1 - 1 0 root@ubt:/ysl/shell# echo $? 1 root@ubt:/ysl/shell# ``` #### 6 判断是否为数字 1、正则 if echo $num1 | grep -qE ^[0-9]+$;then echo "$num1 是数字" else echo "${num1} 不是数字" fi 2、expr expr $num1 + $num2 > /dev/null 2>&1

if [ $? -ge 2 ];then

​ echo “Usage $0 num1 num2”

​ exit 1

fi

#### 7 let,$(()),$[]

let

“`sh
root@ubt:/ysl/shell# n1=666
root@ubt:/ysl/shell# n2=999
root@ubt:/ysl/shell# let c=n1+n2
root@ubt:/ysl/shell# echo $c
1665
root@ubt:/ysl/shell# let i++
root@ubt:/ysl/shell#

“`

$(())

“`sh
root@ubt:/ysl/shell# n1=666
root@ubt:/ysl/shell# n2=999
root@ubt:/ysl/shell# echo $((n1+n2))
1665
root@ubt:/ysl/shell# d=$((n1+n2))
root@ubt:/ysl/shell# echo $d
1665
root@ubt:/ysl/shell#

“`

echo $((RANDOM%100)) 生成0-99随机数

$[]

“`sh
root@ubt:/ysl/shell# n1=666
root@ubt:/ysl/shell# n2=999
root@ubt:/ysl/shell# e=$[n1+n2]
root@ubt:/ysl/shell# echo $e
1665
root@ubt:/ysl/shell#

“`

从新写案例01-案例15

根据案例描述(步骤)一步一步写出脚本.

习题: https://www.yuque.com/forest/sre/noqb9gbc71ts5smy

https://www.yuque.com/forest/sre/fh30i4e2qo6l7zsu?singleDoc#

《【Shell阶段】老男孩教育-Shell自动化初级编程-学完shell后》

脚本分析https://www.yuque.com/forest/sre/izry49dqbvomb0iy?singleDo

c# 《老男孩教育-Shell脚本分析案例》

https://www.yuque.com/forest/sre/noqb9gbc71ts5smy)

### 10.12 条件表达式

条件表达式也可以叫条件测试语句

#### 1 案例16-[]和[[]]区别

| 含义与特点 | test或[] | [[]]或(()) |
| ———- | ——————— | ————– |
| 共同点 | 都可以用于判断 | 都可以用于判断 |
| 区别一 | 不支持正则 | 支持正则 |
| 区别二 | 表示与或非-a -o ! -gt | && \|\| ! > |
| 应用场景 | 大部分情况下 | 使用正则时 |

#### 2 条件表达式符号

| 条件表达式符号 | 说明 |
| ————– | ——————– |
| -f | 文件是否存在 |
| -d | 目录是否存在 |
| -x | 是否可执行 |
| -s | 是否大于0 ,非空为真 |
| -r | 是否可读 |
| -w | 是否可写 |
| -nt | 文件修改时间是否更新 |
| -ot | 文件修改时间是否更老 |
| -L或-h | 软连接 |
| -e | 是否存在,任何类型 |

“`sh
root@ubt:/ysl/shell# [ -f /etc/hosts ] && echo “成立 ” || echo “失败”
成立
root@ubt:/ysl/shell# [ -d /etc/ ] && echo “成立 ” || echo “失败”
成立
root@ubt:/ysl/shell# [ -d /etc/hosts ] && echo “成立 ” || echo “失败”
失败
root@ubt:/ysl/shell#

“`

&& 表示前面命令执行成功然后执行echo 成立。

|| 表示前面命令执行失败了,echo 失败

if [ ! -x /sbin/ip ];then

echo “no执行权限”

exit 1

fi

[ -s /etc/hosts ] && echo “成立 ” || echo “失败”

#### 3 案例17-通过脚本传参方式传输一个参数,判断是否为文件,是否为目录,是否具有执行权限

“`sh
root@ubt:/ysl/shell# sh 17.check_file.sh /etc/hosts
17.check_file.sh: 15: [: missing ]
/etc/hosts 是一个文件
/etc/hosts 不是目录
/etc/hosts 没有执行权限
/etc/hosts 不是软连接
root@ubt:/ysl/shell# cat 17.check_file.sh
#!/bin/bash
##############################################################
# File Name: 17.check_file.sh
# Version: V1.0
# Author: ysl
# Organization: www.ysledu.com
# Date: 2024-10-16 18:28:03
# Desc:
##############################################################
#1/vars
file=$1

#2/参数是否是1
if [ $# -eq 0];then
echo “Usage $0 文件名”
exit 1
fi

#3/判断
[ -f $file ] && echo “$file 是一个文件” || echo “$file 不是文件”
[ -d $file ] && echo “$file 是一个目录” || echo “$file 不是目录”
[ -x $file ] && echo “$file 有执行权限” || echo “$file 没有执行权限”
[ -h $file ] && echo “$file 是一个软连接” || echo “$file 不是软连接”

root@ubt:/ysl/shell#

“`

#### 4 字符串对比

用于对比或比较2个字符串内容。

字符串对比的时候加上引号

| 字符串对比 | 说明 |
| —————- | —————— |
| “str1” = “str2” | str1等于str2为真 |
| “str1” != “str2” | str1不等于str2为真 |
| -z “str” | 空为真 |
| -n “str” | 非空为真 |

#### 5 对比两个字符串是否相等

“`sh
root@ubt:/ysl/shell# input=start
root@ubt:/ysl/shell# [ “$input” = “start” ] && echo “成立” || echo “失败”
成立
root@ubt:/ysl/shell# [ “$input” = “start” ] && echo “成立” || echo “失败”
成立
root@ubt:/ysl/shell# str1=forest
root@ubt:/ysl/shell# str2=ysl007
root@ubt:/ysl/shell# [ “str1” = “str2” ] && echo “成立” || echo “失败”
失败
root@ubt:/ysl/shell#

“`

#### 6 在进行字符串比较的时候变量尾巴可以加上个x,防止变量为空,造成匹配/执行失败

“`sh
[root@ysl-devops-shell ~]# [ “${str1}x” = “${str2}x” ] && echo “成立 ” || echo “失败”
失败
[root@ysl-devops-shell ~]# [ “$str1″x = “$str2″x ] && echo “成立 ” || echo “失败”
失败
“`

案例18-检查selinux是否关闭脚本,如果没有关闭,提示是否要关闭,yes则关闭,其他就不关闭

检查selinux是否关闭

检查firewalld是否关闭

“`sh
#1/检查firewalld
active=`systemctl is-active firewalld`
enable=`systemctl is-enabled firewalld`
service=firewalld
if [ “$active” = “active” ];then
echo “$service 已关闭”
else
echo “$service 正在运行中”
fi

if [ “$enable” = “enable” ];then
echo “$service 会开机启动”
else
echo “$service 不会开机启动”
fi

#2/检查selinux
active1=`getenforce`
if [[ $active1 = Disabled ]]; then
echo “selinux 已经关闭”
else
echo “selinux 未关闭” #statements
fi

“`

#### 7 关闭selinux

“`sh
[root@kylin shell]# cat 18.check_stop_selinux.sh
#!/bin/bash
##############################################################
# File Name: 18.check_stop_selinux.sh
# Version: V1.0
# Author: ysl
# Organization: www.ysledu.com
# Date: 2024-10-17 11:16:02
# Desc:
##############################################################
#1/vars
selinux_config=`awk -F= ‘/^SELINUX=/{print $2}’ /etc/selinux/config`
selinux_cmd=`getenforce`

#2/判断是否关闭
if [ “$selinux_config” = “disabled” -a “$selinux_cmd” = “Disabled” ];then
echo “selinux 已经关闭”
else
read -p “是否关闭selinux,请输入yes/no:” xuan
if [ “$xuan” = “yes” ];then
sed -i ‘s/SELINUX=enforcing/SELINUX=disabled/g’ /etc/selinux/config
setenforce 0
else
echo “警告selinux未关闭”
fi
fi
[root@kylin shell]# sh 18.check_stop_selinux.sh
是否关闭selinux,请输入yes/no:yes
setenforce: SELinux is disabled

“`

#### 8 案例19-给使用read指令的脚本增加判断功能,如果变量为空则退出

“`sh
[root@kylin shell]# cat 19.read_shuru.sh
#!/bin/bash
##############################################################
# File Name: 19.read_shuru.sh
# Version: V1.0
# Author: ysl
# Organization: www.ysledu.com
# Date: 2024-10-17 11:30:40
# Desc:
##############################################################
#1/vars
read -p “请输入数字num1 num2:” num1 num2

#2/判断
if [ -z “$num1” ];then
echo “error”
exit 1
fi
if [ -z “$num2” ];then
echo “error”
exit 2
fi
[root@kylin shell]# sh 19.read_shuru.sh
请输入数字num1 num2:
error
[root@kylin shell]# sh 19.read_shuru.sh
请输入数字num1 num2:1 2

“`

#### 9 整数比大小

| 条件表达式-整数相关 | [] | [[]] |
| —————————- | —- | —- |
| 大于 | -gt | > |
| 大于等于 | -ge | >= |
| 小于 | -lt | < | | 小于等于 | -le | <= | | 等于 | -eq | == | | 不等于 | -ne | != | | 不支持小数的对比,仅支持整数 | | | 比较大小[] [ 666 -gt 1 ] && echo "成立 " || echo "失败" 成立 [ 0 -gt -1 ] && echo "成立 " || echo "失败" 成立 [ 0 -gt -1000 ] && echo "成立 " || echo "失败" 成立 [ 0 -gt 0.5 ] && echo "成立 " || echo "失败" -bash: [: 0.5: 期待整数表达式 失败 比较大小[[]] [[ 60 > 6 ]] && echo “成立 ” || echo “失败”

成立

[[ 6 >= 6 ]] && echo “成立 ” || echo “失败”

-bash: 条件表达式中有语法错误

-bash: `6′ 附近有语法错误

不推荐使用,对比的时候会有语法问题。

这里面也可以用-gt -lt ……..

#### 10 逻辑判断

多个条件表示同时成立,表示或者,表示取反

与或非

| 条件表达式-逻辑判断 | [] | [[]] |
| ——————- | —- | —- |
| 与 | -a | && |
| 或 | -o | \|\| |
| 非 | ! | ! |

同时成立

前面失败则运行下一个命令

#### 11 使用正则判断

“`sh
[root@kylin shell]# num=666
[root@kylin shell]# [[ $num =~ [0-9]+ ]] && echo 成立 || echo 不成立
成立
[root@kylin shell]# num=forest
[root@kylin shell]# [[ $num =~ [0-9]+ ]] && echo 成立 || echo 不成立
成立
使用正则精确匹配
[root@kylin shell]# [[ $num =~ ^[0-9]+$ ]] && echo 成立 || echo 不成立
不成立
[root@kylin shell]#

“`

#### 12 案例21-书写一个脚本通过read读取输入,判断输入时整数,浮点还是字符

整数正则: ^-?[0-9]+$

浮点数: ^-?[0-9]+.[0-9]+$ 1.0 2.0 3.0 4.5

字符串: ^[a-zA-Z0-9]+$ forest 996ysl li007dao

“`sh
[root@kylin shell]# sh 21.check_type.sh
请输入内容:888
888 是整数
[root@kylin shell]# sh 21.check_type.sh
请输入内容:1.2
1.2 是小数
[root@kylin shell]# sh 21.check_type.sh
请输入内容:00y
00y 是字符串
[root@kylin shell]# cat 21.check_type.sh
#!/bin/bash
##############################################################
# File Name: 21.check_type.sh
# Version: V1.0
# Author: ysl
# Organization: www.ysledu.com
# Date: 2024-10-17 12:20:34
# Desc:
##############################################################
#1/vars
read -p ‘请输入内容:’ str

#2、检查str是否为空
if [ -z $str ];then
echo “请输入内容”
exit 5
fi

if [[ “$str” =~ ^-?[0-9]+$ ]];then
echo “$str 是整数”
exit 1
fi

if [[ “$str” =~ ^-?[0-9]+\.[0-9]+$ ]];then
echo “$str 是小数”
exit 2
fi

if [[ “$str” =~ ^[a-zA-Z0-9]+$ ]];then
echo “$str 是字符串”
exit 3
fi

[root@kylin shell]#

“`

#### 13 条件表达式小结

| 条件表达式分类 | 必会 | 熟悉 |
| ————– | ———————– | ——————- |
| 文件 | -f -d -x -s | -r -w -nt -ot -L… |
| 字符串比较 | = != == | -n -z |
| 比较大小 | -eq -ne -gt -ge -lt -le | |
| 逻辑 | -a -o ! | |
| 正正则 | | |

if

#### 14 单分支判断

if 条件;then

​ 满足条件后执行的内容

fi

“`sh
[ $# -eq 2 ] || {
echo “必须要2个数字”
exit 1
}
if [ $# -ne 2 ];then
echo “脚本必须要2个参数”
exit 1
fi
“`

#### 15 双分支判断

“`sh
if 条件;then
满足条件后执行的内容。
else
不满足条件执行的内容。
fi

if 丁同学条件;then
迎娶白富美,富婆.
else
是个女的就行.
fi
“`

#### 16 案例22-书写服务检查脚本,执行的时候输入服务名字检查是否运行,检查是否开机自启

“`sh
[root@kylin shell]# sh 22.check_service.sh sshd
sshd 已开机启动
sshd 未启动
[root@kylin shell]# systemctl is-active sshd
active
[root@kylin shell]# vim 22.check_service.sh
[root@kylin shell]# sh 22.check_service.sh sshd
sshd 已开机启动
sshd 正在运行中
[root@kylin shell]# sh 22.check_service.sh firewalld
firewalld 未开机启动
firewalld 未启动
[root@kylin shell]# cat 22.check_service.sh
#!/bin/bash
##############################################################
# File Name: 22.check_service.sh
# Version: V1.0
# Author: ysl
# Organization: www.ysledu.com
# Date: 2024-10-17 12:58:29
# Desc:
##############################################################
#1.vars
service_names=$1

#2.检查是否为空
if [ -z $service_names ];then
echo “Usage $0 服务名”
exit 1
fi

#3.检查服务是否存在
ser_cnt=`systemctl list-unit-files | grep $service_names | wc -l`
if [ $ser_cnt -eq 0 ];then
echo “$service_names 服务不存在,请安装服务”
exit 2
fi

#4.检查服务是否开机启动
kjqd=`systemctl is-enabled $service_names`
if [ “$kjqd” = “enabled” ];then
echo “$service_names 已开机启动”
else
echo “$service_names 未开机启动”
fi

#5.检查是否启动
qd=`systemctl is-active $service_names`
if [ “$qd” = “active” ];then
echo “$service_names 正在运行中”
else
echo “$service_names 未启动”
fi

“`

#### 17 多分支判断

“`sh
#第1次判断
if 条件;then
满足条件后执行的内容。
#第2次判断
elif 条件;then #else if
满足elif条件,执行的内容。
#第3次判断 还可以继续增加.
elif 条件;then
满足elif条件,执行的内容。
else
不满足条件执行的内容。
fi
“`

#### 18 案例23-书写多分支格式比较大小的脚本

“`sh
[root@kylin shell]# sh 23.compare_num.sh 1 2
1 小于 2
[root@kylin shell]# sh 23.compare_num.sh 2 1
2 大于 1
[root@kylin shell]# sh 23.compare_num.sh 1 1
1 等于1
[root@kylin shell]# cat 23.compare_num.sh
#!/bin/bash
##############################################################
# File Name: 23.compare_num.sh
# Version: V1.0
# Author: ysl
# Organization: www.ysledu.com
# Date: 2024-10-17 16:43:16
# Desc:
##############################################################
#1.vars
num1=$1
num2=$2

#2.判断参数是否为2
if [ $# -ne 2 ];then
echo “Usage:$0 数字1 数字2”
exit 1
fi

#3.判断是否为数字
if [[ ! $num1 =~ ^-?[0-9]+$ ]];then
echo “请输入数字”
exit 2
fi

if [[ ! $num2 =~ ^-?[0-9]+$ ]];then
echo “请输入数字”
exit 2
fi

#4.判断大小
if [ $num1 -gt $num2 ];then
echo “$num1 大于 $num2”
elif [ $num1 -lt $num2 ];then
echo “$num1 小于 $num2”
else
echo “$num1 等于$num2”

fi

“`

#### 19 案例24-检查磁盘分区的情况

“`sh
[root@kylin shell]# sh 24.check_dis.sh | column -t -s ,
磁盘名字:/ 磁盘大小:145G 磁盘使用率:4 级别:正常
磁盘名字:/backup 磁盘大小:50G 磁盘使用率:1 级别:正常
磁盘名字:/boot 磁盘大小:1014M 磁盘使用率:17 级别:正常
[root@kylin shell]# cat 24.check_dis.sh
#!/bin/bash
##############################################################
# File Name: 24.check_dis.sh
# Version: V1.0
# Author: ysl
# Organization: www.ysledu.com
# Date: 2024-10-17 21:46:44
# Desc:
##############################################################
#1.vars
part_names=`df -h | grep -v tmpfs | awk ‘NR>=2{print $NF}’`
part_count=`df -h | grep -v tmpfs | awk ‘NR>=2{print $NF}’|wc -l`

#2.for
for name in $part_names
do
part_size=`df -h $name | awk ‘NR==2{print $2}’`
part_percent=`df -h $name | awk -F “[ %]+” ‘NR==2{print $(NF-1)}’`
if [ $part_percent -ge 95 ];then
waring=灾难
elif [ $part_percent -ge 90 ];then
waring=相当严重
elif [ $part_percent -ge 80 ];then
waring=严重
elif [ $part_percent -ge 70 ];then
waring=警告
else
waring=正常
fi
echo “磁盘名字:$name,磁盘大小:$part_size,磁盘使用率:$part_percent,级别:$waring”
done

[root@kylin shell]#

“`

条件表达式: -f -d -x -h, = != -z -n, -gt -ge -lt -le -eq -ne, -a -o ! ,[[ =~ ]]

if: 单分支,双分支,多分支.

#### 20 case语句

##### 1 概述

相当于是if中的字符串对比判断. (= !=) .比大小,文件,目录判断,正则只能使用if

类似于条件分支语句,case一般用于实现有多种选择的脚本(菜单选择)

这个功能:if或多分支if实现,如果使用case语句会更加清晰直观

菜单。

start|stop|restart|status

手写堡垒机.

环境部署脚本

case语句vs if多分支

case 一般用于固定的菜单选择情况.运行脚本用户输入1,2,3,4.

start|stop|restart….

if 可以用于一些范围的比较

##### 2 格式与实践

case “变量” in

​ 1)

​ 命令

​ ;;

​ 2)

​ 命令

​ ;;

​ *)

​ 命令(保底的默认输出)

esac

##### 3 案例25-某会所菜单展示程序

“`sh
oldli会所的菜单功能(套餐)
– 输出可选的套餐
– 1 138套餐) 吃饱套餐
– 2 443套餐) 吃饱喝足套餐
– 3 888套餐) 吃喝拉撒套餐
– 4 1688套餐) 你想干啥就干啥套餐
– 5 8080套餐) 隐藏不便显示 隐藏
– 6 8443套餐) 隐藏老板娘套餐 隐藏
– 其他) 劝退套餐
cat<步骤–>函数–>命令。

把常用的判断,内容写成函数,创建个人函数库.(哪些功能通用的.)

函数传参:$* $@ $n $0

##### 6 个人函数库建立

“`sh
Linux命令行给字体加颜色命令为:
echo -e “\E[1;31m红色字ysl\E[0m”
红色字ysl
echo -e “\033[31m红色字ysl \033[0m”
\E 或\033 表示要开启这种功能。
[1;31m
[字体效果;颜色m
\E[0m 颜色设置结束

红色字ysl

在上述命令中:

echo -e可以识别转义字符,这里将识别特殊字

符的含义,并输出。 \n \t

Linux下面回车是 \n

Windows下面回车是 \r\n
各种颜色的字-效果
1表示加粗,2正常的,5表示闪烁

echo -e “\E[1;31m红色字ysl\E[0m”
echo -e “\E[2;31m红色字ysl\E[0m”
echo -e “\E[3;31m红色字ysl\E[0m”
echo -e “\E[4;31m红色字ysl\E[0m”
echo -e “\E[5;31m红色字ysl\E[0m”
echo -e “\E[6;31m红色字ysl\E[0m”
echo -e “\E[7;31m红色字ysl\E[0m”
echo -e “\E[8;31m红色字ysl\E[0m”

for n in {30..50}; do echo -e “\E[1;${n}m${n}ysl\E[0m”;done
“`

##### 7 案例31-用户自定义的函数库文件,自定义颜色

创建3个函数

redecho 内容 输出显示为红色闪烁

greenecho 内容 输出绿色加粗

yellowecho 内容 输出黄色加粗

redecho 内容

“`sh
#1.红色函数
function redecho() {
str=”$@”
echo -e “\E[5;31m${str}\E[0m”
}
#2.绿色函数
function greenecho() {
str=”$@”
echo -e “\E[1;32m${str}\E[0m”
}
#3.黄色函数
function yellowecho() {
str=”$@”
echo -e “\E[1;33m${str}\E[0m”
}
#4.蓝色函数
function blueecho() {
str=”$@”
echo -e “\E[1;34m${str}\E[0m”
}
“`

#### 22 核心命令

##### 1 命令概述

| 脚本常用监控命令 | 说明 | |
| —————- | ———————————— | ———————————————————— |
| 端口 | 一般用于检查端口是否存在,是否能连接 | 是否存在:ss/netstat -tunlp\|grep 端口,是否能访问:telnet , nc , nmap |
| 进程 | 检查进程状态,指标 | ps/top/iotop |
| 网络 | 检查连通性 | ping,iftop,dig |
| web | http请求 | curl/wget |
| 系统全能 | atop(all) | |

##### 2 是否存在

ss -tunlp | grep 80

netstat -tunlp | grep 80

lsof -i:80

##### 3 能否远程访问

telnet

nc -z -w 0.5

nmap -p端口过滤open即可

“`sh
telnet
-e指定逃脱字符,遇到这个字符相当于按ctrl+c.
[root@kylin shell]# echo q | telnet -eq 127.0.0.1 22
Telnet escape character is ‘q’.
Trying 127.0.0.1…
Connected to 127.0.0.1.
Escape character is ‘q’.

telnet> Connection closed.
[root@kylin shell]# echo $?
0
[root@kylin shell]#

nc(ncat netcat)
-z 无io模式,用于检查端口是否连通。 非交互模式.
-w 指定超时时间.
[root@kylin shell]# echo $?
0
[root@kylin shell]# nc -z -w 1 127.0.0.1 22
[root@kylin shell]# echo $?
0
[root@kylin shell]# nc -z -w 1 127.0.0.1 80
[root@kylin shell]# echo $?
1
[root@kylin shell]#

“`

##### 4 案例33-检查指定的地址的端口是否可以访问

“`sh
[root@kylin shell]# sh 33.check_port.sh 127.0.0.1 80
33.check_port.sh: 第 59 行:[: 缺少 `]’
不能访问
[root@kylin shell]# vim 33.check_port.sh
[root@kylin shell]# sh 33.check_port.sh 127.0.0.1 80
33.check_port.sh: 第 57 行:[: 缺少 `]’
不能访问
[root@kylin shell]# vim 33.check_port.sh
[root@kylin shell]# sh 33.check_port.sh 127.0.0.1 80
不能访问
[root@kylin shell]# sh 33.check_port.sh 127.0.0.1 22
可以访问
[root@kylin shell]# cat 33.check_port.sh
#!/bin/bash
##############################################################
# File Name: 33.check_port.sh
# Version: V1.0
# Author: ysl
# Organization: www.ysledu.com
# Date: 2024-10-19 10:32:05
# Desc:
##############################################################

#1.红色函数
function redecho() {
str=”$@”
echo -e “\E[5;31m${str}\E[0m”
}
#2.红色函数
function greenecho() {
str=”$@”
echo -e “\E[1;32m${str}\E[0m”
}

#2.vars
ip=$1
port=$2

#3判断参数个数
if [ ! $# -eq 2 ];then
greenecho “Usage:$0 IP或域名+端口”
exit 1
fi

#4.判断端口是否为数字
if [[ ! $port =~ ^[0-9]+$ ]];then
redecho “端口为数字”
exit 2
fi

#5.判断IP或域名是否通
ping -c3 -w3 $ip > /dev/null 2>&1
if [ $? -ne 0 ];then
redecho “无法访问$ip”
exit 3
fi

#6.检查是否有telnet命令
telnet_cmd=`which telnet | wc -l`
if [ $telnet_cmd -eq 0 ];then
redecho “没有telnet命令,请安装”
fi

#3.检查
function check() {
echo q | telnet -eq $ip $port >/dev/null 2>&1
if [ $? = 0 ] ;then
greenecho “可以访问”
else
redecho “不能访问”
fi
}

check

“`

##### 5 web与api测试命令

curl/wget

curl: -v -L跟随跳转 -H 修改请求头 -I 只显示响应头 -w 按照指定格式输出 –

o 输出指定到文件或空. -s一般使用管道需要加上

“`sh
#01 curl 获取状态码
#-s slient 安静模式 如果不使用默认输出下载进度
#-o curl的输出到指定位置的文件
#-w 按照指定格式与内容输出 %{http_code}状态码 更多格式 man curl 搜
索 variable

[root@kylin shell]# curl -L -s -I baidu.com |awk ‘NR==1{print $2}’
[root@kylin shell]# curl -L -s -I baidu.com
HTTP/1.1 200 OK
Date: Sat, 19 Oct 2024 02:39:49 GMT
Server: Apache
Last-Modified: Tue, 12 Jan 2010 13:48:00 GMT
ETag: “51-47cf7e6ee8400″
Accept-Ranges: bytes
Content-Length: 81
Cache-Control: max-age=86400
Expires: Sun, 20 Oct 2024 02:39:49 GMT
Connection: Keep-Alive
Content-Type: text/html

[root@kylin shell]# curl -L -s -w ‘%{http_code}\n’ -o /dev/null jd.com
200

“`

wget:

-t 失败后,重复尝试次数、

-T timeout 超时时间

-q quiet 不显示wget输出

–spider 不下载文件,仅访问

“`sh
[root@kylin shell]# wget -t 3 -T 1 -q –spider www.baidu.com
[root@kylin shell]# echo $?
0
[root@kylin shell]#
“`

##### 6 案例34-检查指定网站/api是否可以访问

“`sh
[root@kylin shell]# sh 34.check_url.sh www.baidu.com
网站www.baidu.com 可以访问
[root@kylin shell]# sh 34.check_url.sh 127.0.0.1:22
网站127.0.0.1:22 可以访问
[root@kylin shell]# sh 34.check_url.sh 127.0.0.1:80
网站127.0.0.1:80 不可以访问
[root@kylin shell]# cat 34.check_url.sh
#!/bin/bash
##############################################################
# File Name: 34.check_url.sh
# Version: V1.0
# Author: ysl
# Organization: www.ysledu.com
# Date: 2024-10-19 11:42:17
# Desc:
##############################################################

#颜色函数
#1.红色函数
function redecho() {
str=”$@”
echo -e “\E[1;31m${str}\E[0m”
}
#2.绿色函数
function greenecho() {
str=”$@”
echo -e “\E[1;32m${str}\E[0m”
}

#1.vars
curl_dizhi=$@

#2.for
function check_curl() {
for dizhi in $curl_dizhi
do
wget -p –spider $dizhi > /dev/null 2>&1
if [ $? -eq 0 ];then
greenecho “网站$dizhi 可以访问”
else
redecho “网站$dizhi 不可以访问”
exit 2
fi
done
}

#3.检查是否为空
function check_vars() {
if [ -z $curl_dizhi ];then
redecho “请输入地址”
exit 1
fi
}

main() {
check_vars
check_curl
}

main

“`

##### 7 案例35-检查域名是否过期

##### 8 案例36-:

“`sh
使用for循环在/ysl目录下通过随机小写10个字母加固定字
符串ysl批量创建10个html文件,名称例
如为:
[root@oldgirl C19]# ls /ysl
apquvdpqbk_ysl.html
mpyogpsmwj_ysl.html
txynzwofgg_ysl.html
bmqiwhfpgv_ysl.html
mtrzobsprf_ysl.html
vjxmlflawa_ysl.html
jhjdcjnjxc_ysl.html
qeztkkmewn_ysl.html
jpvirsnjld_ysl.html
ruscyxwxai_ysl.html
“`

##### 9 生成随机数字

mkpasswd -l -10 -s 0

-l 随机字符长度

-s 特殊字符个数

“`sh
[root@kylin shell]# mkpasswd -l -10 -s 0
-bash: mkpasswd:未找到命令
[root@kylin shell]#
[root@kylin shell]# yum install -y mkpasswd
上次元数据过期检查:1:33:30 前,执行于 2024年10月19日 星期六 10时17分46秒。
未找到匹配的参数: mkpasswd
错误:没有任何匹配: mkpasswd
[root@kylin shell]# yum provides mkpasswd
上次元数据过期检查:1:33:40 前,执行于 2024年10月19日 星期六 10时17分46秒。
expect-1:5.45.4-5.ky10.x86_64 : A tool for automating interactive applications
仓库 :ks10-adv-os
匹配来源:
文件名 :/usr/bin/mkpasswd

[root@kylin shell]# yum install -y expect-1:5.45.4-5.ky10.x86_64
上次元数据过期检查:1:34:02 前,执行于 2024年10月19日 星期六 10时17分46秒。
依赖关系解决。
=============================================================================================
Package Architecture Version Repository Size
=============================================================================================
安装:
expect x86_64 1:5.45.4-5.ky10 ks10-adv-os 237 k

事务概要
=============================================================================================
安装 1 软件包

总下载:237 k
安装大小:647 k
下载软件包:
expect-5.45.4-5.ky10.x86_64.rpm 404 kB/s | 237 kB 00:00
———————————————————————————————
总计 402 kB/s | 237 kB 00:00
运行事务检查
事务检查成功。
运行事务测试
事务测试成功。
运行事务
准备中 : 1/1
安装 : expect-1:5.45.4-5.ky10.x86_64 1/1
运行脚本: expect-1:5.45.4-5.ky10.x86_64 1/1
验证 : expect-1:5.45.4-5.ky10.x86_64 1/1

已安装:
expect-1:5.45.4-5.ky10.x86_64

完毕!
[root@kylin shell]# mkpasswd -l -10 -s 0
impossible to generate -10-character password with 2 numbers, 2 lowercase letters, 2 uppercase letters and 0 special characters.
[root@kylin shell]# mkpasswd -l 10
L?yi6qxCi4
[root@kylin shell]# mkpasswd -l 10 -s 0
nSrw8npuF3

“`

tr -cd ‘a-zA-Z0-9’ < /dev/urandom | head -c10 head -c10 取第一行的前10个字符 ```sh [root@kylin shell]# tr -cd 'a-zA-Z0-9' < /dev/urandom | head -c10 KZ9jEIPbB9 [root@kylin shell]# [root@kylin shell]# ``` ```sh 2. debian/ubunt : 软件包叫:libstring-mkpasswd-perl mkpasswd.pl 红帽系列 软件包叫:expect mkpasswd -l 10 -d 0 -s 0 -C 0 -l 密码长度 -d 数字数量 -s special 特殊字符 -C 大写字母 -c 小写字母 3. tr tr -cd 'a-z'

系统服务

## 1 备份服务

备份服务概述

目标:主要解决数据不丢,辅助实现高可用;

备份服务:存放已有的备份的,一般与定时任务,脚本搭配使用.

备份服务:rsyncd服务,不同主机之间数据传输.

备份服务器配置:硬盘空间大.

rsyncd特点:

rsync是个服务也是命令(客户端)

使用方便,具有多种模式.

传输数据的时候是增量传输,第1次传输还是全量

全量: 无论多少数据全部推送走(scp)

增量: 只会把修改,新建了的文件传输走(rsync)

Linux下面/etc与/etc/一般来说是没有区别的.

但是在rsync命令中是有区别的

/etc 传输目录下面的内容,包含目录本身.

/etc/ 传输目录下面的内容,不包含目录本身

### 1.1 rsync 企业应用场景

| 应用场景(业务场景) | 应用建议 |
| —————————————— | ———————————————————— |
| rsync 作为命令使用 | 临时拉取,推送数据,跟scp一样,但是rsync只复制增量 |
| 定时备份:rsync服务+定时任务 | 定时备份,定期备份案例(定时任务进行备份+通过rsync传输备份) |
| 实时同步:rsync服务+sersync/lsyncd实现同步 | 解决存储服务单点问题 |
| rsync服务与异地容灾 | 找一个异地的服务器存放备份 |

在rsync对于目录 /etc/ /etc 是有区别的.

/etc /etc目录+目录的内容

/etc/ /etc/目录下面的内容

### 2 本地模式

将本地一个目录或文件复制到另一个目录或文件

### 3 远程模式

上传

下载

第一次是全量,以后都是增量,新增文件,文件内容修改都是增量

### 4 守护进程模式

环境准备:rsyncd sshd daemon

服务使用流程

1、部署

2、配置

3、启动,使用

4、优化

5、故障

6、自动化(备份、监控、日志、安全、自动部署、容器)

| rsync服务端 | rsync客户端 |
| ———————————————————- | —————————————— |
| 部署 | 部署 |
| 修改配置文件/etc/rsyncd.conf | 测试(传输数据) |
| 准备环境(用户,目录,目录权限,服务端密码文件,共享目录) | 创建客户端密码文件并修改权限(仅存放密码) |
| 启动与检查(端口,进程),测试(传输) | 书写脚本(进行备份+传输备份)+定时任务 |

1、检查是否安装

yum install -y rsync
rpm -ql | grep rsync

2、进行配置

“`sh
[root@backup /etc]# cat /etc/rsyncd.conf
fake super = yes #如果不开启,则C7传输报错(伪装成root权限)
uid = rsync
gid = rsync
use chroot = no
max connections = 2000
timeout = 600
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
log file = /var/log/rsyncd.log
ignore errors
read only = false
list = false
#hosts allow = 10.0.0.0/24
##hosts deny = 0.0.0.0/32
auth users = rsync_backup
secrets file = /etc/rsync.password
######################################
[data]
comment = www by yangsenlin 14:18 2012-1-13
path = /data

“`

3、后续配置

“`sh
#1.添加虚拟用户
useradd -s /sbin/nologin -M rsync
#2.创建密码文件
密码文件格式: 用户名:密码
echo ‘rsync_backup:123’ >/etc/rsync.password
chmod 600 /etc/rsync.password
此处如果不是600端口会报错
#3.共享目录与权限
mkdir /data/
chown rsync.rsync /data/
“`

4、启动服务

“`sh
#启动服务
systemctl enable rsyncd
systemctl start rsyncd
#检查进程
ps -ef |grep rsync
#检查端口
ss -lntup |grep rsync

rsync使用tcp873端口
“`

![image-20250103125445417](D:\Program Files (x86)\Typora\os-services\image-20250103125445417.png)

![image-20250103125504959](D:\Program Files (x86)\Typora\os-services\image-20250103125504959.png)

5测试1

传输本地文件到data

“`sh
rsync -azv /etc/hostname rsync_backup@192.168.137.41::data
“`

测试2

客户端传输文件到服务端

“`sh
客户端只需要有rsync命令就行
[root@nfs01 /tmp/etc]# rsync -avz /etc/hosts rsync_backup@192.168.137.41::data
Password:
sending incremental file list
hosts

sent 210 bytes received 43 bytes 46.00 bytes/sec
total size is 311 speedup is 1.23

服务端查看
[root@backup /data]# ll
total 8
-rw-r–r– 1 rsync rsync 7 Oct 20 11:39 hostname
-rw-r–r– 1 rsync rsync 311 Oct 13 11:31 hosts
[root@backup /data]#

“`

测试3

客户端免密码传输数据到服务端

“`sh
客户端创建密码文件,并将权限改为600,不然会报错
[root@nfs01 /tmp/etc]# echo ‘XZnh@95599′ >> /etc/rsync.client.mima
[root@nfs01 /tmp/etc]# chmod 600 /etc/rsync.client.mima
[root@nfs01 /tmp/etc]# tar zcf /tmp/etc.tar.gz /etc/
tar: Removing leading `/’ from member names
[root@nfs01 /tmp/etc]# rsync -az /tmp/etc.tar.gz rsync_backup@backup::data –pa
–partial –partial-dir= –password-file=
[root@nfs01 /tmp/etc]# rsync -az /tmp/etc.tar.gz rsync_backup@backup::data –password-file=/etc/rsync.client.mima
[root@nfs01 /tmp/etc]#

服务端
[root@backup /data]# ll
total 5344
-rw-r–r– 1 rsync rsync 5461051 Oct 24 17:14 etc.tar.gz
-rw-r–r– 1 rsync rsync 7 Oct 20 11:39 hostname
-rw-r–r– 1 rsync rsync 311 Oct 13 11:31 hosts
[root@backup /data]#

“`

### 5 rsync选项

| rsync选项 | 含义 |
| ——— | ———————————————————— |
| -a | 所有属性 |
| -v | 显示过程 |
| -z | 传输的时候进行压缩,与限速选项冲突 |
| -P | 显示每rsync -av . root@10.0.0.31:/tmp/ –exclude=04 rsync -av . root@10.0.0.31:/mnt –exclude={04,05}个文件传输过程 (进度条) 断点续传 –partial –progress |
| –bwlimit | 限速,限速,注意不要与-z -P一起使用. iftop查看速度情况iftop -i ens34 -nNP -B |
| –exclude | 排除 |
| –delete | 保持客户端与服务端数据一致,删除服务端多余的数据.(高度保持2者一致,用于实时同步场景,其他场景慎用.) |

#### 5.1 限速并传输

“`sh
[root@nfs01 /tmp/etc]# dd if=/dev/zero of=/2g bs=2M count=1000
1000+0 records in
1000+0 records out
2097152000 bytes (2.1 GB, 2.0 GiB) copied, 4.94094 s, 424 MB/s

[root@nfs01 /tmp/etc]# rsync -aP –bwlimit=500k /2g rsync_backup@192.168.137.41::data –password-file=/etc/rsync.client.mima
sending incremental file list
2g
38,305,792 1% 500.12kB/s 1:08:36

root@nfs01 ~]# iftop -i ens33 -nNP -B
interface: ens33
IP address is: 192.168.137.31
MAC address is: 00:50:56:3c:c1:43

“`

#### 5.2 传输并排除

“`sh
客户端
[root@nfs01 ~]# mkdir yangsenlin
[root@nfs01 ~]# cd yangsenlin/
[root@nfs01 ~/yangsenlin]# ll
total 0
[root@nfs01 ~/yangsenlin]# touch {01..10}.txt
[root@nfs01 ~/yangsenlin]# ll
total 0
-rw-r–r– 1 root root 0 Oct 25 12:44 01.txt
-rw-r–r– 1 root root 0 Oct 25 12:44 02.txt
-rw-r–r– 1 root root 0 Oct 25 12:44 03.txt
-rw-r–r– 1 root root 0 Oct 25 12:44 04.txt
-rw-r–r– 1 root root 0 Oct 25 12:44 05.txt
-rw-r–r– 1 root root 0 Oct 25 12:44 06.txt
-rw-r–r– 1 root root 0 Oct 25 12:44 07.txt
-rw-r–r– 1 root root 0 Oct 25 12:44 08.txt
-rw-r–r– 1 root root 0 Oct 25 12:44 09.txt
-rw-r–r– 1 root root 0 Oct 25 12:44 10.txt

[root@nfs01 ~/yangsenlin]# rsync -a –bwlimit=500k ./* rsync_backup@192.168.137.41::data –password-file=/etc/rsync.client.mima –exclude=04.txt
[root@nfs01 ~/yangsenlin]#

服务端
[root@backup /data]# ll
total 0
-rw-r–r– 1 rsync rsync 0 Oct 25 12:44 01.txt
-rw-r–r– 1 rsync rsync 0 Oct 25 12:44 02.txt
-rw-r–r– 1 rsync rsync 0 Oct 25 12:44 03.txt
-rw-r–r– 1 rsync rsync 0 Oct 25 12:44 05.txt
-rw-r–r– 1 rsync rsync 0 Oct 25 12:44 06.txt
-rw-r–r– 1 rsync rsync 0 Oct 25 12:44 07.txt
-rw-r–r– 1 rsync rsync 0 Oct 25 12:44 08.txt
-rw-r–r– 1 rsync rsync 0 Oct 25 12:44 09.txt
-rw-r–r– 1 rsync rsync 0 Oct 25 12:44 10.txt

“`

#### 5.3 通过文件内容进行排除

“`sh
通过文件内容进行排除
[root@backup /yangsenlin]# cat /tmp/paichu.txt
03
05
10
[root@backup /yangsenlin]# rsync -av . root@10.0.0.31:~ –exclude-from=/tmp/paichu.txt

客户端
[root@nfs01 ~/yangsenlin]# touch {01..10}
[root@nfs01 ~/yangsenlin]# ll
total 0
-rw-r–r– 1 root root 0 Oct 25 15:57 01
-rw-r–r– 1 root root 0 Oct 25 12:44 01.txt
-rw-r–r– 1 root root 0 Oct 25 15:57 02
-rw-r–r– 1 root root 0 Oct 25 12:44 02.txt
-rw-r–r– 1 root root 0 Oct 25 15:57 03
-rw-r–r– 1 root root 0 Oct 25 12:44 03.txt
-rw-r–r– 1 root root 0 Oct 25 15:57 04
-rw-r–r– 1 root root 0 Oct 25 12:44 04.txt
-rw-r–r– 1 root root 0 Oct 25 15:57 05
-rw-r–r– 1 root root 0 Oct 25 12:44 05.txt
-rw-r–r– 1 root root 0 Oct 25 15:57 06
-rw-r–r– 1 root root 0 Oct 25 12:44 06.txt
-rw-r–r– 1 root root 0 Oct 25 15:57 07
-rw-r–r– 1 root root 0 Oct 25 12:44 07.txt
-rw-r–r– 1 root root 0 Oct 25 15:57 08
-rw-r–r– 1 root root 0 Oct 25 12:44 08.txt
-rw-r–r– 1 root root 0 Oct 25 15:57 09
-rw-r–r– 1 root root 0 Oct 25 12:44 09.txt
-rw-r–r– 1 root root 0 Oct 25 15:57 10
-rw-r–r– 1 root root 0 Oct 25 12:44 10.txt

[root@nfs01 ~/yangsenlin]# rsync -av * rsync_backup@backup::data –exclude-from=/tmp/paichu.txt –password-file=/etc/rsync.client.mima
sending incremental file list
01
01.txt
02
02.txt
03.txt
04
04.txt
05.txt
06
06.txt
07
07.txt
08
08.txt
09
09.txt
10.txt

sent 998 bytes received 347 bytes 2,690.00 bytes/sec
total size is 0 speedup is 0.00

服务端
[root@backup /data]# ll
total 0
-rw-r–r– 1 rsync rsync 0 Oct 25 15:57 01
-rw-r–r– 1 rsync rsync 0 Oct 25 12:44 01.txt
-rw-r–r– 1 rsync rsync 0 Oct 25 15:57 02
-rw-r–r– 1 rsync rsync 0 Oct 25 12:44 02.txt
-rw-r–r– 1 rsync rsync 0 Oct 25 12:44 03.txt
-rw-r–r– 1 rsync rsync 0 Oct 25 15:57 04
-rw-r–r– 1 rsync rsync 0 Oct 25 12:44 04.txt
-rw-r–r– 1 rsync rsync 0 Oct 25 12:44 05.txt
-rw-r–r– 1 rsync rsync 0 Oct 25 15:57 06
-rw-r–r– 1 rsync rsync 0 Oct 25 12:44 06.txt
-rw-r–r– 1 rsync rsync 0 Oct 25 15:57 07
-rw-r–r– 1 rsync rsync 0 Oct 25 12:44 07.txt
-rw-r–r– 1 rsync rsync 0 Oct 25 15:57 08
-rw-r–r– 1 rsync rsync 0 Oct 25 12:44 08.txt
-rw-r–r– 1 rsync rsync 0 Oct 25 15:57 09
-rw-r–r– 1 rsync rsync 0 Oct 25 12:44 09.txt
-rw-r–r– 1 rsync rsync 0 Oct 25 12:44 10.txt
[root@backup /data]#

“`

#### 5.4 保持源与目标数据一致

“`sh
[root@nfs01 ~/yangsenlin]# rsync -avP –delete rsync_backup@backup::data –exclude-from=/tmp/paichu.txt –password-file=/etc/rsync.client.mima
receiving incremental file list
drwxr-xr-x 216 2024/10/25 15:58:55 .
-rw-r–r– 0 2024/10/25 15:57:27 01
-rw-r–r– 0 2024/10/25 12:44:51 01.txt
-rw-r–r– 0 2024/10/25 15:57:27 02
-rw-r–r– 0 2024/10/25 12:44:51 02.txt
-rw-r–r– 0 2024/10/25 12:44:51 03.txt
-rw-r–r– 0 2024/10/25 15:57:27 04
-rw-r–r– 0 2024/10/25 12:44:51 04.txt
-rw-r–r– 0 2024/10/25 12:44:51 05.txt
-rw-r–r– 0 2024/10/25 15:57:27 06
-rw-r–r– 0 2024/10/25 12:44:51 06.txt
-rw-r–r– 0 2024/10/25 15:57:27 07
-rw-r–r– 0 2024/10/25 12:44:51 07.txt
-rw-r–r– 0 2024/10/25 15:57:27 08
-rw-r–r– 0 2024/10/25 12:44:51 08.txt
-rw-r–r– 0 2024/10/25 15:57:27 09
-rw-r–r– 0 2024/10/25 12:44:51 09.txt
-rw-r–r– 0 2024/10/25 12:44:51 10.txt

sent 48 bytes received 368 bytes 832.00 bytes/sec
total size is 0 speedup is 0.00
[root@nfs01 ~/yangsenlin]#

“`

## 2 存储服务

存储: 用于存放用户上传的内容(数据),一般应用在网站集群中.

为何用?

如果不使用存储,用户上传的数据就直接存放在网站服务器上了,用户下次访问就可能找不到,因为下次访问到的网站服务器可能不是上一次访问到的服务器.

如果使用存储,用户上传的内容存放在存储上面,用户访问就会访问存储.

位置: 网站后排

![image-20250103125859539](D:\Program Files (x86)\Typora\os-services\image-20250103125859539.png)

NFS原理

NFS:网络文件系统

NFS服务端:2个服务组成

NFS服务

rpcbind(portmap)rpc服务(远程调用协议)

![image-20250103125907669](D:\Program Files (x86)\Typora\os-services\image-20250103125907669.png)

### 2.1 环境说明

| 环境 | 主机 | ip |
| ——— | —— | ————————– |
| nfs服务端 | nfs01 | 192.168.137.31/172.16.1.31 |
| nfs客户端 | web01 | 192.168.137.7/172.16.1.7 |
| nfs客户端 | web012 | 192.168.137.8/172.16.1.8 |

![image-20250103125945070](D:\Program Files (x86)\Typora\os-services\image-20250103125945070.png)

![image-20250103130023907](D:\Program Files (x86)\Typora\os-services\image-20250103130023907.png)

| 服务端流程 | 客户端流程 |
| ————————– | ——————— |
| 部署与检查 | 部署与检查 |
| 服务启动,rpcbind,nfs | 不需要启动 |
| 创建共享目录,修改权限 | 创建挂载点 |
| 修改配置文件,并reload nfs | mount挂载和/etc/fstab |

排错指令: rpcinfo -p ip 和showmount -e ip

### 2.2 服务器部署

“`sh
安装
[root@nfs01 ~]# yum install -y rpcbind nfs-utils

启动rpcbind和nfs,rpcbind先启动,关闭时相反
[root@nfs01 ~]# systemctl enable –now rpcbind
Created symlink /etc/systemd/system/multi-user.target.wants/rpcbind.service → /usr/lib/systemd/system/rpcbind.service.
[root@nfs01 ~]# rpcinfo -p
program vers proto port service
100000 4 tcp 111 portmapper
100000 3 tcp 111 portmapper
100000 2 tcp 111 portmapper
100000 4 udp 111 portmapper
100000 3 udp 111 portmapper
100000 2 udp 111 portmapper
[root@nfs01 ~]# systemctl enable –now nfs
Created symlink /etc/systemd/system/multi-user.target.wants/nfs-server.service → /usr/lib/systemd/system/nfs-server.service.
[root@nfs01 ~]# rpcinfo -p
program vers proto port service
100000 4 tcp 111 portmapper
100000 3 tcp 111 portmapper
100000 2 tcp 111 portmapper
100000 4 udp 111 portmapper
100000 3 udp 111 portmapper
100000 2 udp 111 portmapper
100024 1 udp 41798 status
100024 1 tcp 55417 status
100005 1 udp 20048 mountd
100005 1 tcp 20048 mountd
100005 2 udp 20048 mountd
100005 2 tcp 20048 mountd
100005 3 udp 20048 mountd
100005 3 tcp 20048 mountd
100003 3 tcp 2049 nfs
100003 4 tcp 2049 nfs
100227 3 tcp 2049 nfs_acl
100021 1 udp 39149 nlockmgr
100021 3 udp 39149 nlockmgr
100021 4 udp 39149 nlockmgr
100021 1 tcp 37447 nlockmgr
100021 3 tcp 37447 nlockmgr
100021 4 tcp 37447 nlockmgr
[root@nfs01 ~]#

修改配置文件,重启服务

[root@nfs01 ~]# mkdir /nfsdata
[root@nfs01 ~]# id nobody
uid=65534(nobody) gid=65534(nobody) groups=65534(nobody)
[root@nfs01 ~]# chown -R nobody.nobody /nfsdata/
[root@nfs01 ~]# cat /etc/exports
/nfsdata 172.16.1.0/24(rw),12.168.17.0/24(rw)
[root@nfs01 ~]# systemctl reload nfs
Job for nfs-server.service failed.
See “systemctl status nfs-server.service” and “journalctl -xe” for details.
[root@nfs01 ~]# vi /etc/exports
[root@nfs01 ~]# systemctl reload nfs
[root@nfs01 ~]# cat /etc/exports
/nfsdata 172.16.1.0/24(rw) 12.168.17.0/24(rw)
[root@nfs01 ~]#

测试连接
[root@nfs01 ~]# mount 172.16.1.31:/nfsdata /mnt
[root@nfs01 ~]# df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 963M 0 963M 0% /dev
tmpfs 979M 0 979M 0% /dev/shm
tmpfs 979M 9.0M 970M 1% /run
tmpfs 979M 0 979M 0% /sys/fs/cgroup
/dev/mapper/klas-root 97G 6.5G 91G 7% /
tmpfs 979M 64K 979M 1% /tmp
/dev/sda1 1014M 151M 864M 15% /boot
tmpfs 196M 0 196M 0% /run/user/0
172.16.1.31:/nfsdata 97G 6.5G 91G 7% /mnt
[root@nfs01 ~]# df -h /mnt
Filesystem Size Used Avail Use% Mounted on
172.16.1.31:/nfsdata 97G 6.5G 91G 7% /mnt
[root@nfs01 ~]#

“`

### 2.3 客户端挂载

“`sh
客户端1
[root@web01 ~]# mkdir /upload
[root@web01 ~]# mount 172.16.131:/nfsdata /upload
^C
[root@web01 ~]# mount 172.16.1.31:/nfsdata /upload
[root@web01 ~]# echo “172.16.1.31:/nfsdata /upload nfs defaults 0 0″>>/etc/fstab

客户端2
[root@web01 ~]# mkdir /upload
[root@web01 ~]# mount 172.16.131:/nfsdata /upload
^C
[root@web01 ~]# mount 172.16.1.31:/nfsdata /upload
[root@web02 ~]# echo “172.16.1.31:/nfsdata /upload nfs defaults 0 0″>>/etc/fstab
[root@web02 ~]# grep nfs /etc/fstab
172.16.1.31:/nfsdata /upload nfs defaults 0 0
[root@web02 ~]#

“`

### 2.4 故障

“`sh
nfs服务端异常故障案例
现象:df -h或ls挂载点的时候夯住.
原因:一般nfs服务端问题
解决:在/proc/mounts中过滤nfs,找出nfs挂载点,通过umount -lf强制卸载,然
后重新挂载即可

1.挂载好nfs客户端
mount -t nfs 172.16.1.31:/data /mnt/
2.关闭nfs服务端
3. 来的客户端
df -h
4. 在/proc/mounts中过滤nfs,找出nfs挂载点,通过umount -lf强制卸载,然后重新挂载即可
“`

### 2.5 服务端核心配置

| 服务端配置选项 | 说明 |
| ————– | ———————————————————— |
| rw | 读写 |
| ro | 只读 |
| sync | 同步,只要有文件上传,就立刻把数据写到磁盘 |
| async | 异步,用户上传的数据,nfs先临时存放到内存中,过一段时间写入到磁盘. 并发高,数据可能丢失 |

### 2.6 服务端用户压缩

现象:客户端 访问的时候的用户root,到了服务端变成了nfsnobody/nobody

NFS客户端挂载NFS服务端后,创建的文件默认属于nfsnobody,这种操作就叫用户压缩(映射).

用户压缩是通过NFS服务端的配置实现

| 服务端配置选项-用户压缩 | 说明 |
| ———————– | ———————————————————— |
| root_squash | 不配置这个选项就是默认,客户端是root,到了nfs就会被压缩 |
| no_all_squash | 默认,如果不是root,则不进行压缩 |
| all_squash | 所有用户都进行压缩 |
| anonuid和anongid | 用于指定压缩的匿名用户(默认是nobody)anonuid=65534,anongid=65534 |

用户压缩/用户映射: NFS客户端访问NFS共享目录的时候变成了什么用户.

nfs客户端用户 nfs服务端用户

root —> nfsnoboby

### 2.7 用户压缩案例

用户压缩案例: 搭建网站,对存储提出一些需求,

nfs服务端设置/nfs/pics共享目录,匿名用户为www(都压缩为www).

www用户的uid,gid:1999 (服务端,客户端统一)

客户端挂载到/upload-pic/

流程 C(Client 客户端) S(Server 服务端)

CS:部署nfs服务,rpcbind ✅

CS:添加用户www,指定uid,gid ✅

S:创建目录,修改权限,修改服务端配置文件 ✅

C:客户端进行挂载测试 ✅

![image-20250107123532613](D:\Program Files (x86)\Typora\os-services\image-20250107123532613.png)

“`SH
服务端
[root@nfs01 ~]# groupadd -g 1999 www
[root@nfs01 ~]# useradd -g www -s /bin/bash -m -u 1999 www
[root@nfs01 ~]# mkdir /nfs/pics
mkdir: cannot create directory ‘/nfs/pics’: No such file or directory
[root@nfs01 ~]# mkdir /nfs/pics -p
[root@nfs01 ~]# chown -R www.www /nfs/pics/
[root@nfs01 /var/lib/nfs]# systemctl reload nfs
[root@nfs01 /var/lib/nfs]# cat /etc/exports
/nfsdata 172.16.1.0/24(rw,anonuid=1999,anongid=1999) 192.168.17.0/24(rw,anonuid=1999,anongid=1999)
/nfs/pics 172.16.1.0/24(rw,anonuid=1999,anongid=1999) 192.168.17.0/24(rw,anonuid=1999,anongid=1999)
[root@nfs01 /nfs/pics]# ll
total 0
-rw-r–r– 1 www www 0 Oct 25 21:53 01
-rw-r–r– 1 www www 0 Oct 25 21:54 01.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 02
-rw-r–r– 1 www www 0 Oct 25 21:54 02.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 03
-rw-r–r– 1 www www 0 Oct 25 21:54 03.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 04
-rw-r–r– 1 www www 0 Oct 25 21:54 04.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 05
-rw-r–r– 1 www www 0 Oct 25 21:54 05.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 06
-rw-r–r– 1 www www 0 Oct 25 21:54 06.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 07
-rw-r–r– 1 www www 0 Oct 25 21:54 07.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 08
-rw-r–r– 1 www www 0 Oct 25 21:54 08.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 09
-rw-r–r– 1 www www 0 Oct 25 21:54 09.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 10
-rw-r–r– 1 www www 0 Oct 25 21:54 10.txt
[root@nfs01 /nfs/pics]#

客户端1
[root@web02 ~]# mkdir /upload-pic
[root@web02 ~]# groupadd -g 1999 www
[root@web02 ~]# useradd -g www -u 1999 -s /bin/bash -m www
[root@web02 ~]# chown -R www.www /upload-pic/
[root@web01 /upload-pic]# touch {01..10}.txt
[root@web01 /upload-pic]# ll
total 0
-rw-r–r– 1 www www 0 Oct 25 21:53 01
-rw-r–r– 1 www www 0 Oct 25 21:54 01.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 02
-rw-r–r– 1 www www 0 Oct 25 21:54 02.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 03
-rw-r–r– 1 www www 0 Oct 25 21:54 03.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 04
-rw-r–r– 1 www www 0 Oct 25 21:54 04.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 05
-rw-r–r– 1 www www 0 Oct 25 21:54 05.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 06
-rw-r–r– 1 www www 0 Oct 25 21:54 06.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 07
-rw-r–r– 1 www www 0 Oct 25 21:54 07.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 08
-rw-r–r– 1 www www 0 Oct 25 21:54 08.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 09
-rw-r–r– 1 www www 0 Oct 25 21:54 09.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 10
-rw-r–r– 1 www www 0 Oct 25 21:54 10.txt
[root@web01 /upload-pic]#

客户端2
[root@web01 ~]# mkdir /upload-pic
[root@web01 ~]# groupadd -g 1999 www
[root@web01 ~]# useradd -g www -u 1999 -s /bin/bash -m www
[root@web01 ~]# chown -R www.www /upload-pic/
[root@web02 /upload-pic]# touch {01..10}
[root@web02 /upload-pic]# ll
total 0
-rw-r–r– 1 www www 0 Oct 25 21:53 01
-rw-r–r– 1 www www 0 Oct 25 21:54 01.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 02
-rw-r–r– 1 www www 0 Oct 25 21:54 02.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 03
-rw-r–r– 1 www www 0 Oct 25 21:54 03.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 04
-rw-r–r– 1 www www 0 Oct 25 21:54 04.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 05
-rw-r–r– 1 www www 0 Oct 25 21:54 05.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 06
-rw-r–r– 1 www www 0 Oct 25 21:54 06.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 07
-rw-r–r– 1 www www 0 Oct 25 21:54 07.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 08
-rw-r–r– 1 www www 0 Oct 25 21:54 08.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 09
-rw-r–r– 1 www www 0 Oct 25 21:54 09.txt
-rw-r–r– 1 www www 0 Oct 25 21:53 10
-rw-r–r– 1 www www 0 Oct 25 21:54 10.txt

“`

服务端cat /var/lib/nfs/etab

![image-20250107123544616](D:\Program Files (x86)\Typora\os-services\image-20250107123544616.png)

### 2.8 nfs优化

mount -o noexec,nosuid,nodev -t nfs 172.16.1.31:/data

/video/

\#这几个是客户端挂载选项

noexec 挂载的nfs目录中如果有命令,无法运行。

nosuid 带有suid的命令

nodev 带有特殊属性的文件。

### 2.9 nfs小结

说出来网站为何是否存储服务(共享存储)

存储选型

搭建NFS存储,对服务进行配置(比如共享/nfsdata目录)

用户映射选项:all_squash,anonuid,anongid

故障与排查:rpcinfo -p ip ,showmount -e ip

## 3 实时同步

实时同步都是inotify+rsync

lrsync=inotify+rsync

| 角色 | 说明 | 共享目录 |
| ———— | ———————- | ————– |
| backup服务器 | rsync服务端 | 共享/nfsbackup |
| nfs服务器 | 部署lsyncd实时同步服务 | 监控/data |

### 3.1 部署准备

“`sh
backup服务器添加/etc/rsyncd.conf配置

[root@backup ~]# cat >>/etc/rsyncd.conf<>/etc/ssh/sshd_config<>/etc/rc.local</etc/sysconfig/iptables
[root@yangsenlin-m01 ~]# cat /etc/sysconfig/iptables

[root@yangsenlin-m01 ~]# iptables-restore > /etc/sysctl.conf
sysctl -p

iptables -t nat -A POSTROUTING -s 172.16.1.0/24 -j SNAT –to-source 10.0.0.61 10.0.0.61是网关外网地址

公网ip不固定
iptables -t nat -A POSTROUTING -s 172.16.1.0/24 -j MASQUERADE
“`

#### 2 端口转发

“`sh
iptables -t nat -A PREROUTING -d 10.0.0.61 -p tcp –dport 9000 -j DNAT –to-destination 172.16.1.7:22

“`

#### 3 ip映射

“`sh
iptables -t nat -A PREROUTING -d 10.0.0.62 -j DNAT –to-destination 172.16.1.7
“`

linux基础

# 1 命令

## 1.1 linux快捷键

| 快捷键 | 作用 |
| ———– | ——————– |
| ctrl+c | 取消当前操作 |
| ctrl+l | 清屏 |
| ctrl+e/end | 光标移动到行尾 |
| ctrl+a/home | 光标移动到行首 |
| ctrl+u | 删除光标到行首的内容 |
| ctrl+k | 删除光标到行尾的内容 |
| ctrl+y | 粘贴 tab 自动补全 |
| ctrl+w | 删除光标前一个词 |

## 1.2 linux基础命令

| 命令 | 含义 |
| ——————– | ———————————————————— |
| cd – | 进入上次进入的目录 |
| mkdir -p | 递归创建多个目录 |
| mkdir -p {01..10}ysl | 创建多个连续目录 |
| touch | 创建文件或更新文件时间 |
| touch {01..10}.txt | 创建多个连续文件 |
| file | 查看文件类型 |
| stat | 查看文件 |
| ls -lh | 以文件单位来查看 |
| ls -lrt | 逆序查看文件 |
| ls -la | 查看隐藏 |
| cp -r | 递归复制 |
| cp -a | 复制文件或目录所有属性 |
| cp -t | 在 find + -exec上用的较多 |
| cat 查看文件 | 查看日志时不能用cat,因为cat和vivim都是将文件放入内存中,日志太大会引起内存不足 |
| cat -n | 显示文件行号 |
| cat -A | 显示文件末尾符号,有时候文件末尾是空格,可以使用此命令 |
| cat >>test<>passwd.txt<>/etc/yum.conf</etc/apt/apt.conf.d/keep-deb.conf</tpm/log.log &

ctrl +z 中断 中断后使用bg或者fg

screen 命令需要安装,screen创建虚拟机窗口,命令可以在里面运行

top快捷键

q 退出

空格 立刻更新

P cpu排序,例如,cpu4核心,cpu使用率最多400%

M 内存排序

1 数字1查看所有核心

top bn1 显示一次

ps aux

pid 进程

ppid 父进程

vsz 虚拟内存

rss 物理内存

## 5.4 系统负载

![image-20250507170531590](D:\Program Files (x86)\Typora\001-linux基础\image-20250507170531590.png)

定义:在单位时间内系统处于可运行状态(R,S状态)和不可中断状态D的进程数量

如何衡量系统负载值高低

系统负载的值和cpu核心总是比较lscpu,接近cpu数就表示系统负载高,阈值为70%

如果系统负载高

常见原因cpu负载和处于D状态的进程

“`sh
stress压力测试(跑分)
#1.安装
yum install -y stress
#2. 模拟CPU导致的负载高
stress –cpu 2 –timeout 1000
#3. 模拟IO导致的系统负载高
stress –io 2 –hdd 3 –hdd-bytes 1g –timeout 10000s
“`

# 6 系统管理

## 6.1 服务管理

systemctl is-enabled sshd 查看是否开机启动

systemctl is-active sshd 查看是否启动

systemctl enable –now sshd 一键开启,开机和启动

systemctl disable –now sshd 一键关闭,开机不自启和关闭

systemctl list-unit-files 或list-units 查看系统所有服务

ctl结尾的命令

hostnamectl

systemctl

timedatectl

localectl

networkctl

localectl

修改字符集

中文字符集

LANG=zh_CN.UTF-8

LANG=en_US.UTF-8

localectl set-locale LANG=en_US.UTF-8

networkctl

networkctl reload ubt重启网络

netplan apply ubt重启网络

## 6.2 忘记root密码

解决方法

1、系统自带的救援模式;

2、U盘系统进入U盘的救援模式

3、快照恢复

### 1 系统自带的救援模式

关闭selinux

重启linux

在grub菜单中选中第一个带内核的选项按e

找到有linux16的那一行将ro修改为rw,在这一行尾添加init=/bin/bash

ctrl+x进入救援模式

修改/etc/passwd将root那一行的x去掉

然后重启,exec /sbin/init

mount -o rw,remount /

重启进入系统后使用passwd修改密码

### 2 光盘救援模式

插入U盘或光盘

重启并在弹出vmware logo的时候按esc

选择光盘启动

进入到系统安装页面选择troubleshooting然后选择rescue installed system

进入系统后执行fdisk + mount指令

fdisk -l | grep root

mount /dev/mapper/klas-root /mnt

此时硬盘中的跟挂载到了/mnt

## 6.3 运行级别

0 关机

1 单用户,没有网络

2 多用户,命令行,文本,multi-user

3 多用户,命令行,文本,multi-user

4 多用户,命令行,文本,multi-user

5 图形界面

6 重启

设置运行级别

查看 systemctl get-default

修改 systemctl set-default

## 6.4 启动流程

1、开机自检 检查硬件是否有问题

2、加载引导程序 是从硬盘还是u盘还是光盘启动

3、进入grub菜单 这里可以进入单用户模式

4、加载内核 加载/boot目录的配置

5、启动第一个程序systemd

6、读取运行级别 读取运行级别,然后准备启动对应的服务

7、进行系统初始化 设置主机名、ip等信息

8、启动服务 启动各种开机自启的服务

9、启动完成进入登录界面

# 7 磁盘管理

## 7.1 磁盘

“`sh
存储芯片(颗粒)
slc
mlc
tlc
QLC
“`

![image-20241224181038824](D:\Program Files (x86)\Typora\linux基础\image-20241224181038824.png)

磁盘分区

​ 主分区

​ 扩展分区

​ 逻辑分区

mbr引导对应的磁盘分区最多4个主分区

创建扩展分区,无法直接使用,需要在扩展分区下面创建逻辑分区然后使用

为什么4个

硬盘0头0道1扇区512字节

主引导记录mbr所在地446字节

2字节的分区结束标识,结束标识55AA

剩64字节,每个分区占用16字节,所以只有4个分区

fdisk -l 查看磁盘情况

fdisl /dev/硬盘

n 创建

p 查看

d 删除

w 保存并退出

t 修改分区模式

q 退出不保存

parted /dev/sdc

mktable gpt 创建分区表

p 查看

mkpart primary 0 100 创建100m

rm 分区数字 删除分区

q退出

gdisk 用法跟fdisk一样

拿到一块硬盘后的使用流程

分区-格式化-挂载-写入文件

fdisk-mkfs.xfs-mount-写入/etc/fstab

fstab 文件每一列含义

1 设备名字或uuid

2 挂载点

3 文件类型

4 挂载选项,参数,使用defaults

5 是否备份 0是不需要备份,1是需要备份

6 是否进行磁盘检查 0是在启动时不检查,1是启动时首先检查一般用于根,2是用于其他文件系统

## 7.2 raid

“`sh
RAID(独立磁盘冗余阵列)的不同级别提供了不同的数据保护、性能和存储效率的组合。以下是一些常见RAID级别的区别和它们各自的优势:

RAID 0(条带化)
数据保护:没有数据冗余,任何一个磁盘的故障都会导致整个阵列的数据丢失。
性能:最高,因为数据被分散存储在所有磁盘上,提高了读写速度。
存储效率:100%,所有磁盘空间都用于存储数据。
优势:适用于需要高性能但不需要数据冗余的应用,如视频编辑或大型数据库的临时存储。

RAID 1(镜像)
数据保护:最高,数据在两个磁盘上各存储一份,即使一个磁盘失败,数据仍然安全。
性能:相对较低,因为写入操作需要在两个磁盘上进行,但读取性能可以提高。
存储效率:50%,一半的磁盘空间用于数据冗余。
优势:适用于需要高数据安全性的应用,如关键业务数据存储。

RAID 5(带奇偶校验的条带化)
数据保护:较好,使用奇偶校验来保护数据,允许单个磁盘故障。
性能:较高,特别是对于写入密集型操作,因为奇偶校验信息分散在所有磁盘上。
存储效率:(n-1)/n,其中n是磁盘数量,例如,三个磁盘的RAID 5阵列的存储效率为2/3。
优势:平衡了性能和数据保护,适用于需要两者兼顾的应用。

RAID 6(双奇偶校验)
数据保护:更高,使用两个奇偶校验,允许两个磁盘同时故障。
性能:与RAID 5相似,但写入性能可能略低,因为需要计算两个奇偶校验。
存储效率:(n-2)/n,其中n是磁盘数量,例如,四个磁盘的RAID 6阵列的存储效率为3/4。
优势:适用于需要高数据保护和一定性能的应用,尤其是在磁盘数量较多时。

RAID 10(或称RAID 1+0)
数据保护:高,结合了镜像和条带化,提供数据冗余和高性能。
性能:高,特别是在读取时,因为数据被镜像,条带化又提高了写入性能。
存储效率:50%,因为一半的磁盘空间用于镜像。
优势:适用于需要高性能和高数据保护的应用,如数据库和事务处理系统。

RAID 50(RAID 5+0)
数据保护:较好,结合了RAID 5的奇偶校验和RAID 0的条带化。
性能:高,特别是对于大型文件的读写。
存储效率:(n/2-1)/n,其中n是条带化组中的磁盘数量。
优势:适用于需要高性能和一定数据保护的应用,尤其是在处理大量数据时

RAID 0
最少硬盘数量:2块
优势:提高数据读写速度,因为数据被分散存储在所有硬盘上。

RAID 1(镜像)
最少硬盘数量:2块
优势:提供数据冗余,即使一个硬盘失败,数据仍然安全。

RAID 5(带奇偶校验的条带化)
最少硬盘数量:3块
优势:提供数据冗余和较好的性能,允许单个硬盘故障。

RAID 6(双奇偶校验)
最少硬盘数量:4块
优势:提供更高的数据冗余,允许两个硬盘同时故障。

RAID 10(或称RAID 1+0)
最少硬盘数量:4块(2个镜像对,每个镜像对需要2块硬盘)
优势:结合了镜像和条带化,提供数据冗余和高性能。

RAID 50(RAID 5+0)
最少硬盘数量:6块(至少需要2个RAID 5阵列,每个RAID 5阵列至少需要3块硬盘)
优势:结合了RAID 5的奇偶校验和RAID 0的条带化,提供高性能和数据保护
“`

## 7.3 空间不足

swap不足

通过dd命令创建文件

dd if=/dev/zero of=/var/swapfile bs=1m count=1024

dd 创建指定大小的文件

if 从哪里读文件

of 输出到哪里

bs 每次读多少

count 次数

mkswap /var/swapfile 格式化

swapon /var/swapfile 启用

swapoff /var/swapfile 关闭

永久生效就写入/etc/fstab

关闭swap

swapoff -a

找到/etc/fstab swap内容注释

磁盘空间不足的原因

block剩余不足,一般是大文件导致的

inode剩余数量不足,一般小文件多造成的

block被占用,文件未彻底删除导致

block不足

df -h 查看文件系统

du -hs /* | sort -hrk1 一直查看大文件

inode不足

df -i 查看

find -type d -size +1M (查看目录大于1M的)

删除小文件

cd /test/inode

ls | xargs rm

ls 1* | xargs rm

ls 2* | xargs rm

block被占用,文件未被彻底删除导致空间不足

df -h 查看到/data个文件系统是使用率高

进入到/data使用du -sh /data/* | soft -hrk1却看到使用不高

lsof | grep delete 查找已经删除的大文件,可以看到pid

跟业务部门联系服务是否能马上结束

结束pid后释放空间

## 7.4 文件系统只读(系统只读)

解决方法

mount -o rw,remount / 常用于单用户模式

单用户模式重启

exec /sbin/init

如果失败,通过救援模式或u盘救援模式

# 8 其他

## 8.1 四剑客

**四剑客** 擅长

find 查找文件,目录,find与其他命令配合.

grep/egrep 过滤

sed 过滤,替换,取行

awk 过滤,取行,取列,统计与计算

find

-type f文件 d目录

-name/-iname 查找文件名

-size 指定大小+10k 大于10k,-10k小于10k,10k刚好10k

-mtime 指定修改时间,+7 7天前,-7 7天内,7 第七天

-maxdepth 指定深度,

find例子

find /etc/ -type f -name ‘*.conf’

find 目录 类型 名字

find /etc/ -type f -name ‘host*’ #以hosts开头

找出/bin/ /sbin/ 文件中包含ip的文件

find /bin/ /sbin/ -type f -name “*ip*”

find /etc/ -type f -name ‘*.conf’ -size +10k

find /var/log/ -type f -name “*.log” -mtime +3

find /etc/ -type f -iname ‘*.conf’

find /etc/ -maxdepth 1 -type f -name “*.conf”

\rm -f `find -type f -name ‘*.log’ `

find -type f -name ‘*.log’ |xargs rm -f

find -type f -name ‘*.log’ -exec rm -f {} \;

-exec 命令 {} \;

{}前面find找出的文件内容

\;结尾标记.

tar zcf /backup/etc-conf.tar.gz `find /etc/ -type f -name’*.conf’`

find /etc/ -type f -name ‘*.conf’ |xargs tar zcf /backup/etc-conf-v2.tar.gz

find /etc/ -type f -name ‘*.conf’ -exec tar zcf /backup/etc-exec.tar.gz {} \;

有坑,发现打包压缩后只有1个文件.

find 与-exe执行流程

find找出1个文件 exec执行1次命令

find /etc/ -type f -name ‘*.conf’ -exec tar zcf /backup/etc-exec.tar.gz {} +

\+ 先执行前面命令执行完成,结果一次性通exec传递给后面命令.

cp `find /var/cache/yum/ -type f -name “*.rpm” `/backup/rpms/

find /var/cache/yum/ -type f -name “*.rpm” |xargs cp -t /backup/rpms/

find与|xargs传参

cp /backup/rpms/ 参数 … . .. . . .

cp 文件 目录 目标(目录)

cp -t 目标(目录) 文件 目录

find /var/cache/yum/ -type f -name “*.rpm” -exec cp {} /backup/rpms/ \;

## 8.2 引号区别

单引号 所见即所得,引号里是什么内容,就会输出什么内容

双引号 与单引号类似,特殊符号会被解析,不会解析{}

无引号 与双引号类似,会解析{}

反引号 优先执行,先运行引号内容

## 8.3 重定向

输入为0

标准输出为1

错误输出为2

\> 或 1> 标准输出重定向(正确信息),先清空,然后写入

\>> 或 1>> 标准输出追加重定向(正确信息),追加到文件末尾

2> 标准错误输出重定向(错误信息),先清空,然后写入

2>> 标准错误追加输出重定向(错误信息),追加到文件末尾

\>>ysl.txt 2>&1 &>>ysl.txt 标准错误信息和正确信息都写入到指定文件

< 或 0< 输入重定向 << 或 0<< 追加输入重定向 ## 8.4 sed | sed命令格式 | 说明 | | ----------- | ------------------------------- | | -n | 取消默认输出一般与p指令一起使用 | | -r | 支持扩展正则 | | -i | 修改文件内容 | | -i.bak | 先备份再修改 | ### 1 sed查找 ```sh 案例1-根据行号进行过滤 [root@ysl ~]# sed -n '3p' passwd bin:x:2:2:bin:/bin:/usr/sbin/nologin -n是取消sed命令的默认输出 p输出print 案例2-根据行号范围进行过滤 [root@ysl ~]# sed -n '3,9p' passwd 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 [root@ysl ~]# sed -n '30,$p' passwd landscape:x:111:117::/var/lib/landscape:/usr/sbin/nologin usbmux:x:112:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin lxd:x:999:100::/var/snap/lxd/common/lxd:/bin/false _chrony:x:114:124:Chrony daemon,,,:/var/lib/chrony:/usr/sbin/nologin fwupd-refresh:x:115:125:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin mysql:x:113:118:MySQL Server,,,:/nonexistent:/bin/false nginx:x:998:999:nginx user:/nonexistent:/usr/sbin/nologin dnsmasq:x:116:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin [root@ysl ~]# sed -n '$p' passwd dnsmasq:x:116:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin 案例3-类似于egrep进行过滤 [root@ysl ~]# sed -n '/root/p' passwd root:x:0:0:root:/root:/bin/bash [root@ysl ~]# sed -nr '/root|ysl/p' passwd root:x:0:0:root:/root:/bin/bash syslog:x:107:113::/home/syslog:/usr/sbin/nologin 案例04-取出文件中某个范围的内容 [root@ysl ~]# seq 3 15 >num.txt
[root@ysl ~]# sed -n ‘/5/,/15/p’ num.txt
5
6
7
8
9
10
11
12
13
14
15

[root@ysl ~]# sed -n ‘/^5/ , /^15/p’ num.txt
5
6
7
8
9
10
11
12
13
14
15

日志处理,过滤出11点的日志
[root@fuxi ~]# sed -n ‘/11:02:00/,/11:10:00/p’ access.log | wc -l
22603
“`

### 2 sed替换

“`sh
sed用户修改配置文件内容
s///g
s###g
s@@@g
s sub替换 substitute
g 全局 global,不加g默认替换第一个

案例1-把文件中的ysl替换为forest
cat >sed.txt<time.log<=
<= >
< [root@fuxi ~]# awk 'NR>=3 && NR<=10' passwd daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin 案例1-取出passwd中包含bash的行 [root@fuxi ~]# grep 'bash' passwd root:x:0:0:root:/root:/bin/bash forest:x:1000:1000:forest:/home/forest:/bin/bash [root@fuxi ~]# sed -n '/bash/p' passwd root:x:0:0:root:/root:/bin/bash forest:x:1000:1000:forest:/home/forest:/bin/bash [root@fuxi ~]# awk '/bash/' passwd root:x:0:0:root:/root:/bin/bash forest:x:1000:1000:forest:/home/forest:/bin/bash 使用正则 [root@fuxi ~]# awk '/root|ysl/' passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin 案例02-取出日志中指定时间段内的日志 [root@fuxi ~]# seq 5 20 | sed -n '/5/,/6/p' 5 6 15 16 [root@fuxi ~]# seq 5 20 | awk '/5/,/6/' 5 6 15 16 sed -n '/11 15:00/ , /11 16:00/p' secure-20161219 |wc -l 日志过滤专业版 [root@fuxi ~]# awk '$4>=”[22\/NOV\/2015:11:11:13]”‘ access.log

[root@fuxi ~]# awk ‘/04:10:00/,/04:11:00/’ secure
“`

### 2 awk取列

“`sh
案例1-取出passwd的第一列和第三列
[root@fuxi ~]# cat passwd | awk -F: ‘{print $1,$(NF)}’| column -t
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin

案例2-取出ip地址
[root@fuxi ~]# ip a s ens33 | awk ‘NR==3’ | awk -F ‘[ /]+’ ‘{print $3}’
192.168.137.22

案例3-获取系统运行时间
[root@fuxi ~]# uptime | awk -F ‘[ ,]+’ ‘{print $4,$5}’
13 min

案例4-显示passwd每一行的内容与行号
awk ‘{print NR,$0}’ passwd

“`

### 3 取列小结

“`sh
取列格式 awk ‘{print $x}’
$(NF-1)倒数第2列
awk -F指定分隔符,分隔符相当于菜刀,每一列的结束标记,支持正则
“`

### 4 取行与取列

“`
sh
awk -F: ‘NR==1{print $1,$3,$NF}’ /etc/passwd
awk 选项 ‘找谁{干啥}’ /etc/passwd
找谁: 条件 用于让awk定位到某一行或几行.
干啥: 动作 满足上面条件后(找到这行后)如何处理这一行. print 取列.
动作部分可以省略,输出这一行的内容相当于
awk ‘NR==3’ /etc/passwd #显示第3行内容.
awk ‘NR==3{print $0}’ /etc/passwd #与上面一致

ip a s eth0 |awk ‘NR==3’ |awk -F ‘[ /]+’ ‘{print $3}’
ip a s eth0 | awk -F ‘[ /]+’ ‘NR==3{print $3}’

“`

### 5 awk计算与统计

“`sh
1、目标
记忆awk两个常用公式
使用awk进行求和
使用awk计算百分数

2、 案例1-通过awk实现wc -l效果
awk ‘{统计与计算} END{awk读取文件后才会执行,一般用于输出最后的结果}’
[root@fuxi ~]# awk ‘{i=i+1} END{print i}’ /etc/services
11473

案例2-统计seq 10结果的总和
[root@fuxi ~]# seq 10 | awk ‘{sum=sum+$1} END{print sum}’
55

[root@fuxi ~]# awk ‘{sum=sum+$10} END{print sum/1024^3″GB”}’ access.log
2.30828GB
[root@fuxi ~]#

[root@fuxi ~]# free -m
total used free shared buff/cache available
Mem: 7939 223 7385 9 331 7473
Swap: 2047 0 2047
[root@fuxi ~]# free -m | awk ‘NR==2{print $NF/$2*100″%”}’
94.0799%

df -h使用率
[root@fuxi ~]# df -h | awk -F ‘[ %]+’ ‘$5>=10 && NR>=2’
/dev/sda1 1014M 151M 864M 15% /boot

案例3-过滤某一列中有什么

/etc/passwd中第3列UID包含0或1,输出这一行的第1列,第3列和最后一列

条件: 行 第3列包含0或1
动作: 列 输出第一列,第三列,最后一列

awk -F: ‘$3~/[01]/ {print $1,$3,$NF}’ /etc/passwd
[root@fuxi ~]# awk -F: ‘$3~/[01]/ {print $1,$3,$(NF-1)}’ /etc/passwd | column -t
root 0 /root
bin 1 /bin

案例4-过滤出access.log中第7列以.jpg或.bmp或.png或.gif结尾的行,统计行数

[root@fuxi ~]# awk ‘$7~/\.jpg$|\.bmp$|\.png$|\.gif$/ ‘ access.log | wc -l
44235

上面这个可以改写成如下
[root@fuxi ~]# awk ‘$7~/\.(jpg|bmp|png|gif)$/’ access.log | wc -l
44235
“`

###

## 8.6 定时任务

crontab -e 相当于vi /var/spool/cron/root #root当前用户名字

crontab -l 相当于cat /var/spool/cron/root #root当前用户名字

分 时 日 月 周

30 08 * * * 每天8点30执行

\* 每,每隔 \*/2每隔2 \*/2 * * * * 每隔两分钟执行一次

\- 范围 00 10-22 * * * 10-22点运行一次

,逗号 独立,没有规律 00 09,15,22 * * * 9点15点22点执行

查看日志/var/log/cron

| 定时任务中的特殊符号 | 说明 | 案例 |
| ——————– | ———– | —————————————————— |
| * | 每,每隔*/2 | 每两分钟运行cmd */2 * * * * 每两个小时运行00 */2 * * * |
| – | 范围 | 每天10-22点运行cmd 00 10-22 * * * |
| ,逗号 | 没有规律 | 每天9点15点22点运行cmd 00 9,15,22 * * * |

“`sh
crontab -e相当于 vim /var/spool/cron/root root是用户名
crontab -l相当于 cat /var/spool/cron/root root是用户名
“`

ubt中:crontab -e 需要选择编辑器 选择vim.basic 2号

后期可以使用select-editor修改.

## 8.5 发送邮件

### 1 麒麟/centos

“`sh
yum install -y mailx sendmail

vim /etc/mail.rc #写到最后
cat >>/etc/mail.rc <=1
大于 >
不等于 !=
“`

### 5 与或非

“`sh
#过滤端口号大于等于20 小于等于1024
tcp.port >=20 && tcp.port <=1024 tcp.port >=20 and tcp.port <=1024 #组合 过滤出 端口是80 并且 ip地址是虚拟机ip and #并且 && or #或者 || ! #取反 tcp.port == 80 && ip.addr == 10.0.0.200 #并且 tcp.port == 80 || ip.addr == 10.0.0.200 #或者 #过滤出udp协议 53端口数据表 udp && udp.port == 53 测试语句: dig www.baidu.com #过滤源IP是虚拟机(10.0.0.200) 并且目标端口是80的数据包 测试语句:curl www.baidu.com ip.addr == 10.0.0.200 && tcp.dstport == 80 ``` ### 5 linux 抓包 ```sh yum install -y tcpdump #指定网卡 如果有多块网卡的时候需要指定。 tcpdump -i ens33 #过滤协议 tcpdump icmp tcpdump -vvv -nnn icmp #过滤指定端口号 80端口 tcpdump -nnn port 80 tcpdump -nnn src port 80 tcpdump -nnn dst port 80 #抓住指定主机 tcpdump -nnn host 10.0.0.200 #抓取指定ip和端口的数据包 tcpdump -nnn src host 10.0.0.200 and port 80 tcpdump -nnn dst host 10.0.0.200 and port 80 #组合 过滤出 端口是80 并且 ip地址是10.0.0.200 and #并且 or #或者 ! #取反 保存结果为.pcap使用wireshark ``` ![image-20241231170337645](D:\Program Files (x86)\Typora\linux基础\image-20241231170337645.png) 抓包应用场景 ![image-20241231170429484](D:\Program Files (x86)\Typora\linux基础\image-20241231170429484.png) ![image-20241231170437493](D:\Program Files (x86)\Typora\linux基础\image-20241231170437493.png) ### 6 抓包小结 | 过滤条件 | wireshark | tcpdump | | ------------------ | ------------------- | ----------------------------------------- | | 抓出指定协议 | icmp/tcp/http | tcpdump icmp/tcp/udp | | 抓出指定端口 | tcp.port == 80 | tcpdump tcp port 80 | | | udp.port == 53 | tcpdump udp port 53 | | 过滤出源端口 | tcp.srcport == 80 | tcpdump src port 80 | | 过滤出目的端口 | tcp.dstport == 80 | tcpdump dst port 80 | | 抓出指定ip的数据包 | ip.addr == 10.0.0.1 | tcpdump host 10.0.0.1 | | 过滤出源ip | ip.src == 10.0.0.1 | tcpdump src host 10.0.0.1 | | 过滤出目的ip | ip.dst == 10.0.0.1 | tcpdump dst host 10.0.0.1 | | 正则 | ~或matches | 无 | | 与或非 | && and \|\| or ! | and or ! tcpdump 80 and 53 | | 选项 | 无 | -w *.pcap保存 -i 指定网卡 -vvv -nnn更详细 | ### 7 tcp/ip协议 ![image-20241231110813206](D:\Program Files (x86)\Typora\linux基础\image-20241231110813206.png) ## 9.8 三次握手 1、客户端发出建立连接请求: SYN(标记)建立连接请求. 发出seq的随机数(seq=100). 2、服务端收到客户端请求: ACK(确认标记),SYN(与客户端建立连接), 发出ack=seq+1(101),seq=随机(666) 3、客户端收到服务端请求与确认: 发出ACK(确认标记)确认建立连接, 发出 ack=seq+1(667) seq=ack(101) ![image-20241231111454391](D:\Program Files (x86)\Typora\linux基础\image-20241231111454391.png) ## 9.9 四次挥手 1、客户端: 发出断开连接请求: (FIN)断开连接请求,seq=1000 ack=668 2、服务端: 收到客户端请求,确认: (ACK) ,确认断开, seq=668 ack=seq+1(1001) 3、服务端: 向客户端发出断开连接请求,(FIN)断开连接请求, seq=668 ack=seq+1(1001) 4、客户端: 确认收到请求,断开连接, (ACK)确认收到请求, seq=1001 ack=seq+1(669) 5、连接断开 ![image-20241231111445777](D:\Program Files (x86)\Typora\linux基础\image-20241231111445777.png) ## 9.10 dns解析 1、系统在本地的dns缓存查找是否有这个域名对应的IP; 2、系统的hosts文件是否配置域名对应的IP; 3、访问本地DNS服务器,询问是否知晓域名对应的IP地址; 4、本地DNS访问根域名解析服务器(根DNS),但是根DNS只有顶级域名的记录,根告诉我们.cn顶级域的DNS地址; 5、本地DNS访问顶级域的DNS是否知晓域名对应IP,顶级DNS会告诉我们是二级域对应的DNS; 6、本地dns访问二级域名的DNS,二级域名DNS知晓对应的IP地址,IP返回给本地DNS,本地DNS缓存 7、本地DNS把域名和IP对应关系给浏览器 域名解析:dig+trace 购买域名https://wanwang.aliyun.com/newdomain/1yuan?v_=47edc66742fe36fc0a839ea5700b8cd5 ### 1 域名 先注册 [域名查询结果_域名信息_域名交易-万网-阿里云旗下品牌](https://wanwang.aliyun.com/domain/searchresult/?spm=5176.8048432.J_6007716750.3.323269a3UZQZLq&keyword=test&suffix=.cn) ![image-20241231114207889](D:\Program Files (x86)\Typora\linux基础\image-20241231114207889.png) ### 2 记录类型 DNS记录--域名对应着什么 | 记录类型 | 说明 | 应用场景 | | -------- | ----------------------------- | -------------------------- | | A记录 | 域名--ipv4地址 | 常用 | | AAAA | 域名--ipv6地址 | 常用(ipv6) | | CNAME | 别名记录类似于alias,域名跳转 | 未来配置CDN,WAF | | TXT记录 | 域名--字符串,dig txt域名才行 | 校验,检查域名是否属于自己 | | MX记录 | 企业邮箱 | 根据企业邮箱的要求配置即可 | 添加记录地址https://dns.console.aliyun.com/https://dns.console.aliyun.com/#/dns/setting/yangsenlin.top) #### 1 CNAME记录 ```sh map.ysllinux.cn --> map.baidu.com
“`

#### 2 TXT验证

“`sh
配置域名 foresttest.ysllinux.cn txt记录 显示 yslforest
dig txt foresttest.ysllinux.cn
“`

#### 3 MX记录-配置企业邮箱

“`sh
企业邮箱 邮箱 @公司域名
@baidu.com
@aliyun.com
https://work.weixin.qq.com/mail/ 注册
下载企业微信.
创建企业
“`

#### 5 网站备案流程

https://beian.aliyun.com/

![image-20241231154204550](D:\Program Files (x86)\Typora\linux基础\image-20241231154204550.png)

#### 6 DNS解析详细流程

域名解析流程: 域名–过程?–>ip地址

![image-20241231154232508](D:\Program Files (x86)\Typora\linux基础\image-20241231154232508.png)

#### 7 DNS解析的命令

“`sh
1 windows
ipconfig /displaydns #显示
ipconfig /flushdns #清空dns缓存

2 linux
dig nbre.ysllinux.cn
[root@fuxi ~]# dig nbre.ysllinux.cn

; <<>> DiG 9.11.21-9.11.21-19.ky10 <<>> nbre.ysllinux.cn
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25069 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1408 ;; QUESTION SECTION: ;nbre.ysllinux.cn. IN A ;; ANSWER SECTION: nbre.ysllinux.cn. 600 IN A 121.199.49.168 ;; Query time: 250 msec ;; SERVER: 223.5.5.5#53(223.5.5.5) ;; WHEN: Tue Dec 31 15:46:55 CST 2024 ;; MSG SIZE rcvd: 64 ;一个分号是注释 ;;分号是结果 #详细 DNS解析流程 [root@ysl-king-v3 ~]# dig +trace nbre.ysllinux.cn ``` #### 8 DNS小结 ```sh 理解什么是DNS. 理解域名:根域名,顶级域,二级域,三级域. 核心掌握DNS解析流程,配合dig +trace 查看. 配置dns解析,检查域名是否过期. DNS解析故障. ``` ## 9.11 用户访问网站整个过程 1、dns解析得到ip 2、tcp三次握手:通过ip+端口域服务器建立连接 3、用户发出请求http,请求报文 4、网站处理用户请求 5、服务器发出响应,响应报文 6、tcp4次挥手,断开连接 ![image-20241231155457998](D:\Program Files (x86)\Typora\linux基础\image-20241231155457998.png) ### 1、dns解析,解析得到ip 访问电脑本地缓存,hosts文件 访问本地dns服务器 访问根域名解析服务器,得到顶级域 访问顶级域dns,得到二级域 访问二级域dns,得到三级域名的ip 返回给本地dns,缓存,再给电脑 2、tcp3次握手,通过ip+端口,与服务器简历连接 客户端-->服务端发出SYN建立连接请求,seq随机数

服务端–>客户端:发出ACK确认,SYN建立连接,ack=seq+1,seq随机数

客户端–>服务端:发出ACK确认,ack=seq+1,seq

连接建立

3、用户–>服务器:发出请求(http),请求报文

4、网站处理用户的请求

5、服务器–>用户:发出响应(http),响应报文

6、tcp4次挥手:断开连接

## 9.12 网络协议

arp 地址解析协议 ip–>mac地址,ip地址转换为网卡物理地址(mac),arp是3层协议,工作在二层

dns协议 域名–>IP

10.0.0.200–>10.0.0.2

1、发出arp请求,发送广播找人

2、所有局域网设备都收到广播,但是只有10.0.0.2回复单播,并告诉mac地址

3、缓存mac

arp -n 查看当前系统arp缓存表

![image-20241231155551671](D:\Program Files (x86)\Typora\linux基础\image-20241231155551671.png)

icmp

ping使用的就是icmp

\#临时禁止ping,重启后恢复

echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all

\#准许ping

echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_all

## 9.13 网卡改名

### 1 安装完成系统

“`sh
麒麟系统
方法01:安装完成系统
第1步: 修改/boot/grub2/grub.cfg配置
麒麟系统是 linux后面即可
net.ifnames=0 biosdevname=0
sed -ri.bak ‘/\t+linux/s#$# net.ifnames=0 biosdevname=0#g’
/boot/grub2/grub.cfg
#修改之后检查内容
第2步: 修改网卡配置文件.
1)修改网卡配置文件中NAME和DEVICE两个部分
vim修改
2)网卡配置文件名字改为eth0
mv 修改
修改后结果:
[root@ysl-king-v3 ~]# grep -n eth0 /etc/sysconfig/networkscripts/ifcfg-eth0
12:NAME=eth0
14:DEVICE=eth0
重启Linux

centos系统
方法01:安装完成系统
第1步: 修改/boot/grub2/grub.cfg配置
搜索linux16的行,在这行结尾加上 (centos) 麒麟系统是 linux后面即可
net.ifnames=0 biosdevname=0
#修改之后检查内容
[root@ysl-king-v3 ~]# grep -n linux16 /boot/grub2/grub.cfg
100: linux16 /vmlinuz-3.10.0-1160.el7.x86_64
root=/dev/mapper/centos_ysl–81–golden-root ro
spectre_v2=retpoline rd.lvm.lv=centos_ysl-81-golden/root
rd.lvm.lv=centos_ysl-81-golden/swap rhgb quiet
LANG=en_US.UTF-8 net.ifnames=0 biosdevname=0
114: linux16 /vmlinuz-0-rescue-
327861380b6d4c3c87ff2af04a0e187f
root=/dev/mapper/centos_ysl–81–golden-root ro
spectre_v2=retpoline rd.lvm.lv=centos_ysl-81-golden/root
rd.lvm.lv=centos_ysl-81-golden/swap rhgb quiet
net.ifnames=0 biosdevname=0
“`

![image-20241231155940612](D:\Program Files (x86)\Typora\linux基础\image-20241231155940612.png)

“`sh
第2步: 修改网卡配置文件.
1)修改网卡配置文件中NAME和DEVICE两个部分
vim修改
2)网卡配置文件名字改为eth0
mv 修改
修改后结果:
[root@ysl-king-v3 ~]# grep -n eth0 /etc/sysconfig/networkscripts/ifcfg-eth0
12:NAME=eth0
14:DEVICE=eth0
重启Linux

ubt20.04
1. grub
sed -i ‘/linux.*vmlinuz/s#$#biosdevname=0 net.ifnames=0#g’
/boot/grub/grub.cfg
2. 网卡配置文件
sed -i ‘s#ens33#eth0#g’ /etc/netplan/00-installer-config.yaml
3. 重启

ubt22.04
#1.修改/boot/grub/grub.cfg
170,189,226行,增加biosdevname=0 net.ifnames=0
awk ‘$1~/linux/{print NR,$0}’ /boot/grub/grub.cfg
sed -i ‘/linux.*vmlinuz/s#$# biosdevname=0
net.ifnames=0#g’ /boot/grub/grub.cfg
170 linux /vmlinuz-5.15.0-84-generic
root=/dev/mapper/ubuntu–vg-ubuntu–lv ro biosdevname=0
net.ifnames=0
189 linux /vmlinuz-5.15.0-84-generic
root=/dev/mapper/ubuntu–vg-ubuntu–lv ro biosdevname=0
net.ifnames=0
207 linux /vmlinuz-5.15.0-84-generic
root=/dev/mapper/ubuntu–vg-ubuntu–lv ro recovery
nomodeset dis_ucode_ldr
226 linux /vmlinuz-5.15.0-83-generic
root=/dev/mapper/ubuntu–vg-ubuntu–lv ro biosdevname=0
net.ifnames=0
244 linux /vmlinuz-5.15.0-83-generic
root=/dev/mapper/ubuntu–vg-ubuntu–lv ro recovery
nomodeset dis_ucode_ldr
#2.修改网卡配置文件内容
sed -i ‘s#ens33#eth0#g’ /etc/netplan/00-installerconfig.yaml
#3.重启系统
“`

### 2 安装系统的时候修改

安装系统的时候选择第1个然后按tab键. 在最后写入 net.ifnames=0 biosdevname=0

![image-20241231160217501](D:\Program Files (x86)\Typora\linux基础\image-20241231160217501.png)

选择install 然后安装tab键,行尾输入 net.ifnames=0 biosdevname=0

DNS配置文件

网卡配置文件DNS1 DNS2 优先.重启网卡后会覆盖/etc/resolv.conf文件/etc/resolv.conf 实时生效

## 9.14 三次握手的状态

三次握手的状态https://www.processon.com/view/link/6245136a5653bb072bce3259

![image-20241231160541884](D:\Program Files (x86)\Typora\linux基础\image-20241231160541884.png)

“`sh
TCP三次握手状态转换简单说明:
01.准备:首先,建立连接之前服务器和客户端的状态都为CLOSED。
02.准备:服务器创建socket后开始监听(启动服务),变为LISTEN状态。
03.客户端:SYN请求,客户端请求建立连接,向服务器发送SYN报文,客户端的状态变
为SYN_SENT。
04.服务端:服务器收到客户端的报文(SYN)后向客户端发送ACK和SYN报文,此时服务
器的状态变为SYN_RCVD(recevide)(收到了客户端发送的SYN请求)。
05.客户端然后,客户端收到ACK、SYN,就向服务器发送ACK,客户端状态变为
ESTABLISHED
06.服务端服务器收到客户端的ACK后也变为ESTABLISHED。
此时3次握手完成,连接建立!
“`

## 9.15 四次挥手的状态

![image-20241231160534103](D:\Program Files (x86)\Typora\linux基础\image-20241231160534103.png)

“`sh
四次挥手中:
客户端:发出FIN请求这一方.
服务端:接收请求的.
01.客户端:客户端先向服务器发送FIN报文,请求断开连接,其状态变为
FIN_WAIT1。
02.服务端:服务器收到FIN后向客户端发送ACK,服务器状态变为CLOSE_WAIT。
03.客户端:客户端收到ACK后就进入FIN_WAIT2状态。此时连接已经断开了一半了。
如果服务器还有数据要发送给客户端,就会继续发送。
04.服务端:直到发完了,就发送FIN报文,此时服务器进入LAST_ACK状态。
05.客户端:客户端收到服务器的FIN后,马上发送ACK给服务器,此时客户端进入
TIME_WAIT状态,再过了2MSL长的时间后进入CLOSED状态。
06.服务端:服务器收到客户端的ACK就进入CLOSED状态
“`

## 9.16 第十一种状态补充

“`sh
CLOSING状态表示:
客户端发了FIN,但客户端在FIN_WAIT1状态时没有收到服务器的ACK确认字
段,却收到了服务器的FIN字段,这种情况发生在服务器发送的ACK丢包的时
候,因为网络传输有时会有意外。
“`

![image-20241231160650361](D:\Program Files (x86)\Typora\linux基础\image-20241231160650361.png)

“`sh
11种状态小结
核心必会: CLOSED,ESTABLISHED,LISTEN监听,TIME_WAIT,CLOSE_WAIT
逐渐掌握: FIN_WAIT1,FIN_WAIT2,CLOSING,SYN_SENT,LAST_ACK
“`

![image-20241231160723606](D:\Program Files (x86)\Typora\linux基础\image-20241231160723606.png)

## 9.17 网络相关命令

### 1 网络追踪

traceroute -nl jd.com

### 2 端口

ss

netstat

lsof

nc

telnet

nmap

nmap -v -sn 192.168.137.0/24

### 3 状态

ss -ant

netstat -ant

dns

dig

host

nslookup

### 4 域名过期

whois jwhois

### 5 网络流量

iptop

nethogs

“`sh
wget -O /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo
yum install -y iftop
top/htop
iotop
iftop 2s 10s 40s数据传输平均速度
iftop -n #ip反向解析为域名/主机名
iftop -i 指定网卡. 默认eth0 第1个网卡
iftop -P 显示端口
iftop -N 不要把端口解析为服务名字
最终使用.
iftop -nNP -i eth0 #显示端口号,不要把ip解析为域名,不要把端口解析为服
务, 监视指定网卡eth0
#iftop非交互模式 方便进行过滤与处理.
iftop -nNP -Bt -s 1
-B以字节为单位进行显示,默认是位

“`

### 6 网络命令小结

| 网络命令 | linux | windows |
| —————- | —————————— | ———— |
| 查询ip地址 | ip/ifconfig | ipconfig |
| 检查端口号 | ss/netstat/lsof/nc/telnet/nmap | netstat -ant |
| 检查连接情况 | ss -ant/netstat -ant | netsat -ant |
| 检查速度 | iftop/nethogs | |
| dns解析 | dig/host/nslookup | nslookup |
| 检查链路是否畅通 | ping/fping | ping |
| 查询当前系统网关 | ip ro/route -n | route print |