2026-11-01

笔记 · 2026-11-01

Linux笔记

Linux笔记

1

虚拟网络配置器

改子网

NAT设置:改网关

DHCP:自动配IP区间

2

网络模式

桥接模式:物理机与虚拟机同级 公用一个局域网

NAT模式:虚拟机虚拟化出一个局域网与外界隔离

安装ubuntu系统注意事项

安装之前断开NAT

pick a username是登录用户名

开启openssh

远程连接排查逻辑

b36aad7afd6c0404630fc9d9a654ba

提示符与命令 & 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远程连接排查流程

78822805327

  1. vmnet8 ==>> 已连接 ==>> 10.0.0.1
  2. 虚拟网络编辑器 3 虚拟机本身网卡 4)看22端口 ss -lnt

局域网上网排查流程

17DC47C1D7960776C3D6BAEEE3E2DA

用户上网流程

9b041c8c0bba037de3b5bc3136dfa2

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 #创建系统用户

78883476339

linux三大用户类型

超级用户 普通用户 虚拟用户
实例 root oldboy nobody
UID范围i 0 1000-60000 1-999
shell /bin/bash /bin/bash /sbin/nologin

最小化原则

原则 说明
① 安装软件最小化 不装多余的软件包
② 登录安全最小化 使用普通用户登录,不用root,且可以用sudo基于命令设置权限
③ 进程启动权限最小化 用虚拟用户启动服务
④ 权限最小化 给最小的必要权限

用户组

  1. 自动产生: 创建用户时自动生成同名组(如创建oldboy → 生成oldboy组,UID=GID)
  2. 手动创建: 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)接管

![img](file:///D:\Users\18260\Documents\Tencent Files\1826056618\nt_qq\nt_data\Pic\2026-10\Ori\f0330243edfd61d1e93ce9137a921ba9.png) 僵尸不能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剪枝

79042611178

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与数据传输

79249441059

网站无法访问排查流程

网络层ping/traceroute/tracert
传输层ss/telnet/nc
应用层curl/wget
服务日志

用户访问百度流程

  1. DNS解析出目标ip
  2. tcp建立连接三次握手
  3. http/s请求与响应
  4. 断开连接四次挥手

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
}

常见坑

  1. 中括号没有空格

    [$# -eq 0]      # 错
    [ $# -eq 0 ]    # 对
    
  2. 变量不引用

    [ $name = "oldboy" ]      # name 为空时变成 [ = oldboy ],报错
    [ "$name" = "oldboy" ]    # 对
    
  3. 把 % 当成数字

    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
    
  4. [] 里直接写 >、<

    [ $a > $b ]               # 被当成重定向,可能创建文件
    [ $a -gt $b ]             # 对
    
  5. 小数比较

    [ 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:

  1. 文件是否存在、是否 root 运行(略,按前面模板补);
  2. 端口是否还是 22;
  3. 是否允许 root 远程登录(PermitRootLogin);
  4. 是否开启 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 数字端口、-t TCP、-u UDP、-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%

案例:域名过期检查

思路:

  1. 获取域名;
  2. whois 取过期时间;
  3. 过期日期转秒;
  4. 当天日期转秒;
  5. 相减除以 86400 得天;
  6. 判断剩余天数是否 ≤ 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