2

[TOC]

网络管理

关于网络状态常用工具包

  • net-tools 工具包

    • ifconfig 命令
    • route 命令
    • netstat 命令
  • iproute2 工具包

    • ip 命令
    • ss 命令
  • iputils-ping

    • ping 命令

      很多精简的容器中没有安装该工具

centos 7之前常用 net-tools 工具包, 在centos 7及之后则主推 iproute2 工具包.

网络接口

命名规则

概念上, 网络接口名和网卡名在我看来指的是同一个东西.

网络接口(网卡)可能的命名

  • eno1(板载网卡)
  • ens33(PCI-E网卡)
  • enp0s3(无法获取物理信息的PCI-E网卡)
  • eth0

    CentOS 7 使用了一致性网络设备命名, 在以上都不匹配时使用 eth0

eth0 网卡

eth0 通常指第一张网卡, 但有时候配置原因, 并不叫 eth0, 因此为了管理方便, 通常会将网卡名转换成一致的 eth0.

操作步骤如下:

  1. 编辑 /etc/default/grub 文件

    ......
    
    # 默认的配置项
    GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rghb quiet"
    # ↓
    # 在末尾追加配置, 修改后的值如下
    # ↓
    GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rghb quiet biosdevname=0 net.ifnames=0"
    
    ......
  2. 更新 grub 实际的配置

    grub2-mkconfig -o /boot/grub2/grub.cfg
    
    选项
        -o, --output        指定生成的文件的位置
  3. 重启

    reboot
  4. 此时网卡名就变成了 eth0

网卡命名规则受 biosdevnamenet.ifnames 两个参数影响

biosdevnamenet.ifnames网卡名
默认01ens33
组合110em1
组合200eth0

如果一开始的网卡名并非 eth0 , 但通过修改 /etc/default/grub 等相关配置来修改网卡名为 eth0 后, 对应的 ifcfg-* 文件名需要手动修改成 ifcfg-eth0, 包括里面的配置项.

网络配置

mii-tool 命令

查看网卡物理连接状态

mii-tool [<网卡名>]

注意
    CentOS 6 无需写网卡名(接口), 直接执行即可
    CentOS 7 需要指定网卡名(接口)才能查看状态
    虚拟机上可能无法执行(云主机也是), 会报错.

ifup 命令

启用网卡

ifup <接口>

ifdown 命令

禁用网卡

ifdown <接口>

ifconfig 命令 ⭐

属于 net-tools 工具包.

注意: 使用 ifconfig 修改配置由于没有写入配置文件, 因此仅限档次有效, 重启后失效.

配置网络接口


ifconfig                                      # 显示当前有效网络接口状态
ifconfig <接口>                                # 显示指定网络接口状态
ifconfig <接口> <IP地址> [netmask <子网掩码>]        # 设置指定网络接口
                                                 # 子网掩码省略时会默认设置为 255.0.0.0
                                                 # !!! 注意, 操作云主机时会导致掉线且无法重连. 需要到网页控制台打开ssh连接改回来
ifconfig <接口> up                            # 启用该网卡, 等价于 ifup <接口>
ifconfig <接口> down                            # 禁用该网卡. 等价于 ifdown <接口>


网卡
    eth0    # 第一块网卡(网络接口)
    lo        # 本地环回

显示字段解释
    ether XX:XX:XX:XX:XX:XX        # 网卡的MAC地址

route 命令

属于 net-tools 工具包.

网关配置命令

route [选项]

常用
    route -n                                               # 查看当前路由规则
    route add default gw <网关ip>                             # 添加默认网关
    route del default gw <网关ip>                             # 删除默认网关
    
    route add -host <指定ip> gw <网关ip>                    # 添加一条路由规则
    route add -net <指定网段> netmask <子网掩码> gw <网关ip>    # 添加一条路由规则
    

选项
    -n    不解析主机名(默认解析主机名会比较慢)

ip 命令

属于 iproute2 工具包

ip命令是 ifconfig, route, ifup, ifdown 的命令集合体

注意: 使用 ip修改配置由于没有写入配置文件, 因此仅限档次有效, 重启后失效.

网络配置命令

ip addr [ls]                        # 等价 ifconfig
ip addr add 10.0.0.1/24 dev eth1    # 等价 ifconfig eth1 10.0.0.1 netmask 255.255.255.0

ip link set dev eth0 up                # 等价 ifup eth0 以及 ifconfig eth0 up

ip route add 10.0.0.0/24 via 192.168.0.1    # 等价于 route add -net 10.0.0.0 netmask 255.255.255.0 gw 192.168.0.1

网络故障排除

首先检测与目标主机网络是否畅通

  1. 首先使用 ping 确认与目标主机连接
  2. 如果 ping 不同, 则可以用 traceroutemtr 检查中间的路由情况
  3. 如果 ping 不同, 可以用 nslookup 确认域名是否解析正常

确认端口状态

  1. 使用 telnet 检查端口连接状态
  2. 使用 tcpdump 详细分析数据包

确认服务状态

  1. 使用 netstatss

ping 命令 ⭐

通过发送ICMP报文, 检测与目标主机是否畅通

ping <地址>
所属包: inetutils-ping

traceroute 命令

用于辅助 ping 命令, ping不通的时候追踪每一跳路由.

若是中间部分节点不支持 traceroute 的, 则会显示为 *

检测当前主机到目标主机的路由状况

traceroute [选项] <目标主机>

示例
    traceroute -w 1 <目标主机>

选项
    -w <waittime>, --wait=<waittime>    超时等待时间, 默认5秒

mtr 命令 ⭐

用于辅助 ping 命令, ping不通的时候检测到目标主机的数据包是否有丢失.

相较 traceroute 显示的内容更丰富, 建议使用 mtr 来确定是否丢包, 它是 ping, nslookup, traceroute 的结合体

网络诊断工具 My traceroute

mtr [选项] <目标主机>

选项
    -n, --no-dns                            不解析主机名, 强制显示为ip
    -c <count>, --report-cycles <COUNT>        设置发送ping包的数量
    -r, --report                            通常配合 -c (若未指定则默认10次), 在发送完指定包后以报告形式展示结果.


显示结果说明
                Packets                                Pings(延迟 ms)
    Host    Loss%    Snt                Last        Avg        Best    Wrst    StDev
    ip地址   丢包率    ?                最后一次      平均     最佳     最差    标准偏差(衡量数值偏离平均值的程度, 越小则偏差越小)
部分显示丢失可能是由于icmp保护机制造成的, 并不代表真的丢包.

同时只有最后的目标丢包才算真正的丢包???

nslookup 命令

查询域名对应的ip

nslookup <域名>

dig 命令

发送域名查询信息包到域名服务器

dig <域名>

telnet 命令 ⭐

检查端口连接状态

telnet <主机> <端口>


注意:
    如果是在非交互式调用 telnet 时, 需要预留时间用于连接和数据传输, 示例:
    (usleep 100000; echo "info"; usleep 100000;) | telnet 127.0.0.1 6379

tcpdump 命令 ⭐

网络抓包工具

tcpdump [选项] <表达式>

选项
    -i <interface>    监听网络接口(网卡), 不指定时默认eth0.
                    "any" 表示监听所有
    -n                不进行域名解析, 而是显示ip
    -w <文件名>      将抓包结果保存到指定文件, 可以用 wireshark 图形化工具来查看该文件内容.
    -s <字节>          从每个截取指定长度字节的数据, 而不是默认的68字节.
    
表达式
    port <端口>        指定监听端口
    host <主机>        指定监听主机
    
    逻辑表达式
    and                 逻辑与, 比如 port 80 and host 10.0.0.1
    
示例
    telnet -i any port 23 -s 1500 -w /tmp/a.dump        # 抓取 telnet 的包
    
    
Flags 说明
    S        SYN
    F        FIN
    R        RST
    P        PUSH
    U        URG
    W        ECN CWR
    E        ECN-Echo
    .        ACK
    none    未设置Flags
# 安装图形化工具的 wireshark
yum install wireshark-gnome

netstat 命令 ⭐

属于 net-tools 工具包.

显示网络连接, 接口状态等信息

netstat [选项]

选项
    显示格式
    -n, --numeric        显示ip, 而不是对应的域名    
    -p, --program        显示对应的进程
    
    筛选
    -t, --tcp            筛选TCP
    -u, --udp            筛选UDP
    -l, --listening        只显示处于监听状态的

ss 命令

属于 iproute2 工具包

vs netstat

一个socket查看工具

ss [选项]

选项
    显示格式
    -n, --numeric        显示ip, 而不是对应的域名    
    -p, --program        显示对应的进程
    
    筛选
    -a, --all            显示处于listening和non-listening的socket(对于TCP则包含ESTABLISHE连接)
    -t, --tcp            显示TCP socket
    -u, --udp            显示UDP socket
    -l, --listening        筛选查看处于监听状态的

网络服务管理

网络服务管理程序分为两种:

  • SysV (也叫 Sys 5)

    CentOS 6 使用
  • systemd

    CentOS 7 使用

network服务和NetworkManager服务:

  • network服务是centos6的网络默认管理工具, network只能支持 service 来管理.
  • centos7重写了一遍就是NetworkManager服务,centos7默认的服务管理工具换成了systemctl.

    若是为了向下兼容, 可以禁用NetworkManager.

    systemctl disable NetworkManager.service

网络配置文件

ifcfg-*

/etc/sysconfig/network-scripts/ifcfg-* 网络配置文件(随真实网卡名称变化, 比如 ifcfg-eth0)

注意:

  1. 使用 ipipconfig 命令修改网络配置由于并未写入配置文件, 因此仅限当此有效, 重启后还是以配置文件的为准.
  2. 如果一开始的网卡名并非 eth0 , 但通过修改 /etc/default/grub 等相关配置来修改网卡名为 eth0 后, 对应的 ifcfg-* 文件名需要手动修改.

有可能出现一个网络配置文件里面配置多个网卡的情况

ifcfg-eth0 动态(DHCP)配置文件示例

TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no

# dhcp: 动态分配
# none 或 static: 静态分配
BOOTPROTO=dhcp
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INT=yes
IPV6_AUTOCONF=YES
IPV6_DEFROUTE=YES
IPV6_FAILURE_FATAL=NO
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=eth0
UUID=xxxxxxxxxxxxxxxxx
DEVICE=eth0
ONBOOT=YES

ifcfg-eth0 的静态配置示例(需重点掌握)

TYPE=Ethernet
NAME=eth0
DEVICE=eth0
UUID=xxxxxxxxxxxxxxxxxxxxxx
ONBOOT=YES

# dhcp:动态分配
# none:静态分配
BOOTPROTO=none
IPADDR=10.211.55.3
NETMASK=255.255.255.0
GATEWAY=10.211.5.1
DNS1=114.114.114.114
DNS2=8.8.8.8
DNS3=8.8.4.4
UUID 可以通过 nmcli con 查看
hostname 命令

主机名的构成: <主机名称>.<域名>

显示或设置当前主机名

hostname [选项]          # 查看主机名
hostname [<主机名>]      # 设置主机名, 立即生效

选项
    -s, --short            显示短格式主机名, 即 . 之前的部分
    -i, --ip-address    显示主机的IP地址
hostnamectl
控制系统主机名(写入配置, 永久生效)

hostnamectl set-hostname <主机名>
/etc/hosts

主机名相关配置, hosts文件包含了IP地址和主机名之间的映射,还包括主机名的别名。

在没有域名服务器的情况下,系统上的所有网络程序都通过查询该文件来解析对应于某个主机名的IP地址,否则就需要使用DNS服务程序来解决。通常可以将常用的域名和IP地址映射加入到hosts文件中,实现快速方便的访问。

在修改主机名后, 由于有一些程序是依赖主机名工作的, 因此需要在 hosts 文件里添加 新主机名对应ip, 否则部分依赖主机名的服务会在解析主机名时超时.

eg. 主机名修改为 yjx-pc 后, 在 /etc/hosts 文件添加一条

127.0.0.1  yjx-pc

这样

SysV 管理程序

CentOS 6 使用

service 命令


service network (start|stop|restart|status)
chkconfig 命令

chkconfig --list            # 列出所有 SysV 服务
chkconfig --list network    # 列出 network 服务

chkconfig [--level <数字级别>...] network (off|on)    # 一般 network 会保持开机启动

systemd 管理程序

CentOS 6 无法使用, 仅能在 CentOS 7 使用.

systemctl 命令
在 CentOS 7 下使用的 service 命令实际上是调用 systemctl 命令.

重要

在CentOS 7下有两套网络管理工具, 一个是 network , 另一个是 NetworkManager, 在实际工作中不要同时用两套工具管理.

CentOS 6 只有 network

建议按照个人使用习惯禁用掉其中任意一个, 在个人电脑上可能会更建议使用 Network Manager, 在接入新网络时会自动配置较为方便, 但这个功能在服务器上比较鸡肋, 因此服务器上一般是沿用 network, 因此推荐禁用掉 NetworkManager

控制 systemd 系统和服务管理器

systemctl <命令>

命令
    管理器生命周期命令
    daemon-reload                # 重新加载 systemd 管理配置

    单位(unit)命令
    start <service>
    stop <service>
    restart <service>
    reload <service>
    status <service>
    
    单位(unit)文件命令
    list-unit-files    [<unit>]        # 列出所有 systemd 服务, 或指定服务
    enable <service>
    disable <service>
Systemd 入门教程:命令篇

软件包

  • 软件包管理器
  • rpm 包 和 rpm 命令
  • yum 仓库
  • 源代码编译安装
  • 内核升级
  • grub配置文件

概念 - 包管理器

包管理器是方便软件安装、卸载、解决软件依赖关系的工具.

  • RedHat(RHEL) 系列(RedHat, Fedora, CentOS) 使用 yum 包管理器, 软件安装包格式为 rpm
  • Debian、Ubuntu 使用 apt 包管理器, 软件安装包格式为 deb.

在 RedHat 中的包管理器是 rpm 包, 它使用的是 rpm 命令.

集中存放包的地方叫做软件仓库, RedHat 中用的是 yum 仓库.

rpm 包

rpm 包格式

格式
    软件名称-软件版本.系统版本.平台.rpm

示例
    vim-common-7.4.10-5.el7.x86_64.rpm    
    
    软件名称: vim-common
    软件版本: 7.4.10-5
    系统版本: el7                # 指 Enterprise Linux 7
    平台: x86_64

rpm 包的获得方式:

  • 系统光盘 Packages/*.rpm
  • 网上下载

rpm 命令

rpm 包的问题

  • 需要自己解决依赖关系
  • 软件包来源不可靠
rpm - RedHat Package Manager

rpm [选项] <完整软件包名>

<完整软件包名> 参数不支持通配符

示例
    rpm -qa                            # 查询已安装的所有软件包

选项
    -a, --all                         # 查询/验证所有软件包
    -q, --query    [<完整软件包名>]         # 查询软件包, 若使用 -qa 则表示查询所有已安装的, 否则仅查询指定软件包. 若要模糊查询则要 -qa | grep 配合
    -l, --list                         # 列出该包的文件
    -i, --install <rpm文件>            # 安装软件包, 此时若提示依赖关系问题, 则需要先安装好被依赖的安装包. <rpm文件> 也可以指定具体的 url
    -e, --erase    <完整软件包名>...         # 卸载软件包
    -U, --upgrade <完整软件包名>         # 升级软件包, 若不存在则安装, 若已存在则会替换旧版本.
    
    -v, --verbose
    -h, --hash                         # 显示安装进度, 经常配置 -v 来显示准确的进度.
    
示例
    rpm -ql <软件报名>                  # 查看该软件包的文件列表, 比如用于查看有哪些配置文件.⭐

yum 包管理器

/etc/yum.repos.d/*

yum 命令

yum 包管理器

yum <命令>

<软件包> 参数支持通配符

示例
    yum list all|installed|available|updates            # 查看列表(默认是 all)
    yum list vim*                # 查看已安装的 vim* 安装包, 建议用这种方式来速览, 因为同时可提供当前已安装和可安装的列表.
                                # ?? 有些通过 rpm 命令直接安装的好像在这无法通过模糊查询找到

命令    
    makecache                             # 生成元数据缓存
    repolist [all|enabled|disabled]      # 查看当前已生效的源, 默认是 enabled.
    
    install <软件包>                # 安装软件包, <软件包> 支持指定本地的 rpm 文件
    remove <软件包>                # 卸载软件包
    list [<软件包>]                # 查看(所有)软件包(已安装和可安装的)    
    list <软件包> --showduplicates    #  查看软件包的各个版本, 默认只展示最新的版本
    update [<软件包>]                # 升级软件包, 若不指定"软件包"参数, 则会升级当前已安装的所有软件包.
    
    grouplist                       # 查看系列软件包列表(包含了一系列的软件)
    groupinfo <软件组>                # 查看某个具体系列软件包包含的软件列表.
    groupinstall <软件组>            # 安装系列软件包
    

常用的软件组

Development Tools            # 基本开发环境

yum-config-manager 命令

管理 yum 配置选项和仓库

yum-config-manager [选项]

选项
    --enable <repo>...        # 启用指定仓库(同时写入配置文件), 支持通配符?
    --disable <repo>...        # 禁用指定仓库(同时写入配置文件), 支持通配符?
    --add-repo <仓库地址>     # 添加并启用指定仓库, 地址可以是 url. 也可以通过 `yum install <仓库地址>`
    
示例
    yum-config-manager --add-repo https://xxxx/xx.repo        # 添加某个yum仓库
可通过 yum repolist all 确认当前有哪些仓库.

yum-config-manager 命令是由 yum-utils 包提供的

yum install -y yum-utils

yum 基础源

CentOS yum 源: http://mirror.centos.org/cent...

国内镜像: https://developer.aliyun.com/...

建议更换为国内yum镜像源

# 1. 备份旧配置
mv /etc/yum.repos.d/CentOS-Base.repo{,.backup}

# 2. 下载新的yum镜像源配置文件(选择任意一个即可)
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo            # 阿里云镜像
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo    # 163镜像

# 3. 重新生成缓存
yum makecache
注意, yum源配置文件中有的会比较激进, 因此默认通常是禁用的, 其配置文件中 enabled=0
EPEL 源

EPEL 源(Extra Packages for Enterprise Linux) 比较流行,它相当于官方 CentOS/RHEL 源仓库的一个补充.

通俗的说,EPEL 可以认为是 Linux(RHEL)及其衍生发行版的一个事实上的官方仓库。

比如 redis 在epel源才有
# 1. 安装
yum install epel-release

# 2. 生成缓存
yum makecache

或者直接用阿里的源(上面的命令不必执行)

wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum makecache
若出错, 则来个清缓存套餐 yum clean all
webtatic 源

提供最新的稳定版本的Web开发/托管软件,这些版本未在CentOS / RHEL分发版本中提供. php 也在这里面.

依赖 epel-release

比如 默认源只提供 php54 版本, 但webtatic提供了 php55, php71, php72 等高版本
# 1. 安装
rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm

# 2. 生成缓存
yum makecache
city-fan 源

city-fan源 源提供的包版本很新, 但需注意兼容性, 因此该仓库安装后默认是非启用的.(enabled=0)

比如curl版本 7.64.1, 其他源的版本没这么高
# 1. 安装
rpm -Uvh https://mirror.city-fan.org/ftp/contrib/yum-repo/city-fan.org-release-2-1.rhel7.noarch.rpm

# 2. 生成缓存
yum makecache

源代码编译安装

编译安装的一般步骤

以 openresty 为例
# 1. 下载源码包
wget https://openresty.org/download/openresty-1.15.8.1.tar.gz

# 2. 解压
tar -zxvf openresty-<VERSION>

# 3. 进入源代码目录
cd openresty-<VERSION>/

# 4. 自动配置安装所需的相关配置, 比如匹配系统当前系统, 内核版本, 编译器等等, 还可以指定安装目录等.
## --prefix=<指定安装目录>        默认是安装到 /usr/, 会分散开导致卸载不方便, 因此通常指定各自的目录.
./configure --prefix=/usr/local/openresty

# 5. 编译: 将源码编译为可执行的二进制
## -j<num>        指定用<num>个逻辑CPU来加速编译
## 
## 如果在上一阶段配置结束后提示可以用 gmake 和 gmake install(跨平台编译), 那么此处就可以用这两个命令
## 编译好的内容会先存放在 ./build 目录
make -j2

# 6. 将 ./build 目录中的文件全部安装到指定目录中
make install

编译经常需要依赖各种安装环境, 以下是部分常用的

yum install gcc gcc-c++ pcre-devel openssl-devel

*-devel 一般是指开发包

升级内核

TODO

为什么要升级内核?

uname 命令

查看系统信息

uname [选项]

默认是 -s

选项
    -a, --all            # 展示所有信息
    -r, --release        # 查看操作系统(内核)的发行版本
    -m, --machine        # 显示机器(硬件)类型, 比如32位, 64位等

rpm 方式升级内核

# 单独升级内核
yum install kernel-<内核版本>

# 升级所有已安装包(包括内核)
yum update

源代码编译安装内核

https://www.kernel.org

根分区至少要保留10G的空间.

以下以更新到内核 5.5.5 为例.

# 1. 安装依赖包
yum install gcc gcc-c++ make ncurses-devel openssl-devel elfutils-libelf-devel flex bison 

# 2. 下载并解压缩内核
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.5.5.tar.xz
tar xvf linux-5.5.5.tar.xz -C /usr/src/kernels/

# 3. 配置内核编译参数
## 也可以通过复制当前内核配置来直接使用或是在当前系统内核配置基础上进行修改
cp /boot/config-<内核版本>.<平台> ./.config
make (menuconfig|allyesconfig|allnoconfig)

# 4. 编译
## -j 可使用多个CPU来加速编译
make -j<cpu数> all

# 5. 安装内核模块 及 内核
make modules_install
make install

# 6. 重启, 启动时的引导界面(grub界面)选择新内核版本
reboot

grub

系统启动时的引导软件叫做 grub

CentOS 6 使用的是 grub 版本, 需要自己记住设置项, 手动修改配置文件.

CentOS 7 使用的是 grub2 版本, 提供了工具来方便修改, 一般不手动修改配置文件以免出错影响工具使用.

grub 相关命令

grub2-mk-config 命令
生成 grub 配置文件

grub2-mk-config [选项]

选项
    -o, --output <file>        # 指定生成的文件位置, grub默认使用的是在 /boot/grub2/grub.cfg
grub2-editenv 命令

示例
    grub2-editenv list        # 查看当前默认引导项
grub2-set-default 命令

示例
    grub2-set-default <引导序号, 从 0 开始>        # 设置默认引导项

查看所有可选择的引导项

# 按照在文件中的顺序从上到下的序号依次是 0~N
grep "^menu" /boot/grub2/grub.cfg

grub 配置文件

/etc/default/grub 基本的 配置grub 的配置文件, 一般直接修改该文件.

/etc/grub.d/ 详细的 配置grub 的配置文件, 对内核每一项进行更详细的配置, 一般不需要修改这部分的文件.

/boot/grub2/grub.cfg grub2 的实际配置文件, 一般不手动修改该配置文件以免出错.

grub2-mkconfig -o /boot/grub2/grub.cfg 使用 /etc/default/grub/etc/grub.d/ 来生成 /boot/grub2/grub.cfg 配置文件

/etc/default/grub
GRUB_TIMEOUT=5
GRUB_DEISTIBUTOR="....."

# 默认引导项, 可通过 grub2-set-default 命令来修改.
GRUB_DEFAULT=saved

GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"

# 引导时传给内核的参数
## quiet     只打印必要的输出, 在出问题需要排查时可将该参数移除掉
## rghb        以图形界面显示引导进度, 在出问题需要排查时可将该参数移除掉来显示更多的信息
GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rghb quiet biosdevname=0 net.ifnames=0"

GRUB_DISABLE_RECOVERY="true"

文件修改后若想要生效, 则需要执行以下命令来生成grub实际使用的配置文件

grub2-mkconfig -o /boot/grub2/grub.cfg

使用单用户进入系统以重置root密码

  1. 在系统启动到选择引导项时, 根据提示输入 e 来编辑所选择引导项.
  2. 找到第一个 linx16 .... 行, 此时若是 CentOS6 则在末尾追加 single (注意有个空格), 若是CentOS7则在末尾追加 rd.break
  3. 输入 Ctrl+x 启动, 此时会进入到一个命令提示符状态 switch_root:/#

    注意, 此时 系统根目录没有挂载在硬盘根下面

    此时的 / 目录是一个位于内存中虚拟的目录, 实际的硬盘根目录位于 /sysroot 下, 同时 /sysroot默认是以只读方式挂载的.
    # 1. 以 rw 模式重新挂载文件系统
    ## -o, --options <挂载选项, 以逗号分隔>
    mount -o remount,rw /sysroot
    
    # 2. 此时还是处于虚拟的文件系统, 因此需要切换到到实际的系统目录下
    ## 执行完成后命令提示符变成 sh-4.2# , 而非之前的 switch_root:/#
    chroot /sysroot
    
    # 3. 修改root密码
    echo 123456 | passwd --stdin root
    
    # 4. 关闭 SELinux
    ## 由于 SELinux 会校验 /etc/passwd 和 /etc/shadow 文件, 因此此处关闭 SELinux
    ## 生产环境一般也都会关闭 SELinux
    sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
    
    # 5. 回到虚拟的根目录环境
    exit
    
    # 6. 重启
    reboot

修改相关目录权限后开启selinux无法启动

  1. 进入单用户引导模式(即上面的通过grub引导修改 rd.break 进入)
  2. 执行 genhomedircon 给用户的home目录重新生成selinux相关的文件标签
  3. 之后就可以正常启动

或者是在根目录下创建一个文件 touch /.autorelabel, 之后 linux 会检测到该文件, 并自动进行重新检测标签, 重新打标签(约10~20分钟).

进程管理

CentOS 7 的一号进程是 systemd, CentOS 6 的一号进程是 init

进程查看

ps 命令

查看进程状态, 具体请查看 系统综合状态查看 种的 ps 小节.

pstree 命令

进程是树形结构的.

查看进程树形结构

pstree 选项 [进程=1]
 
选项
    -p        打印进程号

top 命令

请参照最下方的系统综合状态查看

进程的控制命令

调整进程的优先级

nice命令

NICE 范围从 -20~19, 值越小优先级越高, 抢占资源就越多.

以指定的优先级来执行程序

nice [选项] <Command>

选项
    -n <优先级>        # 若不指定则默认是10
renice 命令
重新设置正在运行的进程的优先级

renice [选项] <进程号>

选项
    -n, --priority <priority=10>        指定优先级(NICE)

进程的作业控制

进程的前后台切换一般称作进程的作业控制.

& 符号

通过在执行的命令末尾追加一个 &(注意有空格), 使得进程直接进入后台运行状态.

此时我们的键盘输入依旧可以被终端捕获.

执行命令 &
ctrl + z 操作

对于在当前终端在前台执行的作业, 可以通过 ctrl+z 按键使该作业转入后台并挂起, 作业状态变为 S(stopped)/

可以通过 jobs 查看到作业序号, 再通过 fgbg 将该作业调到前台或后台执行.

jobs 命令

jobs 是 shell 内嵌的.

显示作业状态

jobs [选项]

选项
    -l        额外打印出进程号
fg 命令

fg 是 shell 内嵌的.

恢复作业, 令作业在前台执行

fg <作业序号>
bg 命令

bg 是 shell 内嵌的.

恢复作业, 令作业在后台执行

bg <作业序号>

进程的通信方式 - 信号

信号是进程间通信的基本方式之一.

管道也是一种进程间基本通信方式.
终止进程

语法
    kill [-s <signal>] <pid|进程名|%jobid>    发送信号给指定进程|后台作业, 未指定信号则默认发送 SIGTERM(15)
    kill -l [<signal>]                        打印信号列表(或某个信号对应的数字或名称)

示例
    以下命令等效
    kill -1 <pid>    # 发送 SIGHUP 信号给指定进程
    kill -hup <pid>    # 发送 SIGHUP 信号给指定进程(信号名大小写无所谓)
    kill -sighup <pid>    # 发送 SIGHUP 信号给指定进程(信号名大小写无所谓)
    kill -s 1 <pid>    # 发送 SIGHUP 信号给指定进程(信号名大小写无所谓)
    kill -s hup <pid>    # 发送 SIGHUP 信号给指定进程(信号名大小写无所谓)
    kill -s sighup <pid>    # 发送 SIGHUP 信号给指定进程(信号名大小写无所谓)

    发信号给后台作业
    kill -9 %1        # 发送 KILL 信号给作业id为1的后台作业

选项
    -l                打印信号列表
    -s <signal>        发送信号
    
常用信号
    除了信号 9 之外, 其他信号都被被进程捕获并忽略. 1号进程不可杀
    SIGHUP(1)        退出终端, hangup(挂起)信号(使用 nohup 可以忽略该信号)
    SIGINT(2)        通知前台进程终止进程(等同 `ctrl+c`)
    SIGQUIT(3)        中止并生成 core 文件(等同 `ctrl+\`)
    SIGKILL(9)        立即结束进程, 不能被阻塞和捕获处理 kill -9 <pid>
    SIGTERM(15)        会杀死不能捕获该信号的进程
    SIGCONT(18)        继续(与STOP相反, 等同 `bg` 命令)
    SIGSTOP(19)        暂停(等同 `ctrl+z`), 将进程放到后台挂起(不执行状态).
ctrl+d 不是发信号, 而是用于表示一个特殊的二进制值, 表示 EOF

在一些地方很有用, 比如 cat 时会等待输入, 此时则输入完毕后按 ctrl+d 表示输入结束.

守护进程(daemon)和系统日志

注意, nohup 启动的进程并不是守护进程, 概念上不要搞错.

nohup 命令

使用 nohup 命令启动的程序会忽略 SIGHUP 信号, 就算关掉终端, 该程序依然会继续运行.

在运行该程序的终端被关闭后, 该进程会变成孤儿进程.

该孤儿进程自动会被 1 号进程收留, 也就是其父进程会变成 1.

但依然会占用其启动时的目录, 导致该目录无法卸载, 这是其与守护进程的区别之一(守护进程的工作目录是 /)

该命令经常与 & 符号一起使用.

目的是运行某个程序, 并让该程序脱离该终端仍可继续执行.

使程序运行时不挂起, 不向tty输出信息, 忽略输入.
默认是把输出追加到 nohup.out 文件

nohup <command>

/proc 目录

该目录是系统内存中的信息以文件形式的映射, 并非真实存在的物理文件.

每个进程都有一个对应的 /proc/<进程号> 目录, 表示其对应的内存数据.

/proc/<进程号> 部分文件说明

cwd            # (连接)该进程的工作目录(此时该目录是无法卸载的), 守护进程一般是指向 /
fd            # 打开的文件描述符
    |- 0    # (连接)标准输入, 可能是 /dev/pts/0, 或 /dev/null
    |- 1    # (连接)标准输出, 可能是 /dev/pts/0, 或 /dev/null, /path/to/nohup.out, socket:[xxxx], /var/log/message
    |- 2    # (连接)标准错误, 可能是 ...

screen 命令/工具

一般在远程连接到服务器后, 为了防止执行到一半时连接中断导致数据丢失等, 可以通过进入 screen 环境来执行命令, 此时若连接丢失则可在下一次连接后再次进入screen来恢复之前的环境.

CentOS 7 默认没有安装该工具, 需要自行安装.

yum install screen
# 进入 screen 环境
screen

# 退出(detached) screen 环境
## 按Ctrl+a时不会有任何提示信息, 此时再按d就退出screen环境
Ctrl+a d

# 查看 screen 的会话
screen -ls

# 恢复会话
screen -r <sessionid>

# 若掉线后查看到会话状态是 attached, 且无法恢复, 则可踢掉踢掉前一用户并恢复会话
screen -D -r <sessionid>

screen命令

screen [选项]

示例
    screen        直接进入screen环境
    
选项
    -ls, -list            查看screen的会话
    -r <sessionid>        恢复到指定会话

注意: screen 默认使用的是 non-login shell, 如果要使用 login shell, 则需要执行如下语句

echo 'defshell -$SHELL' >> ~/.screenrc

# 如果上述语句无效, 则使用如下语句:
echo 'defshell -bash' >> ~/.screenrc
可通过 shopt login_shell 查看当前是否为 login-shell

系统日志

/var/log/

重点关注文件

  • /var/log/messages 系统常规日志
  • /var/log/dmesg 内核运行相关消息(通常时启动时的内核日志)
  • /var/log/secure 安全日志
  • /var/log/cron crond计划任务日志

服务管理工具 systemctl

服务(提供常见功能的守护进程) 集中管理工具一般是:

  • service
  • systemctl

在 CentOS 7 及以上使用 systemctl 替代 service 工具.

CentOS 6中使用service管理服务, 需要自己编写复杂的启停脚本, 而在 systemctl 中则简化了这一部分.

service

配置文件存放: /etc/init.d/

管理SysV服务

service <服务名> <操作>

操作
    status        查看服务运行状态
    start        启动服务
    stop        停止服务
    restart        重启服务

配置开机自启动需要使用 chkconfig 命令.

service 服务运行级别的查看和设置

chkconfig [选项] <服务名>

示例
    chkconfig --list            # 列出所有 SysV 服务的运行级别
    chkconfig --list <服务名>      # 查看指定服务的运行级别
    chkconfig [--level <level>...] <服务名> (on|off)    # 设置服务在指定级别下是否自动启动
    
常用级别
    0    关机
    3    字符终端
    5    图形终端
    6    重启

systemctl

配置文件(服务单元)存放处: /usr/lib/systemd/system/

控制systemd系统 以及 服务管理

systemctl <命令> [<服务名>]

示例
    systemctl set-default multi-user.target        # 设置以字符界面启动(即多用户级别)

命令
    status <服务>
    start <服务>
    stop <服务>
    restart <服务>
    reload <服务>
    enable <服务>                    启用开机自动启动
    disable <服务>                禁用开机自动启动
    list-unit-files [<服务>]
    get-default                         获取当前的target
    set-default <字母表示的服务级别>          设置指定的target为默认的运行级别
    isolate <字母表示的服务级别>              立即切换到指定的运行级别
    
示例
    systemctl list-unit-files                            # 列出所有 systemd 服务
    systemctl list-unit-files NetworkManager.service    # 列出 NetworkManager 服务

查看所有服务级别 /lib/systemd/system/

ls -l /lib/systemd/system/runlevel*target

# runlevel0.target -> poweroff.target
# runlevel1.target -> rescue.target
# runlevel2.target -> multi-user.target
# runlevel3.target -> multi-user.target
# runlevel4.target -> multi-user.target
# runlevel5.target -> graphical.target
# runlevel6.target -> reboot.target

systemd 服务配置文件示例(以sshd 服务的配置文件 /usr/lib/systemd/system/sshd.service 为例)

[Unit]
Description=OpenSSH server daemon            # 服务描述文本
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target sshd-keygen.service    # 在哪些服务之后启动

Wants=sshd-keygen.service

[Service]
Type=notify
EnvironmentFile=/etc/sysconfig/sshd
ExecStart=/usr/sbin/sshd -D $OPTIONS        # 对应 start 命令
ExecReload=/bin/kill -HUP $MAINPID            # 对应 reload 命令
KillMode=process
Restart=on-failure
RestartSec=42s
# Specifies the maximum file descriptor number that can be opened by this process
#LimitNOFILE=65535
# Specifies the maximum number of processes
#LimitNPROC=4096
# Specifies the maximum size of virtual memory
#LimitAS=infinity
# Specifies the maximum file size
#LimitFSIZE=infinity

[Install]
WantedBy=multi-user.target                    # 设置在哪个级别下自动启动

SELinux 简介

SELinux - 安全增强的 Linux 版本

DAC(自主访问控制): 利用用户权限和文件权限来控制.

MAC(强制访问控制): 进程、用户、文件 的标签三者需一致才允许访问.

SELinux 会降低系统性能, 因此一般生产环境都会关闭.

查看 SELinux 的命令

# 查看当前 enforce 的状态
getenforce

# 查看进程的标签
ps -Z

# 查看文件的标签
ls -Z

# 查看当前用户的标签
id -Z

关闭 SELinux

# 方法1: 临时关闭, 重启失效
setenforce 0

# 方法2: 写入配置永久生效(需重启系统才会生效)
## enforcing 强制访问控制
## permissive 只警告而不控制
## disabled 关闭(生产环境推荐)
sed -i 's/^SELINUX=\w+/SELINUX=disabled/' /etc/selinux/config

获取 selinux 的布尔值

获取 selinux 的布尔值
    on 表示允许访问
    off 表示禁止访问
    

getsebool [<item>]

选项
    -a        # 查看所有布尔值

设置 selinux 的布尔值

设置 selinux 的布尔值

setsebool 选项 <item> <value>

选项
    -P        # 同时写入配置文件(默认只在内存修改)

value
    0        # 表示off, 关闭
    1        # 表示on, 打开

内存和磁盘管理

内存和磁盘使用率查看

内存使用率查看

可以使用 freetop 查看

free 命令
内存使用情况查看

free [选项]

选项
    -b        以byte为单位
    -k        以KB为单位(默认)
    -m        以MB为单位
    -g        以GB为单位(1024, 向下取整)
    -h        根据数值大小自动使用合适的单位
    
输出示例
                  total        used        free      shared  buff/cache   available
    Mem:           1837         619         324          30         893        1006
    Swap:          2047           0        2047

输出字段意义解释
    Mem                系统内存
    Swap            交换分区
    buff/cache        进程运行时拿来作为缓存的内存, 可以通过一定手段释放掉.
    available         表示若 buff/cache 全释放掉后可以使用的内存数量. 一般是看这个值.
一般会设置一部分Swap以避免系统内存耗光后出发系统OOM(?)操作导致随机kill部分进程.

磁盘使用率查看

fdisk 命令
分区表操作工具软件
只能看到分区信息, 但无法看到其挂载的信息.

fdisk [选项]

选项
    -l        查看分区表
    
交互式命令
    n        添加一个分区
    d        删除一个分区
    p        打印分区表
    w        将配置写入数据(在此之前只存在内存中)
    q        退出

打印的设备信息中:

  • Boot列显示 * 表示该分区是启动分区
  • 磁盘设备的 Start、End是以扇区为单位.
  • System 表示该分区所使用的分区格式
  • Blocks 的单位是 KB

类似的命令还有 parted -l, 显示的格式会略微不一样, 会更详细.

df 命令
报告文件系统磁盘空间使用率
可以看作是 fdisk 的补充, 可以看到文件系统的挂载信息.

df [选项] [<file>...]

选项
    -h, --human-readable        用合适的单位来展示
    -T, --print-type            显示每个文件系统的类型
    
    
示例
    df -hT /dev/**        # 查看硬盘/分区的空间及文件系统格式
du 命令
报告磁盘空间使用情况(实际占用空间)

du [选项]

选项    
    -s, --summarize              对每个参数只显示总和。
    -h, --human-readable        用合适的单位来展示

ls 与 du 查看文件大小是不同的:

  • ls 统计的是记录到文件开头和结尾一共占用的长度.
  • du 真正统计了文件的实际长度.

Eg. 比如用 dd 创建有空洞的文件 1GB 时, du 查看的就是真实大小, 可能就几MB, 而 ls 查看到的大小就是 1GB.

lsblk 命令
显示块设备

lsblk [选项]

选项
    -f, --fs        显示文件系统信息

ext4 文件系统

Linux 支持多种文件系统, 常见:

  • ext4
  • xfs
  • NTFS(需安装额外软件 ntfs-3g)
CentOS 6 默认使用 ext4 文件系统.

CentOS 7 默认使用 xfs 文件系统.

NTFS 格式由于版权问题, 在 Linux 挂载后默认是只读的, 需要安装额外软件 ntfs-3g 才能写入.

ext4 文件系统基本结构

  • 超级块
  • 超级块副本
  • i节点(inode)

    文件名称, 大小, 编号, 权限信息都会在 i节点体现.

    也叫索引节点?

    注意, 文件名是记录在文件父目录的i节点中.

    引申: 文件的读权限是读取文件的数据块内容, 而目录的读权限是读取目录底下的文件名称.

  • 数据块(datablock)

    记录数据.

    数据块是挂载在i节点后面, 形成链式结构.

    ext4 和 xfs 默认创建的数据块是 4KB.

ls 命令查看的是i节点中文件大小信息, 而 du 是查看数据块的信息, 所以显示的结果会有差异.

mv 对文件改名实际影响的是其父目录i节点中的信息, 因此文件大小并不会影响修改速度.

rm 命令是将文件名和i节点的链接断开, 这就是为什么文件的大小不会影响删除的速度, 以及有些文件被删除后空间并没有真正释放.

找回被删掉的文件的原理就是搜索磁盘上的i节点及其链接的数据块, 从而找回丢失的数据.

ln 命令原理是让更多的文件名指向i节点, 使用命令 ln afile bfile, 此时会有一个新的文件名 bfile 指向同一个i节点, 使用 ls -l 命令可以看到该文件对应i节点的链接数多了1个.

使用 ln 是不能跨越文件系统的, 因为i节点信息是存在当前文件系统中.

文件、目录与 inode(i节点)

Linux文件系统里文件和文件名的关系如下图。

inodes

目录也是文件,文件里存着文件名和对应的inode编号。通过这个inode编号可以查到文件的元数据和文件内容。文件的元数据有引用计数、操作权限、拥有者ID、创建时间、最后修改时间等等。文件件名并不在元数据里而是在目录文件中。因此文件改名、移动,都不会修改文件,而是修改目录文件。

借《UNIX环境高级编程》里的图说一下进程打开文件的机制。

file pointer

进程每新打开一个文件,系统会分配一个新的文件描述符给这个文件。文件描述符对应着一个文件表。表里面存着文件的状态信息(O_APPEND/O_CREAT/O_DIRECT...)、当前文件位置和文件的inode信息。系统会为每个进程创建独立的文件描述符和文件表,不同进程是不会共用同一个文件表。正因为如此,不同进程可以同时用不同的状态操作同一个文件的不同位置。文件表中存的是inode信息而不是文件路径,所以文件路径发生改变不会影响文件操作。

上面这部分的描述来自: https://www.lightxue.com/how-...

ln 命令

在文件之间建立连接
默认是创建硬链接, 即新建一个文件名并让其指向 <src> 的i节点.
硬链接不能跨越文件系统.

ln [选项] src dest

选项
    -s        创建软链接(符号链接), 其文件内容记录的是对应的访问路径. 软链接的权限设置是无效的. 
            软链接可以跨越分区系统

facl 功能

xfs 和 ext4 支持文件访问控制列表(facl)

ACL 表示访问控制列表Access Control List(ACL)

设置了facl权限的文件会有一个额外的 + 权限表示.

-rw-------+ 2 root root 10 2020-02-24 22:51 afile
getfacl
查看文件或目录的ACL

getfacl [选项] <file>

选项
    -R, --recursive         # 递归

示例
    getfacl -R <目录> > acldir.acl        # 备份目录的acl权限信息, 并通过 `cd <目录> && setfacl --restore acldir.acl` 来恢复
setfacl
设置文件或目录的ACL

setfacl [选项] <权限> <file>

示例
    setfacl -m u:user1:r afile        # 给用户 user1 赋予读 afile 文件的权限
    setfacl -m g:group1:rw afile    # 给组 group1 赋予读写 afile 文件的权限
    setfacl -x u:user1 afile        # 移除给 user1 赋予的 afile文件权限
    setfacl -x g:group1 afile        # 移除给 group1 赋予的 afile文件权限

选项
    -m, --modify <acl>        # 修改文件的访问控制权限, 此时 <acl> 格式为: (u|g):(<user>|<group>):(r|w|x)
    -x, --remove <acl>        # 移除文件的访问控制权限, 此时 <acl> 格式为: (u|g):(<user>|<group>)    
    --set <acl>               # 替换当前所有的acl(可以理解为清空当前的再添加), 注意保留基本的 UGO 权限
    -b, --remove-all        # 删除所有的acl权限    
    
    -R, --recursive         # 递归应用到子目录/文件
    
    默认权限
    -d, --default            # (只)设置默认的acl权限, 只对目录有效, 会被目录中创建的文件和目录继承。
                            # 子文件会继承acl权限, 子目录同时会继承default权限(即递归继承)
                            # 另外一种格式是: d:u:user1:rw, 也就是在权限的前面多一个 `d:`
    -k, --remove-default    # 移除默认的acl权限    
    
    备份和恢复ACL权限(cp -p可以保留ACP权限, 但tar等并不会保留acl权限信息, 因此可以先备份这些信息以供恢复)
    --restore <权限备份文件>    # 恢复acl权限
    

若是报错 Setfacl : Operation not supported 则表示挂载硬盘时默认没有加载acl规则, 因此需要重新挂载硬盘:

  1. 修改 /etc/fstab

    
    /dev/sda1             /data                ext4    defaults,acl    0 0
  2. 重新挂载

    mount -o remount /data
上述操作本人未实际操作过, 需谨慎, 防止重新挂载出错.
示例

我想将某个目录 /data/game 的权限全部分给指定用户 publisher, 同时该目录原先已经有文件了, 属主和属组都是 root.

# 设置该目录的 default 权限
setfacl -d -m u:user1:rwx /data/game

# 递归更改该目录及底下文件的 facl 权限
setfacl -R -m u:user1:rwx /data/game

磁盘的分区与挂载

新的磁盘的处理步骤:

  1. 分区 fdisk
  2. 格式化 mkfs
  3. 挂载 mount
  4. 写入配置 /etc/fstab

fdisk 命令

只能对小于 2TB 的进行分区

对硬盘分区
注意: 会造成数据丢失, 谨慎

fdisk

示例
    fdisk -l          # 查看分区表情况
    fdisk <块设备>        # 对指定块设备分区
    
分区过程中的常用命令
    n        # 创建新分区
    d        # 删除某个分区
    w        # 将分区信息写入磁盘
    p        # 查看当前分区信息
    q        # 退出

Tip.

  • 服务器上一般一块硬盘划分一个分区.
  • 如果要创建超过4个分区, 则需要分配3个主分区, 1个扩展分区, 然后在扩展分区中再创建多个逻辑分区.
  • ext4 和 xfs 默认创建的数据块是 4KB.

mkfs 命令


格式化分区

示例
    mkfs.ext4 [选项] <分区>        # 将分区格式化为 ext4 格式
    mkfs.xfs [选项] <分区>        # 将分区格式化为 xfs 格式
    
选项
    -f        # 强制操作

parted 命令

分区大于 2T 应使用 parted 命令, 而不是 fdisk

另一个分区工具

parted <块设备>

mount 命令

挂载文件系统

mount [选项] <块设备> <目标挂载目录>

选项    
    信息查看
    -l                # 查看当前挂载情况
    
    -a, --all        # 挂载 /etc/fstab 配置文件中的所有配置
    
    挂载选项
    -t, --types <vfstype>        # 指定分区格式类型, 若不指定或指定为 "auto" 则会自行判定分区格式类型.
    -o, --options <options>        # 指定挂载参数, <options> 可用逗号分隔多个参数
                                # 可用参数
                                #     defaults    默认
                                #    noatime        读文件时不修改 inode 的访问记录(atime), 可以提高IO性能.
                                #    remount        重新挂载
    --bind <src> <dest>            # 将某个目录或文件挂载到指定的目录, 而不要求<src>是块设备. 这个操作实际上是修改/替换 inode    
    

注意

  • mount命令并不会写入配置, 仅仅保存在内存, 因此重启后失效

    需写入 /etc/fstab/ 才能持久化
  • 目标挂载目录必须是已存在的.

对文件的操作是文件级别的操作, 是在文件系统的更上一层.

因此我们无法直接对类似 /dev/sdc1 这样的设备进行操作, 需要先挂载到目录, 再对目录操作.

umount 命令

卸载文件系统

umount <挂载目录>|<块设备>

/etc/fstab 配置文件

格式

磁盘挂载配置文件

Eg.
/dev/sdb1     /mnt/sdb1            ext4         defaults         0                         0
<分区>        <挂载目标目录>    <文件系统>        挂载权限    指示是否硬盘备份(dump)        是否开机磁盘自检
            交换分区是swap     交换分区是swap                  一般设置为0              主要是针对ext2, ext3
                                                                                一般设置为0

挂载权限
    defaults    # 默认挂载参数

若配置写错导致重启失败, 则可通过 grub 进入单用户模式来修复该文件.

chroot 命令

以特定目录作为进程的根目录运行指定命令
    - 若未指定 command, 则默认是执行 $SHELL -i (即一般是 /bin/bash -i)

chroot [选项] <新root路径> [<command=$SHELL -i>]

磁盘配额的使用

掌握原理和方法即可, 生产环境一般用虚拟化来限制使用资源, 包括cpu, 内存, 磁盘..

注意: root 用户是不受限的, 不应使用 root 用户来测试.

xfs

xfs 文件系统的用户磁盘配额 quota

操作步骤(以 /dev/sdb1 为例)

# 1. 确保是 xfs 文件系统
mkfs.xfs /dev/sdb1

# 2. 挂载文件系统
mkdir /mnt/disk1
mount -o uquota,gquota /dev/sdb1 /mnt/disk1

# 3. (可选)修改挂载目录权限
## 此处为方便测试, 设置其为 1777, 即 rwxrwxrwt
chmod 1777 /mnt/disk1

# 4. 查看磁盘配额状态
## report 指令参数说明
### -u 显示user限额状态
### -g 显示group限额状态
### -i 显示inode配额状态
### -b 显示block(块)配额状态
### -h 以human-readable方式展示
xfs_quota -x -c 'report -ugibh' /mnt/disk1

# 5. 设置磁盘配额
## 命令意义说明: 以下命令是限制用户 "user1" 创建的 inode 数量软硬限制分别是5和10, 超过软限制后会有一段宽限时间.
## limit 指令参数说明
### -u 限制用户
### isoft 设置inode节点数量的软限制
### ihard 设置inode节点数量的硬限制
### bsoft 设置block数量的软限制
### bhard 设置block数量的硬限制
xfs_quota -x -c 'limit -u isoft=5 ihard=10 user1' /mnt/disk

交换分区(虚拟内存)的查看与创建

命令

mkswap 命令
创建交换分区

mkswap
swapon 命令

需要先用 mkswap 将目标文件或设备创建为交换分区才可以挂载.

启用

swapon [选项] [<文件或设备>]

示例
    swapon /swapfile    # /swapfile 是交换分区文件, 此处启用该文件作为交换分区.

选项
    -s, --summary        # 显示已使用的交换分区
swapoff 命令
关闭用于交换分区的设备

swapoff [选项] [<文件或设备>]

选项
    -a        # 关闭所有用于交换分区的文件和设备

使用新的分区作为交换分区

此处以 /dev/sdb1 作为示例

# 格式化指定分区
mkswap /dev/sdb1

# 启用该分区作为交换分区
swapon /dev/sdb1

# 4. 写入配置以持久化
cat <<"EOF" >> /etc/fstag
/dev/sdb1 swap swap defaults 0 0
EOF

使用文件制作交换分区

使用带空洞的文件(此处以 /swapfile 文件为例)来作为交换分区

# 1. 创建带空洞的文件
dd if=/dev/zero of=/swapfile bs=4M count=1024

# 2. 修改文件权限(不然会报警告)
chmod 600 /swapfile

# 3. 启用该文件作为交换分区
swapon /swapfile

# 4. 写入配置以持久化
cat >> /etc/fstag <<"EOF"
/swapfile swap swap defaults 0 0
EOF

软件RAID的使用

RAID(磁盘阵列) 的常见级别及含义

  • RAID 0

    stripping 条带方式, 将数据拆成N份分别写到N个磁盘中(任意磁盘损坏数据就全毁了), 可以提高单盘吞吐率.

  • RAID 1

    mirroring 镜像方式, 将数据复制到另一个磁盘中(浪费一块硬盘空间), 提高可靠性.

  • RAID 5

    RAID 0RAID 1 的组合和简化, 有奇偶校验, 至少需要3块硬盘: 第1,2块硬盘写数据, 第3块硬盘写奇偶校验.(轮流写数据和校验)

    坏掉任意一块磁盘数据都可以挽回, 但损坏超过1块则数据丢失.

  • RAID 10

    RIAID 1RAID 0 的组合. 至少需要4块硬盘, 2块硬盘组合RAID 1, 另2块硬盘也组合 RAID 1, 再组合作 RAID 0.

    只要不是同一侧的两个硬盘都损坏数据就不会丢失.

软件实现的RAID会额外占用不少CPU, 因此在工作中一般是使用RAID卡来处理.

madmn 命令

组建RAID, 尽量保持每个磁盘大小一致, 如果不一致, 则一般会按照容量最小的来算.

软件RAID不支持系统引导, 即 /boot 不能存储在该阵列中.

管理MD设备 - 即软件RAID
# 一般约定创建的第一个硬盘是 md0

mdadmin [选项] <设备>...


选项
    创建
    -C, --create                # 创建新的阵列(array)
    -a, --auto yes                # 自动同意, 对于所有提示都是 "yes" (若已存在数据则会被清掉, 谨慎)
    -l, --level <RAID level>    # RAID 级别
    -n, --raid-devices <num>    # 指定在阵列中有 <num> 个块设备是活动(active)的
    
    查看
    -D, --detail                # 查看 md 设备详情
    
    卸载
    -S, --stop                    # 停止 md 设备(deactive), 并释放所有资源
    
    
    --scan
    --verbose
    
示例    
    mdadm -D /dev/md0    # 查看创建的阵列 /dev/md0 的详情
    mdadm -S /dev/md0    # 停止 md 设备

在配置好RAID后将当前的配置持久化

mdadm --detail --scan --verbose > /etc/mdadm.conf

示例: 用两个硬盘组成 RAID 1

/dev/md0
    |- /dev/sdb1
    |- /dev/sdc1

# 1. 创建硬盘 /dev/md0 , 有2块硬盘是活动的, 由 /dev/sdb1, /dev/sdc1 组成RAID 1 级别.
mdadmin -C /dev/md0 -a yes -l 1 -n 2 /dev/sd[b,c]1

# 2. 持久化到配置文件, 下次开机后才能保持软RAID生效
echo DEVICE /dev/sd[b,c]1 >> /etc/mdadm.conf

# 3. 追加配置持久化到文件, 下次开机后才能保持软RAID生效
mdadm -Evs >> /etc/mdadm.conf

# 4. 格式化该分区, 以供正常存储数据
mkfs.xfs /dev/md0

示例: 删除软RAID

# 1. umount 已挂载的 md 设备, 此处以 /dev/md0 设备为例
umount /dev/md0

# 2. 停止RAID设备
mdadm -S /dev/md0

# 3. 删除组成RAID的硬盘中的超级块数据(此处的 /dev/md0 由 /dev/sd[b,c]1 组成)
# 也可以手动用其他命令破坏掉, 比如 dd if=/dev/zero of=/dev/sdb1 bs=1M count=1
mdadm --misc --zero-superblock /dev/sdb1
mdadm --misc --zero-superblock /dev/sdc1

# 4. 删除配置文件(此处假设该文件内只有 /dev/md0 的配置)
rm -f /etc/mdadm.conf

逻辑卷管理

相关概念

在服务器上的磁盘空间只增不减

一个物理设备就是一个物理卷.

文件系统无法跨硬盘使用.

上面的软RAID创建的 md0 也是个逻辑卷, Linux 默认使用的根目录也是用逻辑卷去管理的.

可以把N个大小不一样的硬盘拼成一个卷组, 再切割成逻辑卷.

使用逻辑卷的好处在于可以动态扩容.

首先要理解文件系统是一个分层的结构.

挂载
↑
文件系统
↑
逻辑卷
↑
卷组
↑
物理卷
↑
分区
↑
硬盘

如果要给某个逻辑卷扩容, 则需要依次处理以下:

  1. 新增硬盘并分区 fdisk
  2. 将新分区创建为物理卷 pvcreate
  3. 将物理卷加入到需扩容的卷组 vgextend
  4. 给该卷组的目标逻辑卷扩容 lvextend
  5. 给目标卷的文件系统更新新的容量信息 xfs_growfsresize2fs

整个过程是自底向上逐层处理的.

创建逻辑卷的相关命令

物理卷
pvcreate 命令
为LVM初始化物理卷(physical volumes)

pvcreate <块设备>

示例
    pvs /dev/sd[b,c,d]1        # 初始化物理卷 /dev/sdb1, /dev/sdc1, /dev/sdd1
pvs 命令
显示物理卷(physical volumes)信息

pvs


示例输出信息详解
    PV                VG        Fmt        Attr    PSize            PFree
    /dev/sda2        centos    lvm2    a--        <39.00g            4.00m
    /dev/sdb1                lvm2    ---        <2.00g            <2.00g
    /dev/sdc1                lvm2    ---        <2.00g            <2.00g
    /dev/sdd1                lvm2    ---        <2.00g            <2.00g
    物理卷            卷组                     物理的大小  物理卷在物理空间实际剩余大小
                Volume Group
输出解释
    lvm2        # linux 逻辑卷管理器
    /dev/sda2 属于卷组 centos, 它的空间被卷组 centos 给几乎全占用了.
pvremove 命令
移除物理卷的 LVM 标签

pvremove [选项] 物理卷名
卷组
vgcreate 命令
创建卷组(volume groups)
注意: 单个物理卷只能归属于一个卷组.

vgcreate <卷组名称> <物理卷>

示例
    vgcreate vg1 /dev/sdb1 /dev/sdc1    # 创建卷组 vg1, 并将物理卷加入到卷组里.
vgs 命令
显示卷组(volume groups)信息

vgs

输出示例
    VG        #PV                #LV                #SN    Attr    VSize        VFree
    centos    1                2                0    wz--n-    <39.00g        4.00m
    👆
    卷组名      组成的物理卷数量    划分出的逻辑卷数量                卷组总大小    卷组剩余大小
vgremove 命令
移除卷组
    - 移除有逻辑卷的卷组时会提示是否移除对应逻辑卷

vgremove [选项] 卷组名
逻辑卷
lvcreate 命令
创建逻辑卷

lvcreate [选项] <卷组名>

选项
    -L, --size <大小>            # 指定创建的逻辑卷的大小, eg. 100M
    -n, --name <逻辑卷名>      # 指定要创建的逻辑卷的名字
lvs 命令
查看逻辑卷(logical volumes)信息

lvs
lvremove 命令
从系统上移除逻辑卷
    - 只指定卷组时, 会移除该卷组上的所有逻辑卷

lvremove <卷组>[/<逻辑卷>]
创建逻辑卷的过程

假设提供了2块硬盘 /dev/sdb/dev/sdc, 我们需要创建一个叫做 vg1 的卷组, 并在该卷组上创建一个叫做 lv1 的逻辑卷, 并将其格式化后挂载在 /mnt/test 目录.

# 1. 分别创建 /dev/sdb1 和 /dev/sdc1 分区
fdisk /dev/sdb
fdisk /dev/sdc

# 2. 初始化物理卷, 并查看物理卷详情
pvcreate /dev/sd[b,c]1
pvs

# 3. 创建卷组, 并查看卷组详情
vgcreate vg1 /dev/sdb1 /dev/sdc1
vgs

# 4. 创建逻辑卷, 并查看逻辑卷详情
lvcreate -L 100M -n lv1 vg1
lvs

# 5. 格式化逻辑卷
mkfs.xfs /dev/vg1/lv1

# 6. 挂载并正常使用
mount /dev/vg1/lv1 /mnt/test

动态扩容逻辑卷

vgextend 命令
卷组扩容, 扩容后卷组的可用空间会变大

vgextend <卷组> <物理卷>...

示例
    vgextend centos /dev/sdd1        # 使用物理卷 /dev/sdd1 给卷组 centos 扩容.  centos 是某个卷组的名
lvextend 命令
逻辑卷扩容

lvextend [选项]

选项
    -L, --size <大小>        # 指定扩容大小

示例
    lvextend -L +10G root        # 给逻辑卷 root 增加 10G空间. root 是某个逻辑卷的名.

给逻辑卷扩容后, 但是文件系统并没有变大, 因此还需要使用相应命令给具体文件系统扩容.

# xfs 文件系统
xfs_growfs /dev/centos/root        # 给 /dev/centos/root 逻辑卷的文件系统扩容.

# ext4 文件系统
resize2fs /dev/centos/root        # 未确认

其他

dd 命令

转换和拷贝文件

dd 

if=<input>        # /dev/zero
of=<output>        # 

bs=<size>            # 块大小, 每次按指定的块大小来读写. eg. 4M
count=<num>            # 写次数
seek=<block-size>    # 目标文件跳过的块数

关于 if

  • /dev/zero "输入设备", 读取时提供无限的空字符, 常用于产生一个特定大小的空白文件.
  • /dev/null 空设备, 丢弃写入的任意数据, 读取时会立即得到一个 EOF
  • /dev/random 随机伪设备, 提供永不为空的随机字节数据流.
  • /dev/urandom 随机伪设备, 速度比 /dev/random 快得多, 但"相对"的不够随机. 对随机性要求不高时直接使用该伪设备即可.

资源控制

ulimit

/etc/security/limit.conf 配置文件

目前个人使用

* hard nofile 1000000 #限制单个进程最大文件句柄数(到达此限制时系统报警)
* soft nofile 1000000 #限制单个进程最大文件句柄数(到达此限制时系统报错)
* soft core unlimited   # 创建的核文件的最大尺寸
* soft stack 10240      # 最大栈尺寸

ulimit 命令

shell 资源限制
    若不填写限制值, 则打印对应资源限制报告.
    若填写限制值, 则是设定.

ulimit [选项] [<限制>]

选项
    -a        显示目前资源限制报告

    -S        设定软限制
    -H        设定硬性限制
    
    -c        core 文件创建数量最大值
    -d        程序数据段(data segment)最大值
    -n        打开的文件数量最大值
    -s        栈大小(stack)最大值
    -b        the socket buffer size
    -e        the maximum scheduling priority (`nice')
    -f        the maximum size of files written by the shell and its children
    -i        the maximum number of pending signals
    -l        the maximum size a process may lock into memory
    -m        the maximum resident set size
    -p        the pipe buffer size
    -q        the maximum number of bytes in POSIX message queues
    -r        the maximum real-time scheduling priority
    -t        the maximum amount of cpu time in seconds
    -u        the maximum number of user processes
    -v        the size of virtual memory
    -x        the maximum number of file locks
    
限制值
    <具体数值>         # 限制为指定的具体指, 各自单位请参阅 help ulimit
    soft            # 限制为当前的 soft 值
    hard            # 限制为当前的 hard 值
    ulimited        # 不限制

!!! 注意

  • /etc/security/limit.conf 中的设置对于 systemd 的 service 是不生效的
  • systemd 的 service 有专门的统一配置文件 /etc/systemd/system.conf

    DefaultLimitNOFILE=100000
    DefaultLimitNPROC=100000

    需要重新加载配置文件

    systemctl daemon-reload
  • 针对 systemd 的特定 service, 可以修改其配置文件 /lib/systemd/system/xxx.service

    [Service]
    # ...
    
    LimitNOFILE=65535
    LimitNPROC=65535

    需要重新加载配置文件

    systemctl daemon-reload
    systemctl restart nginx.service

其他待整理


嘉兴ing
284 声望24 粉丝

PHPer@厦门