RHCE8
- 操作系统
- 2022-12-13
- 13热度
- 0评论
shell语句
case判断语句
#!/bin.bash
cat <<EOF
############################################
# #
# welcome everybody #
# #
############################################
EOF
read -p "dvd is connceted ?(y/n)" ans
case $ans in
y|Y)
;;
n|N)
echo "please connect!"
exit 1 ;;
*)
echo "only y or n"
exit 1 ;;
esac
统计文件行数
#!/bin/bash
# 必须输入一个文件
if [ $# -eq 0 ];then
echo "must insert a file."
exit 1
fi
# 判断输入的文件是否存在或者是不是一个文件类型
if [ ! -f $! ]; then
echo "$1 is not a file or not exist."
exit 1
fi
# 统计输入的文件行数
declare -i n=0
while read aa ;
do
let n=$n+1
done < $1
# 输出统计信息
echo "$n $1"
计划任务
at计划任务
是一次性的,不会重复性的执行
# 设置好计划任务后,按 Ctrl+D 进行提交
[zhuchun@server1 ~]$ at 10:00 2022-12-03
warning: commands will be executed using /bin/sh
at> /home/zhuchun/c.sh
at> <EOT>
job 1 at Sat Dec 3 10:00:00 2022
[zhuchun@server1 ~]$ date
2022年 12月 02日 星期五 03:10:30 PST
# 不加具体时间的话,默认取未来日期的当前的时
[zhuchun@server1 ~]$ at 2022-12-3
warning: commands will be executed using /bin/sh
at> /home/zhuchun/c.sh
at> <EOT>
job 4 at Sat Dec 3 03:10:00 2022
# 三天后的上午10点执行
[zhuchun@server1 ~]$ at 10am+3days
warning: commands will be executed using /bin/sh
at> /home/zhuchun/c.sh
at> <EOT>
job 7 at Mon Dec 5 10:00:00 2022
[zhuchun@server1 ~]$ atq
1 Sat Dec 3 10:00:00 2022 a zhuchun
4 Sat Dec 3 03:10:00 2022 a zhuchun
7 Mon Dec 5 10:00:00 2022 a zhuchun
[zhuchun@server1 ~]$ at -l
1 Sat Dec 3 10:00:00 2022 a zhuchun
4 Sat Dec 3 03:10:00 2022 a zhuchun
7 Mon Dec 5 10:00:00 2022 a zhuchun
# 查看某个任务的具体内容
[zhuchun@server1 ~]$ at -c 7
[root@server1 ~]# ll /var/spool/at/
总用量 24
-rwx------. 1 zhuchun zhuchun 4505 12月 2 02:15 a0000101a8b9d8
-rwx------. 1 zhuchun zhuchun 4505 12月 2 03:10 a0000401a8b83e
-rwx------. 1 zhuchun zhuchun 4505 12月 2 03:14 a0000701a8c518
drwx------. 2 root root 6 8月 12 2018 spool
# 查看某个任务的具体内容
[root@server1 ~]# cat /var/spool/at/a0000101a8b9d8
# 删掉7号任务,jobid是7
[root@server1 ~]# atrm 7
[root@server1 ~]# at -d 7
# 此文件配置哪些用户没有配置计划任务的权限
[root@server1 ~]# cat /etc/at.deny
zhuchun
# 此文件配置哪些用户可以有配置计划任务的权限
[root@server1 ~]# cat /etc/at.allow
zhuchun
# 如果同一个用户 deny 和 allow 都配置了,则拥有 allow 权限
crontab 计划任务
是周期性的,循环执行的
# 查看当前用户的计划任务
[root@server1 ~]# crontab -l
no crontab for root
# 查询 zhuchun 用户的计划任务
[root@server1 ~]# crontab -l -u zhuchun
no crontab for zhuchun
# 编辑当前用户的计划任务
[root@server1 ~]# crontab -e
# 在crontab -e 编辑器中,凡是以井号开头的都是注释信息
# 分 时 天 月 周 命令
# 中间用空格或者 tab 都可以
# 分:几点积分
# 时:几点
# 天:几号
# 月:几月份
# 周:星期几
# *:代表 每
# 每天早晨七点整
0 7 * * * /home/zhuchun/c.sh
# 每周一至周五 早晨7点整执行
0 7 * * 1-5 /home/zhuchun/c.sh
0 7 * * 1-5/1 /home/zhuchun/c.sh
# 每周一、三、五执行
0 7 * * 1,3,5 /home/zhuchun/c.sh
0 7 * * 1-5/2 /home/zhuchun/c.sh
# 每周一到五,七点0分5分10分执行
0,5,10 7 * * 1-5 /home/zhuchun/c.sh
0-10/5 7 * * 1-5 /home/zhuchun/c.sh
# 一季度的每周一到五,七点0/5/10分执行
0-10/5 7 * 1-3 1-5 /home/zhuchun/c.sh
# 一季度上旬7点整执行
0 7 1-10 1-3 * /home/zhuchun/c.sh
# 一季度上旬的周一至周五7点整执行
0 7 1-10 1-3 1-5 /home/zhuchun/c.sh
[root@server1 ~]# cat /var/spool/cron/root
# 删除计划任务
[root@server1 ~]# crontab -r
# 不给zhuchun用户配置 crontab 的权限
[root@server1 ~]# cat /etc/cron.deny
zhuchun
# 给zhuchun用户配置 crontab 的权限,allow优先
[root@server1 ~]# cat /etc/cron.allow
zhuchun
# 脚本放/etc/cron.daily里,每天都会执行一次
# /etc/cron.hourly,每小时都会执行一次
[root@server1 ~]# ll /etc/cron*
-rw-r--r--. 1 root root 8 12月 2 03:46 /etc/cron.allow
-rw-r--r--. 1 root root 8 12月 2 03:45 /etc/cron.deny
-rw-r--r--. 1 root root 451 1月 8 2021 /etc/crontab
/etc/cron.d:
总用量 8
-rw-r--r--. 1 root root 128 6月 12 2019 0hourly
-rw-r--r--. 1 root root 108 1月 11 2021 raid-check
/etc/cron.daily:
总用量 4
-rwxr-xr-x. 1 root root 189 1月 4 2018 logrotate
/etc/cron.hourly:
总用量 4
-rwxr-xr-x. 1 root root 575 6月 12 2019 0anacron
/etc/cron.monthly:
总用量 0
/etc/cron.weekly:
总用量 0
[root@server1 ~]#
# 配置一个定期清理临时文件的定时任务
[root@server1 ~]# systemd-tmpfiles --clean
# systemd-tmpfiles 会读取规则文件,规则文件路径在 /usr/lib/tmpfiles.d/、/run/tmpfiles.d/
# 管理员想自己定义的话,在 /etc/tmpfiles.d/xxx.conf 文件中定义
[root@server1 tmpfiles.d]# cat aa.conf
# /tmp/aa 这个目录如不存在,则给创建出来,所属用户所属组均为 root。权限维 0755 ,/tmp/aa 目录下文件 10s 清理一次。
d /tmp/aa 0755 root root 10s
# 读取临时文件规则,执行创建,在 /tmp/aa 目录会生成,或者制定规则配置
[root@server1 aa]# systemctl start systemd-tmpfiles-clean
[root@server1 tmpfiles.d]# systemd-tmpfiles --create
[root@server1 tmpfiles.d]# systemd-tmpfiles --create aa.conf
[root@server1 aa]# cat /usr/lib/systemd/system/systemd-tmpfiles-clean.timer
[Unit]
Description=Daily Cleanup of Temporary Directories
Documentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8)
[Timer]
OnBootSec=15min
OnUnitActiveSec=1d
使用 tuned 优化系统
优化的思想
三层优化
1、硬件升级
2、OS优化
- 内核参数
- 硬件参数
3、app的优化
tuned
[root@server1 tmpfiles.d]# systemctl status tuned
● tuned.service - Dynamic System Tuning Daemon
Loaded: loaded (/usr/lib/systemd/system/tuned.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2022-12-01 16:50:47 PST; 11h ago
Docs: man:tuned(8)
man:tuned.conf(5)
man:tuned-adm(8)
Main PID: 1041 (tuned)
Tasks: 4 (limit: 11094)
Memory: 14.6M
CGroup: /system.slice/tuned.service
└─1041 /usr/libexec/platform-python -Es /usr/sbin/tuned -l -P
12月 01 16:50:46 server1.rhce.cc systemd[1]: Starting Dynamic System Tuning Daemon...
12月 01 16:50:47 server1.rhce.cc systemd[1]: Started Dynamic System Tuning Daemon.
# tuned 提供了以下解决方案,当前使用的是 virtual-guest 方案
[root@server1 ~]# tuned-adm list
Available profiles:
- accelerator-performance - Throughput performance based tuning with disabled higher latency STOP states
- balanced - General non-specialized tuned profile
- desktop - Optimize for the desktop use-case
- hpc-compute - Optimize for HPC compute workloads
- intel-sst - Configure for Intel Speed Select Base Frequency
- latency-performance - Optimize for deterministic performance at the cost of increased power consumption
- network-latency - Optimize for deterministic performance at the cost of increased power consumption, focused on low latency network performance
- network-throughput - Optimize for streaming network throughput, generally only necessary on older CPUs or 40G+ networks
- optimize-serial-console - Optimize for serial console use.
- powersave - Optimize for low power consumption
- throughput-performance - Broadly applicable tuning that provides excellent performance across a variety of common server workloads
- virtual-guest - Optimize for running inside a virtual guest
- virtual-host - Optimize for running KVM guests
Current active profile: virtual-guest
# 还可以安装以下的一些方案
[root@server1 ~]# yum list tuned*
Updating Subscription Management repositories.
Unable to read consumer identity
This system is not registered to Red Hat Subscription Management. You can use subscription-manager to register.
上次元数据过期检查:0:29:34 前,执行于 2022年12月02日 星期五 04时05分55秒。
已安装的软件包
tuned.noarch 2.15.0-2.el8 @anaconda
可安装的软件包
tuned.noarch 2.15.0-2.el8_4.1 base
tuned-gtk.noarch 2.15.0-2.el8_4.1 appstream
tuned-profiles-atomic.noarch 2.15.0-2.el8_4.1 base
tuned-profiles-compat.noarch 2.15.0-2.el8_4.1 base
tuned-profiles-cpu-partitioning.noarch 2.15.0-2.el8_4.1 base
tuned-profiles-mssql.noarch 2.15.0-2.el8_4.1 base
tuned-profiles-oracle.noarch 2.15.0-2.el8_4.1 base
tuned-utils.noarch 2.15.0-2.el8_4.1 appstream
tuned-utils-systemtap.noarch 2.15.0-2.el8_4.1 appstream
配置文件在 /usr/lib/tuned
路径下
[root@server1 ~]# cd /usr/lib/tuned/
[root@server1 tuned]# pwd
/usr/lib/tuned
[root@server1 tuned]# ll
总用量 16
drwxr-xr-x. 2 root root 24 11月 9 01:19 accelerator-performance
drwxr-xr-x. 2 root root 24 11月 9 01:19 balanced
drwxr-xr-x. 2 root root 24 11月 9 01:19 desktop
-rw-r--r--. 1 root root 14833 12月 17 2020 functions
drwxr-xr-x. 2 root root 24 11月 9 01:19 hpc-compute
drwxr-xr-x. 2 root root 24 11月 9 01:19 intel-sst
drwxr-xr-x. 2 root root 24 11月 9 01:19 latency-performance
drwxr-xr-x. 2 root root 24 11月 9 01:19 network-latency
drwxr-xr-x. 2 root root 24 11月 9 01:19 network-throughput
drwxr-xr-x. 2 root root 24 11月 9 01:19 optimize-serial-console
drwxr-xr-x. 2 root root 41 11月 9 01:19 powersave
drwxr-xr-x. 2 root root 27 11月 9 01:19 recommend.d
drwxr-xr-x. 2 root root 24 11月 9 01:19 throughput-performance
drwxr-xr-x. 2 root root 24 11月 9 01:19 virtual-guest
drwxr-xr-x. 2 root root 24 11月 9 01:19 virtual-host
[root@server1 tuned]# cat virtual-guest/tuned.conf
[main]
summary=Optimize for running inside a virtual guest
include=throughput-performance
[sysctl]
# If a workload mostly uses anonymous memory and it hits this limit, the entire
# working set is buffered for I/O, and any more write buffering would require
# swapping, so it's time to throttle writes until I/O can catch up. Workloads
# that mostly use file mappings may be able to use even higher values.
#
# The generator of dirty data starts writeback at this percentage (system default
# is 20%)
vm.dirty_ratio = 30
# Filesystem I/O is usually much more efficient than swapping, so try to keep
# swapping low. It's usually safe to go even lower than this on systems with
# server-grade storage.
vm.swappiness = 30
[root@server1 tuned]#
切换模式
[root@server1 ~]# tuned-adm list
Available profiles:
- accelerator-performance - Throughput performance based tuning with disabled higher latency STOP states
- balanced - General non-specialized tuned profile
- desktop - Optimize for the desktop use-case
- hpc-compute - Optimize for HPC compute workloads
- intel-sst - Configure for Intel Speed Select Base Frequency
- latency-performance - Optimize for deterministic performance at the cost of increased power consumption
- network-latency - Optimize for deterministic performance at the cost of increased power consumption, focused on low latency network performance
- network-throughput - Optimize for streaming network throughput, generally only necessary on older CPUs or 40G+ networks
- optimize-serial-console - Optimize for serial console use.
- powersave - Optimize for low power consumption
- rhel134 - Optimize for running inside a virtual guest
- throughput-performance - Broadly applicable tuning that provides excellent performance across a variety of common server workloads
- virtual-guest - Optimize for running inside a virtual guest
- virtual-host - Optimize for running KVM guests
Current active profile: virtual-guest
# 执行下面命令进行切换
[root@server1 ~]# tuned-adm profile rhel134
查看建议模式
[root@server1 tuned]# tuned-adm recommend
virtual-guest
[root@server1 tuned]#
ACL访问控制列表
ACL基本用法
获取文件的访问控制列表
[root@server1 opt]# ll 1.txt
-rw-r--r--. 1 root root 5 12月 2 04:56 1.txt
[root@server1 opt]# getfacl -c 1.txt
user::rw-
group::r--
other::r--
[root@server1 opt]#
设置 ACL
# 给用户设权限
# zhuchun 用户就可以向 root 用户的 /opt/1.txt 文件写内容了
[root@server1 opt]# setfacl -m u:zhuchun:rw- 1.txt
[root@server1 opt]# getfacl -c 1.txt
user::rw-
user:zhuchun:rw-
group::r--
mask::rw-
other::r--
# 给组设权限后,再将一个已登录用户添加到此权限组,此用户必须重新登录才能拥有组的acl权限
[root@server1 opt]# setfacl -m g:zhuchun:rw- 1.txt
[root@server1 opt]# getfacl -c 1.txt
user::rw-
group::r--
group:zhuchun:rw-
mask::rw-
other::r--
取消ACL
[root@server1 opt]# setfacl -x u:zhuchun 1.txt
[root@server1 opt]# getfacl -c 1.txt
user::rw-
group::r--
mask::r--
other::r--
[root@server1 opt]#
mask权限
[root@server1 opt]# getfacl -c 1.txt
user::rw- | ACL_USER_OBJ | 文件的所有者 |
user:zhuchun:rw- | ACL_USER | 通过acl授权的用户 |
group::r-- | ACL_GROUP_OBJ | 文件所属组 |
group:zhuchun:rw- | ACL_GROUP | 通过acl授权的组 |
mask::r-- | ACL_MASK | ACL_USER,ACL_GROUP_OBJ,ACL_GROUP的最大权限 |
other::r-- |
如果没有手动配置 ACL_MASK 的权限,则 ACL_MASK 的权限会随着 ACL_USER,ACL_GROUP_OBJ,ACL_GROUP 的变化而变化,始终是这几个权限的最大值。
如果 mask 设置的是 ---,则用户使用的权限是 other 的权限;如果不是 ---,则用户使用的是 acl 的权限
总结:如果没有手动设置 acl 的 mask 权限,则对用户/组设置的 acl 权限生效,不用考虑 o 的权限。如果手动设置了 mask 的权限,则用户最终的权限是 acl 最终权限 +other 权限的集合。
给目录设置 ACL 权限
[root@server1 opt]# ll -d aa
drwxr-xr-x. 2 root root 6 12月 2 05:33 aa
[root@server1 opt]# getfacl -c aa
user::rwx
group::r-x
other::r-x
# 此命令针对的是 aa 目录中新建的文件
[root@server1 opt]# setfacl -m d:u:zhuchun:rwx aa
# 取消 acl 权限
[root@server1 opt]# setfacl -x d:u:zhuchun aa
SELinux
什么是 selinux
selinux全称是 Security-Enhanced Linux,目的是提高系统的安全性。当我们执行某个操作的时候,如果 selinux 认为此操作有危险,则会拒绝进一步的访问。在 Ubuntu 中叫 apparmor。
了解 selinux 的上下文
在开启了 selinux 的情况下,selinux 会为每个文件,每个进程都分配一个标签,这个标签称之为上下文。
假设一个进程 xx 的标签是 aa-p,它能访问标签为 aa-f 的文件,所以 xx 进程访问文件 aa 是没问题的,因为标签匹配。但是 xx 进程访问文件 bb 的时候却是访问不了的,因为文件 bb 的标签是 bb-f。
查看上下文
# 加上 -Z 查看,usr_t 是此文件的上下文
[root@server1 opt]# ll -dZ aa
drwxr-xr-x+ 2 root root unconfined_u:object_r:usr_t:s0 20 12月 2 05:36 aa
# httpd_t 是对应进程的上下文,特定上下文的进程只能访问特定上下文的文件
[root@server1 opt]# ps -efZ |grep httpd |grep -v grep
system_u:system_r:httpd_t:s0 root 12973 1 0 05:54 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 12976 12973 0 05:54 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 12977 12973 0 05:54 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 12978 12973 0 05:54 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 12979 12973 0 05:54 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
改变上下文
[root@server1 ~]# ls -ldZ /www
drwxr-xr-x. 2 root root unconfined_u:object_r:default_t:s0 6 12月 4 04:14 /www
# 改上下文,-R是递归目录
[root@server1 ~]# chcon -R -t httpd_sys_content_t /www
[root@server1 ~]# ls -ldZ /www
drwxr-xr-x. 2 root root unconfined_u:object_r:httpd_sys_content_t:s0 6 12月 4 04:14 /www
还原上下文为默认值
[root@server1 ~]# ls -ldZ /www
drwxr-xr-x. 2 root root unconfined_u:object_r:httpd_sys_content_t:s0 6 12月 4 04:14 /www
[root@server1 ~]# restorecon -R /www
[root@server1 ~]# ls -ldZ /www
drwxr-xr-x. 2 root root unconfined_u:object_r:default_t:s0 6 12月 4 04:14 /www
修改默认上下文
[root@server1 ~]# ls -ldZ /www
drwxr-xr-x. 2 root root unconfined_u:object_r:default_t:s0 6 12月 4 04:14 /www
# fcontext是设置文件的上下文,-a 是添加
[root@server1 ~]# semanage fcontext -a -t httpd_sys_content_t "/www(/.*)?"
[root@server1 ~]# restorecon -R /www
[root@server1 ~]# ls -ldZ /www
drwxr-xr-x. 2 root root unconfined_u:object_r:httpd_sys_content_t:s0 6 12月 4 04:14 /www
# 如果已定义过的,你再定义会报错。
[root@server1 ~]# semanage fcontext -a -t httpd_sys_content_t "/www(/.*)?"
ValueError: /www(/.*)? 的文件上下文已定义
# 删除已定义过的默认上下文
[root@server1 ~]# semanage fcontext -d -t httpd_sys_content_t "/www(/.*)?"
# 再添加默认上下文
[root@server1 ~]# semanage fcontext -a -t httpd_sys_content_t "/www(/.*)?"
# 直接更改
[root@server1 ~]# semanage fcontext -m -t httpd_sys_content_t "/www(/.*)?"
了解 selinux 的端口上下文
查看端口上下文
[root@server1 ~]# semanage port -l |grep '\b80\b'
http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
给端口添加上下文
[root@server1 ~]# semanage port -a -t http_port_t -p tcp 808
[root@server1 ~]# semanage port -l |grep '\b808\b'
http_port_t tcp 808, 80, 81, 443, 488, 8008, 8009, 8443, 9000
取消端口上下文
[root@server1 ~]# semanage port -d -t http_port_t -p tcp 808
selinux的两种模式
查看模式
[root@server1 ~]# getenforce
Enforcing
Enforcing模式
如果不满足selinux条件的话,则selinux会阻止访问服务并提供警报
临时设置Enforcing模式
[root@server1 ~]# setenforce Enforcing
[root@server1 ~]# getenforce
Enforcing
[root@server1 ~]# setenforce 1
[root@server1 ~]# getenforce
Enforcing
Permissive
如果不满足selinux条件,则selinux不阻止访问,但是会警报
临时设置Permissive模式
[root@server1 ~]# setenforce 0
[root@server1 ~]# getenforce
Permissive
[root@server1 ~]# setenforce Permissive
[root@server1 ~]# getenforce
Permissive
永久设置模式
随便修改下面两个文件中的某一个,实际是同一个文件做的软连接
[root@server1 ~]# ll /etc/sysconfig/selinux
lrwxrwxrwx. 1 root root 17 11月 9 01:17 /etc/sysconfig/selinux -> ../selinux/config
[root@server1 ~]# ll /etc/selinux/config
-rw-r--r--. 1 root root 548 11月 9 01:17 /etc/selinux/config
# config 文件内容
[root@server1 ~]# cat /etc/selinux/config
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
# 修改下面的值就可设置 selinux 的模式,enforcing、permissive这两个模式可以在线切换,但是这两个和 disabled 不能在线切换
SELINUX=enforcing
# SELINUXTYPE= can take one of these three values:
# targeted - Targeted processes are protected,
# minimum - Modification of targeted policy. Only selected processes are protected.
# mls - Multi Level Security protection.
SELINUXTYPE=targeted
[root@server1 ~]#
selinux的布尔值
理解为一个功能开关
获取布尔值
# 获取系统中所有的布尔值
[root@server1 ~]# getsebool -a
# 过滤出 ftp 相关的布尔值
[root@server1 ~]# getsebool -a |grep ftp
ftpd_anon_write --> off
ftpd_connect_all_unreserved --> off
ftpd_connect_db --> off
ftpd_full_access --> off
ftpd_use_cifs --> off
ftpd_use_fusefs --> off
ftpd_use_nfs --> off
ftpd_use_passive_mode --> off
httpd_can_connect_ftp --> off
httpd_enable_ftp_server --> off
tftp_anon_write --> off
tftp_home_dir --> off
[root@server1 ~]# getsebool -a |grep ftpd_full_access
ftpd_full_access --> off
设置布尔值(临时生效,重启后失效)
# 设置某个服务的selinux 的布尔值
[root@server1 ~]# setsebool ftpd_full_access on
[root@server1 ~]# setsebool ftpd_full_access 1
[root@server1 ~]# setsebool ftpd_full_access off
[root@server1 ~]# setsebool ftpd_full_access 0
永久设置布尔值,加上(-P)选项
[root@server1 ~]# setsebool -P ftpd_full_access on
[root@server1 ~]# setsebool -P ftpd_full_access 1
[root@server1 ~]# setsebool -P ftpd_full_access off
[root@server1 ~]# setsebool -P ftpd_full_access 0
分区管理
了解分区概念
一块硬盘在进行格式化的时候,会让你选择是用 MBR 格式还是 GPT 格式
MBR:主引导记录,主引导扇区
GPT:Guid partition table
MBR兼容性较好,不能用于大于2T的硬盘,GPT兼容性差一些,但是可以用于大于2T的硬盘,支持到128个主分区。
主分区:直接从硬盘上划分并可以直接格式化使用的分区
扩展分区-直接从硬盘上划分,但是不直接使用的分区,需要在其上面划分更多个小分区
逻辑分区-在扩展分区上划分的分区
划分分区
查看所有硬盘的分区信息
[root@server1 ~]# fdisk -l
Disk /dev/sda:100 GiB,107374182400 字节,209715200 个扇区
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0x16dc60ad
设备 启动 起点 末尾 扇区 大小 Id 类型
/dev/sda1 * 2048 125831167 125829120 60G 83 Linux
/dev/sda2 125831168 146802687 20971520 10G 83 Linux
/dev/sda3 146802688 150996991 4194304 2G 82 Linux swap / Solaris
/dev/sda4 150996992 154904575 3907584 1.9G 83 Linux
Disk /dev/sdb:20 GiB,21474836480 字节,41943040 个扇区
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0x1c04a3b0
查看某个硬盘的分区信息
[root@server1 ~]# fdisk -l /dev/sda
Disk /dev/sda:100 GiB,107374182400 字节,209715200 个扇区
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0x16dc60ad
设备 启动 起点 末尾 扇区 大小 Id 类型
/dev/sda1 * 2048 125831167 125829120 60G 83 Linux
/dev/sda2 125831168 146802687 20971520 10G 83 Linux
/dev/sda3 146802688 150996991 4194304 2G 82 Linux swap / Solaris
/dev/sda4 150996992 154904575 3907584 1.9G 83 Linux
创建分区
[root@server1 ~]# fdisk /dev/sdb
欢迎使用 fdisk (util-linux 2.32.1)。
更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。
命令(输入 m 获取帮助):m # 输入m查看帮助文档
帮助:
DOS (MBR)
a 开关 可启动 标志
b 编辑嵌套的 BSD 磁盘标签
c 开关 dos 兼容性标志
常规
d 删除分区
F 列出未分区的空闲区
l 列出已知分区类型
n 添加新分区
p 打印分区表
t 更改分区类型
v 检查分区表
i 打印某个分区的相关信息
杂项
m 打印此菜单
u 更改 显示/记录 单位
x 更多功能(仅限专业人员)
脚本
I 从 sfdisk 脚本文件加载磁盘布局
O 将磁盘布局转储为 sfdisk 脚本文件
保存并退出
w 将分区表写入磁盘并退出
q 退出而不保存更改
新建空磁盘标签
g 新建一份 GPT 分区表
G 新建一份空 GPT (IRIX) 分区表
o 新建一份的空 DOS 分区表
s 新建一份空 Sun 分区表
命令(输入 m 获取帮助):p # 输入 p 打印分区表
Disk /dev/sdb:20 GiB,21474836480 字节,41943040 个扇区
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0x1c04a3b0
命令(输入 m 获取帮助):n # 输入n创建新分区
分区类型
p 主分区 (0个主分区,0个扩展分区,4空闲)
e 扩展分区 (逻辑分区容器)
选择 (默认 p):p # 类型为主分区
分区号 (1-4, 默认 1): # 默认1
第一个扇区 (2048-41943039, 默认 2048): # 默认从 2048个扇区开始
上个扇区,+sectors 或 +size{K,M,G,T,P} (2048-41943039, 默认 41943039): 4196351 # 创建2GB = 2*2048*2048*2 -1
创建了一个新分区 1,类型为“Linux”,大小为 2 GiB。
命令(输入 m 获取帮助):p
Disk /dev/sdb:20 GiB,21474836480 字节,41943040 个扇区
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0x1c04a3b0
设备 启动 起点 末尾 扇区 大小 Id 类型
/dev/sdb1 2048 4196351 4194304 2G 83 Linux
命令(输入 m 获取帮助):d # 输入d删除分区,因为只有一个分区,所以默认就删了此分区1
已选择分区 1
分区 1 已删除。
命令(输入 m 获取帮助):p
Disk /dev/sdb:20 GiB,21474836480 字节,41943040 个扇区
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0x1c04a3b0
命令(输入 m 获取帮助):n
分区类型
p 主分区 (0个主分区,0个扩展分区,4空闲)
e 扩展分区 (逻辑分区容器)
选择 (默认 p):
将使用默认回应 p。
分区号 (1-4, 默认 1):
第一个扇区 (2048-41943039, 默认 2048):
上个扇区,+sectors 或 +size{K,M,G,T,P} (2048-41943039, 默认 41943039): +2G # 输入 +2G 表示分区大小为2GB
创建了一个新分区 1,类型为“Linux”,大小为 2 GiB。
命令(输入 m 获取帮助):p
Disk /dev/sdb:20 GiB,21474836480 字节,41943040 个扇区
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0x1c04a3b0
设备 启动 起点 末尾 扇区 大小 Id 类型
/dev/sdb1 2048 4196351 4194304 2G 83 Linux
命令(输入 m 获取帮助):n
分区类型
p 主分区 (1个主分区,0个扩展分区,3空闲)
e 扩展分区 (逻辑分区容器)
选择 (默认 p):p
分区号 (2-4, 默认 2):
第一个扇区 (4196352-41943039, 默认 4196352):
上个扇区,+sectors 或 +size{K,M,G,T,P} (4196352-41943039, 默认 41943039): +2G
创建了一个新分区 2,类型为“Linux”,大小为 2 GiB。
命令(输入 m 获取帮助):p
Disk /dev/sdb:20 GiB,21474836480 字节,41943040 个扇区
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0x1c04a3b0
设备 启动 起点 末尾 扇区 大小 Id 类型
/dev/sdb1 2048 4196351 4194304 2G 83 Linux
/dev/sdb2 4196352 8390655 4194304 2G 83 Linux
命令(输入 m 获取帮助):n
分区类型
p 主分区 (2个主分区,0个扩展分区,2空闲)
e 扩展分区 (逻辑分区容器)
选择 (默认 p):e # 新建的类型是扩展分区,只有建了扩展分区才能建逻辑分区
分区号 (3,4, 默认 3):
第一个扇区 (8390656-41943039, 默认 8390656):
上个扇区,+sectors 或 +size{K,M,G,T,P} (8390656-41943039, 默认 41943039):
创建了一个新分区 3,类型为“Extended”,大小为 16 GiB。
命令(输入 m 获取帮助):p
Disk /dev/sdb:20 GiB,21474836480 字节,41943040 个扇区
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0x1c04a3b0
设备 启动 起点 末尾 扇区 大小 Id 类型
/dev/sdb1 2048 4196351 4194304 2G 83 Linux
/dev/sdb2 4196352 8390655 4194304 2G 83 Linux
/dev/sdb3 8390656 41943039 33552384 16G 5 扩展
命令(输入 m 获取帮助):n
所有主分区的空间都在使用中。
添加逻辑分区 5
第一个扇区 (8392704-41943039, 默认 8392704):
上个扇区,+sectors 或 +size{K,M,G,T,P} (8392704-41943039, 默认 41943039): +2G
创建了一个新分区 5,类型为“Linux”,大小为 2 GiB。
命令(输入 m 获取帮助):p
Disk /dev/sdb:20 GiB,21474836480 字节,41943040 个扇区
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0x1c04a3b0
设备 启动 起点 末尾 扇区 大小 Id 类型
/dev/sdb1 2048 4196351 4194304 2G 83 Linux
/dev/sdb2 4196352 8390655 4194304 2G 83 Linux
/dev/sdb3 8390656 41943039 33552384 16G 5 扩展
/dev/sdb5 8392704 12587007 4194304 2G 83 Linux
命令(输入 m 获取帮助):l # 输入 l 可以查看分区的类型,及其对应的 id
0 空 24 NEC DOS 81 Minix / 旧 Linu bf Solaris
1 FAT12 27 隐藏的 NTFS Win 82 Linux swap / So c1 DRDOS/sec (FAT-
2 XENIX root 39 Plan 9 83 Linux c4 DRDOS/sec (FAT-
3 XENIX usr 3c PartitionMagic 84 OS/2 隐藏 或 In c6 DRDOS/sec (FAT-
4 FAT16 <32M 40 Venix 80286 85 Linux 扩展 c7 Syrinx
5 扩展 41 PPC PReP Boot 86 NTFS 卷集 da 非文件系统数据
6 FAT16 42 SFS 87 NTFS 卷集 db CP/M / CTOS / .
7 HPFS/NTFS/exFAT 4d QNX4.x 88 Linux 纯文本 de Dell 工具
8 AIX 4e QNX4.x 第2部分 8e Linux LVM df BootIt
9 AIX 可启动 4f QNX4.x 第3部分 93 Amoeba e1 DOS 访问
a OS/2 启动管理器 50 OnTrack DM 94 Amoeba BBT e3 DOS R/O
b W95 FAT32 51 OnTrack DM6 Aux 9f BSD/OS e4 SpeedStor
c W95 FAT32 (LBA) 52 CP/M a0 IBM Thinkpad 休 ea Rufus 对齐
e W95 FAT16 (LBA) 53 OnTrack DM6 Aux a5 FreeBSD eb BeOS fs
f W95 扩展 (LBA) 54 OnTrackDM6 a6 OpenBSD ee GPT
10 OPUS 55 EZ-Drive a7 NeXTSTEP ef EFI (FAT-12/16/
11 隐藏的 FAT12 56 Golden Bow a8 Darwin UFS f0 Linux/PA-RISC
12 Compaq 诊断 5c Priam Edisk a9 NetBSD f1 SpeedStor
14 隐藏的 FAT16 <3 61 SpeedStor ab Darwin 启动 f4 SpeedStor
16 隐藏的 FAT16 63 GNU HURD 或 Sys af HFS / HFS+ f2 DOS 次要
17 隐藏的 HPFS/NTF 64 Novell Netware b7 BSDI fs fb VMware VMFS
18 AST 智能睡眠 65 Novell Netware b8 BSDI swap fc VMware VMKCORE
1b 隐藏的 W95 FAT3 70 DiskSecure 多启 bb Boot Wizard 隐 fd Linux raid 自动
1c 隐藏的 W95 FAT3 75 PC/IX bc Acronis FAT32 L fe LANstep
1e 隐藏的 W95 FAT1 80 旧 Minix be Solaris 启动 ff BBT
命令(输入 m 获取帮助):t # 输入 t 来变更分区类型
分区号 (1-3,5-9, 默认 9): 2 # 选择分区2 来进行变更
Hex 代码(输入 L 列出所有代码):82 # 变更为类型Id 为 82 的类型,对应上面是 Linux swap / Solaris
已将分区“Linux”的类型更改为“Linux swap / Solaris”。
命令(输入 m 获取帮助):p
Disk /dev/sdb:20 GiB,21474836480 字节,41943040 个扇区
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0x1c04a3b0
设备 启动 起点 末尾 扇区 大小 Id 类型
/dev/sdb1 2048 4196351 4194304 2G 83 Linux
/dev/sdb2 4196352 8390655 4194304 2G 82 Linux swap / Solaris
命令(输入 m 获取帮助):t
分区号 (1-3,5-9, 默认 9): 5
Hex 代码(输入 L 列出所有代码):8e
已将分区“Linux”的类型更改为“Linux LVM”。
命令(输入 m 获取帮助):w # 输入 w 来进行保存我们分区的操作
分区表已调整。
将调用 ioctl() 来重新读分区表。
正在同步磁盘。
# 执行下面步骤,强制刷新下分区表,主动同步
[root@server1 ~]# partprobe /dev/sdb
# 下面两个命令都可以看到最新的分区信息
[root@server1 ~]# fdisk -l
Disk /dev/sda:100 GiB,107374182400 字节,209715200 个扇区
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0x16dc60ad
设备 启动 起点 末尾 扇区 大小 Id 类型
/dev/sda1 * 2048 125831167 125829120 60G 83 Linux
/dev/sda2 125831168 146802687 20971520 10G 83 Linux
/dev/sda3 146802688 150996991 4194304 2G 82 Linux swap / Solaris
/dev/sda4 150996992 154904575 3907584 1.9G 83 Linux
Disk /dev/sdb:20 GiB,21474836480 字节,41943040 个扇区
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0x1c04a3b0
设备 启动 起点 末尾 扇区 大小 Id 类型
/dev/sdb1 2048 4196351 4194304 2G 83 Linux
/dev/sdb2 4196352 8390655 4194304 2G 82 Linux swap / Solaris
/dev/sdb3 8390656 41943039 33552384 16G 5 扩展
/dev/sdb5 8392704 12587007 4194304 2G 8e Linux LVM
/dev/sdb6 12589056 16783359 4194304 2G 8e Linux LVM
/dev/sdb7 16785408 20979711 4194304 2G 8e Linux LVM
/dev/sdb8 20981760 25176063 4194304 2G 8e Linux LVM
/dev/sdb9 25178112 29372415 4194304 2G 8e Linux LVM
[root@server1 ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 100G 0 disk
├─sda1 8:1 0 60G 0 part /
├─sda2 8:2 0 10G 0 part /home
├─sda3 8:3 0 2G 0 part [SWAP]
└─sda4 8:4 0 1.9G 0 part
sdb 8:16 0 20G 0 disk
├─sdb1 8:17 0 2G 0 part
├─sdb2 8:18 0 2G 0 part
├─sdb3 8:19 0 512B 0 part
├─sdb5 8:21 0 2G 0 part
├─sdb6 8:22 0 2G 0 part
├─sdb7 8:23 0 2G 0 part
├─sdb8 8:24 0 2G 0 part
└─sdb9 8:25 0 2G 0 part
也可以使用 parted 命令来进行分区
格式化分区
# 格式化为 MBR
[root@server1 ~]# parted -s /dev/sdb mklabel msdos
# 格式化为 GUID 分区
[root@server1 ~]# parted -s /dev/sdb mklabel gpt
# 既不选择 MBR 也不是 GUID
[root@server1 ~]# parted -s /dev/sdb mklabel loop
[root@server1 ~]# mkfs.xfs /dev/sdb1
meta-data=/dev/sdb1 isize=512 agcount=4, agsize=131072 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=1, sparse=1, rmapbt=0
= reflink=1
data = bsize=4096 blocks=524288, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0, ftype=1
log =internal log bsize=4096 blocks=2560, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
[root@server1 ~]# mkfs.xfs -b size=1024 /dev/sdb1
mkfs.xfs: /dev/sdb1 appears to contain an existing filesystem (xfs).
mkfs.xfs: Use the -f option to force overwrite.
[root@server1 ~]# mkfs.xfs -b size=1024 /dev/sdb1 -f # 通过 -f 强制进行格式化 ;-b 设置区块的大小为1k,默认是4k即4096
meta-data=/dev/sdb1 isize=512 agcount=4, agsize=524288 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=1, sparse=1, rmapbt=0
= reflink=1
data = bsize=1024 blocks=2097152, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0, ftype=1
log =internal log bsize=1024 blocks=10240, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
[root@server1 ~]# xfs_info /dev/sdb1 # 查看分区的属性
meta-data=/dev/sdb1 isize=512 agcount=4, agsize=524288 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=1, sparse=1, rmapbt=0
= reflink=1
data = bsize=1024 blocks=2097152, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0, ftype=1
log =internal log bsize=1024 blocks=10240, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
每个文件系统都有唯一的一个ID,叫作UUID
[root@server1 ~]# blkid
/dev/sda1: UUID="c5c5b198-a07c-4cf9-8c0f-4c71f5d938a2" BLOCK_SIZE="512" TYPE="xfs" PARTUUID="16dc60ad-01"
/dev/sda2: UUID="9dc1bb8e-3294-49d9-ae86-60db9e86c9d0" BLOCK_SIZE="512" TYPE="xfs" PARTUUID="16dc60ad-02"
/dev/sda3: UUID="4250a782-471e-4965-b0f2-a2ecd975b860" TYPE="swap" PARTUUID="16dc60ad-03"
/dev/sda4: LABEL="xx" UUID="c0bb0ee1-032c-450f-81ee-4bdd60c74a99" BLOCK_SIZE="512" TYPE="xfs" PARTUUID="16dc60ad-04"
/dev/sdb1: UUID="3dcbe85d-27b9-4d47-b476-1a26ff3d5bed" BLOCK_SIZE="512" TYPE="xfs" PARTUUID="1c04a3b0-01"
/dev/sdb2: PARTUUID="1c04a3b0-02"
/dev/sdb5: PARTUUID="1c04a3b0-05"
/dev/sdb6: PARTUUID="1c04a3b0-06"
/dev/sdb7: PARTUUID="1c04a3b0-07"
/dev/sdb8: PARTUUID="1c04a3b0-08"
/dev/sdb9: PARTUUID="1c04a3b0-09"
/dev/sr0: BLOCK_SIZE="2048" UUID="2021-05-03-15-21-56-00" LABEL="RHEL-8-4-0-BaseOS-x86_64" TYPE="iso9660" PTUUID="426eea3b" PTTYPE="dos"
xfs文件系统可以通过 xfs-admin 进行查看
[root@server1 ~]# xfs_admin -u /dev/sdb1
UUID = 3dcbe85d-27b9-4d47-b476-1a26ff3d5bed
# 修改UUID
[root@server1 ~]# uuidgen
5ed29923-8248-4473-88bb-a3e6501e4c9d
[root@server1 ~]# xfs_admin -U 5ed29923-8248-4473-88bb-a3e6501e4c9d /dev/sdb1
Clearing log and setting UUID
writing all SBs
new UUID = 5ed29923-8248-4473-88bb-a3e6501e4c9d
了解swap分区
虚拟内存,为了解决物理内存不足情况下,将会使用一部分硬盘空间来模拟内存。当物理内存使用率达到70%时,就会开始使用虚拟内存,通过 /proc/sys/vm/swapiness 可以查看阈值的配置,即当内存使用率达到(100-30)% 的时候就会使用虚拟内存。
[root@server1 ~]# cat /proc/sys/vm/swappiness
30
# 把值设置为0,可以优化使用,即尽可能使用物理内存
[root@server1 ~]# echo 0 > /proc/sys/vm/swappiness
最终能够分配出去的内存总量=物理内存*overcommit_ratio+swap分区
[root@server1 ~]# cat /proc/sys/vm/overcommit_ratio
50
假设 mem 大小是 128G,最终分配出去的内存=128*0.5+swap,如果swap=0,则最终分配出去内存为64G
查看交换分区的大小
[root@server1 ~]# cat /proc/swaps
Filename Type Size Used Priority
/dev/sda3 partition 2097148 30932 -2
[root@server1 ~]# swapon -s
文件名 类型 大小 已用 权限
/dev/sda3 partition 2097148 30932 -2
swap分区不足时,可以调整swap
# 创建交换分区
[root@server1 ~]# mkswap /dev/sdb2
正在设置交换空间版本 1,大小 = 2 GiB (2147479552 个字节)
无标签,UUID=c563a140-88d2-4b84-acc2-089b559a6997
[root@server1 ~]# swapon -s
文件名 类型 大小 已用 权限
/dev/sda3 partition 2097148 30932 -2
# 需要开启一下
[root@server1 ~]# swapon /dev/sdb2
[root@server1 ~]# swapon -s
文件名 类型 大小 已用 权限
/dev/sda3 partition 2097148 30932 -2
/dev/sdb2 partition 2097148 0 -3
# 关闭swap分区
[root@server1 ~]# swapoff /dev/sdb2
[root@server1 ~]# swapon -s
文件名 类型 大小 已用 权限
/dev/sda3 partition 2097148 30556 -2
多个 swap分区的时候,优先根据“权限”来决定用哪个,数值越大,越优先。
调整使用优先级,调整权限
[root@server1 ~]# swapon -p 2 /dev/sdb2
[root@server1 ~]# swapon -s
文件名 类型 大小 已用 权限
/dev/sda3 partition 2097148 30812 -2
/dev/sdb2 partition 2097148 0 2
在 fstab 中配置 swap
[root@server1 ~]# vim /etc/fstab
/dev/sdb2 swap swap defaults,pri=2 0 0
[root@server1 ~]# swapon -a
[root@server1 ~]# swapon -s
文件名 类型 大小 已用 权限
/dev/sda3 partition 2097148 30628 -2
/dev/sdb2 partition 2097148 0 2
逻辑卷 lv
逻辑卷介绍
把多个分区 PV 组合成一个虚拟的硬盘 VG,在虚拟硬盘上可以再次划分逻辑卷 LV,所有逻辑卷空间大小不能超过虚拟硬盘,逻辑卷不会影响性能。
逻辑卷空间不够使用时,可以进行动态扩容,逻辑卷最大特点:空间是可变的
逻辑卷管理
创建删除逻辑卷
[root@server1 ~]# pvscan
No matching physical volumes found
[root@server1 ~]# pvs
[root@server1 ~]# fdisk -l
Disk /dev/sda:100 GiB,107374182400 字节,209715200 个扇区
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0x16dc60ad
设备 启动 起点 末尾 扇区 大小 Id 类型
/dev/sda1 * 2048 125831167 125829120 60G 83 Linux
/dev/sda2 125831168 146802687 20971520 10G 83 Linux
/dev/sda3 146802688 150996991 4194304 2G 82 Linux swap / Solaris
/dev/sda4 150996992 154904575 3907584 1.9G 83 Linux
Disk /dev/sdb:20 GiB,21474836480 字节,41943040 个扇区
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0x1c04a3b0
设备 启动 起点 末尾 扇区 大小 Id 类型
/dev/sdb1 2048 4196351 4194304 2G 83 Linux
/dev/sdb2 4196352 8390655 4194304 2G 82 Linux swap / Solaris
/dev/sdb3 8390656 41943039 33552384 16G 5 扩展
/dev/sdb5 8392704 12587007 4194304 2G 8e Linux LVM
/dev/sdb6 12589056 16783359 4194304 2G 8e Linux LVM
/dev/sdb7 16785408 20979711 4194304 2G 8e Linux LVM
/dev/sdb8 20981760 25176063 4194304 2G 8e Linux LVM
/dev/sdb9 25178112 29372415 4194304 2G 8e Linux LVM
# 基于sdb5-9 分区创建 pv
[root@server1 ~]# pvcreate /dev/sdb{5..9}
Physical volume "/dev/sdb5" successfully created.
Physical volume "/dev/sdb6" successfully created.
Physical volume "/dev/sdb7" successfully created.
Physical volume "/dev/sdb8" successfully created.
Physical volume "/dev/sdb9" successfully created.
# VG列为空,表示还没加入任何卷组中
[root@server1 ~]# pvs
PV VG Fmt Attr PSize PFree
/dev/sdb5 lvm2 --- 2.00g 2.00g
/dev/sdb6 lvm2 --- 2.00g 2.00g
/dev/sdb7 lvm2 --- 2.00g 2.00g
/dev/sdb8 lvm2 --- 2.00g 2.00g
/dev/sdb9 lvm2 --- 2.00g 2.00g
# 删除 pv
[root@server1 ~]# pvremove /dev/sdb{5..9}
Labels on physical volume "/dev/sdb5" successfully wiped.
Labels on physical volume "/dev/sdb6" successfully wiped.
Labels on physical volume "/dev/sdb7" successfully wiped.
Labels on physical volume "/dev/sdb8" successfully wiped.
Labels on physical volume "/dev/sdb9" successfully wiped.
# 系统中目前没有任何卷组
[root@server1 ~]# vgs
[root@server1 ~]# vgscan
# 创建卷组,名为 vg0
[root@server1 ~]# vgcreate vg0 /dev/sdb{5..9}
Volume group "vg0" successfully created
# 再次查看 vg 信息
[root@server1 ~]# vgs
VG #PV #LV #SN Attr VSize VFree
vg0 5 0 0 wz--n- 9.98g 9.98g
[root@server1 ~]# vgscan
Found volume group "vg0" using metadata type lvm2
[root@server1 ~]# pvs
PV VG Fmt Attr PSize PFree
/dev/sdb5 vg0 lvm2 a-- <2.00g <2.00g
/dev/sdb6 vg0 lvm2 a-- <2.00g <2.00g
/dev/sdb7 vg0 lvm2 a-- <2.00g <2.00g
/dev/sdb8 vg0 lvm2 a-- <2.00g <2.00g
/dev/sdb9 vg0 lvm2 a-- <2.00g <2.00g
# 查看vg详细信息
[root@server1 ~]# vgdisplay
--- Volume group ---
VG Name vg0
System ID
Format lvm2
Metadata Areas 5
Metadata Sequence No 3
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 0
Open LV 0
Max PV 0
Cur PV 5
Act PV 5
VG Size 9.98 GiB
PE Size 4.00 MiB # 扩展逻辑卷的时候最小大小,并且为 PE Size 的整数倍,,在创建 vg 时,通过 -s n 来设定此值,此处n默认为4
Total PE 2555
Alloc PE / Size 0 / 0
Free PE / Size 2555 / 9.98 GiB
VG UUID piXDoV-oKfe-RE1a-TiPL-UvGu-i540-Bwn0L8
# 重命名 vg 的名称
[root@server1 ~]# vgrename vg0 myvg
Volume group "vg0" successfully renamed to "myvg"
# 查看逻辑卷 lv
[root@server1 ~]# lvs
[root@server1 ~]# lvscan
# 创建逻辑卷,因为 PE=4,98不是4的整数倍,系统会自动扩展到整数倍的值即100MB,-L指定lv的大小,-l指定PE的倍数,
[root@server1 ~]# lvcreate -L 98M -n lv0 vg0
Rounding up size to full physical extent 100.00 MiB
Logical volume "lv0" created.
[root@server1 ~]# lvcreate -L 100M -n lv1 vg0
Logical volume "lv1" created.
[root@server1 ~]# lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
lv0 vg0 -wi-a----- 100.00m
lv1 vg0 -wi-a----- 100.00m
[root@server1 ~]# lvcreate -l 25 -n lv2 vg0
Logical volume "lv2" created.
[root@server1 ~]# lvscan
ACTIVE '/dev/vg0/lv0' [100.00 MiB] inherit
ACTIVE '/dev/vg0/lv1' [100.00 MiB] inherit
ACTIVE '/dev/vg0/lv2' [100.00 MiB] inherit
# 创建 lv3,使用剩余空间的 10%
[root@server1 ~]# lvcreate -l 10%free -n lv3 vg0
Logical volume "lv3" created.
[root@server1 ~]# lvscan
ACTIVE '/dev/vg0/lv0' [100.00 MiB] inherit
ACTIVE '/dev/vg0/lv1' [100.00 MiB] inherit
ACTIVE '/dev/vg0/lv2' [100.00 MiB] inherit
ACTIVE '/dev/vg0/lv3' [992.00 MiB] inherit
# 删除逻辑卷
[root@server1 ~]# lvremove /dev/vg0/lv3 -f
Logical volume "lv3" successfully removed
[root@server1 ~]# lvremove /dev/vg0/lv2 -f
Logical volume "lv2" successfully removed
[root@server1 ~]# lvscan
ACTIVE '/dev/vg0/lv0' [100.00 MiB] inherit
ACTIVE '/dev/vg0/lv1' [100.00 MiB] inherit
# 对逻辑卷进行格式化
[root@server1 ~]# mkfs.xfs /dev/vg0/lv0
meta-data=/dev/vg0/lv0 isize=512 agcount=4, agsize=6400 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=1, sparse=1, rmapbt=0
= reflink=1
data = bsize=4096 blocks=25600, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0, ftype=1
log =internal log bsize=4096 blocks=1368, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
[root@server1 ~]# mkfs.ext
mkfs.ext2 mkfs.ext3 mkfs.ext4
[root@server1 ~]# mkfs.ext
mkfs.ext2 mkfs.ext3 mkfs.ext4
[root@server1 ~]# mkfs.ext4 /dev/vg0/lv1
mke2fs 1.45.6 (20-Mar-2020)
创建含有 102400 个块(每块 1k)和 25688 个inode的文件系统
文件系统UUID:af01ebbe-7d24-488a-a4e0-716981c14a6f
超级块的备份存储于下列块:
8193, 24577, 40961, 57345, 73729
正在分配组表: 完成
正在写入inode表: 完成
创建日志(4096 个块)完成
写入超级块和文件系统账户统计信息: 已完成
# 挂载逻辑卷
[root@server1 ~]# mkdir /lv_xfs /lv_ext4
[root@server1 ~]# mount /dev/vg0/lv0 /lv_xfs/
[root@server1 ~]# mount /dev/vg0/lv1 /lv_ext4/
[root@server1 ~]# df -hT |grep lv
/dev/mapper/vg0-lv0 xfs 95M 6.0M 89M 7% /lv_xfs
/dev/mapper/vg0-lv1 ext4 93M 1.6M 85M 2% /lv_ext4
[root@server1 ~]# lvscan
ACTIVE '/dev/vg0/lv0' [100.00 MiB] inherit
ACTIVE '/dev/vg0/lv1' [100.00 MiB] inherit
扩大及缩小逻辑卷
# 缩小vg
[root@server1 ~]# vgreduce vg0 /dev/sdb9
Removed "/dev/sdb9" from volume group "vg0"
[root@server1 ~]# vgs
VG #PV #LV #SN Attr VSize VFree
vg0 4 0 0 wz--n- 7.98g 7.98g
[root@server1 ~]# pvs
PV VG Fmt Attr PSize PFree
/dev/sdb5 vg0 lvm2 a-- <2.00g <2.00g
/dev/sdb6 vg0 lvm2 a-- <2.00g <2.00g
/dev/sdb7 vg0 lvm2 a-- <2.00g <2.00g
/dev/sdb8 vg0 lvm2 a-- <2.00g <2.00g
/dev/sdb9 lvm2 --- 2.00g 2.00g
# 扩展vg
[root@server1 ~]# vgextend vg0 /dev/sdb9
Volume group "vg0" successfully extended
[root@server1 ~]# pvs
PV VG Fmt Attr PSize PFree
/dev/sdb5 vg0 lvm2 a-- <2.00g <2.00g
/dev/sdb6 vg0 lvm2 a-- <2.00g <2.00g
/dev/sdb7 vg0 lvm2 a-- <2.00g <2.00g
/dev/sdb8 vg0 lvm2 a-- <2.00g <2.00g
/dev/sdb9 vg0 lvm2 a-- <2.00g <2.00g
扩展逻辑卷的两种方式
# 1、在原有基础上增加200M
[root@server1 ~]# lvextend -L +200M /dev/vg0/lv0
Size of logical volume vg0/lv0 changed from 100.00 MiB (25 extents) to 300.00 MiB (75 extents).
Logical volume vg0/lv0 successfully resized.
# 2、调整总大小为300M
[root@server1 ~]# lvextend -L 300M /dev/vg0/lv1
Size of logical volume vg0/lv1 changed from 100.00 MiB (25 extents) to 300.00 MiB (75 extents).
Logical volume vg0/lv1 successfully resized.
[root@server1 ~]# lvscan
ACTIVE '/dev/vg0/lv0' [300.00 MiB] inherit
ACTIVE '/dev/vg0/lv1' [300.00 MiB] inherit
逻辑卷扩展完,还要将文件系统扩展,不同的文件系统的扩展方式也不同
# xfs文件系统
[root@server1 ~]# df -hT|grep lv
/dev/mapper/vg0-lv0 xfs 95M 6.0M 89M 7% /lv_xfs
/dev/mapper/vg0-lv1 ext4 93M 1.6M 85M 2% /lv_ext4
[root@server1 ~]# xfs_growfs /lv_xfs/
meta-data=/dev/mapper/vg0-lv0 isize=512 agcount=4, agsize=6400 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=1, sparse=1, rmapbt=0
= reflink=1
data = bsize=4096 blocks=25600, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0, ftype=1
log =internal log bsize=4096 blocks=1368, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
data blocks changed from 25600 to 76800
# ext4文件系统
[root@server1 ~]# resize2fs /dev/vg0/lv1
resize2fs 1.45.6 (20-Mar-2020)
/dev/vg0/lv1 上的文件系统已被挂载于 /lv_ext4;需要进行在线调整大小
old_desc_blocks = 1, new_desc_blocks = 3
/dev/vg0/lv1 上的文件系统现在为 307200 个块(每块 1k)。
[root@server1 ~]# df -hT|grep lv
/dev/mapper/vg0-lv0 xfs 295M 7.9M 287M 3% /lv_xfs
/dev/mapper/vg0-lv1 ext4 287M 2.0M 270M 1% /lv_ext4
扩展逻辑卷的时候,可以直接把fs一起扩展了
#lvextend -r 选项,会自动识别逻辑卷的文件系统并自动扩展
[root@server1 ~]# lvextend -L +100M -r /dev/vg0/lv0
Size of logical volume vg0/lv0 changed from 300.00 MiB (75 extents) to 400.00 MiB (100 extents).
Logical volume vg0/lv0 successfully resized.
meta-data=/dev/mapper/vg0-lv0 isize=512 agcount=12, agsize=6400 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=1, sparse=1, rmapbt=0
= reflink=1
data = bsize=4096 blocks=76800, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0, ftype=1
log =internal log bsize=4096 blocks=1368, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
[root@server1 ~]# lvscan
ACTIVE '/dev/vg0/lv0' [400.00 MiB] inherit
ACTIVE '/dev/vg0/lv1' [300.00 MiB] inherit
缩小逻辑卷,先缩小文件系统fs,再缩小逻辑卷lv,尽量避免缩小文件系统
# xfs文件系统只能扩展,不能缩小,ext4是可以的,以下演示 ext4
[root@server1 ~]# lvscan
ACTIVE '/dev/vg0/lv0' [400.00 MiB] inherit
ACTIVE '/dev/vg0/lv1' [400.00 MiB] inherit
# 先卸载文件系统
[root@server1 ~]# umount /lv_ext4
# 执行检查逻辑卷
[root@server1 ~]# fsck -f /dev/vg0/lv1
fsck,来自 util-linux 2.32.1
e2fsck 1.45.6 (20-Mar-2020)
第 1 步:检查inode、块和大小
第 2 步:检查目录结构
第 3 步:检查目录连接性
第 4 步:检查引用计数
第 5 步:检查组概要信息
/dev/mapper/vg0-lv1:11/98800 文件(0.0% 为非连续的), 18883/409600 块
# 将文件系统缩小到 100M
[root@server1 ~]# resize2fs /dev/vg0/lv1 100M
resize2fs 1.45.6 (20-Mar-2020)
将 /dev/vg0/lv1 上的文件系统调整为 102400 个块(每块 1k)。
/dev/vg0/lv1 上的文件系统现在为 102400 个块(每块 1k)。
# 将lv缩小300M到100M
[root@server1 ~]# lvreduce -L -300M /dev/vg0/lv1
WARNING: Reducing active logical volume to 100.00 MiB.
THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce vg0/lv1? [y/n]: y
Size of logical volume vg0/lv1 changed from 400.00 MiB (100 extents) to 100.00 MiB (25 extents).
Logical volume vg0/lv1 successfully resized.
# 重新挂载上去
[root@server1 ~]# mount /dev/vg0/lv1 /lv_ext4/
# 查看下大小
[root@server1 ~]# lvscan
ACTIVE '/dev/vg0/lv0' [400.00 MiB] inherit
ACTIVE '/dev/vg0/lv1' [100.00 MiB] inherit
[root@server1 ~]# df -hT | grep lv
/dev/mapper/vg0-lv0 xfs 395M 8.8M 386M 3% /lv_xfs
/dev/mapper/vg0-lv1 ext4 93M 1.6M 86M 2% /lv_ext4
逻辑卷快照
可以帮助我们备份数据,快照映射到原始lv里的那些文件,是不需要再次格式化的,需要挂载到目录才能正常使用。
创建快照
[root@server1 ~]# lvcreate -L 20M -n lv0_snap -s /dev/vg0/lv0
Logical volume "lv0_snap" created.
[root@server1 ~]# lvcreate -L 20M -n lv1_snap -s /dev/vg0/lv1
Logical volume "lv1_snap" created.
[root@server1 ~]# lvscan
ACTIVE Original '/dev/vg0/lv0' [400.00 MiB] inherit
ACTIVE Original '/dev/vg0/lv1' [100.00 MiB] inherit
ACTIVE Snapshot '/dev/vg0/lv0_snap' [20.00 MiB] inherit
ACTIVE Snapshot '/dev/vg0/lv1_snap' [20.00 MiB] inherit
# 通过lvs 命令查看快照和逻辑卷的关系
[root@server1 ~]# lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
lv0 vg0 owi-aos--- 400.00m
lv0_snap vg0 swi-a-s--- 20.00m lv0 0.08
lv1 vg0 owi-aos--- 100.00m
lv1_snap vg0 swi-a-s--- 20.00m lv1 0.06
挂载 xfs 文件系统的时候,mount 要加 -o nouuid 选项。
恢复
# 先卸载
[root@server1 ~]# umount /lv_xfs
# 再执行恢复
[root@server1 ~]# lvconvert --merge /dev/vg0/lv0_snap
# 再进行mount
[root@server1 ~]# mount /dev/vg0/lv0 /lv_xfs/
# ext4的文件系统同样的操作
[root@server1 ~]# umount /lv_ext4
[root@server1 ~]# lvconvert --merge /dev/vg0/lv1_snap
Merging of volume vg0/lv1_snap started.
vg0/lv1: Merged: 100.00%
[root@server1 ~]# mount /dev/vg0/lv1 /lv_ext4/
stratis 和 VDO
stratis
安装
[root@server1 ~]# yum install -y stratis-cli stratisd
[root@server1 ~]# systemctl enable --now stratisd
创建存储池
[root@server1 ~]# stratis pool list
Name Total Physical Properties
[root@server1 ~]# parted -s /dev/sdc mklabel loop
[root@server1 ~]# stratis pool create pool1 /dev/sdc
添加一个新设备到存储池
[root@server1 ~]# stratis pool add-data pool1 /dev/sdd
[root@server1 ~]# stratis pool list
Name Total Physical Properties
pool1 20 GiB / 37.64 MiB / 19.96 GiB ~Ca,~Cr
[root@server1 ~]# stratis blockdev list pool1
Pool Name Device Node Physical Size Tier
pool1 /dev/sdc 20 GiB Data
stratis 的文件系统默认的大小就是1TB
列出文件系统
[root@server1 ~]# stratis filesystem list
Pool Name Name Used Created Device UUID
[root@server1 ~]# stratis fs list
Pool Name Name Used Created Device UUID
创建文件系统
[root@server1 ~]# stratis fs create pool1 mufs
[root@server1 ~]# stratis fs create pool1 mufs2
[root@server1 ~]# stratis fs create pool1 mufs3
[root@server1 ~]# stratis fs list
Pool Name Name Used Created Device UUID
pool1 mufs 546 MiB Dec 06 2022 04:51 /dev/stratis/pool1/mufs 3517a1b944cf4faeb14ff8f2aa104e5a
pool1 mufs2 546 MiB Dec 06 2022 04:51 /dev/stratis/pool1/mufs2 5f3993d36f444747bd6cba17df0d8724
pool1 mufs3 546 MiB Dec 06 2022 04:51 /dev/stratis/pool1/mufs3 4dc1763cd32f40d2b57e1a798f801a42
挂载文件
[root@server1 /]# mkdir /1 /2 /3
[root@server1 /]# mount /dev/stratis/pool1/mufs /1
[root@server1 /]# mount /dev/stratis/pool1/mufs2 /2
[root@server1 /]# mount /dev/stratis/pool1/mufs3 /3
df 报告文件系统的大小为 1TB,是因为 stratis文件系统没有固定的大小,而且它们使用精简配置,因此 stratis 将自动调整这些文件系统的大小,以根据需要增加空间
[root@server1 /]# df -hT |grep stratis
tmpfs tmpfs 1.0M 0 1.0M 0% /run/stratisd/keyfiles
/dev/mapper/stratis-1-2c299b3277164ce3bd7988c920674d12-thin-fs-3517a1b944cf4faeb14ff8f2aa104e5a xfs 1.0T 7.2G 1017G 1% /1
/dev/mapper/stratis-1-2c299b3277164ce3bd7988c920674d12-thin-fs-5f3993d36f444747bd6cba17df0d8724 xfs 1.0T 7.2G 1017G 1% /2
/dev/mapper/stratis-1-2c299b3277164ce3bd7988c920674d12-thin-fs-4dc1763cd32f40d2b57e1a798f801a42 xfs 1.0T 7.2G 1017G 1% /3
VDO
VDO(Virtual Data Optimize)虚拟数据优化器是RHEL8/Centos8上新推出的一个存储相关技术(最早在7.5测试版中开始测试),是Redhat收购的Permabit公司的技术。
VDO的主要作用是节省磁盘空间,比如让1T的磁盘能装下1.5T的数据,从而降低数据中心的成本。
那vdo是如何实现的呢,关键原理主要是重删和压缩,重删就是硬盘里拷贝来相同的数据,以前要占多份空间,现在只需要1份空间就可以了。类似我们在百度网盘中上传一个大型软件安装包,能实现秒传,其实是之前就有,所以无需再传一遍,也无需再占百度一份空间。另一方面是数据压缩,类似于压缩软件的算法,也可以更加节省磁盘空间。
安装
[root@server1 /]# yum install vdo kmod-kvdo
列出vdo设备
[root@server1 ~]# vdo list
创建vdo虚拟硬盘,/dev/mapper/vdo1
[root@server1 ~]# vdo create --name vdo1 --device /dev/sdb --vdoLogicalSize 50G
Creating VDO vdo1
The VDO volume can address 16 GB in 8 data slabs, each 2 GB.
It can grow to address at most 16 TB of physical storage in 8192 slabs.
If a larger maximum size might be needed, use bigger slabs.
Starting VDO vdo1
Starting compression on VDO vdo1
VDO instance 0 volume is ready at /dev/mapper/vdo1
对 /dev/mapper/vdo1 进行格式化,-K 为快速格式化,可以提升格式化速度
[root@server1 ~]# mkfs.xfs -K /dev/mapper/vdo1
meta-data=/dev/mapper/vdo1 isize=512 agcount=4, agsize=3276800 blks
= sectsz=4096 attr=2, projid32bit=1
= crc=1 finobt=1, sparse=1, rmapbt=0
= reflink=1
data = bsize=4096 blocks=13107200, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0, ftype=1
log =internal log bsize=4096 blocks=6400, version=2
= sectsz=4096 sunit=1 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
[root@server1 ~]# df -hT | grep vdo1
文件系统 容量 已用 可用 已用% 挂载点
/dev/mapper/vdo1 xfs 50G 390M 50G 1% /vdo1
查看 vdo设备使用情况
[root@server1 ~]# vdostats --hu
Device Size Used Available Use% Space saving%
/dev/mapper/vdo1 20.0G 4.0G 16.0G 20% 99%
在 /etc/fstab 中配置挂载 vdo 设备, _netdev 不能忘记写,否则可能会无法启动系统
[root@server1 ~]# cat /etc/fstab
/dev/mapper/vdo1 /vdo1 xfs defaults,_netdev 0 0
删除vdo设备
[root@server1 ~]# vdo remove -n vdo1
nfs/smb客户端
nfs客户端的使用
网络文件系统,Net-File-System,类Unix系统间的文件共享
安装nfs,并配置开机启动 nfs-server 服务
[root@server1 ~]# yum install nfs-utils -y
[root@server1 ~]# systemctl enable nfs-server --now
服务端配置nfs共享目录
[root@server1 ~]# vim /etc/exports
#本地目录 客户端及权限参数
/aa *(rw,no_root_squash)
#no_root_squash表示不压缩root权限,即客户端用root写入的时候,在服务端也保存的是root用户
# 使配置生效
[root@server1 ~]# exportfs -avr
exporting *:/aa
客户端挂载nfs-server配置的目录
# 先查看服务器共享的目录是什么
[root@server1 ~]# showmount -e 102.168.88.136
Export list for 192.168.88.136:
/aa *
# 执行挂载
[root@server1 ~]# df -hT |grep nfs
192.168.88.136:/aa nfs4 60G 5.6G 55G 10% /aaclient
配置永久生效,重启不会失效
[root@server1 ~]# vim /etc/fstab
192.168.88.136:/aa /aaclient nfs defaults 0 0
samba客户端的使用
windows和类unix之间的文件共享
查看 windows 上现有哪些共享
PS C:\Windows\system32> net share
共享名 资源 注解
-------------------------------------------------------------------------------
C$ C:\ 默认共享
IPC$ 远程 IPC
D$ D:\ 默认共享
F$ F:\ 默认共享
ADMIN$ C:\Windows 远程管理
D D:\
命令成功完成。
查看 windows上有哪些网络用户,可以新增一个网络用户
PS C:\Windows\system32> net user
\\DESKTOP-ZC-HOME 的用户帐户
-------------------------------------------------------------------------------
__SUNLOGIN_USER__ Administrator DefaultAccount
defaultuser0 Guest WDAGUtilityAccount
朱纯
命令成功完成。
# 新增一个网络用户zhuchun,密码是 123456
PS C:\Windows\system32> net user zhuchun 123456 /add
命令成功完成。
安装 smbclient
# 先查询下哪个包提供了这个命令
[root@server1 ~]# yum whatprovides */smbclient
# 然后安装提供命令的这个包
[root@server1 ~]# yum install -y samba-client-4.13.3-5.el8_4.x86_64
用Linux访问windows的共享文件夹
方式一:直接登录访问
# -L 表示列出,以 $ 符结尾的,表示隐藏共享
[root@server1 ~]# smbclient -L //192.168.3.75 -U zhuchun%123456
Sharename Type Comment
--------- ---- -------
ADMIN$ Disk 远程管理
C$ Disk 默认共享
D Disk
D$ Disk 默认共享
F$ Disk 默认共享
IPC$ IPC 远程 IPC
SMB1 disabled -- no workgroup available
# 加上 /D 表示访问 D 盘
[root@server1 ~]# smbclient //192.168.3.75/D -U zhuchun%123456
Try "help" to get a list of possible commands.
smb: \> dir
$RECYCLE.BIN DHS 0 Wed Feb 3 05:10:40 2021
360Downloads D 0 Sat May 7 06:41:04 2022
360驱动大师目录 D 0 Fri May 21 07:04:08 2021
awrrpt_1_3717_3722.html A 647034 Tue Jul 17 02:21:34 2018
BaiduNetdiskDownload D 0 Tue Nov 29 04:15:41 2022
install D 0 Fri Oct 21 08:21:24 2022
LOCAL_MAVEN_REPO D 0 Mon Aug 29 05:39:30 2022
Program Files D 0 Sat Jul 30 08:16:34 2022
System Volume Information DHS 0 Wed Jun 8 04:46:37 2022
VM D 0 Tue Nov 8 23:36:51 2022
WorkSpace D 0 Tue Jul 5 07:06:03 2022
Youdao D 0 Tue Nov 29 04:19:44 2022
下载 D 0 Sun Nov 6 16:49:33 2022
性能测试理论模型.xmind A 26221254 Wed Apr 24 07:51:03 2019
我的项目 D 0 Mon Aug 16 18:26:10 2021
30719999 blocks of size 4096. 10018470 blocks available
smb: \> quit
方式二:挂载访问
# 需要提前安装此包
[root@server1 ~]# yum install -y cifs-utils.x86_64
# 执行挂载
[root@server1 ~]# mount -o username=zhuchun,password=123456 //192.168.3.75/D /smb
[root@server1 ~]# df -hT |grep smb
//192.168.3.75/D cifs 118G 79G 39G 68% /smb
[root@server1 ~]# ll /smb/
总用量 26240
drwxr-xr-x. 2 root root 0 2月 3 2021 '$RECYCLE.BIN'
drwxr-xr-x. 2 root root 0 5月 21 2021 360驱动大师目录
drwxr-xr-x. 2 root root 0 5月 7 2022 360Downloads
drwxr-xr-x. 2 root root 0 8月 16 2021 我的项目
drwxr-xr-x. 2 root root 0 11月 6 16:49 下载
-rwxr-xr-x. 1 root root 26221254 4月 24 2019 性能测试理论模型.xmind
-rwxr-xr-x. 1 root root 647034 7月 17 2018 awrrpt_1_3717_3722.html
drwxr-xr-x. 2 root root 0 11月 29 04:15 BaiduNetdiskDownload
drwxr-xr-x. 2 root root 0 10月 21 08:21 install
drwxr-xr-x. 2 root root 0 8月 29 05:39 LOCAL_MAVEN_REPO
drwxr-xr-x. 2 root root 0 7月 30 08:16 'Program Files'
drwxr-xr-x. 2 root root 0 6月 8 04:46 'System Volume Information'
drwxr-xr-x. 2 root root 0 11月 8 23:36 VM
drwxr-xr-x. 2 root root 0 7月 5 07:06 WorkSpace
drwxr-xr-x. 2 root root 0 11月 29 04:19 Youdao
在 /etc/fstab 中配置永久生效
[root@server1 ~]# cat /etc/fstab
//192.168.3.75/D /smb cifs defaults,username=zhuchun,password=123456 0 0
[root@server1 ~]# mount -a
最后,windows里的网络用户,如果后面不用了,可以删除掉
PS C:\Windows\system32> net user zhuchun /del
命令成功完成。
了解和配置自动挂载
定义一种规则:可以把某个设备和某个目录进行关联,平时有没有把该设备挂载到目录下不用关注,但是当我去访问此目录的时候,能够将设备进行自动挂载。
需要先安装 autofs 包
[root@server1 ~]# yum install autofs -y
[root@server1 ~]# systemctl enable autofs --now
Created symlink /etc/systemd/system/multi-user.target.wants/autofs.service → /usr/lib/systemd/system/autofs.service.
配置规则,进行挂载
方式一:
[root@server1 ~]# cd /etc/auto.master.d/
[root@server1 auto.master.d]# vim aa.autofs
# 中间是用 tab 隔开,/etc/auto.aa 这个文件内容定义关联规则
/xx /etc/auto.aa
[root@server1 auto.master.d]# cat /etc/auto.aa
# 把本地的 /dev/cdrom 挂载到本地的 /xxx/cdrom 这个目录,挂载的文件系统是 iso9660,只读模式
cdrom -fstype=iso9660,ro :/dev/cdrom
# 执行重启生效
[root@server1 auto.master.d]# systemctl restart autofs
[root@server1 etc]# df -hT |grep cdrom
[root@server1 etc]# ll /xx/
总用量 0
# 访问关联的目录
[root@server1 etc]# ll /xx/cdrom
总用量 48
dr-xr-xr-x. 4 zhuchun zhuchun 2048 5月 3 2021 AppStream
dr-xr-xr-x. 4 zhuchun zhuchun 2048 5月 3 2021 BaseOS
dr-xr-xr-x. 3 zhuchun zhuchun 2048 5月 3 2021 EFI
-r--r--r--. 1 zhuchun zhuchun 8154 5月 3 2021 EULA
-r--r--r--. 1 zhuchun zhuchun 1455 5月 3 2021 extra_files.json
-r--r--r--. 1 zhuchun zhuchun 18092 5月 3 2021 GPL
dr-xr-xr-x. 3 zhuchun zhuchun 2048 5月 3 2021 images
dr-xr-xr-x. 2 zhuchun zhuchun 2048 5月 3 2021 isolinux
-r--r--r--. 1 zhuchun zhuchun 103 5月 3 2021 media.repo
-r--r--r--. 1 zhuchun zhuchun 1669 5月 3 2021 RPM-GPG-KEY-redhat-beta
-r--r--r--. 1 zhuchun zhuchun 5134 5月 3 2021 RPM-GPG-KEY-redhat-release
-r--r--r--. 1 zhuchun zhuchun 1796 5月 3 2021 TRANS.TBL
# 发现居然自动挂载上了
[root@server1 etc]# df -hT |grep cdrom
/dev/sr0 iso9660 9.5G 9.5G 0 100% /xx/cdrom
# 重启 autofs 后,自动挂载是会断开的
方式二:
# 不指定父目录
[root@server1 auto.master.d]# cat bb.autofs
/- /etc/auto.bb
[root@server1 auto.master.d]# cat /etc/auto.bb
#* -fstype=nfs,rw 192.168.88.136:/rhome/& # 这个 * 和 & 表示,访问的 * 是啥,那 & 就是啥,这个配置在下面的模拟 windows 漫游用户会用到
/yy/cdrom -fstype=iso9660,ro :/dev/cdrom
[root@server1 auto.master.d]# systemctl restart autofs
# 访问一下,触发自动挂载
[root@server1 auto.master.d]# ll /yy/cdrom/
总用量 48
dr-xr-xr-x. 4 zhuchun zhuchun 2048 5月 3 2021 AppStream
dr-xr-xr-x. 4 zhuchun zhuchun 2048 5月 3 2021 BaseOS
dr-xr-xr-x. 3 zhuchun zhuchun 2048 5月 3 2021 EFI
-r--r--r--. 1 zhuchun zhuchun 8154 5月 3 2021 EULA
-r--r--r--. 1 zhuchun zhuchun 1455 5月 3 2021 extra_files.json
-r--r--r--. 1 zhuchun zhuchun 18092 5月 3 2021 GPL
dr-xr-xr-x. 3 zhuchun zhuchun 2048 5月 3 2021 images
dr-xr-xr-x. 2 zhuchun zhuchun 2048 5月 3 2021 isolinux
-r--r--r--. 1 zhuchun zhuchun 103 5月 3 2021 media.repo
-r--r--r--. 1 zhuchun zhuchun 1669 5月 3 2021 RPM-GPG-KEY-redhat-beta
-r--r--r--. 1 zhuchun zhuchun 5134 5月 3 2021 RPM-GPG-KEY-redhat-release
-r--r--r--. 1 zhuchun zhuchun 1796 5月 3 2021 TRANS.TBL
[root@server1 auto.master.d]# df -hT |grep yy
/dev/sr0 iso9660 9.5G 9.5G 0 100% /yy/cdrom
# 这种方式是不会隐藏 /yy 下面的原有文件的
[root@server1 auto.master.d]# ll /yy/
总用量 2
-rw-r--r--. 1 root root 0 12月 6 07:09 1.txt
-rw-r--r--. 1 root root 0 12月 6 07:09 2.txt
-rw-r--r--. 1 root root 0 12月 6 07:09 3.txt
-rw-r--r--. 1 root root 0 12月 6 07:09 4.txt
-rw-r--r--. 1 root root 0 12月 6 07:09 5.txt
dr-xr-xr-x. 7 zhuchun zhuchun 2048 5月 3 2021 cdrom
此自动挂载,可以实现类似 windows 的漫游用户功能
本地登录 user1 的时候,自动创建 user1 的家目录,并挂载到服务器的 user1 的家目录
系统启动
系统启动过程
系统引导过程
1.开机 BIOS 激活 MBR
2.MBR加载第二个扇区,里面的内容是 grub 里 stage1.5 反汇编出来
3.第二个扇区加载第3~n个扇区
修改系统参数
4.grub的配置文件 /boot/grub2/grub.cfg 此文件是生效的,但是系统不给修改此文件
6.如需修改参数,应该修改 /etc/default/grub,然后重新生成 /boot/grub2/grub.cfg
7.修改完 /etc/default/grub 文件后,通过 grub2-mkconfig -o /boot/grub2/grub.cfg 命令重新生成此文件,如修改启动页面默认选择的内核、或者自动选择内核的默认等待时间参数。
[root@server1 ~]# vim /etc/default/grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="crashkernel=auto resume=UUID=4250a782-471e-4965-b0f2-a2ecd975b860 rhgb quiet"
GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG=true
grub的不同模式
1.救援模式 rescue
假设系统正常启动需要20个必须服务,如果某个必须服务出问题,就会导致系统没法启动,假设救援模式只有10个必须服务,我们进入到救援模式的时候,出问题的服务不在救援模式的必须服务内,此时系统可以启动起来。需要root密码,此类似于 windows 下的安全模式
2.emergency紧急模式
假设系统正常启动需要20个必须服务,如果某个必须服务出问题会到执行系统无法启动,假设 emergency 模式只有6个必须服务,我们进入到 emergency 模式的时候,出问题的服务不在 emergency 模式的必须服务内,此时系统可以启动起来。需要root密码,类似于windows下的安全模式
重置 root 密码
1.在内核选择页面,按 e
2.在 linux 行的末尾,输入 rd.break 按 Ctrl + x 进行提交
4.等待一会儿就进入到了系统中
5.真的系统是在 /sysroot 目录里的,是以只读的形式挂载的
6.需要重新挂载下,已可读可写方式进行挂载 mount -o remount,rw /sysroot/
7.chroot /sysroot/ 切换根路径
8.echo redhat | LANG=C passwd --stdin root ,变更 root 用户的密码为 redhat
9.touch /.autorelabel
10.exit,会执行一会儿时间,然后自动进入重启系统正常进入系统
系统修复
当 boot loader 启动程序出问题的时候,可以通过光盘引导的方式对系统进行修复,类似 win 下面的 winPE 模式
1.光盘引导的时候,不选择安装系统,选择 Troubleshooting
2.在 Troubleshooting 页面选择 “Rescue a Red Hat Enterprise Linux system",回车
3.选择 1)continue ,回车
4.chroot /nmt/sysimage
5.grub2-install /dev/sda 执行 boot loader 的重新安装
6.exit
当 /boot 下的文件有问题时,即需要重装内核,同样是上面的 1-4 步
5.mount /dev/cdrom /nmt
6.rpm -ivh /nmt/BaseOS/Packages/kernel-4.18.0-193.el8.x86_64.rpm /nmt/BaseOS/Packages/kernel-core-4.18.0-193.el8.x86_64.rpm --force
7.mkdir /boot/grub2
8.grub2-mkconfig -o /boot/grub2/grub.cfg
9.grub2-install /dev/sda 执行 boot loader 的重新安装
10.exit
防火墙
firewalld里的zone
firewalld 里的 zone 理解为一个安检入口,不同的 zone 里制定不同的规则。某网卡要和某个 zone 关联,则从此网卡进来的流量都要使用关联 zone 的对应过滤规则。
一张网卡最多只能和一个 zone 关联,不能同时关联到多个 zone ,如果没有关联到任何 zone ,则走默认的 zone。
1.有多少个 zone?
[root@server1 ~]# firewall-cmd --get-zones
block dmz drop external home internal libvirt nm-shared public trusted work
2.默认的zone是什么?如何修改默认zone?
[root@server1 ~]# firewall-cmd --get-default-zone
public
[root@server1 ~]# firewall-cmd --set-default-zone=trusted
success
[root@server1 ~]# firewall-cmd --get-zone-of-interface=ens160
trusted
[root@server1 ~]# firewall-cmd --get-default-zone
trusted
如果修改了默认的 zone,则网卡默认是和默认的zone关联的,所以网卡关联的zone也会改变,
3.网卡是和哪个zone关联?如何设置网卡和某个zone关联?
[root@server1 ~]# firewall-cmd --get-zone-of-interface=ens160
trusted
设置关联:方式一:
要修改关联,需要先解除目前的关联,解除关联后,ens160使用默认的zone
[root@server1 ~]# firewall-cmd --remove-interface=ens160 --zone=trusted
success
然后再添加关联
[root@server1 ~]# firewall-cmd --add-interface=ens160 --zone=home
设置关联:方式二:
直接一次切换,如果不指定 --zone 则切换到默认zone
[root@server1 ~]# firewall-cmd --change-interface=ens160 --zone=public
success
4.每个zone里的规则如何查看?
# 不指定 --zone 则查看默认 zone 里的规则
[root@server1 ~]# firewall-cmd --list-all
You're performing an operation over default zone ('trusted'),
but your connections/interfaces are in zone 'libvirt,public' (see --get-active-zones)
You most likely need to use --zone=libvirt option.
trusted
target: ACCEPT
icmp-block-inversion: no
interfaces:
sources:
services:
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
# 指定 --zone 查看对应 zone 里的规则
[root@server1 ~]# firewall-cmd --list-all --zone=home
home
target: default
icmp-block-inversion: no
interfaces:
sources:
services: cockpit dhcpv6-client mdns samba-client ssh
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
5.修改规则
放行一个服务
[root@server1 ~]# firewall-cmd --add-service=http # 临时生效
success
[root@server1 ~]# firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: ens160
sources:
services: cockpit dhcpv6-client http ssh
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
[root@server1 ~]# firewall-cmd --add-service=http --permanent # 永久生效,但是没立即生效
[root@server1 ~]# firewall-cmd --reload #重新加载,使上面永久生效的立即生效
禁用一个服务
[root@server1 ~]# firewall-cmd --remove-service=http # 临时生效
success
[root@server1 ~]# firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: ens160
sources:
services: cockpit dhcpv6-client ssh
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
[root@server1 ~]# firewall-cmd --remove-service=http --permanent # 永久生效,但是没立即生效
[root@server1 ~]# firewall-cmd --reload #重新加载,使上面永久生效的立即生效
基于端口进行限制
# 开启端口
[root@server1 ~]# firewall-cmd --add-port=8080/tcp --permanent
success
[root@server1 ~]# firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: ens160
sources:
services: cockpit dhcpv6-client ssh
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
[root@server1 ~]# firewall-cmd --reload
success
[root@server1 ~]# firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: ens160
sources:
services: cockpit dhcpv6-client ssh
ports: 8080/tcp
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
# 禁用端口
[root@server1 ~]# firewall-cmd --remove-port=8080/tcp --permanent
success
[root@server1 ~]# firewall-cmd --reload
success
[root@server1 ~]# firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: ens160
sources:
services: cockpit dhcpv6-client ssh
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
# 开启端口区间
[root@server1 ~]# firewall-cmd --add-port=1000-2000/tcp
success
[root@server1 ~]# firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: ens160
sources:
services: cockpit dhcpv6-client ssh
ports: 1000-2000/tcp
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
使用富规则 rich rules
放行服务的语法:
firewall-cmd --add-rich-rule='rule family=ipv4 source address=源网段 service name=服务名 accept'
[root@server1 ~]# firewall-cmd --add-rich-rule='rule family=ipv4 source address=192.168.88.100 service name=http accept'
success
[root@server1 ~]# firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: ens160
sources:
services: cockpit dhcpv6-client ssh
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
rule family="ipv4" source address="192.168.88.100" service name="http" accept
放行端口的语法:
firewall-cmd -add-rich-rule 'rule family=ipv4 source address=源网段 port port=N protocol=协议 accept'
记忆技巧
man -k firewall
man firewalld.richlanguage
搜索 EXAMPLE
如果已经添加了某个服务或者端口,已经是允许所有的客户端了
则在富规则里,再写 accept 是没有意义的,应该写 reject,相当于是黑名单,即允许所有但是拒绝个别。
如果没有添加某个服务或者端口,已经是拒绝所有的客户端了
则在富规则里写 accept 相当于白名单,即拒绝所有允许个别。
kickstart
kickstart 无人值守安装系统工作过程
演示
podman
# RHEL8 默认已经安装了 podman
[root@server1 ~]# yum list podman
Updating Subscription Management repositories.
Unable to read consumer identity
This system is not registered to Red Hat Subscription Management. You can use subscription-manager to register.
上次元数据过期检查:1:08:33 前,执行于 2022年12月09日 星期五 02时46分03秒。
已安装的软件包
podman.x86_64 3.0.1-6.module+el8.4.0+10607+f4da7515 @AppStream
可安装的软件包
podman.x86_64 3.2.3-0.11.module_el8.4.0+942+d25aada8 appstream
镜像
镜像加速配置
[zhuchun@server1 ~]$ cat /etc/containers/registries.conf
unqualified-search-registries = ["docker.io"]
[[registry]]
prefix="docker.io"
location="2e1t0zd0.mirror.aliyuncs.com"
[zhuchun@server1 ~]$ poman pull docker.io/nginx
[zhuchun@server1 ~]$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/library/nginx latest 605c77e624dd 11 months ago 146 MB
[zhuchun@server1 ~]$ podman rmi nginx
Untagged: docker.io/library/nginx:latest
Deleted: 605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85
# 导出镜像
[zhuchun@server1 ~]$ podman save nginx > nginx.tar
# 导入镜像
[zhuchun@server1 ~]$ podman load -i nginx.tar
# 有时需要登录才能拉取镜像
[zhuchun@server1 ~]$ podman login -u xxx -p yyy c.163.com
# 对镜像重新做标签
[zhuchun@server1 ~]$ podman tag docker.io/library/nginx 192.168.88.172/rhcsa/nginx:v1
[zhuchun@server1 ~]$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/library/nginx latest 605c77e624dd 11 months ago 146 MB
192.168.88.172/rhcsa/nginx v1 605c77e624dd 11 months ago 146 MB
# 查看指定镜像的历史
[zhuchun@server1 ~]$ podman history docker.io/library/nginx:latest
容器
# 创建容器:
# mynginx为设定的容器名称
# -d 表示后台运行
# --restart=always在podman中即使配置重启机器后也不会启动
# -p 表示端口映射,-p M ,M表示容器端口,宿主机会自动映射一个端口;-p N:M N表示容器端口,M表示映射的指定宿主机端口
# -e 表示注入环境变量到容器中
[zhuchun@server1 ~]$ podman run --name=mynginx -d --restart=always -p N:M -e myenv1=myvalue1 -e myenv2=myvalue2 docker.io/library/nginx:latest
# 查看主机上的容器,-a 表示所有容器,不带 -a 表示查找正在运行中的容器
[zhuchun@server1 ~]$ podman ps -a
# 停止容器,也可以通过容器ID来停止
[zhuchun@server1 ~]$ podman stop mynginx
# 启动容器
[zhuchun@server1 ~]$ podman start mynginx
# 删除容器,删除正在运行的容器带 -f 选项强制删除
[zhuchun@server1 ~]$ podman rm -f mynginx
# 进入容器,-t 表示产生模拟终端,-i表示交互模式
[zhuchun@server1 ~]$ podman exec -it mynginx bash
root@445209fd858b:/# exit
exit
[zhuchun@server1 ~]$
# 查看容器日志
[zhuchun@server1 ~]$ podman logs mynginx
# 查看日志的持续输出
[zhuchun@server1 ~]$ podman logs -f mynginx
数据卷
# 创建容器时,-v 可以将 宿主机本地目录与容器内指定路径做映射,对容器内文件做持久化
[zhuchun@server1 ~]$ podman run --name=mynginx2 -d --restart=always -v /home/zhuchun:/opt nginx:latest
# -Z 可以指定上下文,防止 SELinux 因上下文不匹配没有权限操作
[zhuchun@server1 ~]$ podman run --name=mynginx2 -d --restart=always -v /home/zhuchun:/opt:Z nginx:latest
# 查看容器的详细信息,能看到挂载信息
[zhuchun@server1 ~]$ podman inspect mynginx2
。。。
"Mounts": [
{
"Type": "bind",
"Source": "/home/zhuchun",
"Destination": "/opt",
"Driver": "",
"Mode": "",
"Options": [
"rbind"
],
"RW": true,
"Propagation": "rprivate"
}
],
。。。
通过 linger 服务实现容器跟随系统自动启动
开启 linger
# 开启 Linger 表示,当这个用户通过ssh 或者控制台登录系统的时候,不是 su 过来,会自动触发,吧他创建的容器给启动
[zhuchun@server1 ~]$ loginctl enable-linger zhuchun
[zhuchun@server1 ~]$ loginctl show-user zhuchun
Linger=yes
把容器设置成开机启动
[zhuchun@server1 ~]$ mkdir -p ~/.config/systemd/user ; cd ~/.config/systemd/user
# 生成 service 文件
[zhuchun@server1 user]$ podman generate systemd --name mynginx --files --new
/home/zhuchun/.config/systemd/user/container-mynginx.service
[zhuchun@server1 user]$ systemctl --user daemon-reload
# 设置成开启启动
[zhuchun@server1 user]$ systemctl --user enable container-mynginx.service
[zhuchun@server1 user]$ ls
container-mynginx.service
[zhuchun@server1 user]$ cat container-mynginx.service
# container-mynginx.service
# autogenerated by Podman 3.0.2-dev
# Fri Dec 9 06:30:28 PST 2022
[Unit]
Description=Podman container-mynginx.service
Documentation=man:podman-generate-systemd(1)
Wants=network.target
After=network-online.target
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/container-mynginx.pid %t/container-mynginx.ctr-id
ExecStart=/usr/bin/podman run --conmon-pidfile %t/container-mynginx.pid --cidfile %t/container-mynginx.ctr-id --cgroups=no-conmon --replace --name=mynginx -d --restart=always -p 8080:80 docker.io/library/nginx:latest
ExecStop=/usr/bin/podman stop --ignore --cidfile %t/container-mynginx.ctr-id -t 10
ExecStopPost=/usr/bin/podman rm --ignore -f --cidfile %t/container-mynginx.ctr-id
PIDFile=%t/container-mynginx.pid
Type=forking
[Install]
WantedBy=multi-user.target default.target
[zhuchun@server1 user]$
Ansible
安装 ansible
配置 yum 源
[root@server1 ~]# cat /etc/yum.repos.d/RHEL-tuna.repo
[ansible]
name=RHEL8 - Ansible
baseurl=http://mirrors.ustc.edu.cn/centos-vault/8.4.2105/configmanagement/x86_64/ansible-29/
enabled=1
gpgcheck=0
[root@server1 ~]# yum clean all
[root@server1 ~]# yum makecache
[root@server1 ~]# yum install ansible -y
使用 ansible
ansible.cfg 及清单文件
实验环境:
[zhuchun@server1 ~]$ cat /etc/hosts
# server1 为主控机器
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.88.136 server1.rhce.cc server1
192.168.88.137 server2.rhce.cc server2
192.168.88.138 server3.rhce.cc server3
通过ansible主机控制其他机器,需要先配置 ssh 免密登录
在主控机器上执行:
[zhuchun@server1 ~]$ ssh-keygen
[zhuchun@server1 ~]$ ssh-copy-id server1
[zhuchun@server1 ~]$ ssh-copy-id server2
[zhuchun@server1 ~]$ ssh-copy-id server3
在执行 ansible 或者 ansible-playbook 命令的时候,优先使用当前目录中的 ansible.cfg 如果当前目录没有此文件,则使用默认的配置文件 /etc/ansible/ansible.cfg。
[zhuchun@server1 ~]$ mkdir chap2 && cd chap2/
[zhuchun@server1 chap2]$ vim ansible.cfg
[defaults]
inventory = ./hosts
# 下面这段配置可以提权为root,前提是执行用户在sudoer中且su免密
#[privilege_escalation]
#become=True
#become_method=sudo
#become_user=root
[zhuchun@server1 chap2]$ vim hosts
# []表示分组组名
[web]
# 也可以是 server[1:3] 表示 server1-server3 这个范围的主机
server1
server2
server3 ansible_ssh_port=22 # 默认是22,可以通过ansible_ssh_port配置
#[zz:children] 这个表示 zz 组包含 db 组合 web 组
#db
#web
[zhuchun@server1 chap2]$
# 列出 web 组的主机
[zhuchun@server1 chap2]$ ansible web --list-hosts
hosts (3):
server1
server2
server3
# 测试一下在 server2 主机执行 ping 命令
[zhuchun@server1 chap2]$ ansible server2 -m ping
server2 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
# 测试一下在 web 组主机执行 shell 模块,执行 hostname 命令
[zhuchun@server1 chap2]$ ansible web -m shell -a "hostname"
server2 | CHANGED | rc=0 >>
server2
server1 | CHANGED | rc=0 >>
server1.rhce.cc
server3 | CHANGED | rc=0 >>
server3
常见模块的使用
查看ansible有哪些模块
[root@server1 ~]# ansible-doc -l
查看某个模块的帮助
[root@server1 ~]# ansible-doc 模块名
ping模块
# all是指清单文件里所有的主机,localhost 指本机
[zhuchun@server1 chap2]$ ansible all -m ping
[zhuchun@server1 chap2]$ ansible localhost -m ping
shell 模块
用来执行操作系统的命令
[zhuchun@server1 chap2]$ ansible server2 -m shell -a "hostname -s"
server2 | CHANGED | rc=0 >>
server2
[zhuchun@server1 chap2]$ ansible server2 -m shell -a "ifconfig ens160"
server2 | CHANGED | rc=0 >>
ens160: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.88.137 netmask 255.255.255.0 broadcast 192.168.88.255
inet6 fe80::20c:29ff:fe65:f4a8 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:65:f4:a8 txqueuelen 1000 (Ethernet)
RX packets 25106 bytes 31200903 (29.7 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 7795 bytes 534341 (521.8 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
command 默认的模块
执行命令用
# 没指定模块则默认是 command 模块,和shell类似,但是有些区别,一些操作符,如:"<",">","|",";","&" 符号在 command 中不会起作用;还有一些变量也不会起作用
[zhuchun@server1 chap2]$ ansible server2 -a "hostname -s"
server2 | CHANGED | rc=0 >>
server2
script 模块
用来运行脚本的,参数就是脚本名,就不需要对所需要执行脚本的机器进行脚本分发
[zhuchun@server1 chap2]$ ll a.sh
-rwxrwxr-x. 1 zhuchun zhuchun 123 12月 10 06:58 a.sh
[zhuchun@server1 chap2]$ cat a.sh
#!/bin/bash
echo "我的主机名是 $(hostname -s)"
echo "我的IP地址是 $(ifconfig ens160 | awk '/inet /{print $2}')"
[zhuchun@server1 chap2]$ ansible server2 -m script -a "./a.sh"
server2 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to server2 closed.\r\n",
"stderr_lines": [
"Shared connection to server2 closed."
],
"stdout": "我的主机名是 server2\r\n我的IP地址是 192.168.88.137\r\n",
"stdout_lines": [
"我的主机名是 server2",
"我的IP地址是 192.168.88.137"
]
}
get_url 下载模块
常见参数: url=下载地址 dst=下载到哪里
[zhuchun@server1 chap2]$ ansible server2 -m get_url -a "url=http://xxx.xx.xx/xx dest=/opt"
group 组管理模块
参数包括: name=组名 state=present/absent
present为创建,absent为删除
[zhuchun@server1 chap2]$ ansible server2 -m group -a "name=group1 state=present"
user 用户管理模块
常用参数包括: name=用户名 comment=”注释信息“ group=主组 groups=附属组 password={{‘字符串’ | password_hash('sha512')}} state=present/absent remove=true(remove选项在删除用户时使用,相当于 userdel -r删除家目录)
[zhuchun@server1 chap2]$ ansible server2 -m user -a "name=tom comment='its tom' group=zhuchun groups=root password={{'redhat' | password_hash('sha512')}}"
debug模块
打印调试
参数:msg=‘’
类似于 echo 命令,及其他语言的print/println/printf 命令
setup 模块
获取信息,setup所获取的这些变量--facts变量
参数 :filter=xxx(信息中的key值)
[zhuchun@server1 chap2]$ ansible server2 -m setup
[zhuchun@server1 chap2]$ ansible server2 -m setup -a "filter=ansible_bios_version"
server2 | SUCCESS => {
"ansible_facts": {
"ansible_bios_version": "6.00",
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false
}
# ansible 过滤两级的话,是看不到返回结果的,下面这个就没返回具体的日期
[zhuchun@server1 chap2]$ ansible server2 -m setup -a "filter=ansible_date_time.date"
server2 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false
}
file 文件模块
用来创建、删除文件或目录
常见的参数:src(软链接、硬链接专用) dest/name/path=在哪里创建文件 owner=文件拥有者 group=所属组 mode=权限 setype=上下文 state=touch/file/directory/link/hard/absent(touch-文件不存在则创建;file-文件已存在修改属性;link-软链接;hard-硬链接;absent-删除)
# 创建文件
[zhuchun@server1 chap2]$ ansible server2 -m file -a "dest=/home/zhuchun/aa.txt owner=zhuchun group=zhuchun mode=000 setype=user_home_t state=touch "
server2 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"dest": "/home/zhuchun/aa.txt",
"gid": 1000,
"group": "zhuchun",
"mode": "0000",
"owner": "zhuchun",
"secontext": "unconfined_u:object_r:user_home_t:s0",
"size": 0,
"state": "file",
"uid": 1000
}
# 创建文件链接
[zhuchun@server1 chap2]$ ansible server2 -m file -a "src=/home/zhuchun/aa.txt dest=/home/zhuchun/aal.txt state=link "
server2 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"dest": "/home/zhuchun/aal.txt",
"gid": 1000,
"group": "zhuchun",
"mode": "0777",
"owner": "zhuchun",
"secontext": "unconfined_u:object_r:user_home_t:s0",
"size": 20,
"src": "/home/zhuchun/aa.txt",
"state": "link",
"uid": 1000
}
copy/fetch 拷贝文件模块
参数:src=本地源文件 dest=拷贝到远端目的文件 owner、group、setype等和file模块一样
[zhuchun@server1 chap2]$ touch bb.txt
[zhuchun@server1 chap2]$ ansible server2 -m copy -a "src=bb.txt dest=/home/zhuchun/bb-cp.txt owner=zhuchun group=zhuchun"
server2 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
"dest": "/home/zhuchun/bb-cp.txt",
"gid": 1000,
"group": "zhuchun",
"md5sum": "d41d8cd98f00b204e9800998ecf8427e",
"mode": "0664",
"owner": "zhuchun",
"secontext": "unconfined_u:object_r:user_home_t:s0",
"size": 0,
"src": "/home/zhuchun/.ansible/tmp/ansible-tmp-1670687926.8385549-14583-262383626209378/source",
"state": "file",
"uid": 1000
}
[zhuchun@server1 chap2]$ ansible server2 -m copy -a "dest=/home/zhuchun/cc.txt content='这是远程写文件内容' owner=zhuchun group=zhuchun"
# 下面命令从远端 server2 拉取 /home/zhuchun/cc.txt 文件到本地,会创建server2 命名的逐级目录文件
[zhuchun@server1 chap2]$ ansible server2 -m fetch -a "src=/home/zhuchun/cc.txt dest=."
[zhuchun@server1 chap2]$ tree server2/
server2/
└── home
└── zhuchun
└── cc.txt
2 directories, 1 file
yum_repository 配置yum源
参数:name=源名称 description=”描述信息“ baseurl=源地址 enabled=yes gpgcheck=no
# 会在server2 的/etc/yum.repos.d/ 创建 ansible.repo 文件
[zhuchun@server1 chap2]$ ansible server2 -m yum_repository -a "name=ansible description='ansible源' baseurl=http://mirrors.ustc.edu.cn/centos-vault/8.4.2105/configmanagement/x86_64/ansible-29/ enabled=yes gpgcheck=no"
yum 模块
对软件包进行管理
参数:name=包名 name=’@组名‘ name=’@模块名‘ state=installed/present/removed/absent/latest
[zhuchun@server1 chap2]$ ansible server2 -m yum -a "name=vsftpd state=installed"
[zhuchun@server1 chap2]$ ansible server2 -m yum -a "name=vsftpd state=removed"
[zhuchun@server1 chap2]$ ansible server2 -m yum -a "name='@RPM 开发工具' state=installed"
package 对软件包进行管理
与 yum 模块一致
service 服务管理模块
参数:name=服务名 state=started/stopped/restarted enabled=yes/no
[zhuchun@server1 chap2]$ ansible server2 -m service -a "name=vsftpd state=started enabled=yes"
systemd 模块
参数和 service 一样,只是多了一个 daemon_reload=true
修改了服务的启动脚本的时候,需要 systemctl deamon-reload
[zhuchun@server1 chap2]$ ansible server2 -m systemd -a "name=vsftpd state=stopped enabled=no daemon_reload=true"
fierewalld 防火墙管理模块
参数:service=http/ftp/https... port=80/tcp immediate=yes/no(没有默认值) permanent=yes/no(没有默认值) state=enabled/disabled
[zhuchun@server1 chap2]$ ansible server2 -m firewalld -a "service=http immediate=yes permanent=yes state=enabled"
replace 替换操作模块
参数:path=文件名 regexp=正则表达式(修改的是哪行里的内容) replace=修改之后的内容
# 将server2 中 /home/zhuchun/cc.txt 文件内容中的 cc开头的行整行替换成 cc=456
[zhuchun@server1 chap2]$ ansible server2 -m replace -a "path=/home/zhuchun/cc.txt regexp=^cc.+ replace=cc=456"
server2 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"msg": "1 replacements made"
}
lineinfile 模块
也可以用于替换
参数:path=文件名 regexp=正则 line=修改后的内容
[zhuchun@server1 chap2]$ ansible server2 -m lineinfile -a "path=/home/zhuchun/cc.txt regexp=^cc line=cc=12345667890"
server2 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"backup": "",
"changed": true,
"msg": "line replaced"
}
磁盘管理模块
parted对硬盘进行分区
参数:device=/dev/sdb number=磁盘编号 part_type=分区类型 part_start=xxxMiB/GiB(起始点) part_end=yyyMiB/GiB state=present/absent
[zhuchun@server1 chap2]$ ansible server2 -m parted -a "device=/dev/sdb number=1 part_end=2GiB state=present"
[zhuchun@server1 chap2]$ ansible server2 -m parted -a "device=/dev/sdb number=2 part_start=2GiB part_end=5GiB state=present"
filesystem对分区进行格式化
参数:dev=对哪个设备进行格式化 fstype=指定文件系统 force=yes/no
[zhuchun@server1 chap2]$ ansible server2 -m filesystem -a "dev=/dev/sdb3 fstype=xfs"
[zhuchun@server1 chap2]$ ansible server2 -m filesystem -a "dev=/dev/sdb3 fstype=ext4 force=yes"
mount挂载分区
参数:src=设备 path=挂载点 fstype=指定文件系统 opts=挂载选项 state=mounted(除了挂载外还写入到/etc/fstab)/pesent(只写入到/etc/fstab当前并不挂载)/absent(卸载并从/etc/fstab里删除)/umounted(当前卸载并不从/etc/fstab中删除)
# 挂载并写入 /etc/fstab
[zhuchun@server1 chap2]$ ansible server2 -m mount -a "src=/dev/sdb3 path=/aa fstype=xfs state=mounted"
[zhuchun@server1 chap2]$ ansible server2 -m mount -a "src=/dev/sdb3 path=/aa fstype=xfs state=absent"
lvg管理卷组
参数:
pvs=物理卷(直接指定分区,不需要提前把pv创建出来)
pesize=PE的大小
vg=卷组名
state=present/absent
[zhuchun@server1 chap2]$ ansible server2 -m lvg -a "vg=vg0 pvs=/dev/sdb1,/dev/sdb2 state=present"
[zhuchun@server1 chap2]$ ansible server2 -m lvg -a "vg=vg0 pvs=/dev/sdb1,/dev/sdb2 state=absent"
lvol对逻辑卷进行管理
参数:
vg=卷组
lv=逻辑卷名
size=大小 M/G
force=yes/no 对删除lv生效
state=present/absent 默认是present
[zhuchun@server1 chap2]$ ansible server2 -m lvol -a "vg=vg0 lv=lv0 size=2G "
[zhuchun@server1 chap2]$ ansible server2 -m lvol -a "vg=vg0 lv=lv0 size=2G state=absent force=yes"
playbook的使用
上面都是在命令行中进行的操作,一次执行一个命令
playbook叫做剧本,剧本中包含一个个故事play
整个playbook的内容以 yaml 格式来编写,playbook 文件要以 yaml 或者 yml 为后缀
格式:
- name: 第一个play的名称
hosts: 主机组1,主机组2,...
tasks:
- name: task1-name
模块1:
参数1: 值1
参数2: 值2
...
- name: task2-name
模块2:
参数1: 值1
参数2: 值2
...
- name: 第二个play的名称
hosts: 主机组1,主机组2,...
tasks:
- name: task1-name
模块1:
参数1: 值1
参数2: 值2
...
- name: task2-name
模块2:
参数1: 值1
参数2: 值2
...
[zhuchun@server1 chap3]$ cat server-ip.yaml
---
- hosts: server2
tasks:
- name: 打印IP地址
debug: msg={{ansible_default_ipv4.address}}
[zhuchun@server1 chap3]$ ansible-playbook server-ip.yaml
PLAY [server2] ***************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
TASK [打印IP地址] ****************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "192.168.88.137"
}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
两个练习:
1、显示server2的IP
2、显示server2和server3的主机名
[zhuchun@server1 chap3]$ cat server-ip.yaml
---
- name: 显示IP
hosts: server2
tasks:
- name: 打印IP地址
debug: msg={{ansible_default_ipv4.address}}
- name: 显示主机名
hosts: server2,server3
tasks:
- name: 显示主机名
debug: msg={{ansible_fqdn}}
[zhuchun@server1 chap3]$ ansible-playbook server-ip.yaml
PLAY [显示IP] ******************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
TASK [打印IP地址] ****************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "192.168.88.137"
}
PLAY [显示主机名] *****************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
ok: [server3]
TASK [显示主机名] *****************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "server2.rhce.cc"
}
ok: [server3] => {
"msg": "server3.rhce.cc"
}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
server3 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[zhuchun@server1 chap3]$
练习:写一个 playbook xxx.yaml,实现如下操作
1、在server2上安装httpd,并启动httpd,且开机启动,防火墙里开放http服务,并设置永久生效
2、在server3上安装vsftpd,启动 vsftpd并设置开启自动启动,防火墙里开放 ftp服务并设置永久生效
3、在server2和server3上安装 autofs,启动autofs并设置开机自启
[zhuchun@server1 chap3]$ cat xxx.yaml
---
- name: 安装httpd
hosts: server2
tasks:
- name: 安装httpd
yum: name=httpd state=installed
- name: 启动httpd并设置开机启动
service: name=httpd state=started enabled=yes
- name: 防火墙里开放httpd服务
firewalld: service=http immediate=yes permanent=yes state=enabled
- name: 安装vsftpd
hosts: server3
tasks:
- name: 安装vsftpd服务
yum: name=vsftpd state=installed
- name: 启动vsftpd服务并设置开机启动
service: name=vsftpd state=started enabled=yes
- name: 防火墙里开放ftp服务
firewalld: service=ftp immediate=yes permanent=yes state=enabled
- name: 安装autofs
hosts: server2,server3
tasks:
- name: 安装autofs服务
yum: name=autofs state=installed
- name: 启动autofs服务并设置开机启动
service: name=autofs state=started enabled=yes
[zhuchun@server1 chap3]$ ansible-playbook xxx.yaml
变量的使用
手动定义变量
定义格式:
vars:
变量1: 值1
变量2: 值2
...
引用变量时,用 {{变量名}},大括号内侧两边是不是有空格无所谓,不影响。
[root@server1 chap]# cat 1.yaml
---
- hosts: server2
vars:
aa: 11
tasks:
- name: 输出一个变量
debug: msg={{aa}}
[root@server1 chap]# ansible-playbook 1.yaml
PLAY [server2] ***************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
TASK [输出一个变量] ****************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": 11
}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@server1 chap]# cat 1.yaml
---
- hosts: server2
vars:
aa: 11
bb: "adsfa dsfadsf"
tasks:
- name: 输出一个变量
debug: msg="{{aa}}MB,这是bb:{{bb}}"
[root@server1 chap]# ansible-playbook 1.yaml
PLAY [server2] ***************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
TASK [输出一个变量] ****************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "11MB,这是bb:adsfa dsfadsf"
}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
字典变量
所谓字典,简写为 doct,就是存储多个变量的容器,可以把字典理解为是一个木桶,里面存放了很多个变量,要是使用变量的话,必须要指定是哪个木桶里的变量。
dict-name 即上面的木桶,里面的 var1、var2、var3 等就是桶里存放的变量叫做 var-name。
在字典里定义变量时,变量前面是不加 - 的,并且定义变量没有先后顺序,引用的话,通过 dict-name.var-name 的格式来引用。
[root@server1 chap]# cat 2.yaml
---
- hosts: server2
vars:
xx:
aa: 11
bb: 22
yy:
aa: 1111
bb: 2222
tasks:
- name: 输出字典组xx
debug:
msg: "{{xx}}"
- name: 输出xx中的aa
debug:
msg: "{{xx.aa}}"
[root@server1 chap]# ansible-playbook 2.yaml
PLAY [server2] ***************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
TASK [输出字典组xx] ***************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": {
"aa": 11,
"bb": 22
}
}
TASK [输出xx中的aa] **************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "11"
}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
列表变量
由一个个的匿名字典组成,每个匿名字典都表示一个对象。
直接在 playbook 中定义及使用变量
[root@server1 chap]# cat 3.yaml
---
- hosts: server2
vars:
users:
- uname: tom
age: 21
sex: M
- uname: bob
age: 22
sex: F
- uname: mary
age: 23
sex: F
tasks:
- name: 打印所有对象
debug:
msg: "{{users}}"
- name: 打印第一个对象
debug:
msg: "{{users[0]}}"
- name: 打印第一个对象中的uname
debug:
msg: "{{users[0].uname}}"
[root@server1 chap]# ansible-playbook 3.yaml
PLAY [server2] ***************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
TASK [打印所有对象] ****************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": [
{
"age": 21,
"sex": "M",
"uname": "tom"
},
{
"age": 22,
"sex": "F",
"uname": "bob"
},
{
"age": 23,
"sex": "F",
"uname": "mary"
}
]
}
TASK [打印第一个对象] ***************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": {
"age": 21,
"sex": "M",
"uname": "tom"
}
}
TASK [打印第一个对象中的uname] ********************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "tom"
}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@server1 chap]#
通过文件定义变量,在脚本中引用
[root@server1 chap]# cat users.txt
xx: 111
yy: 222
users:
- uname: tom
age: 21
sex: M
- uname: bob
age: 22
sex: F
- uname: mary
age: 23
sex: F
[root@server1 chap]# cat 4.yaml
---
- hosts: server2
vars:
aa: "{{xx}}"
vars_files:
- users.txt
tasks:
- name: 打印所有对象
debug:
msg: "{{users}}"
- name: 打印第一个对象
debug:
msg: "{{users[0]}}"
- name: 打印第一个对象中的uname
debug:
msg: "{{users[0].uname}}"
[root@server1 chap]# ansible-playbook 4.yaml
PLAY [server2] ***************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
TASK [打印所有对象] ****************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": [
{
"age": 21,
"sex": "M",
"uname": "tom"
},
{
"age": 22,
"sex": "F",
"uname": "bob"
},
{
"age": 23,
"sex": "F",
"uname": "mary"
}
]
}
TASK [打印第一个对象] ***************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": {
"age": 21,
"sex": "M",
"uname": "tom"
}
}
TASK [打印第一个对象中的uname] ********************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "tom"
}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@server1 chap]#
注册变量
[root@server1 chap]# cat 5.yaml
---
- hosts: server2
tasks:
- name: 执行命令
shell: "whoami"
register: aa
- name: 显示命令内容
debug: msg={{aa}}
- name: 显示命令输出
debug: msg={{aa.stdout}}
- name: 显示命令执行的返回值
debug: msg={{aa.rc}}
[root@server1 chap]# ansible-playbook 5.yaml
PLAY [server2] ***************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
TASK [执行命令] ******************************************************************************************************************************************************************************************************************************************************************
changed: [server2]
TASK [显示命令内容] ****************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": {
"changed": true,
"cmd": "whoami",
"delta": "0:00:00.004190",
"end": "2022-12-11 04:38:27.134560",
"failed": false,
"rc": 0,
"start": "2022-12-11 04:38:27.130370",
"stderr": "",
"stderr_lines": [],
"stdout": "root",
"stdout_lines": [
"root"
]
}
}
TASK [显示命令输出] ****************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "root"
}
TASK [显示命令执行的返回值] ************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "0"
}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=5 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@server1 chap]#
facts 变量
[root@server1 chap]# cat 6.yaml
---
- hosts: server2
tasks:
- name: 打印主机名
debug: msg="{{ansible_fqdn}}"
- name: 打印IP
debug: msg="{{ansible_default_ipv4.address}}"
- name: 打印/dev/sda这个硬盘大小
debug: msg="{{ansible_devices.sda.size}}"
- name: 打印/dev/sda1这个分区的大小
debug: msg="{{ansible_devices.sda.partitions.sda1.size}}"
- name: 打印内存的总大小
debug: msg="{{ansible_memtotal_mb}}MB"
- name: 打印所使用的系统版本
debug: msg="{{ansible_distribution_version}}"
[root@server1 chap]# ansible-playbook 6.yaml
PLAY [server2] ***************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
TASK [打印主机名] *****************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "server2.rhce.cc"
}
TASK [打印IP] ******************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "192.168.88.137"
}
TASK [打印/dev/sda这个硬盘大小] ******************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "100.00 GB"
}
TASK [打印/dev/sda1这个分区的大小] ****************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "60.00 GB"
}
TASK [打印内存的总大小] **************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "1790MB"
}
TASK [打印所使用的系统版本] *****************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "8.4"
}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=7 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@server1 chap]#
内置变量
groups
[root@server1 chap]# cat 7.yaml
---
- hosts: server2
tasks:
- name: 打印groups这个内置变量
debug: msg="{{groups}}"
- name: 打印有哪些主机组,不打印主机
debug: msg="{{group_names}}"
- name: 打印web主机组这个内置变量
debug: msg="{{groups.web}}"
- name: 打印web主机组这个内置变量
debug: msg="{{groups['web']}}"
[root@server1 chap]# ansible-playbook 7.yaml
PLAY [server2] ***************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
TASK [打印groups这个内置变量] ********************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": {
"all": [
"server1",
"server2",
"server3"
],
"ungrouped": [],
"web": [
"server1",
"server2",
"server3"
]
}
}
TASK [打印有哪些主机组,不打印主机] ********************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": [
"web"
]
}
TASK [打印web主机组这个内置变量] ********************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": [
"server1",
"server2",
"server3"
]
}
TASK [打印web主机组这个内置变量] ********************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": [
"server1",
"server2",
"server3"
]
}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@server1 chap]#
hostvars
在playbook 中,如果定义了
gather_facts: no
则不会去获取远端 facts变量,则不能在脚本中使用 fects 变量,均为未定义变量
[root@server1 chap]# cat 8.yaml
---
- hosts: server3
- hosts: server2
gather_facts: no
tasks:
- name: 打印IP
#debug: msg="{{ansible_default_ipv4.address}}"
debug: msg="{{hostvars['server3'].ansible_default_ipv4.address}}"
[root@server1 chap]# ansible-playbook 8.yaml
PLAY [server3] ***************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server3]
PLAY [server2] ***************************************************************************************************************************************************************************************************************************************************************
TASK [打印IP] ******************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "192.168.88.138"
}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
server3 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@server1 chap]#
inventory_hostname
[root@server1 chap]# cat hosts
[web]
server1
#server2
192.168.88.137
server3
[root@server1 chap]# cat 9.yaml
---
- hosts: all
tasks:
- name: 打印主机名--方法一
debug: msg="{{ansible_fqdn}}"
- name: 打印主机名--方法二
debug: msg="{{ansible_nodename}}"
- name: 打印短主机名
debug: msg="{{ansible_hostname}}"
- name: 打印在清单文件 ./hosts 中定义的主机名
debug: msg="{{inventory_hostname}}"
[root@server1 chap]# ansible-playbook 9.yaml
PLAY [all] *******************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [192.168.88.137]
ok: [server1]
ok: [server3]
TASK [打印主机名--方法一] ************************************************************************************************************************************************************************************************************************************************************
ok: [server1] => {
"msg": "server1.rhce.cc"
}
ok: [192.168.88.137] => {
"msg": "server2.rhce.cc"
}
ok: [server3] => {
"msg": "server3.rhce.cc"
}
TASK [打印主机名--方法二] ************************************************************************************************************************************************************************************************************************************************************
ok: [server1] => {
"msg": "server1.rhce.cc"
}
ok: [192.168.88.137] => {
"msg": "server2"
}
ok: [server3] => {
"msg": "server3"
}
TASK [打印短主机名] ****************************************************************************************************************************************************************************************************************************************************************
ok: [server1] => {
"msg": "server1"
}
ok: [192.168.88.137] => {
"msg": "server2"
}
ok: [server3] => {
"msg": "server3"
}
TASK [打印在清单文件 ./hosts 中定义的主机名] ***********************************************************************************************************************************************************************************************************************************************
ok: [server3] => {
"msg": "server3"
}
ok: [server1] => {
"msg": "server1"
}
ok: [192.168.88.137] => {
"msg": "192.168.88.137"
}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
192.168.88.137 : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
server1 : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
server3 : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@server1 chap]#
变量的过滤器
数字变量的运算
在yaml文件中如果定义的变量,它的值是数字的话,可以对其数值进行加数学运算的。
如下,定义变量 xxx值为3,一次对其进行加减乘除运算
[root@server1 chap]# cat 10.yaml
---
- hosts: server2
vars:
xxx: 3
tasks:
- name: print+
debug: msg="{{xxx+10}}"
- name: print-
debug: msg="{{xxx-10}}"
- name: printx
debug: msg="{{xxx*10}}"
- name: print/
debug: msg="{{xxx/10}}"
- name: print^
debug: msg="{{xxx**2}}"
[root@server1 chap]# ansible-playbook 10.yaml
PLAY [server2] ***************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
TASK [print+] ****************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "13"
}
TASK [print-] ****************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "-7"
}
TASK [printx] ****************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "30"
}
TASK [print/] ****************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "0.3"
}
TASK [print^] ****************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "9"
}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=6 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@server1 chap]#
数字类型
数字类型的函数,int整型、float浮点类型、abs绝对值、round四舍五入、random随机数
如整型 int ,可以把字符串转变为整型类型
# 把字符串 '10' 转成 int 类型与 xxx的3 进行相加
[root@server1 chap]# cat 11.yaml
---
- hosts: server2
vars:
xxx: 3
tasks:
- name: print+
debug: msg="{{xxx+('10'|int)}}"
- name: default
debug: msg="{{yyy | default('NONE')}}"
[root@server1 chap]# ansible-playbook 11.yaml
PLAY [server2] ***************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
TASK [print+] ****************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "13"
}
TASK [default] ***************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "NONE"
}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@server1 chap]#
列表
max、length、sort、sum、shuffle打乱顺序显示
[root@server1 chap]# cat 12.yaml
---
- hosts: server2
vars:
list1: [1,19,8,0,20,5]
tasks:
- name: 打印列表最大值
debug: msg="{{list1|max}}"
- name: 打印列表长度,有多少元素
debug: msg="{{list1|length}}"
- name: 对列表排序
debug: msg="{{list1|sort}}"
[root@server1 chap]# ansible-playbook 12.yaml
PLAY [server2] ***************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
TASK [打印列表最大值] ***************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "20"
}
TASK [打印列表长度,有多少元素] **********************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "6"
}
TASK [对列表排序] *****************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": [
0,
1,
5,
8,
19,
20
]
}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
字符串相关
[root@server1 chap]# cat 13.yaml
---
- hosts: server2
vars:
aa: "qweqw fdasf"
tasks:
- name: 打印变量
debug: msg="{{aa}}"
- name: 打印转为大写后的字符串
debug: msg="{{aa|upper}}"
- name: 大写变为小写的
debug: msg="{{aa|lower}}"
[root@server1 chap]# ansible-playbook 13.yaml
PLAY [server2] ***************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
TASK [打印变量] ******************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "qweqw fdasf"
}
TASK [打印转为大写后的字符串] ***********************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "QWEQW FDASF"
}
TASK [大写变为小写的] ***************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "qweqw fdasf"
}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@server1 chap]#
加密相关
[root@server1 chap]# cat 14.yaml
---
- hosts: server2
vars:
aa: "qweqw fdasf"
tasks:
- name: md5加密
debug: msg="{{aa|hash('md5')}}"
- name: sha1加密
debug: msg="{{aa|hash('sha1')}}"
- name: sha512加密
debug: msg="{{aa|hash('sha512')}}"
- name: passwd加密
debug: msg="{{aa|password_hash('sha512')}}"
[root@server1 chap]# ansible-playbook 14.yaml
PLAY [server2] ***************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
TASK [md5加密] *****************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "969073c3aa5064bb6d780b02e68de3cd"
}
TASK [sha1加密] ****************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "f2046b1529507de02c7a00a2aa9ecae10043239c"
}
TASK [sha512加密] **************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "7fe6f876088d2dac8a7945e958154eae007b9666d43b62867b852913c05437b8e4eb3f712d381a8ea90e0b56fb3372e5add293eb5968e7ba14727f6ffce0b19f"
}
TASK [passwd加密] **************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "$6$Ug991ZyACqMR02it$sXxBJepaq7GwzqLuaMJdj04RNZXuz9h4e/ar7rheup5iubiYS.39SG6QzZ/TfiPSuk1N8lbf4auKoiGg9Op1E/"
}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
对 playbook 进行加密,使用 ansible-vault
加密: ansible-vault encrypt xxx.yaml
解密: ansible-vault decrypt xxx.yaml
查看加密内容: ansible-vault view xxx.yaml
密码也可通过密码文件进行传递
ansible-vault encrypt --vault-id xxx.enc xxx.yaml
ansible-vault view --vault-id xxx.enc xxx.yaml
ansible-vault decrypt --vault-id xxx.enc xxx.yaml
[root@server1 chap]# ansible-vault encrypt 1.yaml
New Vault password:
Confirm New Vault password:
Encryption successful
[root@server1 chap]# cat 1.yaml
$ANSIBLE_VAULT;1.1;AES256
61633863316634323031316331366535643761373238613732376432323661623836303163663932
3263393639643436326466383661663063303466626334360a663264303136643430376130383632
62396237616264623264663166663465636636343633613839393464643666346563616462653162
3436366137633566350a363736623164613334386564383763636532353734393536383764326561
62646330393739393562393332636266393538333638316630656634346331306332353532316265
37306532326635353639333234323436373431636130333265393137623864396262353637306230
34616536356334383732363532313833626236663761636631393732383632636366653938316263
65326439636261656333656236656466326536656537303135323466663434303136356631633865
36633862323235653661393234643335633032333230613335363834636261663666373262666136
33333939356463336633636134623838626663663664356330666131326339623636613931303166
35666235613333643561343039353739396230663232633738356637333361633131356230393338
30353830636433323865
[root@server1 chap]# #被加密后的 1.yaml 不能运行
[root@server1 chap]# ansible-playbook --ask-vault-pass 1.yaml
Vault password:
PLAY [server2] ***************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
TASK [输出一个变量] ****************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "11MB,这是bb:adsfa dsfadsf"
}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@server1 chap]# ansible-vault view 1.yaml
Vault password:
---
- hosts: server2
vars:
aa: 11
bb: "adsfa dsfadsf"
tasks:
- name: 输出一个变量
debug: msg="{{aa}}MB,这是bb:{{bb}}"
[root@server1 chap]# ansible-vault decrypt 1.yaml
Vault password:
Decryption successful
[root@server1 chap]# cat 1.yaml
---
- hosts: server2
vars:
aa: 11
bb: "adsfa dsfadsf"
tasks:
- name: 输出一个变量
debug: msg="{{aa}}MB,这是bb:{{bb}}"
[root@server1 chap]#
想变更密码,可以先解密,再使用新密码加密;
也可以使用 : ansible-vault rekey xxx.yaml,根据提示输入新旧密码就ok。
判断语句
when: 当满足设定条件的时候执行某个task,常用判断包括:==等于、!=不等于、>大于、>=大于等于、<小于、<=小于等于、in、is
[root@server1 chap]# cat 15.yaml
---
- hosts: web
vars:
aa: 1
list1: [1,20,30,22,11]
bb:
tasks:
- name: aaaa
debug: msg="111"
when: aa >= 2 and (3 >= 2 or 3 == 2)
- name: bbbb
debug: msg="2222"
when: ansible_default_ipv4.address == "192.168.88.137"
- name: wheninnotin
debug: msg="3333"
when: 1 not in list1
- name: whenis
debug: msg="4444"
when : aa is defined
- name: whenis2
debug: msg="5555"
when : aa is undefined
[root@server1 chap]# ansible-playbook 15.yaml
PLAY [web] *******************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
ok: [server1]
ok: [server3]
TASK [aaaa] ******************************************************************************************************************************************************************************************************************************************************************
skipping: [server1]
skipping: [server2]
skipping: [server3]
TASK [bbbb] ******************************************************************************************************************************************************************************************************************************************************************
skipping: [server1]
ok: [server2] => {
"msg": "2222"
}
skipping: [server3]
TASK [wheninnotin] ***********************************************************************************************************************************************************************************************************************************************************
skipping: [server2]
skipping: [server3]
skipping: [server1]
TASK [whenis] ****************************************************************************************************************************************************************************************************************************************************************
ok: [server1] => {
"msg": "4444"
}
ok: [server2] => {
"msg": "4444"
}
ok: [server3] => {
"msg": "4444"
}
TASK [whenis2] ***************************************************************************************************************************************************************************************************************************************************************
skipping: [server3]
skipping: [server1]
skipping: [server2]
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server1 : ok=2 changed=0 unreachable=0 failed=0 skipped=4 rescued=0 ignored=0
server2 : ok=3 changed=0 unreachable=0 failed=0 skipped=3 rescued=0 ignored=0
server3 : ok=2 changed=0 unreachable=0 failed=0 skipped=4 rescued=0 ignored=0
[root@server1 chap]#
错误处理
忽略报错:如果某个task出现问题,则后续的所有 task,包括其他 play 里的 task 都不会再执行,通过 ignore_errors: true 忽略执行错误,继续往下执行。
[root@server1 chap]# cat 16.yaml
---
- hosts: server2
vars:
tasks:
- name: aaaa
shell: "cat /etc/host11"
register: aa
ignore_errors: true
- name: 报错-没成功
debug: msg="执行报错"
when: aa.rc != 0
- name: bbbb
debug: msg="{{aa.stdout}}"
when: aa.rc == 0
[root@server1 chap]# ansible-playbook 16.yaml
PLAY [server2] ***************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
TASK [aaaa] ******************************************************************************************************************************************************************************************************************************************************************
fatal: [server2]: FAILED! => {"changed": true, "cmd": "cat /etc/host11", "delta": "0:00:00.003205", "end": "2022-12-12 06:04:05.600187", "msg": "non-zero return code", "rc": 1, "start": "2022-12-12 06:04:05.596982", "stderr": "cat: /etc/host11: 没有那个文件或目录", "stderr_lines": ["cat: /etc/host11: 没有那个文件或目录"], "stdout": "", "stdout_lines": []}
...ignoring
TASK [报错-没成功] ****************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "执行报错"
}
TASK [bbbb] ******************************************************************************************************************************************************************************************************************************************************************
skipping: [server2]
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=3 changed=1 unreachable=0 failed=0 skipped=1 rescued=0 ignored=1
[root@server1 chap]#
有些步骤一旦执行报错,但是添加了 ignore_errors ,后续其他步骤再执行无意义,通过 fail 关键字,在执行完 fail 模块后,会退出 playbook。
[root@server1 chap]# cat 17.yaml
---
- hosts: server2
vars:
tasks:
- name: aaaa
shell: "cat /etc/host11"
register: aa
ignore_errors: true
- name: 报错-没成功
fail: msg="执行报错"
when: aa.rc != 0
- name: bbbb
debug: msg="{{aa.stdout}}"
when: aa.rc == 0
[root@server1 chap]# ansible-playbook 17.yaml
PLAY [server2] ***************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
TASK [aaaa] ******************************************************************************************************************************************************************************************************************************************************************
fatal: [server2]: FAILED! => {"changed": true, "cmd": "cat /etc/host11", "delta": "0:00:00.004167", "end": "2022-12-12 06:09:58.755833", "msg": "non-zero return code", "rc": 1, "start": "2022-12-12 06:09:58.751666", "stderr": "cat: /etc/host11: 没有那个文件或目录", "stderr_lines": ["cat: /etc/host11: 没有那个文件或目录"], "stdout": "", "stdout_lines": []}
...ignoring
TASK [报错-没成功] ****************************************************************************************************************************************************************************************************************************************************************
fatal: [server2]: FAILED! => {"changed": false, "msg": "执行报错"}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=2 changed=1 unreachable=0 failed=1 skipped=0 rescued=0 ignored=1
[root@server1 chap]#
block-rescue
只要有一个 task 没有成功,则block里后续的task就不再执行(除了加上 ignore_errors),整个block就被认为没成功,就会执行 rescue,如果rescue也失败,则会认为整体都失败,会退出 playbook。
block中如果都执行成功,则不再执行 rescue。
block:
task1
task2
rescue:
taska
taskb
[root@server1 chap]# cat 18.yaml
---
- hosts: server2
vars:
tasks:
- name: aaaa
debug: msg="aaaaaaaaaaaaaaa"
- name: taskbr
block:
- name: 1111
shell: "ls /etc/hostx"
- name: 2222
debug: msg="2222"
- name: 3333
shell: "ls /etc/hosts"
rescue:
- name: xxxx
shell: "ls /etc/hosts"
- name: yyyy
debug: msg="yyyy"
- name: bbbb
debug: msg="bbbbbbbbbbbbbb"
[root@server1 chap]# ansible-playbook 18.yaml
PLAY [server2] ***************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
TASK [aaaa] ******************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "aaaaaaaaaaaaaaa"
}
TASK [shell] *****************************************************************************************************************************************************************************************************************************************************************
fatal: [server2]: FAILED! => {"changed": true, "cmd": "ls /etc/hostx", "delta": "0:00:00.004147", "end": "2022-12-12 06:27:14.340792", "msg": "non-zero return code", "rc": 2, "start": "2022-12-12 06:27:14.336645", "stderr": "ls: 无法访问'/etc/hostx': 没有那个文件或目录", "stderr_lines": ["ls: 无法访问'/etc/hostx': 没有那个文件或目录"], "stdout": "", "stdout_lines": []}
TASK [xxxx] ******************************************************************************************************************************************************************************************************************************************************************
changed: [server2]
TASK [yyyy] ******************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "yyyy"
}
TASK [bbbb] ******************************************************************************************************************************************************************************************************************************************************************
ok: [server2] => {
"msg": "bbbbbbbbbbbbbb"
}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=5 changed=1 unreachable=0 failed=0 skipped=0 rescued=1 ignored=0
[root@server1 chap]#
循环语句
loop关键字
[root@server1 chap]# cat users.txt
xx: 111
yy: 222
users:
- uname: tom
age: 21
sex: M
- uname: bob
age: 22
sex: F
- uname: mary
age: 23
sex: F
[root@server1 chap]# cat 19.yaml
---
- hosts: server2
vars_files:
- users.txt
tasks:
- name: 遍历用户
debug: msg="{{item.uname}}"
when: item.age >= 22
loop: "{{users}}"
- name: print xxx
debug: msg="{{item.uname}}"
when: item.age >=22
loop:
- uname: Abe
age: 20
- uname: Amy
age: 23
[root@server1 chap]# ansible-playbook 19.yaml
PLAY [server2] ***************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
TASK [遍历用户] ******************************************************************************************************************************************************************************************************************************************************************
skipping: [server2] => (item={'uname': 'tom', 'age': 21, 'sex': 'M'})
ok: [server2] => (item={'uname': 'bob', 'age': 22, 'sex': 'F'}) => {
"msg": "bob"
}
ok: [server2] => (item={'uname': 'mary', 'age': 23, 'sex': 'F'}) => {
"msg": "mary"
}
TASK [print xxx] *************************************************************************************************************************************************************************************************************************************************************
skipping: [server2] => (item={'uname': 'Abe', 'age': 20})
ok: [server2] => (item={'uname': 'Amy', 'age': 23}) => {
"msg": "Amy"
}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
jinjia2模板
以下示例中,1.txt 这个文件内含有变量,这种文件被称为 jinjia2 模板,一般以 j2 为文件名后缀。
[root@server1 chap2]# cat 1.txt
hello,你好,我是 {{myname}}
我的主机名是:{{ansible_fqdn}}
我的IP地址是:{{ansible_default_ipv4.address}}
[root@server1 chap2]# cat 1.yaml
---
- hosts: server2
vars:
myname: zhuchun
tasks:
- name: 拷贝一个文件到主机里
template: src=1.txt dest=/opt/1.txt
[root@server1 chap2]# ansible-playbook 1.yaml
PLAY [server2] ***************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
TASK [拷贝一个文件到主机里] ************************************************************************************************************************************************************************************************************************************************************
ok: [server2]
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@server1 chap2]#
[root@server2 ~]# cat /opt/1.txt
hello,你好,我是 zhuchun
我的主机名是:server2.rhce.cc
我的IP地址是:192.168.88.137
在 jinjia2 模板文件里,也可以写循环和判断语句,不是在playbook里。
[root@server1 chap2]# cat aa.j2
11111111111
{% if ansible_fqdn == "server3.rhce.cc" %}
aaaaaaaaaaaaa
{% endif %}
222222222222
[root@server1 chap2]# cat aa.yaml
---
- hosts: server2
vars:
myname: zhuchun
tasks:
- name: 拷贝一个文件到主机里
template: src=aa.j2 dest=/opt/aa.txt
[root@server1 chap2]# ansible-playbook aa.yaml
PLAY [server2] ***************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
TASK [拷贝一个文件到主机里] ************************************************************************************************************************************************************************************************************************************************************
ok: [server2]
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@server1 chap2]#
[root@server2 ~]# cat /opt/aa.txt
11111111111
222222222222
[root@server2 ~]#
循环:
[root@server1 chap2]# cat users.txt
xx: 111
yy: 222
users:
- uname: tom
age: 21
sex: M
- uname: bob
age: 22
sex: F
- uname: mary
age: 23
sex: F
[root@server1 chap2]# cat bb.j2
1111111111
{% for i in users %}
{{i.uname}}
{% endfor %}
2222222222
[root@server1 chap2]# cat bb.yaml
---
- hosts: server2
vars_files:
- users.txt
tasks:
- name: 拷贝一个文件到主机里
template: src=bb.j2 dest=/opt/bb.txt
[root@server1 chap2]# ansible-playbook bb.yaml
PLAY [server2] ***************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************
ok: [server2]
TASK [拷贝一个文件到主机里] ************************************************************************************************************************************************************************************************************************************************************
changed: [server2]
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************
server2 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@server1 chap2]#
[root@server2 ~]# cat /opt/bb.txt
1111111111
tom
bob
mary
2222222222
[root@server2 ~]#
handlers
用于做触发,当某个 task 执行了,则可以触发另外的一种行为。
可以有多个handlers,在tasks中关联触发的那个 name 就调用哪个 handlers
handlers:
- name: restart httpd1
service: name=httpd state=restarted
- name: restart httpd2
service: name=httpd state=restarted
然后在tasks中,通过 notify关键字触发 handlers,当 j2 配置文件发生变更时,则会触发 handler执行。
tasks:
- name: 拷贝配置文件
template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
notify: restart httpd1
管理大型项目
并行运行
ansible在多台机器执行task的时候,默认是5台5台的运行,100台机器则分成20组来执行(/etc/ansible/ansible.cfg 文件中的 forks),实际使用中,根据实际情况,调整 forks的值。
在多台机器上同时执行某个task
滚动更新
在某台机器上执行完所有的task,逐台执行,滚动升级
在 playbook 中声明 serial 并指定机器数量既可
- hosts: server2
serial: 1
tasks:
...
serial: 1 表示逐台执行所有task
serial: 3 同理表示3台执行完所有task后再在下面三台执行所有 task
包含
通过 include 关键字引入其他 yaml
通过 import_tasks 关键字引入其他 yaml 中的 tasks
角色
ansible-galaxy init apache 创建一个 role
定义变量写入 defaults/main.yaml 或者 vars/main.yaml ,defaults 里的优先级比较低
tasks 写入 tasks/main.yaml 文件中
handlers 写入 handlers/main.yaml 文件中
templates 中放 j2 模板
files 中放需要拷贝的文件
meta 里面是注释信息
- hosts: server2
vars:
myport: 80
roles:
- role: apache
- hosts: server2
vars:
myport: 80
roles:
- { role: apache,tags: ["aa", "xx"] }
- { role: http,tags: ["bb", "xx"] }
ansible-playbook -t aa xx.yaml # 只会执行含有aa标签的角色
系统自带角色
[root@server1 chap2]# yum install rhel-system-roles.noarch -y
[root@server1 chap2]# ls /usr/share/ansible/roles/
linux-system-roles.certificate linux-system-roles.logging linux-system-roles.postfix linux-system-roles.timesync rhel-system-roles.kdump rhel-system-roles.nbde_server rhel-system-roles.sshd
linux-system-roles.crypto_policies linux-system-roles.metrics linux-system-roles.selinux linux-system-roles.tlog rhel-system-roles.kernel_settings rhel-system-roles.network rhel-system-roles.storage
linux-system-roles.ha_cluster linux-system-roles.nbde_client linux-system-roles.ssh rhel-system-roles.certificate rhel-system-roles.logging rhel-system-roles.postfix rhel-system-roles.timesync
linux-system-roles.kdump linux-system-roles.nbde_server linux-system-roles.sshd rhel-system-roles.crypto_policies rhel-system-roles.metrics rhel-system-roles.selinux rhel-system-roles.tlog
linux-system-roles.kernel_settings linux-system-roles.network linux-system-roles.storage rhel-system-roles.ha_cluster rhel-system-roles.nbde_client rhel-system-roles.ssh
使用时,可以在ansible.cfg 中通过冒号引入多个 role_path 的路径
或者把系统角色直接拷贝过来使用
ansible-galaxy
世界各地的 ansible 用户,会有些自定义的role 会传到 galaxy.ansible.com 中,类似 role 的仓库
# 安装方式一:
ansible-galaxy install ftp://ftp.rhce.cc/auto/web.tar.gz
# 安装方式二:
ansible-galaxy install -r aa.yaml -p roles
aa.yaml 内容格式为:
- src: ftp://ftp.rhce.cc/auto/web.tar.gz
name: webxxx
故障排除
# 检查语法错误
ansible-playbook 1.yaml --syntax-check
# 模拟执行,不做任何改变
ansible-playbook 1.yaml -C
ansible-playbook 1.yaml --check
或者配置文件 check_mode: yes
# 一步步执行进行排错
ansible-playbook 1.yaml --step
# 从特定的 play 执行
ansible-playbook 1.yaml --start-at-task='taskaaa'
# 查看详细报错
ansible-playbook 1.yaml -v
ansible-playbook 1.yaml -vv
ansible-playbook 1.yaml -vvv
ansible-playbook 1.yaml -vvvv
# 记录日志
在 ansible.cfg 文件中配置:
log_path=./xxx.log
自动执行Linux任务
# cron模块
ansible server2 -m cron -a "name='aa' user=root weekday=1-3 day=1-10 hour=* minute=0 job='rm -rf /tmp'"
# reboot 模块
ansible server2 -m reboot -a "reboot_timeout=10"