Linux笔记
Linux笔记
1
虚拟网络配置器
改子网
NAT设置:改网关
DHCP:自动配IP区间
2
网络模式
桥接模式:物理机与虚拟机同级 公用一个局域网
NAT模式:虚拟机虚拟化出一个局域网与外界隔离
安装ubuntu系统注意事项
安装之前断开NAT
pick a username是登录用户名
开启openssh
远程连接排查逻辑

提示符与命令 & cat
[root@oldboy108-kylin ~]#
| root | oldboy108-kylin | ~ | # |
|---|---|---|---|
| 当前用户 | 主机名 | 当前目录 | 管理员用户 |
| whoami | hostname | pwd |
[root@oldboy108-kylin ~]# cat /etc/os-release
NAME="Kylin Linux Advanced Server"
VERSION="V10 (Lance)"
ID="kylin"
VERSION_ID="V10"
PRETTY_NAME="Kylin Linux Advanced Server V10 (Lance)"
ANSI_COLOR="0;31"
cat > /root/lbh.txt <<EOF #想显示参数不加""
$(hostname) #显示主机名
EOF
cat /root/oldboy.txt |xargs -n 5 #文件内容每5个一行显示
find -name /var/log/ "*.log"|xargs rm -f #批量删除 `/var/log/` 目录下所有 `.log` 文件
查看并显示行号
[root@oldboy108-kylin ~]# cat -n /etc/hosts
1 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
2 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
ls -lrt 按照时间逆序查看文件内容
1byte字节=8bit比特(二进制的0/1)
1字节=一个英文字母
1kb=1024bytes
ls
| ls -F | ls -l(ll) | ls -a | ls -r | ll -t | ll -h |
|---|---|---|---|---|---|
| 在不同文件后加不同的符号 | 长格式显示文件 | 显示所有文件包括隐藏文件(以.开头的文件) | 逆序排序 | 按时间排序 | 人类可读 |
ls -i #inode
tree
| tree | tree -L 2 | tree -d |
|---|---|---|
| 显示树形图 | 显示层数 | 只显示目录 |
mkdir
| mkdir | mkdir -p |
|---|---|
| 创建目录 | 递归多级创建文件 |
3
touch
| touch | stat |
|---|---|
| 创建文件 | 查看文件时间戳 |
echo
| echo | echo > | echo >> | cat >文件<<'EOF' 内容 EOF |
|---|---|---|---|
| 显示后面接的字符串 | 覆盖(小) | 追加 | 写入文件(大) |
> / 1>标准输出覆盖重定向,命令正常输出写入文件,覆盖原有内容
>> / 1>>标准输出追加重定向,正常输出追加到文件末尾,不覆盖
2>标准错误覆盖重定向,只把报错信息写入文件,覆盖
2>>标准错误追加重定向,报错信息追加写入文件
command > file 2>&1标准输出进文件,标准错误跟着标准输出,一起写入 file(覆盖)
cmd &> file和上面等价
command >> file 2>&1标准输出、标准错误都追加写入 file
echo {1..10..2}
vim
vim>>i>>esc >>:wq
/向下找
?向上找
{}
echo {1..10}
echo {a..z}
touch file{1..10}
mkdir file{1..10}
seq
批量建文件/目录
seq 1 5
seq -s "" 指定分隔符
cp
cp 1.txt /tmp #复制文件
cp -r oldboy /tmp #复制目录,-a也可以
| cp -r | cp -p | cp -a | cp -d |
|---|---|---|---|
| 复制目录 | 保持属性 | 相当于dpr | 保留软连接本身 |
mv
移动文件/目录 改名
rm
删除文件/目录
| rm -f | rm -r | |
|---|---|---|
| 强制删除 | 删除目录 |
rm -f file1 file2 #删除多个文件
alias
屏蔽别名:命令前面加/或者写命令全路径/bin/rm
临时生效 要完全生效/etc/profile /etc/bashrc (所有用户) ~/.bashrc
4
远程连接失败
IP
(internet protocal)
公网IP:任意地点访问 查询 :IP138.com
局域网IP:办公环境使用 三类(192.168/172.16/10.0.0.0)
ip a(address)
端口
区别不同的服务1-65535
| ssh | 22 |
|---|---|
| http | 80 |
| https | 443 |
| ftp | 21 |
xshell远程连接排查流程

- vmnet8 ==>> 已连接 ==>> 10.0.0.1
- 虚拟网络编辑器 3 虚拟机本身网卡 4)看22端口 ss -lnt
局域网上网排查流程

用户上网流程

linux上不了网排查
查看网关 ip route
!i执行上一次的命令==> ip route
ping 百度 通了不显示网页 网站问题
1)用户>>百度不通 则>>dns
用户>>DNS通了 DNS>>百度不通 DNS问题
2)用户>>百度不通 用户>>DNS不通 用户>>网关通了 网关问题
3)用户>>百度不通 用户>>DNS不通 用户>>网关不通 用户>> 同网段机器 通了 交换机问题
4)都不通 检查主机IP
telnet命令检查一个服务是否开启
telnet 10.0.0.200 22
检查本地端口(ss/netstat)
[root@oldboy108-kylin ~]# ss -lnt(-l 监听 -n 数字 -t tcp协议)
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
[root@oldboy108-kylin ~]# netstat -lntup(-u udp协议 -p 程序名)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 3571/sshd: /usr/sbi
tcp6 0 0 :::22 :::* LISTEN 3571/sshd: /usr/sbi
udp 0 0 127.0.0.1:323 0.0.0.0:* 750/chronyd
udp6 0 0 ::1:323 :::* 750/chronyd
vim快捷键
:set nu #显示行号
:set nonu #取消行号
/内容 #搜索包含指定内容的行,按n继续向下搜索,按N反向搜索
?内容 #搜索包含指定内容的行,按n继续向上搜索,按N反向搜索
#以下快捷键执行直接从普通模式>>编辑模式
i #当前光标处
I #到当前行首
A #到当前行尾
O #新开上一行行首
o #新开下一行行首
#普通模式
0 #行首
$ #行尾
G #文件尾行开头
gg #文件首行开头
5gg #到第五行
yy #复制当前行
p #粘贴
dd #删除当前行
5dd #删除多行
u #回滚
全局替换
:%s#yes#no#g # 有分割线改为 @/#
x #删除字符
5
配置EPEL
curl -s -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
字符集
echo $LANG
vim /etc/locale.conf
source /etc/locale.conf #设置字符集
防火墙
systemctl disable --now firewlld # 同时执行stop和disable
ssh加固
快速备份
cp /etc/ssh/sshd_config{,.ori}
改ssh端口
#进入配置文件
vim /etc/ssh/sshd_config
#修改端口
Port 52113
#重启服务
systemctl restart sshd
#检查正在建立的连接
netstat -an |grep -i est
[root@oldboy108-kylin ~]# netstat -an |grep -i est
Active Internet connections (servers and established)
tcp 0 36 10.0.0.200:22 10.0.0.1:54716 ESTABLISHED
#查看修改是否成功
ss -lnt
[root@oldboy108-kylin ~]# ss -lnt
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 0.0.0.0:52113 0.0.0.0:*
LISTEN 0 128 [::]:52113 [::]:*
虚拟机启动时间
systemd-analyze
虚拟机各服务启动时间
systemd-analyze blame
监控软件
# 一套完整的监控工具安装
yum install -y iotop iftop nethogs iostat mpstat perf glances
# 各工具用途速查
# iotop - 查看进程磁盘I/O情况
# iftop - 实时网络流量监控(按连接)
# nethogs - 按进程查看网络带宽占用
# iostat - 磁盘I/O统计(来自sysstat包)
# mpstat - CPU统计
# perf - 内核性能分析工具
# glances - 全能系统监控(比top更全面)
历史记录优化
cat >>/etc/profile<<'EOF'
# 历史命令优化(追加到 /etc/profile)
# 设置当前会话内存中保存的历史命令条数(仅保留最近5条)
export HISTSIZE=5
# 设置历史命令文件(~/.bash_history)中保存的最大条数(仅保留最近5条)
export HISTFILESIZE=5
# 禁止记录敏感命令(如密码)
export HISTIGNORE="ls:ll:cd:pwd:history"
EOF
# 立即生效
source /etc/profile
##清除指定编号的命令记录-d接编号
history -d 650
6
利用时间创建文件
touch lbh_`date +%F`.txt
时间同步
##放入定时任务,每隔五分钟执行一次更新系统时间
yum install ntpdate -y
cat >>/var/spool/cron/root<<'EOF'
# 每5分钟同步一次时间(生产推荐)
*/5 * * * * /usr/sbin/ntpdate -u ntp7.aliyun.com > /dev/null 2>&1
EOF
##> /dev/null 重定向到空,2>&1错误和正确的输出都定向到空
crontab -l
关机重启
| 关机 | 重启 |
|---|---|
| shutdown -h 10/0/now | shutdown -r 10/now |
| init 0 | init 6 |
| halt | reboot |
grep
| grep | head | tail |
|---|---|---|
| -i 忽略大小写 | 默认前十行 | 默认后十行 |
| -n 显示行号 | -n | -n |
| -v 排除 | a | -f 实时跟随 |
| ^$ 空行 | -F | |
| 查进程要grep -v grep | ||
| -E 过滤多个 | ||
| -A | ||
| -B | ||
| -C |
less
| 操作 | 快捷键 | 说明 |
|---|---|---|
| 慢慢向下看 | 回车 | 逐行向下 |
| 慢慢向上看 | 向上箭头 | 逐行向上 |
| 下一页 | ctrl+f 或 空格 |
向下翻页 |
| 上一页 | ctrl+b |
向上翻页 |
| 搜索内容 | /内容 |
默认向下搜;继续向下搜索n;反向向上搜索N |
| 搜索内容 | ?内容 |
默认向上搜;继续向上搜索n;反向向下搜索N |
| 显示行号读取 | less -N /etc/services |
查看时展示行号 |
管道
命令|命令
wc
wc -l -w -c
sort
| sort | 功能 |
|---|---|
| -n | 对数字排序 |
| -h | 按单位排序 |
| -k | 对第几列排序 |
| -r | 倒序 |
uniq
| uniq | 对相邻的行去重 配合sort使用 |
|---|---|
| uniq -c | 重复了几次 |
awk
| awk | |
|---|---|
| 格式 | awk '{print $1}' #注意用'' |
| 倒数第一行 | $NF |
| 指定分隔符 | -F “:” #指定:为分隔符 |
7
文件属性
[root@oldboy108-kylin ~]# ls -lhi oldboy.txt
35617739 -rw-r--r-- 1 root root 32 9月 6 12:17 oldboy.txt
索引 类型权限,硬链接,用户,用户组,大小,修改时间,名称
ls -lhi #index
inode&block
inode:存储元数据包括文件属性和存储地址
block:存储文件内容
inode==>>block==>>文件==>>inode==>>block
inode被沾满是指槽位被写成1不是槽位里256字节都沾满
文件名存储在上一级存储块里
硬/软链接
ln 源文件 硬链接文件
ln -s 源文件 软链接文件 目录 ->目录 文件->文件
创建软链接时,不需要先手动创建那个“链接名”,ln -s 会自动帮你建
不能写/
| 对比 | 硬链接 | 软连接 |
|---|---|---|
| inode | 相同 | 不同 |
| 文件类型 | 普通文件- | 链接文件l |
| 本质 | 同一文件多个入口 | 快捷方式 |
| 删除源文件 | 不受影响 | 失效 |
| 链接目录 | 不能 | 能 |
| 跨设备 | 不能 | 能 |
| 创建 | ln 源 目标 | ln -s 源 目标 |
| 用于 | 防误删 | 版本管理 |
文件删除原理
计数器
| i_link | i_count |
|---|---|
| 硬链接数 | 进程计数 |
| 指向inode数 | 有多少进程使用该文件 |
| 静态文件删除 | 动态文件删除 |
|---|---|
| i_link=0 | i_count=0 |
| 没有连接inode的了,但凡有一个连接inode文件还存在 | 进程使用文件不能被删除,反之可被删除 |
常用命令汇总
| 命令 | 作用 |
|---|---|
ls -li |
查看文件的inode号和详细信息 |
df -h |
查看磁盘分区容量(block使用情况) |
df -i |
查看磁盘分区inode使用情况 |
ln 源 目标 |
创建硬链接 |
ln -s 源 目标 |
创建软链接 |
readlink 软链接文件 |
查看软链接指向的源文件路径 |
| dd | if= /dev/zero | of= /tmp/oldboy.txt | bs=8k | count=10240 |
|---|---|---|---|---|
| 数据复制转换工具 | 输入文件 | 输出文件 | 块大小 | 块数量 |
磁盘满的两种原因
| inode | block | |
|---|---|---|
| 检查 | df -i | df -h |
| 原因 | 小文件多 | 文件数据大 |
8
用户管理
useradd test1
useradd -u 5000 test2#指定uid
useradd -s /sbin/nologin test3 #创建系统用户

linux三大用户类型
| 超级用户 | 普通用户 | 虚拟用户 | |
|---|---|---|---|
| 实例 | root | oldboy | nobody |
| UID范围i | 0 | 1000-60000 | 1-999 |
| shell | /bin/bash | /bin/bash | /sbin/nologin |
最小化原则
| 原则 | 说明 |
|---|---|
| ① 安装软件最小化 | 不装多余的软件包 |
| ② 登录安全最小化 | 使用普通用户登录,不用root,且可以用sudo基于命令设置权限 |
| ③ 进程启动权限最小化 | 用虚拟用户启动服务 |
| ④ 权限最小化 | 给最小的必要权限 |
用户组
- 自动产生: 创建用户时自动生成同名组(如创建oldboy → 生成oldboy组,UID=GID)
- 手动创建: root使用
groupadd创建
用户管理核心文件
| 文件 | 作用 | 查看命令 |
|---|---|---|
| /etc/passwd | 用户属性(UID、GID、家目录、Shell) | tail -1 /etc/passwd |
/etc/shadow |
用户密码及密码属性(加密存储) | tail -1 /etc/shadow |
/etc/group |
用户组属性 | tail -1 /etc/group |
/etc/gshadow |
用户组密码(基本废弃) | tail -1 /etc/gshadow |
/etc/passwd 格式详解
root:x:0:0:root:/root:/bin/bash
test1:x:1001:1001::/home/test1:/bin/bash
| 字段位置 | 含义 | 示例 |
|---|---|---|
| 第1字段 | 用户名 | root / test1 |
| 第2字段 | 密码占位符(x表示密码在shadow中) | x |
| 第3字段 | UID(用户ID) | 0 / 1001 |
| 第4字段 | GID(主组ID) | 0 / 1001 |
| 第5字段 | 用户说明信息(可空) | root / 空 |
| 第6字段 | 家目录 | /root / /home/test1 |
| 第7字段 | 登录Shell ##命令行解释器 | /bin/bash / /sbin/nologin |
/etc/shadow 格式详解
oldboy:$6$V07NxoML$...:22095:7:60:10:30::
| 字段位置 | 含义 |
|---|---|
| 第1字段 | 用户名 |
| 第2字段 | 加密后的密码(!!表示无密码) |
| 第3字段 | 最近一次密码修改时间(从1970-1-1算起的天数) |
| 第4字段 | 密码最短使用天数(0表示无限制) |
| 第5字段 | 密码最长使用天数(99999表示永不过期) |
| 第6字段 | 过期前警告天数(默认7天) |
| 第7字段 | 过期后宽限天数(禁用前) |
| 第8字段 | 账户过期时间(绝对日期) |
| 第9字段 | 保留字段 |
/etc/group 格式详解
root:x:0:
test1:x:1001:
sa:x:5018:
| 字段位置 | 含义 |
|---|---|
| 第1字段 | 组名 |
| 第2字段 | 组密码占位符(x) |
| 第3字段 | GID |
| 第4字段 | 组内用户列表(逗号分隔) |
用户管理三大辅助文件
| 文件 | 作用 |
|---|---|
/etc/default/useradd |
useradd命令的默认配置文件 |
/etc/skel/ |
用户环境变量模板文件存放地(源头),每次创建用户时,都会把/etc/skel/ 下的所有隐藏文件会自动复制到用户家目录。 |
/etc/login.defs |
用户创建时的系统级默认配置 |
useradd
语法: useradd [选项] 用户名
常用选项:
| 选项 | 含义 | 示例 |
|---|---|---|
-u |
指定UID | useradd -u 5000 test2 |
-s |
指定登录Shell ***** | useradd -s /sbin/nologin test3 |
-d |
指定家目录 | useradd -d /opt test4 |
-g |
指定主组 | useradd -g root test5 |
-e |
设置账户过期时间 | useradd -e "2030/05/30" test6 |
-M |
不创建家目录***** | useradd -M -s /sbin/nologin nginx |
usermod
语法: usermod [选项] 用户名
常用选项(与useradd一致):
| 选项 | 含义 | 示例 |
|---|---|---|
-u |
修改UID | usermod -u 10001 test1 |
-g |
修改主组 | usermod -g root test2 |
-s |
修改登录Shell | usermod -s /bin/bash test3 |
-e |
修改过期时间 | usermod -e "2031/7/18" test6 |
-d |
修改家目录 | usermod -d /newhome test4 |
userdel
语法: userdel [选项] 用户名
| 选项 | 含义 | 说明 |
|---|---|---|
-r |
删除用户并删除家目录和邮件池 | 有风险,谨慎使用 |
不加 -r |
只删除用户,保留家目录 | 推荐方式 |
企业人员离职处理(重要):
| 方式 | 命令 | 评价 |
|---|---|---|
| ① 直接删除 | userdel -r 用户名 |
❌ 容易误删数据,不明智 |
| ② 只删用户 | userdel 用户名 |
✅ 保留家目录数据 |
| ③ 注释账户(推荐) | 编辑 /etc/passwd 注释掉该行 |
✅✅ 生产环境推荐 |
passwd
root给普通用户改密码(无需知道旧密码)
非交互式修改密码 --stdin 从标准输入读取(脚本批量设置),自动化执行 密码会暴漏命令行.
echo 'Oldboy@123456'|passwd --stdin test3
添加新用户的密码是空(禁止登录)
chpasswd
批量设置密码
# 1. 创建用户列表文件:语法 用户:密码
cat >~/user.list<<EOF
oldboy01:Qwert@1010
oldboy02:Qwert@2020
oldboy03:Qwert@3030
EOF
#批量设置密码方法1:
cat ~/user.list | chpasswd
#批量设置密码方法2:
chpasswd < ~/user.list
##<小于号,标准输入重定向,读取后面文件内容
chage
查看和修改密码属性
[root@oldboy108-kylin ~]# useradd oldboy
# 查看用户密码属性(重点)
[root@oldboy ~]# chage -l oldboy
最近一次密码修改时间 :6月 30, 2030
密码过期时间 :从不
密码失效时间 :从不
帐户过期时间 :从不
两次改变密码之间相距的最小天数:0
两次改变密码之间相距的最大天数:99999
在密码过期之前警告的天数:7
# 修改账户过期时间
[root@oldboy108-kylin ~]# chage -E "2041/6/30" oldboy ##useradd -e "2041/6/30" oldboy
[root@oldboy108-kylin ~]# chage -l oldboy
......
帐户过期时间 :6月 30, 2041
chage 常用选项:
| 选项 | 含义 | 示例 |
|---|---|---|
-l |
查看密码属性 | chage -l oldboy |
-E |
设置账户过期日期 | chage -E "2041/6/30" oldboy |
-m |
密码最短使用天数 | chage -m 7 oldboy |
-M |
密码最长使用天数 | chage -M 60 oldboy |
-W |
过期前警告天数 | chage -W 10 oldboy |
-I |
过期后宽限天数 | chage -I 30 oldboy |
su
语法: su [选项] [用户名]
| 方式 | 命令 | 说明 |
|---|---|---|
| 带 - 切换 | su - oldboy |
✅ 加载目标用户的环境变量(推荐) |
| 不带 - 切换 | su oldboy |
❌ 保留当前用户的环境变量(不推荐) |
| 执行单条命令 | su - oldboy -c pwd |
以目标用户身份执行命令后返回 |
sudo
核心思想: 不切换到root用户,仅在执行特定命令时拥有root权限,执行完root权限消失。
配置文件: /etc/sudoers(使用 visudo 编辑)
配置文件格式:
授权用户 主机 =(切换角色) 命令()
root ALL =(ALL) ALL
##给oldboy授权管理员权限,即在任何主机,可以切换任何角色,执行任何命令
授权用户 主机 =(切换角色) 命令
oldboy ALL =(ALL) ALL
[root@oldboy108-kylin ~]# useradd oldboy
[root@oldboy108-kylin ~]# echo 'Qwert@345'|passwd --stdin oldboy
更改用户 oldboy 的密码 。
passwd:所有的身份验证令牌已经成功更新。
#授权oldboy为管理员权限编辑技巧
#第一步执行:
visudo
#第二步:
100gg
#第三步:
yy
p
#第四步
按x一步步删除root
#第五步:
按i处于编辑模式
输入oldboy
#第六步
按esc
按:wq保存
#第七步 退出当前窗口到xshell的windows下 使用ssh命令连接
[C:\~]$ ssh oldboy@10.0.0.200
Connecting to 10.0.0.200:22...
Connection established.
To escape to local shell, press 'Ctrl+Alt+]'.
......
Last login: Tue Nov 10 01:12:37 2026
#第八步 切到root
[oldboy@oldboy108-kylin ~]$ whoami
oldboy
##这条路需要root密码 否则行不通
[oldboy@oldboy108-kylin ~]$ su - root
密码:
su: 拒绝权限
##通过sudo路径进入管理员权限
[oldboy@oldboy108-kylin ~]$ sudo su - root
我们信任您已经从系统管理员那里了解了日常注意事项。
总结起来无外乎这三点:
#1) 尊重别人的隐私。
#2) 输入前要先考虑(后果和风险)。
#3) 权力越大,责任越大。
[sudo] oldboy 的密码: <===仅需要输入oldboy的密码
[root@oldboy108-kylin ~]# ##成功
| 对比项 | su | sudo |
|---|---|---|
| 用户身份 | 切换到root | 还是自己 |
| 权限范围 | 所有权限 | 只有指定命令 |
| 需要root密码 | ✅ 需要 | ❌ 不需要 |
| 权限粒度 | 粗(全有/全无) | 细(可按命令控制) |
| 审计日志 | 难以追踪 | 日志可追踪 |
| 企业推荐度 | ⭐⭐ | ⭐⭐⭐⭐⭐ |
查看用户信息命令
| 命令 | 作用 | 示例 |
|---|---|---|
id |
查看用户UID/GID/组 | id oldboy |
whoami |
查看当前用户名 | whoami |
who |
查看当前登录用户 | who |
w |
查看当前登录用户(详细) | w |
last |
查看历史登录记录 | last |
lastlog |
查看每个用户最后一次登录时间 | lastlog |
/var/log/secure |
远程登录安全日志 | tail -f /var/log/secure |
chown
语法: chown [选项] 所有者[:组] 文件
| 用法 | 命令 | 效果 |
|---|---|---|
| 改所有者(用户) | chown oldboy test.txt |
所有者→oldboy |
| 改所属组 | chown .oldboy test.txt |
所属组→oldboy |
| 同时改 | chown oldboy.oldboy test.txt |
所有者+所属组→oldboy |
| 同时改(冒号) | chown oldboy:oldboy test.txt |
同上 |
| 递归改 | chown -R oldboy /data/ |
目录下所有文件都改 |
用户管理命令速查
| 命令 | 作用 | 常用选项 |
|---|---|---|
useradd |
创建用户 | -u, -s, -d, -g, -e, -M |
usermod |
修改用户 | -u, -s, -g, -e, -d |
userdel |
删除用户 | -r |
passwd |
设置密码 | --stdin |
chpasswd |
批量设置密码 | 从标准输入读取 |
chage |
修改密码属性 | -l, -E, -m, -M, -W, -I |
groupadd |
创建组 | -g |
groupdel |
删除组 | - |
su |
切换用户 | -(必须加) |
sudo |
提权执行 | -u |
id |
查看用户信息 | - |
whoami |
当前用户 | - |
who / w |
登录用户 | - |
last / lastlog |
登录日志 | - |
chown |
修改属主/属组 | -R |
chgrp |
修改属组 | -R |
核心配置文件
| 文件 | 作用 | 重点字段 |
|---|---|---|
/etc/passwd |
用户属性 | UID、GID、家目录、Shell |
/etc/shadow |
密码属性 | 密码、过期时间 |
/etc/group |
组属性 | GID、组成员 |
/etc/gshadow |
组密码 | 了解即可 |
/etc/default/useradd |
useradd默认配置 | HOME、SHELL、SKEL |
/etc/skel/ |
环境变量模板 | .bash* 文件 |
/etc/login.defs |
系统默认配置 | UID范围、密码策略 |
/etc/sudoers |
sudo权限配置 | visudo编辑,不要用vim /etc/sudoers |
9
chattr
| i(immutable) | a(append-only) | lsattr( attributes) |
|---|---|---|
| chattr +i 文件/目录 #设置文件不可变 | chattr +a 文件 #设置文件只允许追加 | 查看扩展属性 目录-d |
权限
| r | w | x | 无权限 |
|---|---|---|---|
| 4 | 2 | 1 | 0 |
批量删除创建用户
tail -13 /etc/passwd|awk -F: '{print "userdel -r",$1}'|bash #删除
seq 3|awk '{print "useradd","oldboy"$1}'|bash #创建
#先拼接后bash
文件权限
| 权限符号 | 文件操作效果 |
|---|---|
--x |
可执行(./file),但不能 cat 看内容 |
r-x |
可 cat 看内容,可执行,但不能编辑修改内容 |
rwx |
可 cat,可编辑(vim/>),可执行(完全控制) |
注意:执行必须有r 想要删文件看上级目录权限有没有w
目录权限
| x | rx | rwx |
|---|---|---|
| cd进目录 | ls列出文件 | 创建删除文件 |
| 仅能进入,但进去后无法 ls 查看有哪些文件 | 能进入,能查看 | 可进入、可查看、可增删改目录内的任何文件 |
chmod
| 用,户组,其他,所有人 | 加减覆盖 | 递归 |
|---|---|---|
| u,g,o,a | +-= rwx | chmod - R |
10
umask
权限掩码
| 目录 | 文件(偶数) | 文件(奇数) |
|---|---|---|
| 777 | 666 | 666 |
| 022 | 022 | 021 |
| 755 | 644 | 645 |
| 001 | ||
| 646 |
SUID
SUID作用:获得命令对应用户的身份权限,例如普通用户下passwd修改密码 实际修改本没有权限的/etc/shadow文件,就是passwd权限属性SUID在起作用
设置 SUID
chmod u+s file chmod 4755 file
取消 SUID
chmod u-s file
chmod 0755 file
| 显示 | 含义 |
|---|---|
rws |
设置了 SUID,且所有者执行位为 x |
rwS |
设置了 SUID,但所有者执行位为 -(无执行权限) |
-rwsr-xr-x |
典型 SUID 程序 |
-rwSr--r-- |
设置了 SUID,但文件不可执行 |
SUID 只对二进制可执行程序生效 对shell无效
权限规划方案
| 目录 | 所有者:组 | 权限 | 说明 |
|---|---|---|---|
/data/html/ |
root:root | 755 | Web服务用www用户运行,程序文件只读,防止被篡改 |
/data/html/upload/ |
www:www | 755 | 上传目录,Web服务用户可写(应用程序上传扩展名.jpg,zip) |
tar
tar -zcvf 位置/打包名.tar.gz 要打包文件 #压缩
tar zxvf 位置/打包名.tar.gz -C 指定的位置 #解压
xf 自动根据后缀解压
h 打包软链接
tar zcvf /backup/etc_conf_$(date +%F).tar.gz $(find /etc -name "*.conf")
#对指定文件打包
tar zcvf /data/backup/src_data.tar.gz -X list.txt /data/project/src/
-X排除
11
date
| %F | %Y | %y | %m | $d |
|---|---|---|---|---|
| 2026-2-1 | 2026 | 26 | 2 | 1 |
%F = %Y-%m-%d # 2026-09-11
%T = %H:%M:%S # 15:30:45
date +%F\ %T #2026-09-11 10:30:49
[root@oldboy ~]# date +%F -d "-3day"
2030-05-12
[root@oldboy ~]# date +%F -d "-3month"
2030-02-15
[root@oldboy ~]# date +%F -d "-3year"
2027-05-15
[root@oldboy ~]# date +%F -d "-24hour"
2030-05-14
[root@oldboy ~]# date +%F -d "-1440min"
2030-05-14
[root@oldboy ~]# date +%F -d "-86400sec"
2030-05-14
zip
zip -rq /backup/etc.zip /etc/
-r 递归(必须加)-q 不显示过程
zip -d test.zip /root/2.txt #在压缩包中删除文件
unzip
# 解压到当前目录
unzip /backup/etc.zip
# 解压到指定目录(-d)
unzip /backup/etc.zip -d /etc/
#覆盖解压 -o -l 查看文件内容
unzip -o /backup/etc.zip
gzip
| 特点 | 说明 |
|---|---|
| 原地压缩 | 压缩后原文件消失,变成 .gz 文件 |
| 只能压缩单个文件 | 不能打包目录 |
- 打包 gzip 文件即可,生成文件.gz 会删除源文件
- 解包 gzip -d 文件.gz 会删除源文件(包)
12
rpm & yum
| rpm | 作用 | yum | 作用 |
|---|---|---|---|
| rpm -qa | 列出所有已安装的 RPM 包 | yum install | 安装 |
| rpm -qf | 查询某个文件属于哪个已安装的 RPM 包(已安装) | yum provides | 找命令/文件属于哪个包(未安装) |
| rpm -ql | 列出某个已安装 RPM 包中包含哪些文件 | yum list | 列出软件包 |
| rpm -qc | 列出某个已安装 RPM 包中的配置文件 | yum clean all | 清除缓存 |
| rpm -qpi | 查询一个未安装的 RPM 包文件的详细信息 | yum clean packages | 清理已下载的 RPM 包缓存 |
| rpm -q | 查询某个包是否已安装,以及它的基本信息 | yum makecache | 下载并生成 YUM 仓库元数据缓存 |
| rpm -ivh | 安装 RPM 包 | yum info | 查看软件包信息 |
| rpm -Uvh | 升级 RPM 包 | yum localinstall | 本地安装RPM包,依赖走网络 |
| rpm -e --force --nodeps | 强制卸载RPM包忽略依赖关系 | yum remove | 连带依赖一起删,永远不用 |
查看已安装的软件包列表 yum list installed
RPM 校验
| 命令 | 时机 | 作用 |
|---|---|---|
| rpm -K 包.rpm | 安装前 | 验签名是否正品 digests signatures OK → 正品 |
| rpm -V 包名 | 安装后 | 验文件是否被改动 ,无输出 = 正常 ,输出中 5(内容变)+ 非配置文件 → 高度警惕,可能被篡改 |
RPM包缓存留存
# 永久保留 rpm 包
echo "keepcache=1" >> /etc/yum.conf
# 缓存目录(麒麟 V10)
/var/cache/dnf/
# 只下载不安装
dnf install --downloadonly --downloaddir=/tmp/rpms nginx
本地光盘源镜像仓库流程
mount /dev/cdrom /mnt # 1. 挂载
cd /etc/yum.repos.d && gzip * # 2. 备份失效现有源
cat > Kylin-cdrom.repo <<'EOF' # 3. 配置本地源
[Kylin-cdrom]
name=Local CDROM
baseurl=file:///mnt
enabled=1 #0 禁用 / 1 启用
gpgcheck=0 #0 不验签 / 1 验签
EOF
yum makecache # 4. 生成缓存
yum install tree -y # 5. 测试
rm -f Kylin-cdrom.repo && gzip -d *.gz # 6. 恢复互联网源
13
yum组包
安装系统时有的组包未安装,进系统后补安装
yum group install "Security Tools" -y
yum groups list
编译安装三步曲
┌─────────────────────────────────────────────────────────────┐
│ 源码编译安装三步曲 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 步骤1:./configure 配置 │
│ ├── 用途:设置安装目录、安装模块等选项 │
│ └── 生成:Makefile │
│ │
│ 步骤2:make 编译 │
│ ├── 用途:将Makefile生成可执行的二进制文件 │
│ └── 依赖:gcc、make等编译工具 │
│ │
│ 步骤3:make install 安装 │
│ ├── 用途:复制二进制文件到系统,配置应用环境 │
│ └── 结果:软件安装完成,可以启动使用 │
│ │
└─────────────────────────────────────────────────────────────┘
源码编译Nginx实战
# 1. 基础环境准备
[root@oldboy108-kylin ~]# rpm -qa make gcc wget
make-4.3-1.ky10.x86_64
gcc-7.3.0-20220207.45.ky10.x86_64
wget-1.20.3-7.ky10.x86_64
# 如果已装好,忽略下面步骤:
[root@oldboy ~]# yum install gcc make wget -y
# (Development Tools含有 gcc make)
# 2. 下载源码包
[root@oldboy108-kylin ~]# cd /usr/src/
[root@oldboy108-kylin src]# wget -q https://nginx.org/download/nginx-1.22.1.tar.gz
# 3. 解压源码包,并进入相应目录
[root@oldboy108-kylin src]# tar xf nginx-1.22.1.tar.gz
[root@oldboy108-kylin src]# cd nginx-1.22.1/
# 4. 配置相关选项,并生成Makefile --prefix安装路径
[root@oldboy108-kylin nginx-1.22.1]# ./configure --prefix=/app/nginx-1.22.1
[root@oldboy108-kylin nginx-1.22.1]# echo $?
0 ##如果为0,前一个操作表示成功.
# 5. 将Makefile文件编译为可执行二进制程序
[root@oldboy108-kylin nginx-1.22.1]# make
# 6. 将二进制文件拷贝至对应的目录中
[root@oldboy108-kylin nginx-1.22.1]# make install
搭建本地局域网(自己公司)yum镜像仓库
1.关闭防火墙与SELinux
2.开启yum缓存功能
3.安装并启动 httpd(apache)
4.准备 YUM 仓库目录
5.安装 createrepo 并生成元数据
配置本地光盘yum源镜像仓库
1.挂载光盘镜像
2.查看光盘内容
3.让现有的yum源配置临时失效(备份为.gz)
4.配置本地光盘源
5.生成缓存并测试
14
进程 vs 程序 vs 守护进程
| 进程的工作流程概念 | 含义 | 特点 |
|---|---|---|
| **程序(program)**磁盘 | 代码文件,静静放在磁盘中 | 静态 |
| **进程(process)**内存 | 程序运行起来的产物,存在于内存中 | 动态,运行结束就销毁 |
| 守护进程(daemon) | 持续运行、提供服务的进程 | 长期运行,如sshd |
进程的工作流程
# 进程的完整工作流程
① 程序运行时产生父进程,并可能fork多个子进程
② 父进程接收任务调度,交给子进程处理,子进程继承父进程属性
③ 子进程处理任务时,父进程进入等待状态
④ 子进程完成任务后,发出信号并退出,唤醒父进程回收资源
⑤ 如果子进程异常退出而父进程未回收 → 僵尸进程(Z)
⑥ 如果父进程退出而子进程未退出 → 孤儿进程,由systemd(祖先进程 进程号为1)接管
 僵尸不能kill-9 杀僵尸进程的父进程
| 命令 | 风格 | 特点 |
|---|---|---|
ps -aux |
BSD风格 | 显示所有进程的详细信息**(排错常用)** |
ps -ef |
UNIX风格 | 显示所有进程的简洁格式**(简单查看)** |
watch -n 1 'ps aux --sort -%cpu|head -5' # 要用'
ps -aux 每一列含义
| 列 | 含义 |
|---|---|
| USER | 启动进程的用户 |
| PID | 进程运行的ID号 |
| %CPU | 进程占用CPU百分比***** |
| %MEM | 进程占用内存百分比***** |
| VSZ | 进程占用虚拟内存大小(KB),VSZ=swap+物理内存***** |
| RSS | 进程占用物理内存实际大小(KB),RSS=物理内存***** |
| TTY | 进程由哪个终端启动,?表示与终端无关 |
| STAT | 进程运行状态 |
| START | 进程的启动时间 |
| TIME | 进程占用CPU的总时间 |
| COMMAND | 程序的运行指令,[方括号]属于内核态进程 |
# 显示进程树f
ps auxf | grep nginx
pstree
# 自定义显示字段-o
ps axo %mem,%cpu,start,time,command
# 按内存排序(降序)--sort
ps aux --sort -vsz | head
# 查看某个进程在哪个CPU上运行
ps -eo pid,args,psr
进程查找三兄弟
| 命令 | 作用 | 示例 |
|---|---|---|
| pstree | 以树形结构显示进程关系 | pstree -p |
| pgrep | 根据名称过滤出进程PID | pgrep -a nginx |
| pidof | 查询进程对应的PID | pidof sshd |
top输出五行详解
第1行:任务队列信息(同uptime)
top - 15:37:08 up 2 days, 6:38, 2 users, load average: 0.61, 1.09, 0.74
| 字段 | 含义 |
|---|---|
| 15:37:08 | 当前系统时间 |
| up 2 days, 6:38 | 系统已运行时间 |
| 2 users | 当前登录用户数 |
| load average | 1分钟、5分钟、15分钟平均负载***** 综合表现系统繁忙的指标 |
第2行:进程统计
Tasks: 157 total, 1 running, 156 sleeping, 0 stopped, 0 zombie
| 字段 | 含义 |
|---|---|
| total | 总进程数 |
| running | 正在运行的进程数(R) |
| sleeping | 睡眠的进程数(S/Ss) |
| stopped | 停止的进程数(T) |
| zombie | 僵尸进程数(Z) |
第3行:CPU状态
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni, 99.8 id, 0.0 wa, 0.2 hi, 0.0 si, 0.0 st
%Cpu0 : 0.3 us, 0.0 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.3 hi, 0.0 si, 0.0 st
%Cpu1 : 0.0 us, 0.3 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
| 字段 | 含义 |
|---|---|
| %Cpu(s) | CPU核数 按数字1显示cpu核数 曾经的面试题 grep processor /proc/cpuinfo |
| us | [用户空间]占用CPU百分比(应用、命令)***** |
| sy | [内核空间]占用CPU百分比(内核进程、硬件操作)***** |
| ni | 高优先级进程占用CPU百分比 |
| id | 空闲CPU百分比,数值越大越空闲 |
| wa | CPU等待IO完成时间***** |
| hi | 硬中断占用CPU百分比 |
| si | 软中断占用CPU百分比 |
| st | 虚拟机占用CPU百分比 |
第4行:内存状态
MiB Mem : 1956.2 total, 1088.3 free, 608.7 used, 259.1 buff/cache
内存总量total==剩余内存free+已用内存used+读写缓冲缓存区buffer/cache
| 字段 | 含义 |
|---|---|
| 1956.2 total | 内存总量2G |
| 1088.3 free | 可用内存 |
| used 608.7 used, | 已使用内存 |
| 259.1 buff/cache | 系统缓存(读数据读cache缓存)和缓冲(写数据写入缓冲buff)占用 |
第5行:swap交换分区(磁盘的一段特殊用来当做内存使用的空间 虚拟内存)
MiB Swap: 2048.0 total, 1987.5 free, 60.5 used. 1172.7 avail Mem
⚠️ 重点关注swap的used,如果这个数值不断变化,说明内存真的不够用了,还有特殊情况,内存够用虚拟内存也被占用了(内存泄漏)。
进程列表部分:
| 字段 | 含义 |
|---|---|
| PID | 进程ID |
| USER | 进程所有者 |
| PR | 进程优先级,比NI大20 |
| NI | nice值,负数高优先级,0正常,正数低优先级 |
| VIRT | 进程使用的虚拟内存总量***** |
| RES | 进程使用的物理内存大小***** |
| SHR | 共享内存大小 |
| S | 进程状态 |
| %CPU | CPU时间占用百分比***** |
| %MEM | 物理内存百分比***** |
| TIME+ | 进程使用的CPU时间总计 |
| COMMAND | 进程名称 |
top常用选项
# 查看进程号为42858的进程
top -p 42858(进程号)
# 查看指定用户的进程
top -u apache
# 显示进程的完整命令路径
top -c -u apache
# 显示进程的所有线程信息
top -Hp 42858
#非交互显示此刻状态 配合awk
top -bn1
top必备快捷键
| 快捷键 | 含义 |
|---|---|
| 1 | 查看系统核心总数,显示所有CPU |
| P | 按CPU使用率排序 |
| M | 按内存使用率排序 |
| q | 退出top |
| R | 对已排序的列反转排序 |
| x | 高亮显示排序的列 |
| z | 以彩色信息展示 |
| b | 高亮显示处于R状态的进程 |
| h | 查看帮助 |
| l,t,m | 显示/隐藏前5行数据 |
信号
信号是Linux进程间通信的一种方式,用于通知进程发生了某个事件。
常用信号:
| 数字 | 信号名 | 作用 |
|---|---|---|
| 1 | SIGHUP | 挂起信号,让进程重新读取配置(reload) |
| 2 | SIGINT | 中断信号,等同于Ctrl+C |
| 3 | SIGQUIT | 退出信号,等同于Ctrl+\ |
| 9 | SIGKILL | 强制结束进程,不能被捕获 |
| 15 | SIGTERM | 进程终止,默认信号 |
| 18 | SIGCONT | 被暂停的进程继续运行 |
| 19 | SIGSTOP | 暂停进程 |
| 20 | SIGTSTP | 用户停止请求,等同于Ctrl+Z |
# 列出所有支持的信号
kill -l
kill -1 PIDkill -l SIGKILL # 输出 9
kill -l 9 # 输出 KILL
kill命令使用
## 1.默认信号15 TERM(终止)
kill PID
## 2.指定信号 9(SIGKILL)(强制终止)
kill -9 PID
## 3.指定信号1(重新加载配置)
kill -1 PID
pkill + 进程名
dos2unix + 文件名 #将win格式转换unix
vimdiff #文件对比
diff a b
killall + 进程名
killall -u nginx
ctrl+z 停止 jobs查看 bg %1 fg %1
系统性能完整排查流程
① uptime → 查看平均负载
#初步判断系统瓶颈,如果平均负载高,说明cpu或IO可能有瓶颈
↓
② ps aux/top/htop → 看CPU(s) CPU%、wa、us、sy 内存占用(三高) 找出可疑进程
#使用top综合查看三高问题
↓
③根据哪个高,具体用命令[细致]看 具体问题到[进程名]
iostat -xd 1 5或iotop -o / mpstat -P ALL 1或vmstat -w 2
↓
④strace 追踪这个进程(程序代码\软件配置) → 看它到底在做什么 最终进行处理,让CPU或IO降下来.
↓
⑤ 也可以同步查看日志是否有异常(nginx error),/var/log/message
strace -tt -f /usr/sbin/nginx
#-f 跟踪目标进程及所有子进程
#-tt 每行前加时间信息,精确到微秒
strace -tt -f -e trace=file /usr/sbin/nginx
# -e trace=file 只跟踪文件操作相关
# -e trace=network只跟踪网络相关
strace -c -o ~/tongji.log /usr/sbin/nginx
#-c 统计每系统调用执行时间、次数
#-o filename 将输出写入文件
strace -c -p PID
#-c 统计每系统调用执行时间、次数
#-p 指定要跟踪的进程PID
strace -T /usr/sbin/httpd
strace -T -p PID
# -T 显示每次系统调用所花费的时间
# 跟踪指定进程
strace -p PID
15
系统启动流程
通电>BIOS>MBR>GRUB>Kernel>Systemd
运行级别与target
| 传统运行级别 | systemd target | 功能说明 |
|---|---|---|
| 0关机 | poweroff.target | 关机 |
| 1单用户 | rescue.target | 单用户模式,救援模式 |
| 2没有nfs的多用户 | multi-user.target | 多用户模式,文本界面 |
| 3多用户文本 | multi-user.target | 多用户模式,文本界面 |
| 4没有使用 | multi-user.target | 多用户模式,文本界面 |
| 5 | graphical.target | 多用户模式,图形界面 |
| 6 | reboot.target | 重启 |
查看运行级别常用命令
systemctl get-default # 查看默认启动目标
systemctl list-units --type=target --all #查看所有可用target
who -r runlevel #查看当前运行级别(传统兼容)
systemd相关路径
/usr/lib/systemd/system/ #rpm/yum安装时自带
/etc/systemd/system/ #系统管理员创建,优先级高
systemctl命令
systemctl list-unit-files --type=service #查看所有服务的开机自启状态
systemctl daemon-reload #重新载入更改的systemd配置文件
systemctl is-enabled sshd #查看服务是不是开机自启动
开机自启动原理
enable本质是创建软链接
ln -s /usr/lib/systemd/system/sshd.service /etc/systemd/system/multi-user.target.wants/sshd.service
disable本质删除软链接
rm -f /etc/systemd/system/multi-user.target.wants/sshd.service
systemd文件三段结构
[Unit] # 通用选项,描述信息、依赖关系
[Service] # 特定服务类型,启动、关闭、重启选项
[Install] # 定义开机自启和不开机自启的选项
#特殊说明
#rpm/yum安装的网络服务,默认自带systemd配置文件,直接可以用systemctl start nginx
#源码安装,二进制安装,需要自定义,否则没法用systemctl start nginx方式管理.
单用户模式破解root密码
1. 重启系统,在GRUB菜单出现时按 e 键
2. 输入GRUB账户密码:root / Kylin123123
3. 找到以 linux 开头的行
4. 将 ro 参数改为 rw,并在行尾添加:init=/bin/bash console=tty0
5. 按 Ctrl+X 启动
6. 进入单用户模式后,输入 passwd root 修改密码
7. 重启:/usr/sbin/reboot -f(注意使用完整路径)
16
seq -s xargs -n sed -i
通配符
只对文件名
| 符号 | 作用 |
|---|---|
| * | 匹配所有 |
| ? | 匹配有且只有一个字符 |
| [abcd] / [1234] / [a-z] / [1-9] | 匹配任意字符 |
| [**!**abcd] / [!1-9] | 匹配不包括括号里的一个 |
引号
| 引号 | 作用 |
|---|---|
| '' | 里面是什么就显示什么 |
| "" | 解析变量、命令、转义符 |
| `` | 里面加命令 |
分号
表示一个命令的结束
cd /tmp; ls; pwd # 一条命令执行多个操作
转义符
把有特殊意义的符号变成普通字符
touch \?.txt
ls \?.txt
&& ||
%%前面命令成功了执行后面的 ||前面命令失败了执行后面的
echo -e
| 转义符 | 作用 |
|---|---|
| \n | 换行且光标移至行首 |
| \t | 插入tab |
正则表达式
只能grep sed awk用
| 符号 | 作用 |
|---|---|
| **^**6 | 以666开头的行 |
| 6**$** | 以6结尾的行 |
| ^$ | 空行 |
| . | 任意一个且只有一个字符 |
| 6* | 前一个字符0-n次 |
| .* | 所有 |
| [abc]或[a-c] | 匹配任意字符 |
| **[^abc] **不能用! | 不匹配其中任何 |
17
扩展正则表达式
使用扩展正则需要用 grep -E 或 egrep或sed -r或awk。
| 符号 | 作用 |
|---|---|
| 0**+** | 前面字符1~N次/至少一次 |
| [:/]+ | 括号内字符1次或多次 |
| 0? | 匹配前一个字符0次或1次 |
| (0)(0)\1\2 | 括号内是一个集合 \1是代表第一个() |
| 0{1,3} | 取出包含1-3次的0 |
预定字符
| 字符 | 作用 |
|---|---|
| [[:alnum:]] | 字母数字 |
| [[:digit:]] | 数字 |
| [[:alpha:]] | 字母 |
| [[:upper:]] | 大写 |
| [[:lowwer:]] | 小写 |
sed
| 参数 | 功能 |
|---|---|
| sed -n '2,4p' | 输出2-4行 |
| sed -n '/teacher/p' | 过滤含teacher的行 |
| sed '/teacher/d' | 删除带teacher的行 |
| sed '2,4d' | 删除2-4行 |
| sed -i.bak '/oldboy/d' | 备份并删除 |
| sed -i 's/A/B/g' | 全局替换 |
| sed -i '3s/666/777/g' | 指定行替换 |
| sed -i '3,5s/666/777/g' | 指定多行替换 |
| sed -i '2a 666' | 第二行后追加 |
| sed -i '2i 666' | 第二行前插入 |
| sed -i '2i 666\n77' | 插入多行 |
sed -E / -r开启扩展正则表达式 一条命令搞定(后向引用) s/以什么开始(.*)以什么结束)/\1/gawk -F "[:/]+" '{print &}'
awk
| 符号 | 作用 |
|---|---|
| NF | 字段数 |
| NR | 行数 |
| $0 | 整行 |
| NR>n && NR<m | 取范围行 |
| awk -F "()|()" '{print &}' | 指定分隔符 |
| awk -F "[:/]+" '{print &}' | 指定分隔符 |
删除所有以 # 开头的行,输出其余行
awk '!/^#/{print $0}' config.conf
18
PATH
命令会在此文件中找要查询的路径 要让命令能执行需要在PATH里加命令位置
export PATH="/root:$PATH" #临时更改PATH
find
| 参数 !取反 | 作用 |
|---|---|
| -name | 按名字查找 |
| -type | 按类型查找 |
| -size +大于 无等于 -小于 | 按大小查找 |
| -perm 755 | 按权限查找 |
| -mtime +7 7 -7 | 按修改时间 |
| -user | 按时间查找 |
多参数查找 默认-a 不用写 或者用 -o
find结果处理
| 命令 | 作用 |
|---|---|
| find ~ -name "*.txt" -mtime +7 -exec rm -rf {} ; | 一条一条删除 |
| find ~ -name "*.txt" -mtime +7 -exec rm -rf {} + | 整体删除 |
| find ~ -name "*.txt" -mtime +7|xargs rm -rf | 整体删除 |
| find ~ -name "*.txt" -mtime +7|xargs -i cp {} /tmp | 复制目标文件到tmp |
| find ~ -name "*.txt" -mtime +7 -exec cp -t /tmp {} + | 复制目标文件到tmp |
prune剪枝

26
脚本与变量
脚本:多个命令的集合 变量:空间存放内容 静态动态都可以 不能数字
编写脚本
vim script.sh 创建一个脚本
#!/bin/bash 格式
#author
#desc
#1.vars
ip=hostname -I
bash script.sh 执行脚本
bash -x 检查脚本 显示运行过程
cat <<EOF 批量输出
主机名:$hostname
ip:$ip
EOF
邮件
下载mailx
yum install -y mailx
配置邮件授权
#进入163邮箱开启POP3/SMTP服务获取授权码
cat >>/etc/mail.rc <<EOF
set from=libinghao66@163.com
set smtp=smtp.163.com
set smtp-auth-user=libinghao66@163.com
set smtp-auth-password=FMbhsNMP7gmsSytG
set smtp-auth=login
EOF
发送邮件格式
echo 内容 |mailx -s "标题" 目标邮箱
cat a.txt |mailx -s "标题" 目标邮箱
脚本运行结果发给邮箱
脚本结果写入文件
cat >/var/a.txt<<EOF
ip:$ip
EOF
命令行运行
cat /var/a.txt|mailx -s " 巡检" 123qq.com
27
面试题总结
- 平常用什么脚本语言?
- 运维常用的Linux命令?
- 查看Linux操作系统版本命令?
- 主流的Linux都熟悉吧?
- 会做哪些Linux系统/内核优化?
- 主机常用命令(内存、CPU、硬盘、IO、进程、网络)?
- 查看哪些服务端口正在被监听,用什么命令?
- centos和ubuntu的区别?
- centos用的什么版本?怎么查看版本?
- 中间件的这种部署升级吗?
- 系统部署和升级用了什么命令?
- 查找和过滤相关命令用了什么?有什么区别?
- 查看进程分别用什么命令?
- Linux系统中,已知JAVA进程号为2818,请写出查看该进程内存使用
- 目前已知xxservice进程监听了某个端口,如何通过xxservice进程名称查看到其对应监听的端口,请写出对应操作指令
- 进程和线程有什么区别?
- 为什么有多进程的?有些程序是单线程的?
- 查看系统已用内存、系统CPU利用率的对应操作指令
- CPU突然飙升你的排查思路
- 8核的服务器能跑到百分之多少?
- Linux服务器里它的CPU比较正常、平均的数据正常30-40左右,但是它的负载很高,还有哪些可能的原因?
- 服务器CPU占用很低,但业务卡顿,是什么原因、怎么排查?
- OOM遇到过吗?
- 给你一台新服务器你怎么操作?
平常用什么脚本语言?
shell/bash
python
golang
运维常用的Linux命令?
系统巡检类:
基本信息:hostamectl uname w uptime
cpu信息:lscpu top ps aux
内存信息:free -h top
磁盘信息:df -h du-sh
网络信息:ip a iftop
用户信息:id last
进程信息:ps top
服务信息:systemctl
软件包信息:rpm
故障排查类:
检查网络:ping
检查端口:telnet
检查ip:ip a
检查页面:curl
查看Linux操作系统版本命令?
cat /etc/os-relrase
hostnamectl
主流的Linux都熟悉吧?
centos 7.9
kylin v10 sps 4.19
ubuntu 22.04 24.04
debian 10 /11 /12
rocky 10
OpenEuler 欧拉系统(华为)
OpenAnolis 龙蜥(阿里)
会做哪些Linux系统/内核优化?
配置/关闭防火墙
常用软件包
配置yum/apt源加速
优化ssh 修改ssh端口号 禁止root远程登录
添加普通用户配置sudo权限
配置别名
命令行颜色
内核优化 其他安全优化
主机常用命令(内存、CPU、硬盘、IO、进程、网络)?
日常巡检类
故障排查类
查看哪些服务端口正在被监听,用什么命令?
ss -lntup
centos和ubuntu的区别?
密码要求 添加用户 设置密码(非交互) 时间修改 防火墙
centos用的什么版本?怎么查看版本?
centos 7.9
hostnamectl
中间件的这种部署升级吗?
yum /rpm
编译安装
系统部署和升级用了什么命令?
1.服务升级用的命令?
yum/apt升级
编译安装: ./configure ; make -j `nproc` ; make install
2.系统部署用的服务?
100台服务需要批量安装系统.
kickstart/cobbler 网络安装.
查找和过滤相关命令用了什么?有什么区别?
find
grep/sed/awk
查看进程分别用什么命令?
ps top
Linux系统中,已知JAVA进程号为2818,请写出查看该进程内存使用
ps aux |grep 2818
top -bn1 |grep 2818
目前已知xxservice进程监听了某个端口,如何通过xxservice进程名称查看到其对应监听的端
口,请写出对应操作指令
ss -lntup
进程和线程有什么区别?
进程:占用内存空间 系统资源
线程:处理请求 处理任务
为什么有多进程的?有些程序是单线程的?
ps aux看进程状态,带有l(小写L) 就有线程
pstree -p 查看
top -Hp 进程pid
查看系统已用内存、系统CPU利用率的对应操作指令
top
CPU突然飙升你的排查思路
查看cpu使用情况 top/ps aux
查看哪些进程使用率高
进程--->服务(nginx,mysql,tomcat)
查看日志
8核的服务器能跑到百分之多少?
800%
Linux服务器里它的CPU比较正常、平均的数据正常30-40左右,但是它的负载很高,还有哪些可
能的原因?
1.系统负载高
2.不是cpu导致的,可能是磁盘io
3.top看iowait
4.pidstat -d 1 查看进程级别的读写速度.
5.ps aux |grep D (进行磁盘io或等待磁盘io)
服务器CPU占用很低,但业务卡顿,是什么原因、怎么排查?
负载高
网络问题
OOM遇到过吗?
out of memory
1.free -h
2.ps aux 或top
3.定位到进程
给你一台新服务器你怎么操作?
简单: 1.巡检 2.优化 3.根据要求部署服务环境
物理机/虚拟机:
做raid然后部署系统
巡检 优化 根据要求部署服务环境
云服务器:
巡检 优化 根据要求部署服务环境
28
star法则
s:情况 t:目标 a:步骤 r:结果
背景:连不上ssh
目标:连接上
步骤:ping telnet ssh服务 防火墙
结果:ping不通
磁盘
| 接口 | 硬盘 | 选型 |
|---|---|---|
| sata | 机械/固态 | 容量大适用于备份 访问率低 |
| sas | 机械/固态 | 企业服务器首选 |
| pcie/U2 | 固态 | 性能为主 |
分区
针对磁盘
磁盘命名: sata/sas/scsi /dev/sda /dev/sdb 固态 /dev/nvme0n1 /dev/nvme0n2 云服务器 /dev/vda /dev/vdb 分区命令:
fdisk -l #查看磁盘信息
fdisk /dev/nvme01
p #打印
n #新建分区
w #保存
d #删除分区
格式化/创建文件系统
针对分区 1.临时,重启后失效
#1.看先前/是什么文件系统
df -hT
#2.创建文件系统
mkfs.xfs +分区
#3.挂载让mnt这个目录成为访问分区内容的入口
mount +分区 +/mnt
2.永久修改,编辑配置文件
#1.编辑配置文件
vim /etc/fstab
#2.添加配置内容(六列)
/dev/nvme0n1p1 /data-new xfs defaults 0 0
挂载目录需要提前建好
#3.加载配置或者重新启动
umount /data-new #卸载挂载点
mount -a #从配置文件中读取挂载
注意:挂载点删除后数据仍存在分区里不会消失,新建挂载点后仍能找到
parted
2T以上使用
parted +磁盘
p #查看表名称
mktable gpt #创建表
mkpart primary 0 100#创建分区
rm #删除分区
q #退出
29
swap
1.创建
#创建swap文件
mkdir /swap
dd if=/dev/zero of=/swap/swap bs=1M count=1024
#格式化
mkswap /swap/swap
#挂载swap(临时)
swapon /swap/swap
2.永久挂载
vim /etc/fstab
swap文件 swap swap defaults 0 0
3.关闭
#指定关闭
swapoff /swap/swap
#关闭所有
swapoff -a
#彻底关闭
注释掉/etc/fstab中包含swap的行
#debian/ubt系统
systemctl mask swap
raid
| raid级别 | 最少需要几块硬盘 | 安全冗余 | 可用容量 | 性能 |
|---|---|---|---|---|
| Raid 0 | 1/2 | 最低 | 所有硬盘容量的和 | 读写最快 |
| Raid 1 | 只能有2块 | 100% | 一半(两块硬盘容量之和) | 写入速度慢,读取OK |
| Raid 5 | 3 | 最多损坏一块 | 损失一块盘的容量 | 写入性能不好 读取速度OK |
| Raid 10 | 4 | 可以损坏一半 | 损失所有硬盘一半的容量 | 读写很快 |
磁盘空间不足系列
no space left on device
1.block不足
#查看磁盘哪快满
df -h
#按层排查
du -sh /*|sort -hrk1
du -sh /var/*|sort -hrk1
du -sh /var/log/*|sort -hrk1 |head
#find查找
find / -type f -size +1G |xargs ls -lh
2.inode不足
#现象: 提示磁盘空间不足,df -h 磁盘空间还有,df -i发现不足
原因:小文件多,inode被使用的多
#找大目录
find / -type -d -size +1M
#提示Argument list too long怎么解决?
ls |xargs rm -f
3.文件未彻底删除
#如何判断有这样的未释放的情况?
对比df -h结果与du -sh 结果
#定位到具体哪个进程,哪个文件重启服务或结束进程.
lsof |grep delete
30
lvm原理
| 物理硬盘 | PV (物理卷) | VG (卷组) | LV (逻辑卷) | 挂载点 |
|---|---|---|---|---|
| 硬盘1 | pv1 | vg1 | lv1 | /data-lv1 |
| 硬盘2 | pv2 | vg1 | lv2 | /data-lv2 |
lvm创建
#创建pv
pvcreate /dev/sdb /dev/sdc /dev/sdd
#创建vg
vgcreate vg1 /dev/sdb /dev/sdc /dev/sdd
#创建lv
lvcreate -L 10G -n lv1 vg1
#格式化
mkfs.xfs /dev/vg1/lv1
#挂载
mkdir -p /data-lv1
mount /dev/vg1/lv1 /data-lv1/
lvm扩容
#lv扩容
lvextend -L +20G /dev/vg1/lv1
#文件系统识别
xfs_growfs /dev/vg1/lv1
xfs_growfs #xfs文件系统使用
resize2fs #ext系列文件系统使用
#vg扩容
pvcreate /dev/sde
vgextend vg1 /dev/sde
lvextend -L +20G /dev/vg1/lv1
xfs_growfs /dev/vg1/lv1
lvm命令汇总
| 序号 | 功能 | PV物理卷命令 | VG卷组命令 | LV逻辑卷命令 |
|---|---|---|---|---|
| 1 | 扫描功能 (scan) | pvscan | vgscan | lvscan |
| 2 | 建立功能 (create) | pvcreate | vgcreate | lvcreate |
| 3 | 查询功能 (display) | pvdisplay/pvs | vgdisplay/vgs | lvdisplay/lvs |
| 4 | 删除功能 (remove) | pvremove | vgremove | lvremove |
| 5 | 扩容功能 (extend) | vgextend | lvextend | |
| 6 | 缩容功能 (reduce) | vgreduce | lvreduce |
磁盘面试题
1查看磁盘空间? 2要查看具体的目录或磁盘使用情况时用什么? 3查看磁盘空间利用率的对应操作指令? 4iostat哪项值比较重要? 5raid有什么级别? 6 raid 1的镜像组数据完全一致吗? 7请简述Raid5的工作原理,并阐述Raid5与Raid0、Raid1的侧重点? 8你们怎么做的的raid? 9了解raid吗?假如是财务系统,你怎么做raid? 10服务器安装系统,是先装系统还是先配置raid? 11硬盘扩容怎么做? 12讲下LVM扩容的步骤? 13硬盘dev/sdc扩容的命令和步骤? 14用户一个虚拟机的磁盘满了,怎么扩容? 15服务器磁盘满了怎么扩容? 16你们公司硬盘怎么安排的?
解答: 1查看磁盘空间?
df -h
2要查看具体的目录或磁盘使用情况时用什么?
du -sh /root/
df -h /
3查看磁盘空间利用率的对应操作指令?
df -h
4iostat哪项值比较重要?
%iowait
5raid有什么级别?
0 1 5 10 60 6
6 raid 1的镜像组数据完全一致吗?
一致
7请简述Raid5的工作原理,并阐述Raid5与Raid0、Raid1的侧重点?
有一份做校验 其余存数据 允许丢十一份数据
raid0 主要增加硬盘的容量和性能 抛弃了冗余
raid1 主要保证了安全性 100%冗余 但是抛弃了磁盘的容量 读写性能中等
raid5 可以说处于0-1之间 性能中等 容量可丢失一个
8你们怎么做的的raid?
0 1 5 10
9了解raid吗?假如是财务系统,你怎么做raid?
财务系统一般并发量低 不需极致的性能 主要侧重于数据安全性
所以 可以使用raid1 充分保证数据的安全冗余 如需要增加性能可以使用raid10
10服务器安装系统,是先装系统还是先配置raid?
先安装raid
11硬盘扩容怎么做?
lvm扩容:扩容 pv vg lv
磁盘:找大目录,增加硬盘,把目录改名,挂载原目录名,把目录内容最后移过来
12讲下LVM扩容的步骤?
先看看vg够不够用是vg不够的原因就要增加硬盘 重新创建pv
在创建vg vg够用lv不够 直接lvextend扩展
13硬盘dev/sdc扩容的命令和步骤?
同11
14用户一个虚拟机的磁盘满了,怎么扩容?
同11
15服务器磁盘满了怎么扩容?
同11
16你们公司硬盘怎么安排的?
8tb*4
31
md5
是什么:哈希计算 干什么的:用于检查文件内容是否被修改过
#生成md5值
md5sum s.txt
#更改文件
echo 1 >s.txt
#文件内容被修改后md5值被修改以此校验文件完整性
#md5通过文件检查
md5sum -c a.log
弊端:文件权限更改或新建文件检查不出来
aide
是什么:入侵检测软件 干什么:用来检测文件有没有被修改
#下载:
yum install aide -y
#配置文件:
vim /etc/aide.conf
#初始化:
aide -i
#mv改.new.gz后启用
aide -C
堡垒机
是什么:安全审计平台 干什么:监控与集中管理服务器
#安装与使用
tar xf jumpserver-ce-v4.10.6-x86_64.tar.gz -C /app/tools/
cd /app/tools/jumpserver-ce-v4.10.6-x86_64/
./jmsctl.sh install
./jmsctl.sh status
./jmsctl.sh start
./jmsctl.sh status
#进入jumpserver网站
初始账号密码:admin ChangeMe
资产列表:添加已经存在的服务器
添加账号:添加的是服务器的用户
添加用户:添加的是堡垒机的用户
资产授权:指定哪个堡垒机用户可以用哪个服务器
32
网络基础知识
网速:1000Mbps=125MBps因为1字节等于8比特
#查看实时速度命令
iftop -nB
-nN 不要把ip,端口反向解析为名字 22端口-->ssh 80--->http
-P显示端口号
-B 以字节为单位.
交换机
在一个交换机的端口上所连接的所有终端设备,均在一个网段(局域网 LAN)上(称为一个广播域)
产生广播消耗设备CPU资源
终端用户的设备接入,连接交换机
路由器
连接不同的网络
核心功能:路由功能(指路),ip(DCHP分配IP)
路由表
windows命令:
#查看路由表
route print
#路由追踪命令
tracert -d baidu.com
加-d 参数后,tracert 就会跳过 DNS 解析步骤,直接在结果中显示路由器的 IP 地址
linux命令:
#查路由表
ip -r
route -n 详细
#路由追踪命令
traceroute -nI www.baidu.com
-n不对ip解析反向解析(ip-->名字)
-I或--icmp使用icmp协议检查(ping)
33
OSI七层模型
| OSI7层模型 | 含义. | 协议与概念 | 命令 |
|---|---|---|---|
| 7 应用层 | 应用之间互相调度使用,提供接口. | http(80),https(443),smtp(25),dns(53) | curl/wget/浏览器访问 |
| 6 表示层 | 数据加密,解密;编码,解码;压缩,解压缩 | ||
| 5 会话层 | 负责建立,管理维护会话信息. | ||
| 4 传输层 | 负责连接建立/断开,传输是否可靠 | 协议:tcp/udp, 核心概念:端口 | telnet/nmap/nc.... ss |
| 3 网络层 | 负责路由(指路)与寻址(根据ip地址找人) | IP 核心概念: ip地址 设备: 三层路由器 三层交换 协议 icmp | ping/tracert/traceroute |
| 2 数据链路层 | 负责数据到达局域网后传输 | 核心概念: mac地址 设备:二层交换 | arp命令(mac地址) |
| 1 物理层 | 负责把数据转换为介质可以识别信号(数据),通过介质传输 | 网卡,传输介质 |
tcp三次握手四次挥手
三次握手:建立连接 SYN>SYN+ACK>ACK,客户端请求连接发送syn+seq给服务端,服务端接受请求发送ACK+ack并发送syn+seq给客户端,客户端发送ACK+ack连接建立 四次挥手:断开连接 FIN>ACK>FIN>ACK.服务端发给客户端FIN+seq,客户端回ACK+ack,客户端发送FIN+seq给服务端,服务端ACK+ack,连接断开
抓包
使用wireshark抓包(windows)
#3层 抓取ping的数据包(网络层)
ping baidu.com 过滤条件是icmp协议
#4层 tcp
telnet baidu.com 80
wireshark过滤 tcp.port == 80
##4层 udp 过滤ntpdate结果 (udp)
ntpdate ntp.aliyun.com
wireshark过滤条件是ntp 或 udp.port == 123
##4层 tcp
telnet jd.com 80 #过滤 tcp.port == 80
##7层抓取http协议数据包(tcp)
curl www.baidu.com 过滤条件是http协议
使用tcpdump(linux)
tcpdump抓包命令
tcpdump -nnn port 80 and host 10.0.0.1
port 指定端口
host 指定ip
-nnn 不要把ip,端口反向解析为名字
网络层
负责将数据从源地址传输到目的地址(IP)
src ip 源ip
dst/dest ip 目标ip
收件人,发件人的地址.
主要负责: 主要作用就是路由(指路)和寻址(根据ip地址找人)
提供ip地址(DHCP).
进行路由(问路,指路)(路由表.
设备: 3层路由器,3层交换.
小结:
网络层:用于指定源ip和目标ip.
网络层核心概念:ip地址.
协议:IPv4(32位)/IPv6(128位)/ICMP(ping协议 互联网控制信息协议)
传输层
负责数据传输: 可靠/不可靠 端口管理
可靠: TCP 连接建立需要3次握手 连接断开需要4次挥手 ....
不可靠: UDP 连接建立与断开是直接进行
ss -lntup 有没有指定的端口
telnet 命令检查端口是否可用,检查4层传输层的内容
传输层用于管理或控制连接(端到端连接).
传输层控制了,连接或数据传输是否可靠.指定端口号.
如何指定数据传输是否可靠?根据代码书写的时候指定
可靠的连接(面向连接的). tcp协议(建立连接经历3次握手,断开连接经历4次断开,重传)
不可靠的连接(无连接). udp协议(直接建立,直接断开,尽全力传输)
通过端口与对方连接.(访问百度连接百度80或443端口)
一句话:可靠或不可靠的连接+端口号.
核心:传输层用于控制数据传输是否可靠,这里还指定了端口. (tcp,udp)
可靠:tcp,不可靠是udp
应用层
大部分软件,服务运行在应用层中.
详细含义: 暴露很多接口,提供给其他服务软件使用.主要就是提供应用程序可以接入网络的接口,并根据程序的不同对应不同的接口协议.
接口: 别人定义好的规范.usb接口一样,这里的接口指的是软件的接口,用于软件之间,服务之间相互使用.
API (应用程序编程接口Application Programming Interface) 软件开发后提供给用户使用的接口(http/https)
| 协议 | 含义 | 默认端口 |
|---|---|---|
| http | 超文本传输协议: 网站基础协议之一 | 80 |
| https | 多了个secure: 对数据加密了. | 443 |
| smtp | 简单邮件传输协议 发邮件. smtp未加密 smtps加密 | 25(smtp),465(smtps) |
| dns | 域名解析服务 目的: 域名-->ip | 53 |
| 其他 | ntp,rtmp,hls,ftp,websocket,...... |
34
osi与数据传输

网站无法访问排查流程
网络层ping/traceroute/tracert
传输层ss/telnet/nc
应用层curl/wget
服务日志
用户访问百度流程
- DNS解析出目标ip
- tcp建立连接三次握手
- http/s请求与响应
- 断开连接四次挥手
DNS缓存
windows查看dns缓存命令
ipconfig /displaydns #显示缓存
ipconfig /flushdns #清除缓存
#linux下查看dns解析流程的命令
dig +trace www.baidu.com
#正常使用可以去掉+trace
dig www.baidu.com
35
tcp/ip 3次握手4次挥手过程中11种状态
三次握手状态变化 四次挥手状态变化
客户端 服务端 主动端 被动端
closed closed ESTA ESTA
SYN_sent listen FIN_wait1 close_wait
ESTA SYN_RCVD FIN_wait2 close_wait
ESTA TIME_wait LAST_ACK
closed closed
如果主动端没收到ACK只收到FIN会进入closing
socket
应用程序与网络之间的通信接口 Socket = IP + 端口
fd
#文件描述符,可以看见进程打开了哪些文件
cd /proc/pid/fd
ll
ARP
地址解析协议,三层协议工作在二层
将IP转化为网卡物理地址(mac)
为什么要转换为mac:网卡、交换机这些 “二层设备”,天生就只认 MAC 地址,不认 IP 地址
解析流程: 一问(广播)一答(单播)
10.0.0.200 找 10.0.0.2
1.发出arp请求:发送广播找人 谁知道10.0.0.2的mac地址,请告诉10.0.0.200
2.单播:所有局域网的设备都收到广播,只有10.0.0.2这个机器进行响应(回复): 我是10.0.0.2 我的mac地址是00:50:56:c0:00:08
3.缓存mac地址
arp -n #查看当前系统arp缓存表
arp -d 10.0.0.201 #删除arp缓存
禁ping
1.内核参数<===这次 配置文件 /etc/sysctl.conf /etc/sysctl.d/下面以.conf结尾的文件
2.防火墙软件
3.安全组或物理防火墙
#内核参数:
临时禁止ping,重启后恢复
#临时,重启系统失效
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
或者
sysctl -w net.ipv4.icmp_echo_ignore_all=1
#准许ping
echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_all
或者
sysctl -w net.ipv4.icmp_echo_ignore_all=0
#永久生效
#/proc/sys/
#/proc/sys/目录下.
#目录中的/改为.就可以使用.
#net/ipv4/icmp_echo_ignore_all --> #net.ipv4.icmp_echo_ignore_all =1
echo 'net.ipv4.icmp_echo_ignore_all = 1 ' >>/etc/sysctl.conf
sysctl -p #生效
十进制转为二进制
| 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 | ||
|---|---|---|---|---|---|---|---|---|---|
| 十进制 | 128 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 十进制 | 192 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
ip格式与分类
32位二进制8个一组转化为十进制
A类:00000001 ~ 01111111 1 ~ 126 127除外
B类:10000000 ~ 10111111 128 ~ 191
C类:11000000 ~ 11011111 192 ~ 223
D类:11100000 ~ 11101111 224 ~ 239
子网掩码
确定主机位与网络位
子网掩码确定这个网络中主机数量是多少
10.0.0.0/24
10.0.0.0/255.255.255.0
24表示32位二进制中使用24位作为网络位剩下8位表示主机位
| 题号 | IP 地址 A | IP 地址 B | 两者的子网掩码 |
|---|---|---|---|
| 1 | 10.0.0.10 | 10.0.0.200 | 255.255.255.0 (/24) |
| 2 | 10.0.0.10 | 10.0.1.10 | 255.255.255.0 (/24) |
| 3 | 10.0.0.10 | 10.0.1.10 | 255.255.0.0 (/16) |
| 4 | 192.168.1.126 | 192.168.1.129 | 255.255.255.128 (/25) |
| 5 | 192.168.1.130 | 192.168.1.190 | 255.255.255.192 (/26) |
| 6 | 192.168.1.190 | 192.168.1.200 | 255.255.255.192 (/26) |
| 7 | 172.16.10.10 | 172.16.11.200 | 255.255.254.0 (/23) |
| 8 | 10.0.31.10 | 10.0.32.20 | 255.255.240.0 (/20) |
判断在不在同一网段
1.256-不是255的位得出块大小
2.找出块 判断两个ip在不在同一块内
36
检查端口命令
ss -lntup |grep 22
lsof -nPi :22
#lsof -n 不要把ip反向解析为主机名、域名。
#lsof -P 不要把端口解析为对应的服务。
nmap -p22 10.0.0.200
nmap -p22 10.0.0.0/24 jd.com taobao.com
nc -v 10.0.0.200 22
网络速度命令
iftop -nNP -i eth0 #显示端口号,不要把ip解析为域名,不要把端口解析为服务, 监视指定网卡eth0
DNS解析命令
dig www.baidu.com
nslookup www.baidu.com
host www.baidu.com
追踪命令
ping baidu.com
mtr www.baidu.com
mtr --tcp -r -c 2 www.baidu.com
链路测试工具
#服务端 server
iperf -s
#客户端连接服务端 client
iperf -c 服务端ip
网络命令总结
| 网络命令 | linux | windows |
|---|---|---|
| 查询ip地址 | ip/ifconfig | ipconfig |
| 检查端口号 | ss/netstat/lsof / nc/telnet/nmap | netstat -ant |
| 检查连接情况 | ss -antp /netstat -ant | netstat -ant |
| 检查速度 | iftop -NnBP -i ens33 /nethogs | |
| dns解析 | dig/host/nslookup | nslookup |
| 路径追踪 | traceroute -nl,mtr | tracert |
| 检查链路是否通畅 | ping,fping | ping |
| 查询当前系统配置的网关/路由信息 | ip ro /route -n | route print |
| 测试带宽 | iperf |
抓包参数总结
| 过滤条件 | wireshark | tcpdump |
|---|---|---|
| 抓出指定协议 | icmp/tcp/http | icmp/tcp/udp(不支持7层协议) 需要通过指定端口方法 |
| 抓住指定端口 | tcp.port == 80 | port 80 |
| 过滤出源端口 | tcp.srcport == 80 | [tcp或udp] src port 80 #tcp或udp |
| 过滤目标端口 | tcp.dstport == 80 | [tcp或udp] dst port 80 |
| 抓出指定ip的数据包 | ip.addr == 10.0.0.200 | host 10.0.0.200 |
| 过滤出源ip | ip.src == 10.0.0.200 | src host 10.0.0.200 |
| 过滤出目标ip | ip.dst == 10.0.0.200 | dst host 10.0.0.200 |
tcpdump结合wireshark
tcpdump -nnn -vvv -i any port 80 and host 10.0.0.210 -w http-80.pcap
37
安全组
- 云产品中的防火墙,使用控制web页面进行.不是在linux系统
- 不是在linux中的防火墙(firewalld,ufw)
- 默认规则是拒绝. 可能添加了准许22,80,443.
DNS记录类型
| DNS记录类型 | 含义 | 应用场景 |
|---|---|---|
| A记录 | 域名解析到IPv4的ip上. | 使用最多的.解析后还需要web访问, 需要备案. |
| AAAA记录 | 域名解析到IPv6的ip上. | 需要ipv6的时候配置. 同一个域名同事解析到A记录/AAAA记录. |
| TXT记录 | 解析到一个字符串上.不是用浏览器访问,命令行测试.做校验使用,验证域名所有权. | 要求: lidao.oldboylinux.cn txt显示: oldboylidao996 |
| CNAME记录 | 别名记录,域名1--->域名2 | 未来使用CDN,WAF需要. |
| MX记录 | 企业邮箱使用 | 根据企业邮箱的要求配置即可.公司域名:oldboy.cn邮箱: lidao996@oldboy.cn |
38
创建脚本自动添加说明信息
红帽: /etc/vimrc ubt/debian: /etc/vim/vimrc
autocmd BufNewFile *.py,*.cc,*.sh,*.java,*.bash,Dockerfile,docker-compose.yml exec ":call SetTitle()"
func SetTitle()
if expand("%:e") =~ 'sh\|bash'
call setline(1,"#!/bin/bash")
call setline(2, "##############################################################")
call setline(3, "# File Name: ".expand("%"))
call setline(4, "# Version: V1.0")
call setline(5, "# Author: lidao996")
call setline(6, "# Organization: www.oldboyedu.com")
call setline(7, "# Description:")
call setline(8, "##############################################################")
call setline(9, "")
endif
if expand("%") == 'Dockerfile'
call setline(1, "#####################Dockerfile###############################")
call setline(2, "##############################################################")
call setline(3, "# File Name: ".expand("%"))
call setline(4, "# Version: V1.0")
call setline(5, "# Author: lidao996")
call setline(6, "# Organization: www.oldboyedu.com")
call setline(7, "# Description:")
call setline(8, "##############################################################")
call setline(9, "")
call setline(10, "FROM")
call setline(11, "LABEL maintaniner='oldboy lidao@oldboyedu.com' author=lidao996")
call setline(12, "CMD []")
endif
if expand("%") == 'docker-compose.yml'
call setline(1, "#####################docker-compose###########################")
call setline(2, "##############################################################")
call setline(3, "# File Name: ".expand("%"))
call setline(4, "# Version: V1.0")
call setline(5, "# Author: lidao996")
call setline(6, "# Organization: www.oldboyedu.com")
call setline(7, "# Description:")
call setline(8, "##############################################################")
call setline(9, "")
call setline(10, "version: '3.3'")
call setline(11, "services:")
call setline(12, "volumes:")
endif
endfunc
金庸新作问题
变量与其他内容拼接时需注意
[root@oldboy108-kylin ~]# name=lbh
[root@oldboy108-kylin ~]# echo $name
lbh
[root@oldboy108-kylin ~]# echo $namelbh
[root@oldboy108-kylin ~]# echo ${name}lbh
lbhlbh
$n
位置参数 执行脚本时后边添加的参数
bash a.sh install
$1:第一个参数
$0
文件名
[root@oldboy108-kylin ~]# cat a.sh
#!/bin/bash
echo $0
[root@oldboy108-kylin ~]# bash a.sh
a.sh
$?
判断前一个命令执行是否成功 输出0成功 不是0失败
#参数为空显示帮助
name=$1
if [ $# -eq 0 ];then
echo "无参数"
fi
$
参数个数
[root@oldboy108-kylin ~]# cat a.sh
#!/bin/bash
echo "$#"
[root@oldboy108-kylin ~]# bash a.sh A B C D
4
$* $@
列出所有参数
[root@oldboy108-kylin ~]# cat a.sh
#!/bin/bash
echo "$*"
[root@oldboy108-kylin ~]# bash a.sh A B N F
A B N F
if判断格式
if [ ];then
else
fi
exit
exit 1
退出 返回
ps使用注意事项
1过滤进程的时候排除grep命令的进程 grep -v grep
2脚本运行的时候也是一个进程,进程名字中包含ps过滤的内容 解决排除脚本名字的进程 排除grep命令和排除脚本名字
3使用ps -eo ps -eo pid=,comm=与pgrep pgrep -x 进程名字
环境变量
| 环境变量 | 作用 | 应用场景 |
|---|---|---|
| PATH | 存放命令的位置/目录 | 二进制安装软件或编译安装,修改PATH增加命令的位置 |
| PS1 | 命令行格式. | 系统优化进行配置 |
| LANG | language 语言,字符集 | 系统优化进行配置 en_US.UTF-8或zh_CN.UTF-8 |
| UID | 获取当前用户的UID | 搭配判断判断是否为root. |
修改字符集
#临时修改(重新登录失效) 书写在脚本开头即可.
export LANG=en_US.UTF-8
#永久生效
localectl set-locale zh_CN.UTF-8
alias
/etc/profile #永久生效
.bashrc #当前用户
profile改了当前用户没改需需要删除当前用户的alias
alias改完后的rm 用 \rm即可恢复到rm命令
回收站脚本
#1.命令行临时-重启后失效
umount -lf /tmp
#2.命令行永久-重启后生效
systemctl mask tmp.mount
mktemp -d #默认在/tmp/下创建随机名字的目录
#1.vars
files="$*"
#1.5 if+$#
if [ $# -eq 0 ];then
echo "Usage: $0 file/dir"
exit 1
fi
#2.tmp dir
tmp_dir=`mktemp -d`
#3.mv
mv ${files} ${tmp_dir}
#4.echo
echo "${files}已经移动到回收站,回收站路径:${tmp_dir}"
39
条件测试[ ]
# 写法一:中括号(最常用)
[ -f /etc/hosts ] && echo "存在"
# 写法二:双中括号(bash 扩展,支持正则)
[[ -f /etc/hosts ]] && echo "存在"
注意:
[和]两边、条件两边都必须有空格。[是命令,不是语法符号;[$# -eq 0]这种写法会报错。- 条件成立看
$?:0成功/真,非0失败/假。
[ -f /etc/hosts ]
echo $? # 0
文件类型判断
| 参数 | 含义 | 典型场景 |
|---|---|---|
-d |
目录是否存在 | 操作 /backup/ 前检查目录 |
-f |
普通文件是否存在 | 配置文件、日志文件检查 |
-e |
路径是否存在(不区分类型) | 通用存在性检查(补充) |
-x |
是否存在且有执行权限 | 检查命令/脚本是否可执行 |
-s |
文件存在且大小大于 0 | 判断文件是否为空 |
-h / -L |
是否为软链接 | 检查软链接 |
[ -f /etc/hosts ] && echo "文件存在"
[ -d /etc/ ] && echo "目录存在"
[ -x /bin/ls ] && echo "可执行"
[ -s /etc/hosts ] && echo "有内容"
[ -L /etc/rc.local ] && echo "是软链接"
案例:
# 目录不存在则创建([] + || 简写)
[ -d /backup/lidao996 ] || mkdir -p /backup/lidao996
# 等价的 if 写法
if [ ! -d /backup/lidao996 ]; then
mkdir -p /backup/lidao996
fi
数值比较
只能比较整数
| 运算符 | 英文 | 含义 | 数学符号 |
|---|---|---|---|
-eq |
equal | 等于 | == |
-ne |
not equal | 不等于 | != |
-gt |
greater than | 大于 | > |
-ge |
greater or equal | 大于等于 | >= |
-lt |
less than | 小于 | < |
-le |
less or equal | 小于等于 | <= |
if [ "$num" -ge 70 ]; then
echo "大于等于 70"
fi
注意:
[]只能比较整数,小数要用bc或awk。- 在
[]中不要直接写>、<,它们会被当成重定向;数值比较用-gt、-lt。 - 变量可能为空时,
[ "$num" -ge 70 ]仍可能报integer expression expected;可先用-z判断,或改用[[ ]]。
字符串比较
| 写法 | 含义 | 备注 |
|---|---|---|
[ "$a" = "$b" ] |
字符串等于 | 等号两边要有空格 |
[ "$a" != "$b" ] |
字符串不等于 | |
[ -z "$a" ] |
字符串为空 | zero |
[ -n "$a" ] |
字符串不为空 | not zero |
name="oldboy"
if [ "$name" = "oldboy" ]; then
echo "相等"
fi
if [ -z "$name" ]; then
echo "变量为空"
fi
用途:不方便用数字表达的判断,例如服务状态 active、enabled,系统发行版名称等。
逻辑运算
| 运算 | 写法 | 含义 |
|---|---|---|
| 与 | -a |
多个条件同时成立 |
| 或 | -o |
任意一个条件成立 |
| 非 | ! |
取反 |
# 70 <= disk < 80
if [ "$disk" -ge 70 -a "$disk" -lt 80 ]; then
echo "警告"
fi
# 200 或 301 或 302
if [ "$status" -eq 200 -o "$status" -eq 301 -o "$status" -eq 302 ]; then
echo "正常"
fi
# 取反:目录不存在
if [ ! -d /backup ]; then
echo "目录不存在"
fi
-a/-o在[]中可用,但可读性差;条件复杂时优先用[[ ]]的&&/||。
[ ]与[[ ]]的区别
| 能力 | [ ] / test |
[[ ]] |
|---|---|---|
正则匹配 =~ |
不支持 | 支持 |
| 逻辑运算 | -a、-o |
&&、` |
| 数值比较 | -eq -ne -gt -ge -lt -le |
同样支持 |
| 字符串比较 | =、!= |
==、!=,且 == 支持通配符 |
>、< |
容易被当成重定向 | 字符串按字典序比较 |
<=、>= |
不支持 | 不支持(坑) |
| 变量为空/含空格 | 容易因分词出错 | 更安全,不进行分词 |
| 可移植性 | POSIX,通用 | bash 扩展 |
# [] 不支持正则
[ "$num" =~ ^[0-9]+$ ] # 报错/不可用
# [[ ]] 支持正则;右边不要加引号
[[ "$num" =~ ^[0-9]+$ ]] && echo "是数字"
#复杂一点时用 { } 包起来
[[ "$port" =~ ^[0-9]+$ ]] || {
echo "Usage: port error"
exit 2
}
常见坑
-
中括号没有空格
[$# -eq 0] # 错 [ $# -eq 0 ] # 对 -
变量不引用
[ $name = "oldboy" ] # name 为空时变成 [ = oldboy ],报错 [ "$name" = "oldboy" ] # 对 -
把
%当成数字percent=`df -h / | awk 'NR==2{print $(NF-1)}'` echo $percent # 60% [ $percent -ge 70 ] # 报错:需要整数表达式解决:去掉
%再比较percent=`df -h / | awk -F '[ %]+' 'NR==2{print $(NF-1)}'` echo $percent # 60 -
[]里直接写>、<[ $a > $b ] # 被当成重定向,可能创建文件 [ $a -gt $b ] # 对 -
小数比较
[ 1.5 -gt 1 ] # 报错:整数表达式 echo "1.5 > 1" | bc # 用 bc
if 判断
单分支:条件成立才执行,常用于脚本开头的参数/环境检查。
if [ 条件 ]; then
命令
fi
双分支:成功/失败两种情况。
if [ 条件 ]; then
命令1
else
命令2
fi
多分支:多个区间/多种情况。
if [ 条件1 ]; then
命令1
elif [ 条件2 ]; then
命令2
else
命令3
fi
案例:SSH 优化检查
检查 /etc/ssh/sshd_config:
- 文件是否存在、是否 root 运行(略,按前面模板补);
- 端口是否还是 22;
- 是否允许 root 远程登录(
PermitRootLogin); - 是否开启 DNS 反向解析(
UseDNS)。
file=/etc/ssh/sshd_config
# 1.检查端口
port_count=`egrep -v '^$|#' $file | grep -i '^port' | wc -l`
port_num=`egrep -v '^$|#' $file | grep -i '^port' | awk '{print $2}'`
if [ $port_count -eq 0 ]; then
echo "ssh 服务端口是默认的 22 端口,请修改"
else
if [ $port_num -eq 22 ]; then
echo "ssh 服务端口是默认的 22 端口,请修改"
else
echo "ssh 服务端口已经修改,$port_num"
fi
fi
# 2.检查 root 远程登录
root_login=`egrep -v '^$|#' $file | grep -i '^permitrootlogin' | awk '{print $2}'`
if [ "${root_login}" = "yes" ]; then
echo "系统准许 root 远程登录,请优化"
else
echo "系统不准许 root 远程登录"
fi
# 3.检查 UseDNS
use_dns=`egrep -v '^$|#' $file | grep -i '^usedns' | awk '{print $2}'`
if [ "${use_dns}" = "no" ]; then
echo "禁止 DNS 反向解析,已经禁止"
else
echo "禁止 DNS 反向解析,没有禁止"
fi
关键点:
egrep -v '^$|#':去掉空行和注释行。grep -i '^port':忽略大小写匹配以port开头的行。awk '{print $2}':取第二列的值。- 没有
Port行时,SSH 默认就是 22。
案例:检查服务是否运行、是否开机自启
name="$1"
if [ $# -eq 0 ]; then
echo "Usage: bash $0 server_name"
exit 1
fi
run=`systemctl is-active $name`
if [ "$run" = "active" ]; then
echo "$name service is running"
else
echo "$name service is stopped"
fi
startup=`systemctl is-enabled $name`
if [ "$startup" = "enabled" ]; then
echo "$name service is enabled"
else
echo "$name service is disabled"
fi
关键命令:
systemctl is-active 服务名 # active / inactive / failed
systemctl is-enabled 服务名 # enabled / disabled
案例:ping、telnet、curl 三层检查
curl 常用选项:
| 选项 | 作用 |
|---|---|
-I |
只取响应头(HEAD 请求) |
-s |
静默模式,不显示进度/错误 |
-w '%{http_code}' |
只输出 HTTP 状态码 |
-o /dev/null |
丢弃响应正文 |
取状态码:
curl -Is 10.0.0.200/lidao.txt | awk 'NR==1{print $2}'
# 404
curl -s -w '%{http_code}' -o /dev/null 10.0.0.200/lidao.txt
# 404
判断 200/301/302 都算正常:
status=`curl -Is $url | awk 'NR==1{print $2}'`
if [ $status -eq 200 -o $status -eq 301 -o $status -eq 302 ]; then
echo "$url 7层页面 ok"
else
echo "$url 7层页面 failed"
fi
案例:嵌套
一个 if 里面再套一个 if:
if [ 条件1 ]; then
if [ 条件2 ]; then
echo "条件1和条件2都成立"
else
echo "条件1成立,条件2不成立"
fi
else
echo "条件1不成立"
fi
能用一个 -a 表达时优先扁平化:
if [ 条件1 -a 条件2 ]; then
echo "都成立"
fi
需要“内层判断依赖外层结果”时,才用嵌套。
案例:检查指定端口是否存在
#!/bin/bash
##############################################################
# File Name: 09.check_port_exist.sh
# Version: V1.0
# Author: lidao996
# Description: 检查本机端口是否在监听
##############################################################
port=$1
# 1.检查参数是否为数字
if [[ ! "$port" =~ ^[0-9]+$ ]]; then
echo "Usage: bash $0 port"
exit 1
fi
# 2.统计端口出现次数
port_count=`ss -Lntup | awk '{print $5}' | awk -F: '{print $NF}' | grep -w "$port" | wc -l`
# 3.判断
if [ $port_count -ne 0 ]; then
echo "$port 端口存在"
ss -Lntup | grep -w $port | awk '{print $NF}'
else
echo "$port 不存在"
fi
要点:
ss -Lntup:-L监听状态、-n数字端口、-tTCP、-uUDP、-p显示进程(通常需要 root)。awk '{print $5}'取本地地址列(如0.0.0.0:80、[::]:22)。awk -F: '{print $NF}'取最后一个冒号后的端口号。grep -w "$port"精确匹配端口,避免80匹配到8080。- 检查远程端口通不通,用
nc -zv 主机 端口,再用$?判断。
案例:根分区磁盘空间分级告警
需求:根分区使用率分档输出。
| 使用率 | 输出 |
|---|---|
| 70% ~ 79% | 警告 |
| 80% ~ 89% | 紧急 |
| 90% ~ 94% | 严重 |
| 95% 及以上 | 灾难 |
| 其他 | 正常 |
# 1.获取根分区使用率(去掉 %)
root_usage=`df -h / | awk -F '[ %]+' 'NR==2{print $(NF-1)}'`
# 2.多分支判断
if [ $root_usage -ge 70 -a $root_usage -lt 80 ]; then
echo "磁盘空间不足,警告,$root_usage"
elif [ $root_usage -ge 80 -a $root_usage -lt 90 ]; then
echo "磁盘空间不足,紧急,$root_usage"
elif [ $root_usage -ge 90 -a $root_usage -lt 95 ]; then
echo "磁盘空间不足,严重,$root_usage"
elif [ $root_usage -ge 95 ]; then
echo "磁盘空间不足,灾难,$root_usage"
else
echo "磁盘正常:$root_usage"
fi
课件截图里最低档写的是
-ge 60,文字需求写的是 70;上面按 70 整理,实际可自行调整阈值。
for 循环
语法
for 变量 in 值列表
do
命令
done
值列表的常见形式:
for num in {1..10}; do
echo $num
done
for num in `seq 15 20`; do
echo $num
done
for name in lidao oldboy 1 2 3 4 {1..10} `ls`; do
echo $name
done
推荐用 $( ) 代替反引号:
for num in $(seq 15 20); do
echo $num
done
案例:把 ping/telnet/curl 检查改成 for 循环
需求:一次检查多个 URL。
#!/bin/bash
##############################################################
# File Name: 13.check_url_v4_for.sh
# Version: V1.0
# Author: lidao996
# Description: for 循环批量检查 URL
##############################################################
# 1.变量:所有参数
urls="$*"
# urls="`cat /server/scripts/url.txt`"
# 2.检查参数
if [ -z "$urls" ]; then
echo "Usage: $0 域名"
exit 1
fi
# 3.检查依赖命令
which telnet nc nmap >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "命令不存在,请安装"
exit 2
fi
# 4.循环检查
for url in $urls
do
# 4.1 三层:ping
echo "1.ping检查:$url"
ping -c 2 ${url} >/dev/null 2>&1
if [ $? -eq 0 ]; then
echo "ping $url ok"
else
echo "ping $url failed"
fi
# 4.2 四层:端口
echo "2.检查端口$url 80"
nc -zv ${url} 80 >/dev/null 2>&1
if [ $? -eq 0 ]; then
echo "port $url 80 ok"
else
echo "port $url 80 failed"
fi
# 4.3 七层:HTTP 状态码
echo "3.检查web页面:$url"
status=`curl -Is $url | awk 'NR==1{print $2}'`
if [ $status -eq 200 -o $status -eq 301 -o $status -eq 302 ]; then
echo "$url 7层页面 ok"
else
echo "$url 7层页面 failed"
fi
done
要点:
urls="$*"把所有参数拼成一个字符串。for url in $urls默认按空格/换行拆分。- 如果参数本身含空格,应改用数组:
urls=("$@"),再for url in "${urls[@]}"(补充)。
案例:批量检查磁盘分区
需求:从 /etc/fstab 取出所有挂载点,逐个用 df -h 检查。
#!/bin/bash
##############################################################
# File Name: 14.check_part.sh
# Version: V1.0
# Author: lidao996
# Description: 批量检查磁盘分区
##############################################################
# 1.取出挂载点:排除空行、注释、swap
parts=`egrep -v '^$|#|swap' /etc/fstab | awk '{print $2}'`
# 2.循环
for part in $parts
do
part_fs=`df -h $part | awk 'NR==2{print $1}'`
part_name=`df -h $part | awk 'NR==2{print $NF}'`
part_size=`df -h $part | awk 'NR==2{print $2}'`
part_percent=`df -h $part | awk 'NR==2{print $(NF-1)}'`
cat <<EOF
磁盘分区巡检-磁盘:$part_fs
磁盘分区挂载点: $part_name
磁盘分区大小: $part_size
磁盘分区使用率: $part_percent
EOF
done
要点:
egrep -v '^$|#|swap':过滤空行、注释、swap。awk '{print $2}':fstab 第二列是挂载点。df -h第二行才是数据行,所以NR==2。$(NF-1)取倒数第二列,即使用率。
40
case
case "$var" in
pattern1)
命令1
;;
pattern2|pattern3)
命令2
;;
*)
默认命令
;;
esac
要点:
case适合离散的菜单选择,不适合范围比较。- 每个分支以
;;结束(最后一个分支可省略,但建议写)。 |表示多个模式共用一段逻辑。*是兜底分支。case常与read -p、source搭配。
案例:安装菜单
cat <<EOF
安装脚本
1.安装 nginx
2.安装 mysql
3.安装 prometheus
4.安装 grafana
5.安装 jumpserver
EOF
read -p "请选择:" num
case "$num" in
1) echo 安装nginx ;;
2) echo 安装mysql ;;
3) echo 安装prometheus ;;
4) echo 安装grafana ;;
5) echo 安装jumpserver ;;
*) echo "输入错误,请重新输入" ;;
esac
read -p:交互式创建变量,-p 后面是提示语。
案例:判断系统发行版本
方式一:hostnamectl
os_name=`hostnamectl | grep -i 'Operating System' | awk '{print $3}'`
case "$os_name" in
Kylin|Rocky|CentOS) echo 使用yum安装 ;;
Debian|Ubuntu) echo 使用apt安装 ;;
*) echo "未识别的系统,请手动检查" ;;
esac
方式二:source /etc/os-release(更稳)
source /etc/os-release
case "$ID" in
kylin|rocky|centos) echo 使用yum安装 ;;
debian|ubuntu) echo 使用apt安装 ;;
*) echo "未识别的系统,请手动检查" ;;
esac
source 的作用:
source /etc/os-release # 把文件里的变量加载到当前 shell
source /etc/profile # 让环境变量配置立即生效
区别:
source file/. file:在当前 shell 执行,变量会保留。bash file/sh file:开子 shell 执行,变量默认不影响当前 shell。
while
while 条件
do
命令
done
条件成立就继续循环,不成立就退出。
num=0
while [ $num -lt 10 ]
do
echo $num
let num=num+1
done
等价写法:
num=0
while [ $num -lt 10 ]
do
echo $num
((num++))
done
死循环
while true
do
命令
sleep 5
done
或:
while :
do
命令
done
用途:定时巡检、每隔 N 秒检查一次。
while读取文件
方案一(推荐):输入重定向
while read line
do
echo "$line"
done < 文件名
方案二:管道
cat 文件名 | while read line
do
echo "$line"
done
方案三:exec 重定向(少用)
exec < 文件名
while read line
do
echo "$line"
done
多列读取:
while read user pass
do
echo "用户:$user 密码:$pass"
done < user.txt
注意:
read user pass按空格/TAB 分列,最后一个变量会拿到剩余内容。- 管道方案会开子 shell,循环里修改的变量在循环结束后可能拿不到;需要保留变量时用方案一或进程替换。
案例:批量添加用户并设置密码
user.txt 格式:
lidao 123456
oldboy 654321
脚本:
#!/bin/bash
##############################################################
# File Name: 17.useradd.sh
# Version: V1.0
# Author: lidao996
# Description: 从文件批量创建用户
##############################################################
file=/server/scripts/user.txt
while read user pass
do
# 1.创建用户
useradd -s /bin/bash -m $user
# 2.设置密码
echo $pass | passwd --stdin $user
# 3.输出
echo "用户$user 密码$pass"
done < $file
注意:passwd --stdin 是 RedHat 系用法;Debian/Ubuntu 可用 echo "$user:$pass" | chpasswd。
循环控制语句
| 语句 | 作用 |
|---|---|
break |
打断并结束当前循环 |
continue |
跳过本次循环,进入下一次 |
exit |
结束整个脚本 |
return |
结束函数,并设置函数返回值 |
# break:到 4 就停
for n in {1..10}
do
[ $n -eq 4 ] && break
echo $n
done
# continue:跳过 4
for n in {1..10}
do
[ $n -eq 4 ] && continue
echo $n
done
区别:
break/continue只影响循环。exit直接退出脚本,后面的代码都不执行。return只用于函数,返回状态码给调用者。
41
计算操作
常用方案
| 方案 | 适用 | 示例 |
|---|---|---|
let |
整数 | let i=i+1、let i++ |
$(( )) |
整数 | num=$((RANDOM%100+1)) |
$[ ] |
整数(旧写法) | echo $[1+2] |
expr |
整数(旧) | expr 1 + 2 |
bc |
小数 | echo "scale=2;10/3" | bc -l |
awk |
小数 | awk 'BEGIN{print 10/3}' |
i=1
let i=i+1 # 2
let i++ # 3
let sum+=1
num=$((RANDOM%100+1))
echo $((1+2*3)) # 7
expr 注意空格:
expr 1 + 2 # 3
expr 1+2 # 输出 1+2(错误)
bc 控制小数位数
echo "scale=2;10/3" | bc -l
# 3.33
echo "10/3" | bc -l
# 3.33333333333333333333
num1=10
num2=3
echo "$num1/$num2" | bc -l
# 3.33333333333333333333
scale=2:保留小数点后 2 位。-l:加载数学库,支持更多运算。bc默认做整数除法,要小数必须设置scale或用-l。
awk 计算
num1=10
num2=20
awk -v n1=$num1 -v n2=$num2 'BEGIN{print n1,n2}' # 10 20
awk -v n1=$num1 -v n2=$num2 'BEGIN{print n1/n2}' # 0.5
计算内存空闲率:
free -m | awk 'NR==2{print $NF/$2*100"%"}'
# 63.866%
案例:域名过期检查
思路:
- 获取域名;
whois取过期时间;- 过期日期转秒;
- 当天日期转秒;
- 相减除以 86400 得天;
- 判断剩余天数是否 ≤ 30。
#!/bin/bash
##############################################################
# File Name: 19.check_domain.sh
# Version: V1.0
# Author: lidao996
# Description: 检查域名剩余天数
##############################################################
name=$1
# 1.参数检查
if [ -z "$name" ]; then
echo "Usage: bash $0 domain"
exit 1
fi
# 2.root 检查
if [ $UID -ne 0 ]; then
echo "使用 root 运行"
exit 2
fi
# 3.命令检查
which whois >/dev/null 2>&1
if [ $? -ne 0 ]; then
# Kylin 用 jwhois;Rocky/CentOS 用 whois;Ubuntu/Debian 用 whois
yum install -y jwhois >/dev/null 2>&1
if [ $? -eq 0 ]; then
echo "命令安装成功"
else
echo "命令安装失败"
exit 3
fi
fi
# 4.取过期时间
expire_date=`whois ${name} | egrep 'Expiration (Date|Time)' | awk -F ': ' '{print $NF}'`
expire_date_seconds=`date -d "$expire_date" +%s`
now_seconds=`date +%s`
days_left=`echo "($expire_date_seconds-$now_seconds)/86400" | bc`
# 5.判断
if [ $days_left -le 30 ]; then
echo "$name 域名,剩余时间不足,请续费,还剩 $days_left 天"
else
echo "$name 域名,一切正常,还有 $days_left 天过期"
fi
关键命令:
whois baidu.com | grep 'Expiration Date' | awk '{print $NF}'
date -d "2028-10-11T11:05:17+0000" +%s # 日期转秒
date +%s # 当前时间秒
echo "(1854875117-1770101817)/86400" | bc # 相差天数(整数)
注意:
- 不同 whois 服务器字段可能是
Expiration Date或Expiration Time,所以用egrep 'Expiration (Date|Time)'。 - 麒麟系统 whois 软件包叫
jwhois。
函数
- 把重复逻辑封装成一个“自定义命令”;
- 脚本更模块化、更专业;
- 可以建立自己的函数库。
注意事项:
- 函数名不要和系统命令重名。
- 函数必须先定义,再调用。
三种定义格式
# 方法一
function 函数名() {
命令
return $?
}
# 方法二
函数名() {
命令
return $?
}
# 方法三
function 函数名 {
命令
return $?
}
调用:
函数名 参数1 参数2
return:
- 返回 0~255 的状态码;
- 调用后用
$?获取; - 不写
return时,函数返回最后一条命令的状态码。
函数传参
函数内部:
$1、$2... 是函数的参数,不是脚本参数;$#是函数参数个数;$*/$@是函数的所有参数;$0仍然是脚本名。
#!/bin/bash
function show() {
name=$1
echo "参数个数:$#"
echo "所有参数:$*"
echo "所有参数:$@"
echo "$name.cn"
echo "$name.org"
echo "$name.com"
return $?
}
show $*
bash show.sh lidao
# 参数个数:1
# 所有参数:lidao
# 所有参数:lidao
# lidao.cn
# lidao.org
# lidao.com
脚本 vs 函数:
| 特殊符号 | 脚本中 | 函数中 |
|---|---|---|
$n |
脚本第 n 个参数 | 函数第 n 个参数 |
$0 |
脚本名 | 仍是脚本名 |
$* |
脚本所有参数 | 函数所有参数 |
$@ |
脚本所有参数 | 函数所有参数 |
$# |
脚本参数个数 | 函数参数个数 |
补充:函数内变量默认是全局的;需要局部变量时用 local name=value。
$* 与 $@ 的区别
不加引号时,两者都会分词,行为基本一样;加双引号后区别明显:
#!/bin/bash
# $*
for i in "$*"
do
echo "star:$i"
done
# $@
for j in "$@"
do
echo "at:$j"
done
执行:
bash test.sh a b c
输出:
star:a b c
at:a
at:b
at:c
结论:
| 写法 | 结果 |
|---|---|
"$*" |
所有参数拼成一个整体,循环只执行 1 次 |
"$@" |
每个参数独立,循环执行 N 次 |
$* / $@(不加引号) |
都按空格拆分,通常等价 |
echo颜色
function redecho() {
local str="$*"
echo -e "\E[1;31m${str}\E[0m"
return $?
}
function greenecho() {
local str="$*"
echo -e "\E[1;32m${str}\E[0m"
return $?
}
function yellowecho() {
local str="$*"
echo -e "\E[1;33m${str}\E[0m"
return $?
}
function blueecho() {
local str="$*"
echo -e "\E[1;34m${str}\E[0m"
return $?
}
案例知识点
| 案例 | 核心知识点 |
|---|---|
| SSH 优化检查 | 文件判断、grep/awk、字符串比较 |
| 检查服务运行/自启 | systemctl is-active、is-enabled |
| ping/telnet/curl 检查 | curl -Is、HTTP 状态码、-o /dev/null |
| 嵌套 | if 嵌套 |
| 端口检查 | 正则、ss -Lntup、nc -zv |
| 根分区磁盘检查 | 多分支 if、df/awk 去 % |
| 判断系统发行版本 | case、source /etc/os-release |
| 改造 ping/telnet/curl | for、$*、批量 URL |
| 批量检查磁盘分区 | for、/etc/fstab、df -h |
| 每 5 秒检查磁盘 | while true、sleep 5 |
| 批量添加用户 | while read、useradd、passwd --stdin |
| 日志统计分析 | awk/sort/uniq、while read、mail |
| 猜数字 | RANDOM、while、continue/break |
| 域名过期检查 | whois、date +%s、bc |
| 函数化改造 | function、return、main |