Skip to content

1. tar 压缩选项速查 ​

选项压缩格式文件后缀解压命令
-czfgzip.tar.gz / .tgz-xzf
-cjfbzip2.tar.bz2-xjf
-cJfxz.tar.xz-xJf
-caf自动检测任意-xaf

常用示例:

bash
# 压缩
tar -czf archive.tar.gz /path/to/dir      # gzip
tar -cjf archive.tar.bz2 /path/to/dir     # bzip2
tar -cJf archive.tar.xz /path/to/dir      # xz

# 解压
tar -xzf archive.tar.gz
tar -xjf archive.tar.bz2
tar -xJf archive.tar.xz
tar -xaf archive.tar.gz                    # 自动检测格式

gzip 与 bzip2 格式对比:

gzipbzip2
魔数 (Magic)1f 8b42 5a ("BZ")
头部结构10 字节固定头4 字节魔数 + 1 字节版本
压缩算法DEFLATE (LZ77 + Huffman)Burrows-Wheeler + Huffman
尾部CRC32 + 原始大小 (各 4 字节)CRC + 原始大小

⚠️ 两者格式完全不同,不能互相替换或混合使用。



2. 容器管理完整指南 ​

镜像与容器的关系 ​

Containerfile/Dockerfile   ←  配方(怎么装软件、配什么环境)
        ↓ podman build
      镜像 (Image)          ←  打包好的成品(只读,不动)
        ↓ podman run
     容器 (Container)       ←  跑起来的实例(活的,占内存)
概念类比
Containerfile菜谱(写清楚要什么材料、怎么做)
镜像 (Image)做好的菜,放冰箱里不动,随时能端出来
容器 (Container)餐桌上正在吃的那盘菜(可以吃、可以加调料)
  • 镜像:只读模板,包含操作系统基础层 + 软件 + 配置文件,存在本地磁盘上,一个镜像可以同时跑多个容器
  • 容器:镜像跑起来的实例,在镜像基础上加了一个可写层,占用 CPU 和内存

完整操作流程 ​

准备工作(root 用户) ​

bash
# 1. 创建用户并设置密码
useradd sashat
echo "redhat" | passwd --stdin sashat

# 2. 安装 podman
yum install podman -y

# 3. 配置镜像仓库
vim /etc/containers/registries.conf
toml
unqualified-search-registries = ["registry.lab.example.com"]

[[registry]]
location = "registry.lab.example.com"
insecure = true
blocked = false
参数含义
unqualified-search-registries不带域名前缀时默认搜索的仓库
insecure = true允许 HTTP 连接(考试内网无证书)
blocked = false不阻止该仓库

构建镜像流程(sashat 用户) ​

bash
# 1. 切换用户
ssh sashat@servera

# 2. 下载 Containerfile
wget http://content.example.com/Containerfile

# 3. 登录镜像仓库
podman login registry.lab.example.com
# Username: admin / Password: 321

# 4. 构建镜像
podman build -t modify_file:latest .
#                                    ^ 点不能忘!

# 5. 查看构建结果
podman images

⚠️ podman build -t name:tag . 最后的 . 表示当前目录作为构建上下文,漏掉会报错。

导入/推送镜像流程 ​

bash
# 1. 从 tar 包导入镜像
podman load < rsyslog.tar

# 2. 打标签(镜像名必须匹配仓库地址)
podman image tag localhost/rsyslog:latest registry.lab.example.com/library/rsyslog:latest

# 3. 登录仓库
podman login registry.lab.example.com

# 4. 推送到仓库
podman push registry.lab.example.com/library/rsyslog:latest

⚠️ podman load 用 < 重定向读取,不能直接跟文件名。

运行容器 ​

bash
# 创建挂载目录
mkdir /home/sashat/syslog

# 运行容器
podman run -d --privileged \
  -v /home/sashat/syslog:/var/log:Z \
  --name logserver \
  registry.lab.example.com/library/rsyslog:latest

# 进入容器执行命令
podman exec -it logserver /bin/bash
logger "This is a rhcsa exam"

# 验证
grep rhcsa /home/sashat/syslog/messages
skopeo inspect docker://registry.lab.example.com/library/rsyslog:latest
参数含义
-d后台运行(detach)
--privileged特权模式,允许容器访问宿主机设备
-v 宿主机:容器:Z挂载目录,:Z 为 SELinux 标签
--name给容器命名
-it交互模式 + 伪终端

rm vs rmi ​

命令用途删除对象
podman rm删除容器运行中/已停止的容器
podman rmi删除镜像镜像(i = image)
bash
podman rmi localhost/rsyslog:latest
podman rmi --all    # 删除所有镜像

⚠️ 用 podman images 确认镜像已删除。



Podman 容器 systemd 开机自启 ​

为什么需要先运行临时容器再生成服务文件? ​

podman generate systemd 需要读取一个已存在的容器配置来生成 .service 文件。正确流程:

run 临时容器(配好所有参数) → generate systemd 生成服务文件 → 删除临时容器 → systemd 接管

完整操作流程 ​

bash
# 1. 准备挂载目录(root)
mkdir /opt/txt.pdf
chown sashat:sashat /opt/txt.pdf

# 2. 切换到用户
ssh sashat@servera

# 3. 运行临时容器
podman run -d --name txt2pdf \
  -v /opt/txt/:/opt/txt:Z \
  -v /opt/pdf:/opt/pdf:Z \
  localhost/modify_file:latest

# 4. 生成 systemd 服务文件
mkdir -p ~/.config/systemd/user
cd ~/.config/systemd/user
podman generate systemd txt2pdf --files --name new

# 5. 启用开机自启
systemctl --user daemon-reload
systemctl --user enable container-txt2pdf.service

# 6. 清理临时容器并重启服务
podman rm -f txt2pdf
systemctl --user restart container-txt2pdf.service

# 7. 验证
podman ps
命令含义
podman generate systemd txt2pdf --files --name new根据容器配置自动生成 .service 文件
systemctl --user daemon-reload重新加载 systemd 用户级服务
systemctl --user enable设置用户级开机自启

⚠️ rootless 容器必须用用户级 systemd(--user),不能用系统级。


Podman 删除远程 Registry 中的错误镜像 ​

问题: tag 错了本地镜像,push 到了远程 registry,需要删除

解决方法:

bash
# 方法1:skopeo 删除
skopeo delete --force docker://registry.lab.example.com/library/rsyslog:latest

# 方法2:curl 调 API 删除
DIGEST=$(skopeo inspect docker://registry.lab.example.com/library/rsyslog:latest | python3 -c "import json,sys; print(json.load(sys.stdin)['Digest'])")
curl -X DELETE -k https://registry.lab.example.com/v2/library/rsyslog/manifests/$DIGEST

前提条件: Registry 需要开启 delete 功能(storage.delete.enabled: true),否则返回 405

本地清理: podman rmi -f <image> 可以本地取消 tag


Docker 临时容器执行命令 ​

场景: 用 Docker 运行一次性容器执行某个操作,容器自动删除。

bash
# 生成 UUID(以 sing-box 代理工具为例)
docker run --rm ghcr.io/sagernet/sing-box:latest generate uuid
参数含义
--rm容器执行完后自动删除,不留垃圾
ghcr.io/sagernet/sing-box:latestDocker 镜像地址(GitHub Container Registry)
generate uuid容器内执行的命令

原理: Docker 拉取镜像 → 启动容器 → 执行 generate uuid → 输出 UUID 字符串 → 容器自动销毁。

⚠️ --rm 和 -d 不能同时用:--rm 会在容器退出时删除,-d 是后台运行。


Docker 端口映射 -p 主机端口:容器端口 ​

命令示例:

bash
docker run --name nginx_container_test -d -p 8080:80 nginx
参数含义
docker run运行一个新容器
--name nginx_container_test给容器起个名字
-d后台运行(detached),不占终端
-p 8080:80端口映射(核心)
nginx用 nginx 镜像(默认 nginx:latest)

-p 主机端口:容器端口 核心原理:

宿主机(你的电脑)        容器(隔离的小盒子)
   8080  ←————— 映射 —————→  80
   ↑                          ↑
   外部访问入口              Nginx 内部监听端口
  • 8080 = 宿主机端口,外部能访问
  • 80 = 容器内部端口,外部访问不到
  • Docker 做中转:访问宿主机 8080 → 自动转到容器的 80

为什么不直接用 80? 容器是网络隔离的,容器内的 80 端口外面访问不到,必须通过 -p 暴露出来。 还能避免端口冲突:

  • 容器 A:-p 8080:80
  • 容器 B:-p 8081:80
  • 两个 Nginx 同机跑,互不打架

实测访问: http://localhost:8080(浏览器应看到 Nginx 欢迎页)

常用端口参数:

bash
-p 8080:80                 # 指定映射(最常用)
-p 127.0.0.1:8080:80       # 只允许本机访问(绑定指定 IP,更安全)
-P                          # 大写P:随机映射端口(自动选空闲端口)

查看实际映射:

bash
docker port nginx_container_test
# 输出:80/tcp -> 0.0.0.0:8080

一句话总结: 主机端口:容器端口 = 外面的人怎么敲门进哪个房间。8080 是大门铃,80 是屋里 Nginx 的房间号。



3. 用户与权限管理 ​

语法公式 ​

用户/组  主机=(目标用户)  NOPASSWD:命令

示例 ​

%admins ALL=(root) NOPASSWD:ALL
  ①         ②          ③    ④
字段值含义
① %admins% = 组,admins = 组名admins 组所有成员
② ALL主机名在任何主机上生效
(root)目标用户可切换到 root
③ NOPASSWD无需密码执行 sudo 不需要输密码
④ ALL命令范围可执行任何命令

常见写法速查 ​

bash
# 用户 harry 可 sudo,需要密码
harry ALL=(root) ALL

# 用户 harry 可 sudo,不需要密码
harry ALL=(root) NOPASSWD:ALL

# wheel 组可 sudo(RHEL 默认)
%wheel ALL=(ALL) ALL

# 用户 bob 只能重启 httpd
bob ALL=(root) /usr/bin/systemctl restart httpd

# users 组可 sudo,不需要密码
%users ALL=(root) NOPASSWD:ALL

配置文件位置 ​

/etc/sudoers              ← 主配置文件(一般不动)
/etc/sudoers.d/admins     ← 额外配置文件(推荐在这里写)

⚠️ /etc/sudoers.d/ 下的文件名不要有 .(如 admin.conf),否则可能不被加载。

验证 ​

bash
su - harry
sudo id
# uid=0(root) gid=0(root) groups=0(root)  ← sudo 提权成功


密码策略 + chage 命令 ​

全局默认策略:/etc/login.defs ​

bash
vim /etc/login.defs
参数含义默认值
PASS_MAX_DAYS密码最长有效天数(过期时间)99999
PASS_MIN_DAYS密码最短修改间隔(天)0
PASS_MIN_LEN密码最小长度(会被 PAM 覆盖)5
PASS_WARN_AGE密码到期前警告天数7

考试常考:修改 PASS_MAX_DAYS 20 表示新用户密码 20 天后过期。

⚠️ /etc/login.defs 只对新创建的用户生效,已存在的用户不受影响。

验证新用户策略 ​

bash
useradd user1
chage -l user1
# Maximum number of days between password change : 20  ← 确认生效

chage 命令:精确控制单个用户 ​

bash
chage [选项] 用户名
参数含义示例
-l列出用户的密码策略信息chage -l harry
-M设置密码最大有效期(天)chage -M 90 harry
-m设置密码最短修改间隔(天)chage -m 7 harry
-W设置密码到期提前警告天数chage -W 14 harry
-I密码过期后强制停用天数chage -I 30 harry
-E设置账户过期日期chage -E 2026-12-31 harry
-d设置上次改密码日期chage -d 2026-01-01 harry

常用场景:

bash
chage -M 90 harry           # 密码 90 天过期
chage -I 3 harry            # 过期后 3 天不改就锁定
chage -E 2026-12-31 intern1 # 账户 2026-12-31 过期
chage -d 0 harry            # 强制下次登录必须改密码

chage -l 输出解读 ​

Last password change                : Jan 01, 2026
Password expires                    : Mar 02, 2026
Password inactive                   : never
Account expires                     : never
Minimum number of days between password change : 0
Maximum number of days between password change : 90    ← 关键字段
Number of days of warning before password expires : 7

login.defs vs chage 区别 ​

/etc/login.defschage
作用范围全局默认,只影响新用户单个用户,精确控制
生效时机创建用户时读取立即生效
适合场景改默认策略改已有用户


useradd -g 与 -G 的区别 ​

-g(小写)= 主组(primary group)

  • 指定用户登录时的默认组
  • 用户只能有一个主组
  • 示例:useradd -g admins harry → harry 的主组是 admins

-G(大写)= 附加组(supplementary groups)

  • 指定用户额外属于的组,可以有多个(逗号分隔)
  • 示例:useradd -G admins harry → harry 主组是默认的 harry 组,admins 是附加组

记忆技巧: 小 g = group(一个),大 G = Groups(多个)

验证: id harry 可以看到 gid(主组)和 groups(所有组)


umask 详解(user file-creation mask) ​

一句话 ​

umask = 「新创建的文件/目录默认要扣掉的权限」,进程级别,全称 user file-creation mask。

核心算式 ​

最终权限 = 基权限 - umask(按位减,更准确地说:& ~umask)
类型基权限八进制
文件(无 x)rw-rw-rw-666
目录(含 x)rwxrwxrwx777

为什么文件默认没 x?避免刚建的文件能被意外执行,是历史约定。

umask 常见值对照 ​

umask文件目录场景
022(默认)644 rw-r--r--755 rwxr-xr-x普通文件
027640 rw-r-----750 rwxr-x---严格组权限
077600 rw-------700 rwx------私钥 / 密码文件
002664 rw-rw-r--775 rwxrwxr-x团队共享

算式(umask=077):

文件:666 & ~077 = 110 110 110 & 111 000 111 = 600(-rw-------)
目录:777 & ~077 = 700(drwx------)

老大的命令拆解 ​

bash
(umask 077; openssl genrsa -out devman.key 2048)
部分含义
( ... )子 shell:括号里是新 shell,不影响当前 shell 的 umask
umask 077子 shell 里临时设 umask 为 077
openssl genrsa -out devman.key 2048生成 2048 位 RSA 私钥到 devman.key
效果生成的私钥自动是 600(只有 owner 读写)

为什么必须用子 shell ( )? 直接 umask 077 会污染当前 shell;{ } 是同 shell;( ) 退出后自动还原,是一次性改 umask 的标准安全写法。

为什么私钥一定要 600?

bash
# 默认 umask 022 + 生成私钥:
$ umask        # 系统默认 022
$ openssl genrsa -out bad.key 2048
$ ls -l bad.key
-rw-r--r-- ... bad.key       # 其他用户可读!危险

# 用子 shell 加 umask 077:
$ (umask 077; openssl genrsa -out good.key 2048)
$ ls -l good.key
-rw------- ... good.key      # 只有 owner 读写

私钥泄露 = 任何能读这文件的用户都能解密/伪装身份。私钥几乎一定要 600,是行业铁规。

相关实用命令 ​

bash
umask               # 当前 umask(数字)
umask -S            # 当前 umask(符号格式)
umask 077           # 设为 077(影响当前 shell 及后续子进程)

stat -c '%a %n' file      # 看文件八进制权限:600 devman.key
stat -c '%A %n' file      # 看文件符号权限:-rw------- devman.key

chmod 600 file            # 手动改,不依赖 umask

易踩坑清单 ​

  1. 子 shell ( ) vs 命令组 { ; }:( ) 真子 shell、退出环境还原;{ ; } 同 shell、大括号右侧需空格
  2. openssl genrsa 默认不锁权限:跟 umask 强依赖,不主动 chmod 就会按默认 umask 走
  3. SSH 私钥要求 600:否则 ssh 直接报错 Permissions 0644 for 'xxx' are too open
  4. root 创建文件默认也是 644:root 不自动 600,同样依赖 umask
  5. umask 只决定新文件默认权限:已存在文件改动用 chmod,不跟 umask 走
  6. umask 不能加可执行位:就算 umask 000,文件也是 666,想可执行必须显式 chmod +x
  7. Docker / k8s 容器内 umask 跟宿主机可能不同:跨环境生成文件要醒一下
  8. 台子里 umask 027 很常见:很多发行版在 /etc/profile 设过,影响所有交互登录
  9. 一些系统命令(比如 install)有自己的 mode 覆盖:不会顺着 umask


4. 磁盘与存储管理 ​

LVM 三层架构 ​

物理硬盘/分区 → 物理卷(PV) → 卷组(VG) → 逻辑卷(LV) → 格式化 → 挂载
   /dev/vdb      pvcreate      vgcreate     lvcreate      mkfs     mount
层级命令含义
物理卷 (PV)pvcreate把硬盘/分区注册进 LVM
卷组 (VG)vgcreate把 PV 合成一个大存储池
逻辑卷 (LV)lvcreate从 VG 里切出一块空间
格式化mkfs创建文件系统
挂载mount接到目录树上

扩容逻辑卷 ​

bash
lvextend -r -L 512M /dev/exam/rhel
参数含义
lvextend扩展逻辑卷大小
-r同时调整文件系统大小(自动 resize)
-L 512M目标大小(绝对大小)

⚠️ 传统方式需两步:先 lvextend 再 resize2fs(ext4)或 xfs_growfs(xfs)。加 -r 一步搞定。

创建逻辑卷(含 PE 大小设置) ​

题目要求: 卷组 myvg,逻辑卷 mylv,PE 大小 16M,LV 大小 50 个 PE(= 800M),文件系统 ext3,挂载 /mnt/mydata

bash
# 1. 创建分区
fdisk /dev/vdb
# n → p → 默认分区号 → +1G

# 2. 设置分区类型为 LVM
# t → 分区号 → 8e

# 3. 保存
# w

# 4. 创建卷组,PE 大小 16M(关键!)
vgcreate -s 16M myvg /dev/vdb3

# 5. 创建逻辑卷(50 个 PE)
lvcreate -l 50 -n mylv myvg

# 6. 格式化为 ext3
mkfs.ext3 /dev/myvg/mylv

# 7. 创建挂载点并永久挂载
mkdir /mnt/mydata
echo '/dev/myvg/mylv /mnt/mydata ext3 defaults 0 0' >> /etc/fstab
mount -a

# 8. 验证
df -Th /mnt/mydata/

-L vs -l 区别 ​

参数含义示例
-L(大写)指定绝对大小-L 800M
-l(小写)指定PE 数量-l 50

PE (Physical Extent) 说明 ​

  • PE 是 LVM 最小的存储分配单位,默认 4M
  • 逻辑卷大小必须是 PE 大小的整数倍
  • 用 vgcreate -s 16M 可以修改 PE 大小

易错点 ​

易错点正确做法
PE 大小忘了改vgcreate -s 16M,不是默认 4M
用 -L 而不是 -l-l 50(PE 数量),不是 -L 50M
格式化用 ext4题目要求 ext3
缩容顺序反了必须先缩文件系统,再缩 LV(扩容顺序相反)

⚠️ 扩缩容顺序相反: 扩容先扩 LV 再扩文件系统;缩容先缩文件系统再缩 LV。xfs 文件系统不能缩容。



Swap 交换区配置 ​

完整流程 ​

bash
# 1. 创建分区
fdisk /dev/vdb
# n → p → 2 → +512M

# 2. 设置分区类型为 swap
# t → 2 → 82

# 3. 保存
# w

# 4. 格式化为 swap
mkswap /dev/vdb2

# 5. 临时启用
swapon /dev/vdb2

# 6. 写入 fstab 永久生效
echo '/dev/vdb2 swap swap defaults 0 0' >> /etc/fstab

# 7. 验证 fstab
swapoff -a
mount -a
swapon -a

# 8. 确认生效
free -m

Swap 是什么? ​

物理内存 (RAM) 不够用时,把不活跃的数据暂时放到硬盘上,这块硬盘空间就是 Swap。

为什么需要 Swap?

  • 当物理内存不足时,系统把不活跃的数据从内存搬到磁盘上的 swap 空间,腾出内存给当前需要的进程
  • 好处:防止 OOM (Out of Memory) killer 杀进程
  • 坏处:磁盘比内存慢几十倍,swap 频繁使用会导致系统变慢

两种创建 swap 的方式:

bash
# 方式一:用文件创建(简单,推荐小容量)
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab

# 方式二:用分区创建(正式环境,已在上方详述)
# fdisk → t → 82 → mkswap → swapon → fstab

⚠️ fallocate 方式不支持 ZFS 和某些旧内核。创建后记得 chmod 600,否则 swap 可能不生效。

关键参数说明 ​

步骤命令含义
格式化mkswap /dev/vdb2把分区格式化为 swap 格式
临时启用swapon /dev/vdb2告诉内核开始使用这个 swap
永久生效fstab 中 swap swap defaults 0 0开机自动启用
停用swapoff -a停用所有 swap

fstab 中 swap 条目格式 ​

设备文件      挂载目录  格式   选项      备份  自检
/dev/vdb2    swap     swap   defaults   0     0

free -h vs free -m ​

参数输出格式示例
free -h人类可读(G/M/K)Mem: 3.7Gi 1.2Gi 2.1Gi ...
free -m以 MB 为单位Mem: 3812 1234 2156 ...
free -g以 GB 为单位Mem: 3 1 2 ...

推荐: 日常使用 free -h 最直观,脚本中用 free -m 方便解析。

bash
free -h
#               total   used   free   shared  buff/cache  available
# Mem:          3.7Gi  1.2Gi  2.1Gi   128Mi     400Mi      2.3Gi
# Swap:         2.0Gi  0.0Gi  2.0Gi

输出字段含义:

字段含义
total总物理内存
used已用内存(包含 buffer/cache)
free完全空闲的内存
shared多进程共享的内存
buff/cache缓冲区/缓存(可回收)
available可用内存(free + 可回收的 cache)

⚠️ 看内存够不够用,看 available 而不是 free。

free -m 输出解读 ​

              total   used   free
Swap:           511      0    511     ← 看这行,511M ≈ 512M

易错点 ​

易错点正确做法
分区号选错vdb1 已被 LVM 用,swap 用 vdb2
没改分区类型必须 t → 82 设为 swap 类型
只 swapon 没写 fstab必须写 fstab 否则重启失效
忘了验证 fstab写完用 swapoff -a && swapon -a 测试


fdisk Partition number 默认值 ​

  • Partition number (1, 2, default 2): 中默认是 2 的原因:/dev/vdb1 已被占用
  • MBR 分区表的分区号从 1 开始编号,fdisk 检测到 1 号已被使用,所以默认给出第一个空闲号 2
  • 如果磁盘是全新的,默认就是 1
  • MBR 最多 4 个主分区(编号 1-4)


分区类型(Partition Type)与修改方法 ​

分区类型是什么: 只是一个标签,告诉系统这个分区的用途,不影响实际功能

常见类型:

  • 83 = Linux(普通分区)
  • 82 = Linux swap
  • 8e = Linux LVM
  • fd = Linux RAID
  • ef = EFI System

修改方法:

  • fdisk /dev/sdb → 按 t → 输入类型编号
  • gdisk /dev/sdb → 按 t → 输入 GUID 代码
  • parted /dev/sdb set 1 lvm on(非交互式)
  • sfdisk /dev/sdb <<< ',8e'(脚本化)

RHCSA 考试流程(创建 LVM):

  1. fdisk 创建分区 → t → 改为 8e(LVM)
  2. pvcreate /dev/sdb1
  3. vgcreate vg0 /dev/sdb1
  4. lvcreate -n lv0 -L 500M vg0

注意: 改类型只是改标签,不丢数据;但 pvcreate 会写入 LVM 元数据,会清掉原有数据



MBR vs GPT 分区表类型 ​

MBR(Master Boot Record):

  • 最大 2TB 磁盘
  • 最多 4 个主分区(或 3主+1扩展,扩展里分逻辑分区)
  • BIOS 启动用
  • 工具:fdisk、parted(默认 MBR)

GPT(GUID Partition Table):

  • 支持超 2TB 磁盘
  • 最多 128 个主分区
  • UEFI 启动用
  • 工具:gdisk、parted

查看分区表类型:

  • lsblk -f
  • parted /dev/sdb print(看 Label:msdos=MBR,gpt=GPT)
  • fdisk -l /dev/sdb(看 disklabel type)

创建分区表:

  • fdisk /dev/sdb → 默认 MBR
  • parted /dev/sdb mklabel msdos → MBR
  • parted /dev/sdb mklabel gpt → GPT

RHCSA 考试: 一般用 MBR + fdisk,简单直接




5. Cron 计划任务完整指南 ​

cron 写法含义执行时间
*/2每隔 2 分钟0, 2, 4, 6, 8, ...
2每小时的第 2 分钟x:02:00

原理:* 表示"所有值",*/2 = "所有值中每隔 2 个取一个",即 0, 2, 4, 6...

常见例子:

  • */5 → 每 5 分钟
  • */10 → 每 10 分钟
  • */15 → 每 15 分钟

一句话:*/数字 = 每隔 N 分钟,单独写数字 = 每小时的第 N 分钟



Cron 计划任务相关命令总结 ​

一、Linux 系统 cron 命令 ​

命令含义
crontab -l查看当前用户的计划任务
crontab -l -u natasha查看指定用户的计划任务
crontab -e编辑当前用户的计划任务(交互式)
crontab -r删除当前用户的所有计划任务
crontab mycron.txt从文件导入计划任务

cron 时间格式 ​

┌────── 分钟 (0-59)
│ ┌──── 小时 (0-23)
│ │ ┌── 日 (1-31)
│ │ │ ┌ 月 (1-12)
│ │ │ │ ┌ 星期 (0-7, 0和7都是周日)
│ │ │ │ │
*/2 * * * *  echo hello

特殊符号 ​

符号含义示例
*每* * * * * 每分钟
*/n每隔 n*/5 * * * * 每5分钟
,列举1,3,5 * * * * 第1、3、5分钟
-范围1-5 * * * * 第1到5分钟

常见 cron 示例 ​

  • 每天凌晨2点:0 2 * * * /scripts/backup.sh
  • 每周一早上8点:0 8 * * 1 /scripts/report.sh
  • 每5分钟:*/5 * * * * /scripts/check.sh

二、Ansible cron 模块 ​

参数含义
name任务描述(标识,用于删除)
minute分钟
hour小时
day日
month月
weekday星期
job执行的命令
user执行用户
statepresent(创建) / absent(删除)

创建:cron: name="任务描述" minute="*/2" user=natasha job="echo hello" 删除:cron: name="任务描述" state=absent(用 name 匹配精确删除)

三、系统 crontab vs Ansible cron ​

项目系统 crontabAnsible cron 模块
编辑方式crontab -e 交互式Playbook 声明式
删除任务手动删行或 crontab -r 清空state: absent 按 name 精确删除
标识无name 字段(Ansible 自动加注释)



6. 系统监控脚本 ​

脚本内容 ​

bash
#!/bin/bash
ps -xao user,pid,vsz,rss,%cpu --sort=%cpu

ps 参数拆解 ​

ps -xao user,pid,vsz,rss,%cpu --sort=%cpu
   ① ②        ③              ④
参数含义
-x显示所有用户的进程,包括不依附终端的
-a显示所有终端(tty)上的进程
-o自定义输出格式(字段用逗号隔开)
--sort=%cpu按 CPU 使用率升序排列

输出字段说明 ​

字段含义
user进程的所有者
pid进程 ID
vsz虚拟内存大小(KB)
rss实际占用的物理内存(KB)
%cpuCPU 使用率

创建和运行 ​

bash
# 1. 创建脚本
vim /usr/local/bin/exam_sysinfo

# 2. 加执行权限
chmod +x /usr/local/bin/exam_sysinfo

# 3. 运行
exam_sysinfo

ps 其他常用参数 ​

参数含义
-ef显示所有进程 + 完整命令
-auxBSD 风格,显示所有进程
--sort=-%cpu降序排列(CPU 最高的在前面)
--sort=-%mem按内存降序排列

⚠️ 脚本放在 /usr/local/bin/ 可以直接用名字运行,不用写全路径。


top 与 htop 实时监控 ​

top 基本用法 ​

bash
top

常用快捷键:

按键功能
Shift+M按内存 (MEM%) 降序排列
Shift+P按 CPU 降序排列
Shift+N按 PID 降序排列
1展开每个 CPU 核心
k杀死进程(输入 PID)
q退出 top

htop(增强版 top) ​

bash
# 安装
yum install -y htop   # RHEL/CentOS
apt install -y htop   # Debian/Ubuntu

# 运行
htop

htop 优势:

  • 鼠标可点击,无需记快捷键
  • 彩色显示,更直观
  • 支持树状视图(按 F5)
  • 搜索进程(按 F3)

⚠️ htop 需要额外安装,top 系统自带。


6.1 lsof 详解(查进程 / 文件 / 端口 / 网络资源) ​

查进程“三件套” ​

需求命令说明
进程快照ps aux最常用,一次列出所有进程
实时监控top / htop动态刷新(htop 更友好)
查 PIDpidof nginx / pgrep -f 关键字按名字/命令行反查 PID

ps aux 输出字段:USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND STAT 常见值:R 运行、S 睡眠、Z 僵尸(有害)、T 停止、s 会话首进程。

lsof 是什么 ​

全名:LiSt Open Files —— 列出打开的文件 核心思想:Linux 一切皆文件(普通文件、目录、socket、管道、设备),所以 lsof 能查所有打开的资源。

最常用的 7 个用法 ​

① 端口被占,谁在监听?

bash
lsof -i :80
# COMMAND  PID  USER  FD  TYPE  DEVICE  NAME
# nginx   1234  root  6u IPv4  ...     TCP *:http (LISTEN)

② 文件被占,删不掉?

bash
rm /var/log/nginx/access.log   # Device or resource busy
lsof /var/log/nginx/access.log   # 查谁在用

③ 进程打开了哪些东西?

bash
lsof -p 1234           # 进程 1234 所有打开的资源
lsof -p 1234 -i        # 进程 1234 的网络连接

④ 谁在用某个目录?

bash
lsof +D /var/log/nginx/   # 递归查目录(慢)
lsof +d /var/log/nginx    # 不递归

⑤ 指定用户的进程

bash
lsof -u root -i           # root 的网络连接

⑥ 协议过滤

bash
lsof -i tcp:22            # 只看 22 端口 TCP

⑦ 反向查连接

bash
lsof -p 1234 -i -a | grep ESTABLISHED

实战场景速查 ​

场景命令
端口被占lsof -i :端口
文件删不掉lsof <文件>
查进程在干啥lsof -p <PID>
查进程网络连接lsof -p <PID> -i
查谁在写日志lsof +D /var/log/

lsof vs ss vs netstat ​

命令特点用途
lsof文件级精确(进程+FD+文件)文件/端口/网络全能查
ss -tlnp快(读内核),netstat 替代品仅查端口监听
netstat -tlnp老工具,慢同上(逐渐淘汰)

推荐:查端口用 ss -tlnp(快),查具体进程占文件用 lsof(精)。

一句话速记: lsof = LiSt Open Files,Linux 一切皆文件,所以能查进程、文件、端口、socket、目录的所有打开状态。最常用三招:端口占用 lsof -i :端口、文件被占 lsof <文件>、进程资源 lsof -p <PID>。


7. find 命令综合题 ​

脚本内容 ​

bash
#!/bin/bash
find /usr -size +30k -size -50k -perm -4000 -type f > /root/myfile

参数拆解 ​

参数含义
/usr从 /usr 目录开始搜索
-size +30k大于 30KB
-size -50k小于 50KB
-perm -4000包含 SUID 权限位
-type f只找普通文件
> /root/myfile结果写入文件

两个 -size 同时使用是 AND 关系:30k < 文件 < 50k

特殊权限位 ​

权限位数字含义
SUID4000执行时以文件所有者身份运行
SGID2000执行时以文件所属组身份运行
SBIT1000粘滞位(如 /tmp)

创建和运行 ​

bash
vim /usr/local/bin/mysearch
chmod a+x /usr/local/bin/mysearch
/usr/local/bin/mysearch
cat /root/myfile

脚本命名说明 ​

Linux 里文件扩展名不影响执行。系统只关心:

  1. 文件有没有执行权限(chmod +x)
  2. 文件开头有没有 shebang(#!/bin/bash)

.sh 后缀只是给人看的,考试/规范推荐不加后缀(像系统命令 ls、grep 一样)。


8. chattr -i 锁定文件属性 ​

bash
chattr +i /etc/resolv.conf   # 加 immutable 属性,文件不可改/删/重命名(root 也不行)
chattr -i /etc/resolv.conf   # 去掉 immutable 属性,恢复可编辑

用途:RHEL 7+ 的 /etc/resolv.conf 被 NetworkManager 管理,手动改 DNS 后用 chattr +i 锁死防止被覆盖;需要再改时先 chattr -i 解锁。

考试常考:改 DNS 配置前先解锁,改完再锁上。



9. free -m vs df -Th vs lsblk 三者对比 ​

free -mdf -Thlsblk
看什么内存 + swap文件系统空间块设备结构
层级RAM 层文件系统层磁盘/分区层
swap 相关✅ 显示 swap 总量和使用❌ 不显示⚠️ 只标 [SWAP] 标记
能看到设备关系❌❌✅ 树状展示
能看到可用空间✅ 内存可用✅ 磁盘可用❌ 只有大小

为什么验证 swap 用 free -m 而不是 df -Th? swap 分区没有文件系统,df -Th 根本看不到它。



10. sed 替换命令详解 ​

bash
sed -i "s/^Listen  80/Listen 82/g"

参数拆解 ​

参数含义
sedStream Editor,流编辑器
-i原地编辑(in-place),直接修改文件
s/替换命令(substitute)
^Listen 80匹配内容(^ = 行首锚定)
Listen 82替换内容
g全局替换(一行中多个匹配全换)

正则说明 ​

  • ^ 行首锚定:只匹配行开头的,不匹配行中间的
  • 没有 ^:一行中任何位置出现都替换
  • 有 g:一行中所有匹配都替换
  • 没有 g:只替换每行第一个匹配

常见用法 ​

bash
# 替换并备份原文件
sed -i.bak "s/old/new/g" file.conf

# 只输出不改文件(不加 -i)
sed "s/old/new/g" file.conf

# 删除空行
sed -i '/^$/d' file.conf

# 删除行首空格
sed -i 's/^[[:space:]]*//' file.conf


11. Bash 单引号与双引号的区别 ​

无变量时两者等价:

  • logger 'This is a rhcsa exam' 和 logger "This is a rhcsa exam" 效果相同

有变量时不同:

  • 单引号:所见即所得,不解析变量 → echo '$VAR' 输出 $VAR
  • 双引号:解析变量和命令替换 → echo "$VAR" 输出变量值

记忆: 字符串里有 $ 才需要考虑用哪种引号,纯文本随便用



12. Samba 共享配置详解 ​

配置示例 ​

ini
[share]
 path = /media/bbben/disk/share
 browseable = yes
 writable = yes
 valid users = @bbben
 create mask = 0660
 directory mask = 2770

逐项说明 ​

  • [share]:共享名,客户端连接时显示的名字(如 \\IP\share)
  • path:共享目录的物理路径
  • browseable = yes:在网络浏览中可见(no 则隐藏共享)
  • writable = yes:允许写入(no 则只读)
  • valid users = @bbben:@ 表示用户组,只有 bbben 组内用户可访问(不带@是用户名)
  • create mask = 0660:新建文件权限 rw-rw----(属主6+同组6+其他0)
  • directory mask = 2770:新建目录权限 rwxrws---(770 + setgid位2,子文件自动继承父目录组)

部署注意 ​

  1. 确保系统有 bbben 组,用户已加入
  2. Samba 密码独立设置:smbpasswd -a 用户名
  3. 目录权限:chown root:bbben /media/... && chmod 2770 /media/...
  4. 改完配置先 testparm 检查语法,再 systemctl restart smbd

查看连接与日志 ​

  • sudo smbstatus:查看当前活跃的 SMB 连接
  • 日志目录:/var/log/samba/
    • log.smbd:核心日志
    • log.nmbd:名称解析日志
    • log.<hostname>:按客户端主机名分文件

smb.conf 完整结构 ​

ini
[global]          # 全局配置(workgroup、security、hosts allow、log level)
[homes]           # 用户家目录共享(%S 自动指向当前用户目录)
[共享名]           # 自定义共享(path、writable、valid users、create mask)

关键配置项 ​

  • security = user:推荐模式,每个连接都要认证
  • hosts allow:建议只放行需要的网段
  • 常用变量:%m=客户端主机名,%M=客户端IP,%S=当前用户名

13. 终端传文件到服务器的方式 ​

1. scp(最常用) ​

核心语法:

bash
# 本地 → 远程
scp /本地/文件 用户@主机:/远程路径

# 远程 → 本地
scp 用户@主机:/远程/文件 /本地路径

# 路径格式必须是 用户@主机:/路径,冒号不能漏

常用选项:

选项作用注意
-r递归传目录传目录必须加
-P 端口SSH 端口大写 P
-p保留文件属性(时间、权限)小写 p
-C启用压缩慢网络有用
-i 密钥指定私钥密钥登录时
-v详细输出调试用
-l 限速限速 KB/s大文件避免占带宽

实战例子:

bash
scp nginx.conf root@server:/etc/nginx/                     # 传配置
scp -r ./myapp/ root@server:/opt/                          # 传项目目录
scp -i ~/.ssh/id_rsa test.txt root@server:/root/            # 密钥登录
scp -P 2222 test.txt root@server:/root/                    # 改 SSH 端口

常见坑:

  1. 远程目录必须存在,scp 不会自动创建
  2. 冒号别漏(漏了就成本地路径,报错找不到)
  3. 大写 -P 是端口,小写 -p 是保留属性,别混
  4. 第一次连接要确认 fingerprint(输入 yes)

基于 SSH,简单直接,无断点续传(大文件用 rsync)。

2. rsync(推荐,增量同步) ​

bash
rsync -avz 本地目录/ 用户名@IP:/远程路径/

支持断点续传、增量同步,适合大文件和目录同步。

3. sftp(交互式) ​

bash
sftp 用户名@IP
# put/get/lcd/cd 等交互命令

适合不确定路径时慢慢操作。

4. cat + ssh(管道流,小文件) ​

bash
cat 本地文件 | ssh 用户名@IP "cat > /远程路径/文件"

适合传配置文件等小内容。

5. ssh + tar(大批量传输) ​

bash
tar czf - /本地目录 | ssh 用户名@IP "tar xzf - -C /远程路径/"

打包压缩传输,一次性大量文件。

6. lrzsz(rz/sz,终端内传) ​

bash
rz    # 上传(弹文件选择框)
sz 文件   # 下载

需服务器安装 lrzsz,适合小文件,无断点续传。

日常推荐 ​

  • 小文件 → scp
  • 目录同步 → rsync
  • 覆盖 90% 场景


14. macOS 与 Linux 服务管理体系对比 ​

macOS 服务管理 ​

1. launchd(核心机制) ​

  • 系统级:/Library/LaunchDaemons/(后台守护)、/Library/LaunchAgents/(登录启动)
  • 用户级:~/Library/LaunchAgents/
  • 管理命令:launchctl list、launchctl load/unload
  • 配置文件:plist 格式

2. Homebrew Services(第三方,推荐) ​

  • brew services list/start/stop/restart
  • 简化了 launchd 的操作

3. 应用目录 ​

  • /Applications/(系统级)、~/Applications/(用户级)

Linux 服务管理 ​

systemd(核心) ​

  • 服务文件:/lib/systemd/system/
  • 自定义服务:/etc/systemd/system/
  • 用户服务:~/.config/systemd/user/
  • 管理命令:systemctl list-units --type=service、systemctl status/start/stop/enable/disable

关键区别 ​

维度macOSLinux
服务管理launchd + brew services(两层)systemd(一个管所有)
服务配置plist 文件service 文件
查看端口`lsof -i -Pgrep LISTEN`
包管理brewapt/yum/dnf

15. 运维学习路线与概念梳理 ​

脚本、服务、容器的关系 ​

脚本(shell/python)
  ↓ 注册为 systemd 服务 → systemctl 管理
  ↓ 打包为 Docker 镜像 → docker/podman 管理
  ↓ 镜像运行 → 容器(轻量隔离的"服务")

systemd 服务 vs Docker 容器 ​

维度systemd 服务Docker 容器
管理工具systemctldocker / podman
隔离性共享宿主机环境,无隔离独立文件系统/网络/进程,强隔离
启动方式systemctl start xxxdocker run xxx
资源占用轻,直接跑在宿主机稍重(但比虚拟机轻很多)
部署方式手动装依赖、写 service 文件Dockerfile 一键构建
可移植性换台机器要重新装环境镜像在哪都能跑
适合场景单机、简单服务微服务、多环境、团队协作

systemd 服务示例 ​

ini
# /etc/systemd/system/my-app.service
[Unit]
Description=My App

[Service]
ExecStart=/usr/bin/python3 /opt/my-app/main.py
Restart=always

[Install]
WantedBy=multi-user.target

Docker 镜像示例 ​

dockerfile
FROM python:3.11
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
CMD ["python", "main.py"]

学习路线 ​

第一阶段(基础巩固):

  • systemd 服务管理 ✅
  • Nginx 反向代理 ✅
  • 进程管理、文件权限

第二阶段(自动化运维):

  • Shell 脚本(变量、条件、循环、函数、正则)
  • Crontab 定时任务
  • 日志管理(journalctl、logrotate)
  • 网络排查(curl、dig、ss、tcpdump、iptables)

第三阶段(容器化):

  • Docker 基础(镜像、容器、Dockerfile、docker-compose)
  • Docker 网络和数据卷
  • docker-compose 多容器编排

第四阶段(进阶方向):

  • 云原生/K8s(大规模容器编排)
  • CI/CD(GitHub Actions、Jenkins)
  • 监控告警(Prometheus + Grafana)
  • 安全加固(服务器安全)

建议下一步 ​

  1. 写实用脚本练手(健康检查、备份、日志清理)
  2. 把知识库做成 Docker 镜像(练 Docker 基础)
  3. 考完 RHCSA/RHCE 后进入 Docker 阶段

核心:Shell 脚本 + Docker = 运维入门


16. apt update 与 apt upgrade 的区别 ​

  • apt update:更新软件源索引(本地缓存的包列表),不安装任何软件
  • apt upgrade:根据最新索引,实际升级已安装的软件包

为什么要先 update?

  • apt install/upgrade 查的是本地缓存的索引,不会实时访问远程服务器
  • 不 update → 本地索引过期 → 可能装不上或装旧版本
  • 类比:先去超市拿最新价目表,再按价格买东西

标准流程:sudo apt update && sudo apt upgrade -y


17. Alias 别名配置 ​

配置文件:

  • Linux bash:~/.bashrc
  • Linux zsh / macOS zsh:~/.zshrc
  • 全局:/etc/bash.bashrc 或 /etc/profile.d/

用法:

  • 临时生效:alias python=python3
  • 永久生效:写入 ~/.zshrc 或 ~/.bashrc,然后 source 加载
  • 查看所有别名:alias
  • 删除别名:unalias python

python3 vs python:很多 Linux 发行版默认只有 python3,没有 python,用 alias python=python3 即可解决

注意:python3 和 pip3 本身就是标准命令,不需要起别名。需要 alias 的是 python 和 pip(让它们指向 python3/pip3)。在 venv 虚拟环境里 python/pip 自动可用,不需要 alias。

18. HTTPS 反向代理配置(Nginx + Let's Encrypt) ​

核心概念:

  • HTTPS = HTTP + TLS 加密,防止窃听、篡改、伪装
  • Nginx 作为反向代理终止 TLS,解密后转发 HTTP 到后端应用
  • Let's Encrypt 提供免费 TLS 证书,90 天有效期,自动续期

操作步骤:

  1. 安装 Nginx + Certbot:apt install nginx certbot python3-certbot-nginx
  2. 确保域名 DNS 解析到服务器 IP
  3. 配置 Nginx 反向代理(先只配 HTTP 80 端口)
  4. certbot --nginx -d 域名1 -d 域名2 一键申请+配置
  5. 确认自动续期:systemctl status certbot.timer + certbot renew --dry-run
  6. 防火墙放行 80 和 443 端口

常见坑:

  • 没配 HTTPS 时浏览器自动尝试 443 端口超时导致页面加载慢
  • Nginx 以 www-data 用户运行,无法读 /root/ 目录下的文件(Permission denied → 500)

19. Nginx gzip 压缩配置 ​

  • 在 /etc/nginx/nginx.conf 的 http {} 块中添加 gzip 配置
  • 关键参数:gzip on; gzip_vary on; gzip_comp_level 5; gzip_min_length 1024;
  • gzip_types 覆盖 text/css/js/json/xml/svg 等
  • 验证:curl -sI -H "Accept-Encoding: gzip" https://域名 | grep content-encoding
  • 效果:HTML/CSS/JS 压缩 60-80%,页面加载明显变快

20. Nginx 500 错误排查命令 ​

命令:awk '$9 == 500 {print $4, $7, $1}' /var/log/nginx/access.log | head -20

拆解:

  • awk 默认分隔符:空格(包括连续多个空格、Tab),行首行尾空格自动忽略
  • $9 == 500:Nginx combined 日志格式中 $9 是 HTTP 状态码,匹配 500 错误
  • {print $4, $7, $1}:打印请求时间 $4、URI 路径 $7、客户端 IP $1
  • head -20:只看前 20 条
  • 自定义分隔符:用 -F 参数,如 awk -F',' '{print $1}' file.csv
  • 注意:== 是精确匹配,不是正则匹配(正则用 ~)

用途:排查服务器 500 错误时,快速找出出错的请求时间、路径和来源 IP


21. Git 本地修改与远程同步(合并冲突实战) ​

本地修改后远程更新,本地修改会不会丢? ​

核心答案:本地修改不会丢,但取决于操作方式:

1. 同一目录用 git pull(正确做法)

  • git pull origin main 会保留本地修改,尝试自动合并
  • 无冲突:本地修改 + 远程更新都在
  • 有冲突:Git 提示,手动解决

2. 在新目录重新 clone

  • 旧目录不动,新目录是干净版本
  • 两个目录互不影响

3. ⚠️ 千万别这么干

  • 在已有仓库目录再 git clone → 报错 "destination path already exists"
  • 用 rm -rf 清空再 clone → 修改全丢
  • 绝对不要用删除旧目录的方式"重新 clone"

关键概念:

  • git clone 是一次性的,把远程完整复制到本地
  • 本地仓库建立后,后续同步用 git pull(= git fetch + git merge)
  • 本地修改只要不删本地目录,永远都在

最佳实践:

bash
git add .              # 暂存
git commit -m "..."    # 先提交本地修改(无需 push)
git pull               # 再拉远程更新

先 commit 再 pull,保证不丢任何东西。


pull 时遇到 CONFLICT(合并冲突实战) ​

报错解读:

Auto-merging KVM虚拟化/KVM虚拟化技术.md        ← Git 试图自动合并
CONFLICT (content): Merge conflict in ...        ← 但失败了:本地和远程改了同一段
Automatic merge failed; fix conflicts and then commit the result.
                                                ← 需要手动解决冲突再 commit

原因: 本地和远程都改了同一个文件的同一段内容,Git 无法判断保留谁,必须手动选。

冲突文件标记: 打开冲突文件会看到:

<<<<<<< HEAD
你本地的修改内容
=======
远程最新的内容
>>>>>>> origin/main
  • <<<<<<< HEAD ~ ======= = 你的版本
  • ======= ~ >>>>>>> origin/main = 远程版本

三种解决方式:

1. VSCode 编辑器(推荐) 打开冲突文件会高亮冲突区域,顶部按钮:

  • Accept Current Change → 保留你的
  • Accept Incoming Change → 保留远程的
  • Accept Both Changes → 全部保留
  • Compare Changes → 对比查看

2. 手动编辑 删掉 <<<<<<<、=======、>>>>>>> 三个标记,保留需要的内容,保存。

3. 放弃合并回滚

bash
git merge --abort    # 取消合并,回到 pull 之前状态

解决完提交:

bash
git add .                                    # 标记冲突已解决
git commit -m "解决 xxx.md 合并冲突"          # 完成合并

常用查看命令:

bash
git status        # 看哪些文件冲突
git diff          # 看具体冲突内容
git log --oneline -5  # 看提交历史

21.1 git config 查看当前配置(速查表) ​

查配置命令 ​

bash
# 1. 列出所有生效配置(按优先级从高到低输出)
git config --list

# 2. 推荐:每个值显示来源文件(一眼分清全局 / 仓库 / 系统)
git config --list --show-origin

# 3. 显示作用域(git 2.26+)
git config --list --show-scope

# 4. 按层级过滤
git config --list --local       # 当前仓库 .git/config
git config --list --global      # 用户级 ~/.gitconfig 或 ~/.config/git/config
git config --list --system      # 系统级 /etc/gitconfig

# 5. 单项查询
git config user.name
git config user.email

# 6. 脚本里取值(未设置时返回非零退出码,便于判断)
git config --get user.name

核心知识点:配置层级(高 → 低覆盖) ​

  1. 命令行参数(本次有效,git -c user.name=x commit)
  2. --local → 仓库 .git/config
  3. --global → ~/.gitconfig(新系统可能是 ~/.config/git/config)
  4. --system → /etc/gitconfig
  5. 默认值(最低)

高层级覆盖低层级 —— 不会清空低层级,是叠加后再覆盖。同名 key 最终用最细的那条。

调试场景 ​

  • "明明全局设了 user.name,仓库里还是另一个人" → git config --list --show-origin,看仓库层是否覆盖
  • "想确认这个机器的 git 装在哪、版本" → git --version + which git
  • "想批量改所有仓库的某项配置" → 用 --global,不要写到 --system(影响其他用户)

写入 / 取消(顺手补) ​

bash
git config --global user.name "你的名字"
git config --global user.email "your@email"
git config --local user.name "项目专用名"   # 仅仓库内
git config --unset user.name                # 取消当前仓库的设置
git config --global --unset user.name       # 取消全局的设置
git config --global --edit                  # 直接打开 ~/.gitconfig 编辑

22. stress-ng 压力测试工具 ​

是什么 ​

压力测试工具,可施加 CPU / 内存 / IO / 网络 等压力,常用于:

  • 验证 Docker 资源限制(-m、--cpus)是否生效
  • 测试系统在极限负载下的表现

--vm 参数详解(重点) ​

核心理解: --vm 不是"虚拟内存"本身,是 vm 压力 worker 的数量。

  • --vm N:启动 N 个 vm 压力 worker
  • --vm-bytes SIZE:每个 worker 占多少内存
  • 总占用 = --vm × --vm-bytes

示例:

bash
docker run tylersmith22/docker-stress-ng --vm 2 --vm-bytes 256m
# 2 个 worker × 256MB = 512MB 总占用

vm worker 反复写入内存,模拟"内存被疯狂使用"。

常用参数 ​

参数作用默认
--vm Nvm worker 数量0
--vm-bytes SIZE每个 worker 占用内存256M
--vm-hang N写完挂 N 秒再写0
--vm-keep占着内存不释放-
--cpu NCPU 压力 worker(算素数)0
--io N磁盘 IO worker0
--timeout 60s跑 60 秒自动停永久

Docker 资源限制验证示例 ​

bash
# 内存限制测试:-m 256m + 想用 512m → OOM
docker run -m 256m tylersmith22/docker-stress-ng --vm 2 --vm-bytes 256m

# CPU 限制测试:--cpus 1 限制只用 1 核
docker run --cpus 1 tylersmith22/docker-stress-ng --cpu 1

一句话总结 ​

--vm = worker 数量,--vm-bytes = 每个 worker 内存大小 总内存压力 = --vm × --vm-bytes

💡 配合 Docker 资源限制:-m 是硬上限,设多少就是多少,超了直接 OOM kill。CPU 限制分硬(--cpus)和软(--cpu-shares)两种。详见 cloud.md §3.8。

23. lrzsz 文件传输工具(rz 上传 / sz 下载) ​

配合 Xshell / SecureCRT / WindTerm / tabby 等支持 Zmodem 协议的终端使用。

rz(上传) ​

bash
rz
# 弹窗选本地文件上传到 Linux

Received by zmodem —— 服务器接收客户端发来的文件。

sz(下载) ​

bash
sz /path/file.txt
sz file1.txt file2.log
sz /path/*.log              # 通配符

Send to zmodem —— 服务器向客户端发送文件。

注意要跟文件名,不像 rz 直接回车。

sz 不支持目录下载 ​

bash
sz /etc/nginx/         # ❌ 报错:找不到文件
sz -y /etc/nginx/      # ❌ 也不行

必须先打包再下载 ​

bash
# zip 包(Windows 用户友好)
cd /etc/nginx
zip -r nginx_conf.zip ./
sz nginx_conf.zip

# tar.gz 包(推荐,保留权限)
tar czf nginx_conf.tar.gz nginx/
sz nginx_conf.tar.gz

收下之后 Linux 命令:

bash
unzip nginx_conf.zip         # 解 zip
tar xzf nginx_conf.tar.gz    # 解 tar.gz

常用参数 ​

参数作用
-y覆盖时不提示(默认会问 y/n)
-b二进制传输(推荐,默认就行)
-e转义所有控制字符(传输脚本常用)
-v显示详细过程
-Esz 专属:文件存在时强制覆盖
bash
sz -y /var/log/messages    # 强制覆盖,不问
sz -be script.sh           # 二进制 + 转义控制字符
sz -Ey file.conf           # 强制覆盖 + 二进制

终端兼容性 ​

sz/rz 默认只支持:

  • ✅ Xshell、SecureCRT、PuTTY(Xmodem 扩展)
  • ✅ tabby、WindTerm、MobaXterm
  • ❌ Windows Terminal、iterm2 默认不支持
    • 需要额外装 zmodem 脚本支持或者用别的终端

安装 ​

bash
# CentOS / RHEL
yum install -y lrzsz

# Debian / Ubuntu
apt install -y lrzsz

24. Rocky Linux 配置网卡 IP(nmcli / NetworkManager) ​

来源:2026-07-18 交换区

Rocky Linux(RHEL 系)推荐用 NetworkManager 体系,三种方式:nmcli(命令行,生产推荐)、nmtui(图形菜单)、直接改配置文件。

核心概念:device vs connection ​

  • device(网卡设备):物理/虚拟网卡本身,如 ens160
  • connection(连接配置):网卡的配置档案,可与设备不同名
  • nmcli connection 操作的是 connection,nmcli device 操作的是设备

查网卡和连接 ​

bash
nmcli device status                  # 查看所有网卡设备
nmcli connection show                # 查看所有连接
nmcli connection show "ens160"       # 看 ens160 的现有配置

nmcli 配置静态 IP(推荐) ​

bash
# 1. 设置 IP + 子网掩码(CIDR 格式)
nmcli connection modify "ens160" ipv4.addresses 192.168.1.100/24

# 2. 设置网关
nmcli connection modify "ens160" ipv4.gateway 192.168.1.1

# 3. 设置 DNS(多个用空格分隔)
nmcli connection modify "ens160" ipv4.dns "223.5.5.5 8.8.8.8"

# 4. 把 ipv4 改为手动(manual),默认是 auto(DHCP)
nmcli connection modify "ens160" ipv4.method manual

# 5. 关闭 IPv6(可选)
nmcli connection modify "ens160" ipv6.method disabled

# 6. 让配置生效(推荐 up,不是重启网络)
nmcli connection up "ens160"
  • modify 只写入配置文件,不立即生效
  • up 才真正应用配置
  • 改完不需要 systemctl restart NetworkManager

重新读取配置(不改变连接状态) ​

bash
nmcli connection reload "ens160"

配置文件位置 ​

nmcli modify 会写到下面两个位置之一:

  • 新版(Rocky 9+ 默认):/etc/NetworkManager/system-connections/ens160.nmconnection
  • 传统(兼容):/etc/sysconfig/network-scripts/ifcfg-ens160

keyfile 格式示例 ​

ini
[connection]
id=ens160
type=ethernet
interface-name=ens160

[ipv4]
method=manual
address1=192.168.1.100/24,192.168.1.1
dns=223.5.5.5;8.8.8.8

[ipv6]
method=disable

也可以直接 vi 改这个文件,保存后跑 nmcli connection reload + nmcli connection up "ens160"。

nmtui(图形菜单) ​

bash
nmtui

方向键选 "Edit a connection" → 选 ens160 → 改 IP/网关/DNS → OK → 退出。

适合不熟 nmcli 的场景,批量配置还是得用 nmcli。

临时 IP(重启失效,不写文件) ​

bash
ip addr add 192.168.1.200/24 dev ens160
ip route add default via 192.168.1.1
ip link set ens160 up

调试/排错时用,重启就没了。

验证 ​

bash
ip addr show ens160                       # 看 IP
ip route                                  # 看网关
nmcli -t -f IP4 connection show "ens160"  # 看 NM 里的 IP 配置
ping 192.168.1.1                          # 测网关
ping 223.5.5.5                            # 测外网
cat /etc/resolv.conf                      # 看 DNS

25. watch 命令(实时监控面板) ​

是什么 ​

Linux 标准命令(来自 procps-ng 包),周期性执行同一个命令并全屏刷新输出 = 实时监控面板。

  • 默认每 2 秒执行一次
  • 不会滚屏,每次刷新整个屏幕
  • 顶部默认显示 Every 2.0s: <command> + 当前时间
  • 退出:Ctrl+C

常用参数 ​

参数作用
-n <秒>刷新间隔(覆盖默认 2s)
-d / --differences高亮显示变化的部分
-t关闭顶部标题行

K8s 场景的经典用法 ​

bash
watch -n 1 kubectl get pod

= 每 1 秒重跑 kubectl get pod 并全屏刷新。适合观察 Pod 状态从 Pending → ContainerCreating → Running 的过渡,或者看 Pod 被删除/重启。

教学常见套路:

  • 滚动更新:watch 一边 + kubectl set image 一边 → 看 Pod 一个个被替换
  • Pod 删除:watch 一边 + kubectl delete pod 一边 → 看新 Pod 被补上
  • HPA 扩容:watch 一边 + ab -c 100 压测一边 → 看 Pod 数量自动增加

watch vs kubectl -w 的区别 ​

方式行为输出方式
watch -n 1 kubectl get pod定期重跑整个命令每次重画整个表格
kubectl get pod -w只在有变化时输出新行只追加变化行
  • watch:看整个表(Status / READY / AGE 等所有列)
  • kubectl -w:只看事件流(Pod scheduled、Container started)

生产跟变化用 -w,教学盯表用 watch。

一句话速记 ​

watch -n 1 <cmd> = 每 1 秒重画命令输出,实时监控面板。Ctrl+C 退出。-d 高亮变化。

相关记忆 ​

  • watch 默认 2s 刷新,-n 覆盖间隔
  • watch 重画全表,kubectl -w 只追加变化行
  • watch 来自 procps-ng 包(包含 ps、top、kill 等经典命令)


小弟二号打造的知识体系