目录索引

Linux实用实战手册

分类: 操作系统

Linux运维实战参考手册


索引

第一部分:发行版差异与基础环境


第一章:主流发行版概述与包管理

本章是整本手册的基石。在进入具体命令之前,我们需要先理解Linux世界的生态格局。不同发行版不仅仅是界面不同,其内核、工具链、包管理系统、服务管理方式都有显著差异。掌握这些差异,能让你在迁移环境时少踩坑,在排查问题时更快定位根因。

1.1 主流发行版家族概览

Linux发行版数以千计,但生产环境中最常见的可以归纳为三大体系:Debian系、Red Hat系、以及 Alpine系。每个体系都有其设计哲学和适用场景,了解这些是成为多面手运维工程师的第一步。

Debian系

Debian系是目前历史最悠久、社区最活跃的发行版家族。其衍生版本包括Ubuntu、Linux Mint、Pop!_OS等。Debian系的最大特点是社区驱动,软件包质量经过充分测试,稳定性极佳。Ubuntu作为Debian的分支,在桌面和服务器领域都拥有极高的市场占有率,其LTS(长期支持)版本更是企业服务器的首选。Debian系采用APT作为包管理系统,配合dpkg底层工具,安装、更新、卸载软件都非常方便。Ubuntu还发展出了Snap通用包格式,试图解决跨发行版的软件分发问题。

运维建议:在生产环境中使用Ubuntu时,优先选择LTS版本以获得5年的安全更新支持。对于需要运行Docker容器的服务器,建议使用Ubuntu Server而非Desktop版本以减少不必要的资源消耗。

Red Hat系

Red Hat系是企业级Linux的事实标准。RHEL(Red Hat Enterprise Linux)是商业闭源收费版本,但其源代码公开衍生出了CentOS和Rocky Linux等免费替代品。2020年CentOS突然宣布停止维护CentOS Linux,转向CentOS Stream,引发了业界的广泛讨论,随后社区涌现出AlmaLinux和Rocky Linux等替代方案。Red Hat系传统上使用yum作为包管理器,RHEL 8及CentOS 8之后全面转向dnf,dnf与yum命令完全兼容但性能更优。Red Hat系的另一大特色是Systemd作为初始化系统,以及SELinux强制访问控制带来的安全增强。

运维建议:如果你的业务运行在AWS或阿里云上,很大可能使用的是Amazon Linux 2或Alibaba Cloud Linux,它们都是RHEL系的衍生版。在这些环境中工作,必须熟悉yum/dnf命令和systemd服务管理。

Alpine系

Alpine Linux是一个面向安全的轻量级发行版,其设计理念是“小而美”。Alpine的默认C库是musl libc而非glibc,镜像体积通常只有5-10MB,这使其成为Docker镜像的首选基础系统。几乎所有官方Docker镜像的latest标签都基于Alpine。然而,Alpine的包管理器apk与Debian/Red Hat系完全不同,软件生态相对有限,在某些场景下可能缺少特定的软件包。此外,由于采用musl libc,某些在glibc环境下编译的程序可能需要重新编译。

运维建议:在Dockerfile中优先使用Alpine作为基础镜像以减小镜像体积,但要注意某些复杂应用可能需要基于Ubuntu或Debian镜像。Alpine的包索引更新较快,建议在CI/CD流程中定期更新基础镜像以获取安全补丁。

1.2 包管理器对比与实战

包管理器是操作系统的心脏,它决定了我们如何获取、安装、更新和卸载软件。不同发行版采用不同的包管理方案,下面我们进行详细的对比分析。

APT(Debian/Ubuntu)

APT(Advanced Package Tool)是Debian系的标准包管理器,它工作在dpkg之上,提供了自动依赖解决、版本管理和软件源配置等高级功能。apt-get是APT的命令行接口,适合脚本和自动化场景;apt命令则是apt-get的现代化封装,交互更友好。了解apt的工作原理对于快速排查软件安装问题至关重要,因为很多软件的依赖问题都源于软件源配置错误。

DNF/YUM(Red Hat系)

dnf(Dandified YUM)最初在Fedora中出现,RHEL 8和CentOS 8将其作为默认包管理器。dnf与yum命令完全兼容,yum实际上已经成为dnf的符号链接。在RHEL 7及更早版本中,yum仍然是主角。dnf相比yum的主要改进包括:更快的依赖解析速度、更好的内存占用、更清晰的API设计,以及Python 3支持。在企业环境中,你可能同时遇到使用yum和dnf的服务器,掌握两者的用法都很重要。

APK(Alpine)

apk是Alpine的包管理器,设计极其简洁。apk add安装包,apk del删除包,apk search搜索包,apk update更新索引。Alpine的包命名遵循name-version-release的格式,例如openssh-9.0_p1-r0。在Docker环境中,apk的轻量特性使其成为构建最小化镜像的首选。

发行版包管理器对照表

操作 Debian/Ubuntu RHEL/CentOS/Rocky Alpine
安装软件 apt install pkg dnf install pkg apk add pkg
删除软件 apt remove pkg dnf remove pkg apk del pkg
更新索引 apt update dnf check-update apk update
升级软件 apt upgrade dnf upgrade apk upgrade
搜索包 apt search keyword dnf search keyword apk search keyword
查看已安装 dpkg -l 或 apt list --installed rpm -qa apk info
清理缓存 apt clean dnf clean all apk cache clean

实际运维经验

场景一:企业内网无法访问公网软件源

在某次客户现场部署中,客户的数据中心完全隔离外网,必须配置本地镜像源。我们首先需要确定操作系统的版本:cat /etc/os-release,然后根据版本挂载对应的ISO镜像作为本地源。在RHEL/CentOS系统中,编辑/etc/yum.repos.d/下的repo文件,将baseurl指向本地ISO挂载点;在Ubuntu系统中,则需要配置/etc/apt/sources.list,指向本地仓库路径。这里有一个关键点:RHEL系需要先安装createrepo工具来生成仓库元数据,否则即使配置了源也无法使用。

场景二:处理软件依赖冲突

有时候安装一个软件会触发大量依赖更新,可能影响生产环境的稳定性。此时可以使用apt-mark hold package(Ubuntu)或rpm --setflags package(RHEL)来锁定特定软件包版本,防止意外升级。在Ubuntu 22.04升级到22.10时,我们发现openssh-server的升级会导致某些老旧客户端无法连接,通过hold住该包解决了兼容性问题。

场景三:紧急安全补丁

当爆出一个高危漏洞(如Log4j、Heartbleed)时,快速批量修复至关重要。在RHEL系中,可以使用dnf update --security仅安装安全更新;在Ubuntu中,unattended-upgrades可以配置自动安全更新。对于大规模服务器环境,建议使用Ansible或Salt Stack等自动化工具批量执行补丁更新。

1.3 服务管理机制差异

不同发行版采用不同的服务管理机制,从古老的SysVinit到现代的Systemd,再到轻量级的OpenRC,不同系统启动和管理服务的方式有显著差异。理解这些差异对于排查服务启动失败问题至关重要。

Systemd(主流方案)

Systemd是当前Linux世界的主流初始化系统,Ubuntu(15.04+)、RHEL 7+、CentOS 7+、Debian 8+都采用它。Systemd的核心概念是Unit(单元),每种资源(服务、挂载点、socket、timer等)都是一个Unit。服务单元文件通常位于/lib/systemd/system//etc/systemd/system/目录。Systemd的优势在于:并行启动服务加快开机速度、按需启动服务减少资源消耗、统一的日志管理(journalctl)、以及强大的依赖管理。

SysVinit(传统方案)

在一些老旧的服务器或嵌入式设备中,你可能仍然会遇到SysVinit。它使用/etc/init.d/目录下的shell脚本管理服务,通过service命令调用。SysVinit的服务启动是串行的,开机速度较慢,但原理简单直观。在CentOS 6及更早版本中,这是唯一的方案。虽然新版本已全面转向Systemd,但理解SysVinit有助于维护遗留系统。

OpenRC(轻量方案)

OpenRC是Gentoo Linux的初始化系统,也被Alpine、OpenWrt等采用。它在SysVinit和Systemd之间寻求平衡,保持简单性的同时提供必要的功能。OpenRC的配置文件位于/etc/rc.conf,服务脚本在/etc/init.d/。在Docker容器中,Alpine默认使用OpenRC作为服务管理器,了解其用法对于容器化运维很有帮助。

服务管理命令对照表

操作 Systemd SysVinit OpenRC
启动服务 systemctl start nginx service nginx start rc-service nginx start
停止服务 systemctl stop nginx service nginx stop rc-service nginx stop
重启服务 systemctl restart nginx service nginx restart rc-service nginx restart
查看状态 systemctl status nginx service nginx status rc-status
开机自启 systemctl enable nginx chkconfig nginx on rc-update add nginx default
禁用自启 systemctl disable nginx chkconfig nginx off rc-update del nginx default
查看日志 journalctl -u nginx tail /var/log/nginx/ tail /var/log/nginx/

实际运维经验

场景一:服务启动失败排查

在一次排查Apache服务无法启动的问题时,我们首先使用systemctl status httpd查看详细错误信息,Systemd会显示完整的启动失败原因。如果日志不够详细,可以journalctl -u httpd -n 50查看最近的50条日志。常见的启动失败原因包括:端口被占用(lsof -i :80检查)、配置文件语法错误(apachectl configtest验证)、依赖服务未启动(查看Unit文件的After/Requires指令)。Systemd的依赖管理很严格,如果服务声明依赖其他服务但那些服务未启动,本服务也无法启动。

场景二:紧急重启后的服务恢复

生产服务器意外重启后,需要快速确认所有关键服务已正常运行。我们编写了一个简单的检查脚本:systemctl list-units --type=service --state=failed列出所有失败的服务,然后逐一排查。对于必须运行但未自动启动的服务,使用systemctl enable --now service同时启用并立即启动。在RHEL 7+环境中,如果某个服务启动特别慢,可以使用systemctl mask暂时屏蔽它以加快开机速度,但这需要谨慎操作。

场景三:容器内服务管理

在Alpine Docker容器中,我们通常不使用Systemd,而是直接运行进程。但有时需要在容器内管理多个服务,这时OpenRC就派上用场了。在Dockerfile中安装OpenRC:RUN apk add openrc && touch /run/openrc/softlevel,然后可以在entrypoint脚本中使用rc-service nginx start启动服务。值得注意的是,容器内使用OpenRC时需要设置RC_STRIPVR=no环境变量,否则某些服务可能无法正常工作。


第二章:文件与目录管理

文件操作是Linux运维最基本的技能。每天我们都要与成千上万的文件打交道:查看日志、编辑配置、移动数据、备份文件。本章从最基础的ls、cd讲起,逐步深入到find高级查找、tar归档压缩,帮你建立完整的文件管理能力。

2.1 基础文件操作命令

ls

列出目录内容,是使用最频繁的命令之一

语法

ls [options] [file or directory]

常用参数

参数 长参数 说明
-l --format=long 使用长格式显示详细信息
-a --all 显示所有文件,包括隐藏文件
-h --human-readable 以人类可读的方式显示文件大小
-t --sort=time 按修改时间排序
-S --sort=size 按文件大小排序
-r --reverse 反向排序
-R --recursive 递归列出子目录内容
-1 --format=single-column 每行只显示一个文件
-d --directory 只显示目录本身,不列出内容
-i --inode 显示文件的inode号

实战示例

场景一:查看目录详细内容

ls -lh /var/log

这个命令以长格式显示/var/log目录,文件大小以人类可读方式(K、M、G)显示。输出包含:文件类型和权限、硬链接数、所有者、所属组、文件大小、修改时间、文件名。在排查问题时,我们经常需要查看日志文件的大小和修改时间来判断哪些是最新生成的日志。

场景二:按时间排序查看最新文件

ls -ltr /var/log/nginx

-t按修改时间倒序,-r反向,所以这个命令会显示最旧的在前、最新的在最后。当你想找刚刚更新的日志文件时,配合tail使用效果更好:ls -ltr /var/log | tail -5

场景三:显示隐藏文件并查看权限

ls -la ~

-a显示所有文件包括以点开头的隐藏文件,~代表用户主目录。这个命令常用来检查用户主目录的配置,比如。bashrc、.ssh等隐藏目录和文件。注意观察以d开头的目录和以-开头的普通文件,以及-rwx------这样的权限位。

💡 运维经验

  • 警惕权限问题:如果ls -l显示文件属主是root但你用普通用户运行,可能无法访问某些系统日志。排查权限问题时应首先确认当前用户身份(whoami)。
  • inode耗尽:有时磁盘没满但无法创建文件,可能是inode耗尽了。使用df -i检查。如果发现大量小文件(如缓存),可以考虑归档清理。
  • 符号链接:以l开头的行表示符号链接,->后面是链接目标。ls -L可以不解引用直接显示链接本身的信息。

cd

切换当前工作目录

语法

cd [directory]

常用参数

参数 说明
- 切换到上一个工作目录
~ 或空 切换到用户主目录
.. 切换到上级目录
-P 解析符号链接后再切换

实战示例

场景一:快速切换目录

cd /etc/nginx/sites-enabled
cd -

第二行的cd -可以快速切换回上一个目录,在两个目录之间频繁切换时非常有用。

场景二:在符号链接目录中切换

cd -P /etc/sysconfig/network-scripts

如果/etc/sysconfig/network-scripts是到/sysconfig/network-scripts的符号链接,使用-P参数会切换到实际目录而非链接目录,这在某些需要获取真实路径的场景中很重要。

cp

复制文件和目录

语法

cp [options] source destination

常用参数

参数 长参数 说明
-r --recursive 递归复制目录
-p --preserve 保留源文件的属性(权限、时间戳等)
-a --archive 相当于-dR --preserve=all,保留所有属性
-i --interactive 覆盖前询问确认
-f --force 强制覆盖,不询问
-v --verbose 显示详细操作信息
-l --link 创建硬链接而非复制
-s --symbolic-link 创建符号链接而非复制
-u --update 只复制源文件更新的文件
-n --no-clobber 不覆盖已存在的文件

实战示例

场景一:安全复制整个目录

cp -av /home/wwwroot /backup/

-a参数保留所有属性(权限、所有者、时间戳),-v显示详细进度。在备份网站数据时,这个命令可以确保复制后的文件与源文件完全一致,包括隐藏的配置文件的权限。

场景二:只复制比目标新的文件

cp -u /source/*.log /destination/

这个命令常用于增量备份场景,只同步新的或修改过的文件,大大减少传输量和时间。

场景三:避免覆盖错误

cp -ni /source/* /destination/

-i在覆盖前询问,-n绝对不覆盖。在复制重要数据时,这两个参数可以防止手滑导致的数据丢失。

💡 运维经验

  • 尾随斜杠的陷阱cp -r source/ dest/cp -r source dest/结果完全不同。前者复制source目录下的内容到dest目录,后者将整个source目录复制为dest。建议始终明确意图,使用trailing slash时更要小心。
  • 硬链接与复制cp -l创建硬链接,速度快且不占用额外空间,但修改任一文件会影响另一个。在备份场景中,如果需要保留原文件的同时创建副本,应该使用普通复制或硬链接+copy-on-write机制。
  • 权限问题:从root用户复制文件给普通用户时,普通用户可能无法读取。使用cp -a后,普通用户可能无法写入,因为权限也被保留了下来。这种情况下需要后续用chown调整所有权。

mv

移动或重命名文件和目录

语法

mv [options] source destination

常用参数

参数 长参数 说明
-i --interactive 覆盖前询问确认
-f --force 强制覆盖,不询问
-n --no-clobber 不覆盖已存在的文件
-v --verbose 显示详细操作信息
-u --update 只移动源文件更新的文件
-t --target-directory 指定目标目录(适用于多个源文件)

实战示例

场景一:批量移动文件到指定目录

mv -t /destination/ file1.txt file2.txt file3.txt

-t参数允许先指定目标目录,然后将所有后续文件移动到该目录。语法比传统的mv file1 file2 ... dest/更清晰。

场景二:重命名文件

mv oldfilename newfilename

在同一个目录下,mv命令可以用来重命名文件。这在批量重命名时尤其有用,配合循环可以做很多事情。

场景三:批量重命名文件

# 去除文件名中的空格
for f in *\ *; do mv "$f" "${f// /_}"; done

# 批量添加前缀
for f in *.log; do mv "$f" "backup_$f"; done

# 批量修改扩展名
for f in *.txt; do mv "$f" "${f%.txt}.md"; done

Shell的参数扩展${f%.txt}可以去除扩展名,非常适合批量重命名操作。

rm

删除文件和目录

语法

rm [options] file or directory

常用参数

参数 长参数 说明
-r --recursive 递归删除目录及其内容
-f --force 强制删除,不提示确认
-i --interactive 删除前询问确认
-v --verbose 显示详细操作信息
-d --dir 删除空目录
--one-file-system 跨文件系统删除时跳过

实战示例

场景一:删除空目录

rmdir /tmp/empty_directory

rmdir只能删除空目录,相对安全,不会误删目录中的文件。

场景二:删除目录下所有内容

rm -rf /var/log/nginx/old_logs/

-r递归删除目录,-f强制不询问。这个命令在清理旧日志时很常用。

场景三:删除所有匹配的文件

rm -f /var/log/nginx/*.log.{1..9}

使用通配符可以批量删除匹配的文件。注意在生产环境中使用通配符删除前,建议先用ls确认匹配范围。

⚠️ 致命警告:rm -rf / 的灾难

# 绝对不要执行以下任何命令!!!
rm -rf /
rm -rf /*
rm -rf .
rm -rf --no-preserve-root /

执行rm -rf /会删除根目录下的一切,系统将立即不可用,数据全部丢失。这不是玩笑,互联网上有无数受害者。在使用rm -rf时,请遵循以下原则:永远不要在根目录执行,永远不要使用变量作为路径(如果变量为空,rm -rf $DIR/会变成rm -rf /),在生产环境执行前先用ls确认路径。

运维经验补充:一个真实的教训是,某次运维人员在清理/tmp目录时,使用了rm -rf $TEMP_DIR/*,但变量TEMP_DIR未设置,结果瞬间删除了服务器上的所有Web应用文件。后来我们在脚本中添加了路径验证:[ -z "$TEMP_DIR" ] && exit 1[ "$TEMP_DIR" != "/" ]

mkdir

创建目录

语法

mkdir [options] directory

常用参数

参数 长参数 说明
-p --parents 递归创建父目录
-m --mode=MODE 设置目录权限
-v --verbose 显示创建信息

实战示例

场景一:创建嵌套目录

mkdir -p /var/www/html/project/assets/images

-p参数自动创建所有不存在的父目录。如果没有-p,父目录不存在时mkdir会报错。

场景二:创建权限特定的目录

mkdir -m 700 /root/.ssh

-m参数直接设置目录权限为700,只有所有者可以读写执行。这在创建SSH目录时特别有用。

touch

创建空文件或更新文件时间戳

语法

touch [options] file

常用参数

参数 长参数 说明
-a --time=access 只更新访问时间
-m --time=modify 只更新修改时间
-c --no-create 不创建文件,只更新时间
-t 指定时间戳 [[CC]YY]MMDDhhmm[.ss]
-r --reference=FILE 使用参考文件的时间

实战示例

场景一:批量创建空文件

touch app_{1..100}.log

Bash的花括号展开可以快速创建多个文件。

场景二:更新文件时间戳

touch -r oldfile newfile

将newfile的时间戳设置为与oldfile相同,这在某些需要保持文件时间一致性的场景中很有用。

2.2 文件查找与归档

find

在目录树中查找文件,是最强大的文件查找工具

语法

find [path...] [expression]

常用参数

参数 说明
-name 按文件名查找,支持通配符
-type 按文件类型查找(f普通文件、d目录、l符号链接)
-mtime 按修改时间查找(天)
-mmin 按修改时间查找(分钟)
-size 按文件大小查找
-perm 按权限查找
-user 按所有者查找
-group 按所属组查找
-empty 查找空文件或空目录
-exec 对找到的文件执行命令
-delete 删除找到的文件
-maxdepth 限制搜索深度
-mindepth 最小搜索深度

实战示例

场景一:按名称精确查找

find /var/log -name "nginx*.log"

在/var/log目录下查找所有名称以nginx开头、以.log结尾的文件。*是通配符,匹配任意字符。

场景二:按修改时间查找

find /var/www -mtime +7 -type f

查找7天前修改过的普通文件。常用于清理旧日志:find /var/log -mtime +30 -name "*.log" -delete

场景三:按文件大小查找

find / -size +100M -type f

查找大于100MB的文件。在排查磁盘空间问题时,这个命令可以快速定位大文件。注意-size的格式:+100M大于100M,-100M小于100M,100M约等于100MB。

场景四:查找后执行命令

find /var/log -name "*.log" -exec chmod 644 {} \;

对所有.log文件执行chmod命令。{}代表找到的文件,\;是命令结束标志。-exec优点是原子执行每个文件,缺点是效率较低。

场景五:查找后删除

find /tmp -type f -atime +30 -delete

删除30天未访问的文件。注意-delete必须在find表达式的最后。另一种更安全的方式是-exec rm {} \;

场景六:组合条件查找

find /var/www -type f \( -name "*.php" -o -name "*.html" \)

使用(和)组合条件,-o表示或(or)。这个命令查找所有PHP和HTML文件。

💡 运维经验

  • 性能优化:find默认会递归搜索整个目录树,在大型文件系统中可能很慢。使用-maxdepth限制搜索深度可以显著提升速度。例如:find /home -maxdepth 2 -name "*.conf"
  • -name vs -path:-name只匹配文件名,-path匹配完整路径。如果你想排除某个子目录,使用-path配合否定:-path '*/.git/*' -prune -o
  • -print vs -print0:默认行为是-print,使用空格分隔文件名;-print0使用null字符分隔,适合处理包含空格或特殊字符的文件名。配合xargs -0使用:find . -print0 | xargs -0 rm
  • 隐藏文件:默认find不会匹配以.开头的隐藏文件,需要显式使用-name ".*"。

tar

归档打包工具,Linux下最常用的打包压缩命令

语法

tar [options] [archive] [file or directory]

常用参数

参数 说明
-c 创建归档
-x 解压归档
-t 列出归档内容
-v 显示详细过程
-f 指定归档文件名
-z 使用gzip压缩(.tar.gz/.tgz)
-j 使用bzip2压缩(.tar.bz2)
-J 使用xz压缩(.tar.xz)
-C 指定解压目录
-p 保留权限信息
--exclude 排除指定模式

实战示例

场景一:打包目录

tar -cvf backup_20240314.tar /var/www/html

-c创建,-v显示过程,-f指定文件名。将/var/www/html打包成backup_20240314.tar。注意:tar打包时路径是绝对路径,解压时会恢复到绝对路径。

场景二:打包并压缩

tar -czvf backup.tar.gz /var/www/html
tar -cjf backup.tar.bz2 /var/www/html
tar -cJf backup.tar.xz /var/www/html

-z使用gzip压缩(最快),-j使用bzip2压缩(压缩率中等),-J使用xz压缩(压缩率最高但最慢)。在磁盘空间紧张时,推荐使用xz压缩。

场景三:排除特定文件

tar -czvf website.tar.gz /var/www/html \
  --exclude='*.log' \
  --exclude='*/cache/*' \
  --exclude='.git'

--exclude可以排除不需要打包的文件或目录。注意:模式应该相对于打包的起始路径。

场景四:解压到指定目录

tar -xzf backup.tar.gz -C /tmp/

-C指定解压目录。如果归档内包含绝对路径,解压后文件会回到原位置。

场景五:只解压特定文件

tar -xzf backup.tar.gz -C /tmp/ "path/to/specific/file"

从归档中只提取指定文件,而不需要解压整个归档。这在只需要某个配置文件时非常有用。

场景六:查看归档内容

tar -tzf backup.tar.gz | head -20

-t列出归档内容但不实际解压。在解压前先确认归档内容是良好实践。

💡 运维经验

  • 压缩级别:gzip默认级别为6(0-9,9最高但最慢)。对于日常备份,-6是很好的平衡点。对于归档后长期存储,可以使用-9以节省空间。
  • 增量备份:tar本身不支持增量备份,但可以配合find实现。思路是记录上次备份的时间戳,只打包该时间点之后修改的文件。
  • tar与符号链接:tar会打包符号链接指向的文件,而不是链接本身。如果想只打包链接,使用-h参数让tar跟随链接,或者在打包时用-P参数保留绝对路径链接。
  • 大文件处理:tar在处理几十GB甚至更大的文件时非常稳定。split命令可以分割大tar包:tar -czf - /data | split -b 2G - backup.tar.gz.

ln

创建文件链接,分为硬链接和符号链接

语法

ln [options] source [linkname]
ln -s source linkname

常用参数

参数 说明
-s 创建符号链接(软链接)
-f 强制创建,删除已存在的目标
-i 覆盖前询问
-v 显示链接信息
-n 将符号链接视为普通文件

实战示例

场景一:创建符号链接

ln -s /var/www/html /home/www

创建符号链接/home/www指向/var/www/html。访问/home/www实际上访问的是/var/www/html的内容。符号链接可以跨文件系统,可以指向目录。

场景二:创建硬链接

ln file1 file2_hard

硬链接是同一文件的多个目录项,它们共享相同的inode。修改任一文件内容,另一个也会改变。硬链接不能跨文件系统,不能指向目录。

场景三:强制覆盖已存在的链接

ln -sf /new/target /existing/link

-f强制覆盖已存在的链接目标。

💡 运维经验

  • 符号链接失效:如果删除源文件,符号链接会变成悬空链接(dangling link),访问时会提示"No such file or directory"。硬链接则不同,删除一个不会影响另一个,因为文件内容由inode管理,只要inode的引用计数不为零,文件就不会被删除。
  • 相对路径:创建符号链接时,如果使用相对路径,是相对于链接位置而非当前工作目录。建议始终使用绝对路径以避免混淆:ln -s /path/to/target linkname
  • 目录链接:符号链接可以指向目录,这在需要多个入口访问同一组文件时很有用。但要注意可能的循环引用,find -L或ln -P可以检测。

第三章:系统状态与性能监控

当服务器出现卡顿、响应变慢、负载异常时,如何快速定位问题?这就需要掌握系统状态监控的命令。本章涵盖CPU、内存、磁盘、进程等核心资源的监控方法,以及常用的性能分析工具。

3.1 系统整体状态

top

实时显示系统进程状态,是最基础的动态监控工具

语法

top [options]

常用参数

参数 说明
-d 指定刷新间隔(秒)
-p 只显示指定PID的进程
-u 只显示指定用户的进程
-c 显示完整命令行
-H 显示线程
-M 以内存大小排序
-P 以CPU使用率排序
-k 杀死进程
-1 显示每个CPU核心的使用率

交互式命令(进入top后按键)

按键 功能
q 退出top
h 或 ? 显示帮助
k 杀死进程
r 调整进程优先级(renice)
f 或 F 选择显示字段
o 或 O 调整排序字段
l 切换显示负载行
t 切换显示CPU信息行
m 切换显示内存信息行
1 汇总或逐个显示CPU
W 保存配置

实战示例

场景一:基本使用

top

启动top后,默认按CPU使用率排序。第一行显示系统运行时间、用户数、负载平均值;第二行显示进程状态总数和各类进程数;第三行显示CPU使用情况;第四、五行显示内存和交换分区使用情况;下方是进程列表。

场景二:监控特定用户进程

top -u www-data

只显示www-data用户的进程。在排查某个服务占用资源过多时很有用。

场景三:显示所有CPU核心

top -1

按数字1可以切换显示所有CPU核心的使用率。这对于判断负载是否均衡分布在多核CPU上很有帮助。

💡 运维经验

  • Load Average的含义:top第一行显示的三个数字分别代表过去1分钟、5分钟、15分钟的系统负载。负载的含义是处于可运行状态和不可中断睡眠状态的进程数。在单核CPU上,负载1表示CPU满载;在4核CPU上,负载4表示CPU满载。一般认为负载不超过CPU核心数是正常的。
  • CPU使用率的计算:top显示的CPU使用率是自上次刷新以来的平均值。如果刷新间隔太短(默认3秒),瞬时峰值可能导致误判。建议使用-d 5或更大的间隔来获取更稳定的平均值。
  • 内存问题排查:注意观察RES(常驻内存)和%MEM列。如果某个进程内存使用异常高,可能存在内存泄漏。使用top -p持续监控几个采样点,观察内存是否持续增长。
  • 批量杀死进程:在紧急情况下,可以使用pkill -9 -u username杀死某用户的所有进程,比在top中逐个处理更快。

htop

top的增强版,提供更友好的交互界面和更丰富的功能

语法

htop [options]

常用参数

参数 说明
-d 指定刷新间隔(百分之一秒)
-p 只显示指定PID的进程
-u 只显示指定用户的进程
-C 使用单色模式
-s 按指定列排序

交互式快捷键

按键 功能
上下箭头 选择进程
Enter 查看进程详情
空格 标记进程
U 取消标记
k 杀死标记的进程
l 显示进程打开的文件(Lsof)
t 树形视图
p 按程序名过滤
/ 搜索进程

实际运维经验

场景一:更直观的CPU监控

相比top,htop的优势在于可以直观地看到每个CPU核心的使用情况,用彩色条形图显示。在多核服务器上,htop可以快速发现单核负载异常高的情况(可能存在单线程性能瓶颈)。

场景二:批量操作进程

在htop界面中,可以用空格键标记多个进程,然后按k调出杀死进程菜单,一次性结束多个进程。这在处理某个用户的多个问题进程时特别方便。

场景三:安装htop

# Debian/Ubuntu
apt install htop

# RHEL/CentOS
dnf install htop

# Alpine
apk add htop

如果系统没有htop,可以快速安装。在某些极简的Docker镜像中可能没有htop,这时只能使用top。

uptime

显示系统运行时间、平均负载和当前用户数

语法

uptime [options]

常用参数

参数 说明
-p 以可读格式显示运行时长
-s 系统启动时间
-V 显示版本

实战示例

uptime
# 输出: 14:23:45 up 128 days,  3:12,  2 users,  load average: 0.52, 0.58, 0.59

输出依次为:当前时间、系统运行时间、当前登录用户数、过去1/5/15分钟的平均负载。

💡 运维经验

  • 快速检查服务器状态uptime && free -h && df -h是一个经典的快速检查命令组合,一行命令了解服务器运行时间、负载、内存、磁盘状态。
  • 负载异常检测:如果负载明显高于CPU核心数,说明存在瓶颈。检查是哪个进程导致:top -bn1 | head -20ps auxk -%cpu
  • 平均负载的历史:配合历史数据(监控系统或脚本记录),uptime可以反映服务器的整体稳定性。持续高负载可能需要扩容或优化。

free

显示内存使用情况

语法

free [options]

常用参数

参数 长参数 说明
-b --bytes 以字节为单位
-k --kilo 以KB为单位(默认)
-m --mega 以MB为单位
-g --giga 以GB为单位
-h --human 以人类可读方式显示
-s --seconds 持续显示,间隔秒数
-t --total 显示内存总量行
-w --wide 宽格式显示

实战示例

free -h
#               total        used        free      shared  buff/cache   available
# Mem:           15Gi       4.2Gi       8.1Gi       123Mi       2.7Gi        10Gi
# Swap:         2.0Gi          0B       2.0Gi

💡 运维经验

  • 理解内存字段:Linux会尽可能利用空闲内存作为缓存(buff/cache),这部分内存在需要时可以立即释放给应用程序使用。所以真正紧张的内存是used - buff/cache,或者直接看available字段。在排查OOM(Out of Memory)问题时,available是最值得关注的指标。
  • Swap使用:如果Swap使用量不为零,说明物理内存已经不够用。但某些情况下少量Swap是正常的(内存压缩等)。如果Swap使用量持续增长或接近满,说明物理内存严重不足。
  • 可用内存告警:设置监控脚本,当available低于阈值时告警:free -m | awk 'NR==2 {if($7<1024) print "Memory Low!"}'
  • OOM Killer:当内存耗尽时,Linux会启动OOM Killer杀死进程。查看系统日志dmesg | grep -i out of memoryjournalctl | grep -i killed可以找到被杀的进程。

df

显示磁盘空间使用情况

语法

df [options] [file]

常用参数

参数 长参数 说明
-h --human-readable 以人类可读方式显示
-H --si 使用1000而非1024
-T --print-type 显示文件系统类型
-i --inodes 显示inode使用情况
-k --kilobytes 以KB为单位
-P --portability POSIX格式输出

实战示例

场景一:查看磁盘使用

df -hT

显示所有挂载点的空间使用,包括文件系统类型。输出包括:文件系统类型、容量、已用、可用、已用%、挂载点。

场景二:检查inode使用

df -i

inode耗尽是常见的"磁盘满"原因。虽然磁盘还有空间,但因为inode用完,无法创建新文件。常见于大量小文件的场景。

💡 运维经验

  • 假性磁盘满:有时df显示磁盘未满,但写入失败。可能的原因:inode耗尽(df -i检查)、文件系统损坏(fsck修复)、磁盘配额限制(quota -u查看)、只读挂载(mount检查)。排查时应全面考虑。
  • 删除大文件后空间未释放:如果某个大文件被进程打开并写入,删除后空间不会立即释放。找到占用文件的进程:lsof | grep deleted,然后重启进程或清理。
  • 日志目录监控:对/var/log等日志目录重点监控,设置告警阈值。建议当使用率超过80%时告警,超过90%时可能影响系统功能。

du

估算文件空间使用,是磁盘清理的利器

语法

du [options] [file or directory]

常用参数

参数 长参数 说明
-h --human-readable 以人类可读方式
-s --summarize 只显示总计
-a --all 显示所有文件
-d --max-depth=N 目录深度限制
-c --total 显示总计
--max-depth 同-d

实战示例

场景一:查找最大的目录

du -h --max-depth=1 / | sort -hr | head -10

查找根目录下占用空间最大的10个子目录。-h人类可读,-max-depth=1只显示一级目录,sort -hr按大小倒序排列,head -10取前10。

场景二:快速查看目录总大小

du -sh /var/log

-s显示总大小,-h人类可读。这个命令比du -h /var/log更简洁,适合快速检查。

场景三:查找大文件

find / -type f -size +100M -exec ls -lh {} \; 2>/dev/null | sort -k5 -h

全局搜索大于100MB的文件,并按大小排序。2>/dev/null过滤权限错误。

💡 运维经验

  • du vs df:du统计文件系统的实际使用,df统计挂载点的整体情况。有时候两者会有差异(比如文件已删除但进程仍持有句柄),这时df显示已用更多。排查时应该对比两者找原因。
  • 定期清理:建立日志轮转机制,使用logrotate自动压缩和清理旧日志。手动清理时先确认文件是否仍在被写入。
  • 目录大小异常:如果某个目录突然变得非常大(比如缓存目录),可能是程序异常产生了大量文件。先找到问题根源再清理,治标要治本。

3.2 进程监控与管理

ps

报告当前进程快照,是进程管理的基础命令

语法

ps [options]

常用参数组合

参数 说明
aux BSD风格完整格式(最常用)
-ef SystemV风格格式
-eo pid,ppid,%cpu,%mem,cmd 自定义格式
-C cmdname 按命令名筛选
-p pid 按PID筛选
-U user 按用户筛选

实战示例

场景一:查看所有进程

ps aux

a显示所有终端进程,x显示所有非终端进程,u显示用户导向格式。输出包含:USER(用户)、PID(进程ID)、%CPU(CPU使用)、%MEM(内存使用)、VSZ(虚拟内存)、RSS(常驻内存)、TTY(终端)、STAT(状态)、START(启动时间)、TIME(CPU时间)、COMMAND(命令)。

场景二:查看进程树

ps -ef --forest

--forest以树形显示进程父子关系。这对于理解进程间关系和init进程位置很有帮助。

场景三:按CPU/内存排序

ps aux --sort=-%cpu | head -10
ps aux --sort=-%mem | head -10

--sort按指定字段排序,-表示降序。快速找到最耗资源的前10个进程。

场景四:自定义输出格式

ps -eo pid,ppid,cmd,%cpu,%mem --no-headers

-eo指定需要的字段,--no-headers不显示表头。适合在脚本中提取进程信息。

💡 运维经验

  • 进程状态:STAT列显示进程状态。常见状态:R运行中、S睡眠(可中断)、D不可中断睡眠(通常是IO等待)、Z僵尸、T停止、X死亡。Zombie进程需要杀死其父进程才能清理。
  • 进程和线程:ps默认显示进程,ps -eLf显示线程(LWP列)。在Java或Go等有goroutine的程序中,线程数可能远多于进程数。
  • 僵尸进程:Z状态进程是僵尸。如果父进程没有调用wait()回收子进程,子进程会变成僵尸。大量僵尸进程会消耗系统资源。找到僵尸的父进程并修复它。

pkill/pgrep

按名称或其他属性查找或杀死进程

语法

pkill [options] pattern
pgrep [options] pattern

常用参数

参数 说明
-f 匹配完整命令行
-l 显示进程名
-a 显示完整命令行
-u user 匹配用户
-signal 发送信号
-9 强制杀死(SIGKILL)
-15 正常终止(SIGTERM,默认)

实战示例

场景一:按名称查找进程

pgrep nginx

返回所有nginx进程的PID。如果没有任何匹配,返回1。

场景二:杀死指定用户的所有进程

pkill -9 -u www-data

杀死www-data用户的所有进程。危险操作,确认目标正确后再执行。

场景三:杀死特定名称的进程

pkill -9 nginx

杀死所有名称包含nginx的进程。等同于kill -9 $(pgrep nginx)

kill/killall

发送信号给进程

语法

kill [options] pid
killall [options] process_name

常用信号

信号名 编号 说明
SIGHUP 1 终端断开,通常导致进程重新加载配置
SIGINT 2 Ctrl+C中断
SIGQUIT 3 Ctrl+\退出
SIGKILL 9 强制杀死,无法捕获
SIGTERM 15 正常终止(默认)
SIGUSR1 10 用户自定义信号,常用于平滑重启
SIGUSR2 12 用户自定义信号

实战示例

场景一:正常终止进程

kill 12345

发送SIGTERM信号给PID 12345的进程,这是终止进程的优雅方式。进程收到信号后可以清理资源再退出。

场景二:强制杀死进程

kill -9 12345

SIGKILL无法被进程捕获或忽略,会立即杀死进程。用于进程已经挂起、无法响应SIGTERM的情况。注意:强制杀死可能导致数据丢失(如未保存的数据)。

场景三:杀死所有同名进程

killall nginx

杀死所有名为nginx的进程。危险操作,可能影响其他用户的同名进程。

💡 运维经验

  • 平滑重启 vs 强制杀死:对于nginx、apache、mysql等服务,发送SIGHUP可以触发配置重载(nginx -s reload),比杀死再启动更安全。某些服务支持SIGUSR1进行日志轮转。
  • 进程假死:进程既不退出也不响应,可能是D状态(不可中断睡眠),通常是等待IO或硬件响应。这种情况下kill -9也无法杀死,只能等待IO恢复或重启系统。检查:ps aux | grep D
  • 进程名匹配:pkill/killall使用进程名匹配,可能误伤。比如pkill java会杀死所有Java进程。如果只想杀死特定实例,使用pkill -f "java -jar app.jar"匹配完整命令行。

第四章:网络管理与排查

网络是现代服务的命脉。当网站无法访问、服务连接失败时,如何快速定位问题?这需要掌握一系列网络诊断命令。本章涵盖连接状态查看、网络配置、连通性测试、数据包捕获等核心技能。

4.1 网络连接状态

netstat/ss

查看网络连接、路由表、接口统计等

语法

netstat [options]
ss [options]

常用参数

参数 说明(netstat) 说明(ss)
-a 显示所有连接 显示所有连接
-t TCP连接 TCP连接
-u UDP连接 UDP连接
-l 监听中的套接字 监听中的套接字
-p 显示进程 显示进程
-n 数字格式地址 数字格式地址
-r 路由表 路由信息
-i 接口统计 接口信息
-s 协议统计 协议统计

实战示例

场景一:查看所有TCP连接

ss -tunap

-t TCP、-u UDP、-n数字格式、-a所有、-p显示进程。这个组合可以快速看到系统所有网络连接以及对应的进程。

场景二:查看监听端口

ss -tlnp
ss -ulnp

-l显示监听中的端口。排查服务是否正常监听时非常有用。比如检查80端口:ss -tlnp | grep :80

场景三:查看连接状态统计

ss -s

显示各种状态的连接数量统计。Time-wait和Close-wait过多可能需要关注,可能是程序没有正确关闭连接。

场景四:按状态筛选

ss -t state established
ss -t state time-wait

按连接状态筛选。ss的状态过滤比netstat更强大。

💡 运维经验

  • ss vs netstat:ss是netstat的现代替代品,性能更好。在高并发服务器上,netstat可能很慢甚至卡住,ss是更好的选择。两者语法略有不同,ss用空格分隔选项,netstat用连字符。
  • TIME_WAIT问题:大量TIME_WAIT连接会占用端口,影响新连接。如果使用短连接或频繁建立断开连接,可能会遇到"Port Exhausted"。可以通过调整内核参数(net.ipv4.tcp_tw_reuse、net.ipv4.ip_local_port_range)或使用连接池解决。
  • 端口被占用:排查端口被哪个进程占用:ss -tlnp | grep :8080lsof -i:8080

lsof

列出打开的文件,在Linux中一切皆文件,网络连接也是文件

语法

lsof [options]

常用参数

参数 说明
-i 显示网络文件
-i:port 显示指定端口的文件
-p pid 显示指定进程的文件
-u user 显示指定用户的文件
-c cmd 显示指定命令的文件
+D path 递归显示目录下的文件
-n 数字格式地址
-P 数字格式端口

实战示例

场景一:查看端口占用

lsof -i:80

显示所有占用80端口的进程和文件。类似ss -tlnp | grep :80,但输出更详细。

场景二:查看进程打开的文件

lsof -p 12345

显示PID 12345进程打开的所有文件。排查进程异常打开大量文件时很有用。

场景三:查看网络连接

lsof -i
lsof -iTCP
lsof -iUDP

显示所有网络相关的文件(socket)。

场景四:查找打开某文件的进程

lsof /var/log/nginx/access.log

某个日志文件正在被写入时,删除它不会立即释放空间(因为进程持有文件句柄)。用这个命令可以找到占用文件的进程。

💡 运维经验

  • deleted文件:有时磁盘满了但找不到大文件,可能是因为某些进程打开了已删除的文件还在写入。lsof | grep deleted可以找到这些悬空文件。重启进程或杀死进程可以释放空间。
  • 文件描述符限制:如果lsof显示大量文件打开,可能是达到了ulimit限制。lsof -p $$ | wc -l查看当前进程打开的文件数,ulimit -n查看限制。
  • 端口冲突:新启动服务报"Address already in use",用lsof找出占用端口的进程,考虑是迁移旧进程还是更换端口。

ping

测试网络连通性和延迟

语法

ping [options] destination

常用参数

参数 说明
-c count 发送数据包数量
-i interval 发送间隔(秒)
-s size 数据包大小
-t ttl TTL值
-W timeout 等待超时(秒)
-M do 设置分片策略(dont/dont)

实战示例

ping -c 4 -s 1000 8.8.8.8

发送4个1000字节的数据包到8.8.8.8。输出包括:数据包往返时间(rtt min/avg/max/mdev)、丢包率。

💡 运维经验

  • DNS问题:ping域名失败但ping IP成功,说明DNS配置有问题。检查/etc/resolv.conf和/etc/hosts。
  • 延迟问题:一般同城机房延迟1-3ms,跨省20-50ms,跨国100-300ms。延迟突然增大可能存在网络拥塞或路由问题。
  • MTU问题:ping大包失败但小包成功,可能是MTU设置问题。尝试:ping -M do -s 1472 目标IP(1472是常见MTU 1500减去IP头)。

curl

多功能网络请求工具,支持多种协议

语法

curl [options] url

常用参数

参数 说明
-X method 指定HTTP方法
-H header 添加请求头
-d data POST发送的数据
-G 将数据转换为GET参数
-k 忽略证书错误
-L 跟随重定向
-o file 保存到文件
-O 使用远程文件名保存
-s 静默模式,不显示进度
-v 详细输出
-w format 写入格式
-x proxy 使用代理

实战示例

场景一:发送HTTP请求

curl -X GET "https://api.example.com/data" -H "Authorization: Bearer token"

基本GET请求,带认证头。

场景二:POST提交数据

curl -X POST "https://api.example.com/login" \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"123456"}'

POST JSON数据。-d自动添加Content-Type: application/x-www-form-urlencoded。

场景三:下载文件

curl -O "https://example.com/file.tar.gz"
curl -o myfile.tar.gz "https://example.com/file.tar.gz"

-O使用远程文件名保存,-o指定本地文件名。

场景四:测试API响应

curl -w "\nHTTP_CODE: %{http_code}\nTIME: %{time_total}s\n" \
  -o /dev/null -s "https://api.example.com/endpoint"

-w输出格式化信息:HTTP状态码、响应时间。这对API性能测试很有用。

💡 运维经验

  • 接口测试:curl是调试REST API的利器。配合jq工具可以格式化JSON响应:curl -s api.example.com | jq .
  • 跳过证书验证:测试内部HTTPS服务时,-k参数跳过证书验证。注意生产环境不应跳过。
  • 请求耗时分析:使用-w "%{time_namelookup} %{time_connect} %{time_appconnect} %{time_total}"分析各阶段耗时。

4.2 网络配置与路由

ip

现代化的网络配置工具,替代ifconfig、route、arp等老旧命令

语法

ip [options] object command

常用对象和命令

对象 命令 说明
addr show/add/del IP地址管理
link show/set 网络接口管理
route show/add/del 路由表管理
neigh show/add/del ARP缓存管理
addrlabel 地址标签
maddr 多播地址

实战示例

场景一:查看网络接口

ip addr show
ip -s link

显示所有网络接口的IP地址和状态。-s显示统计信息(收包数、发包数、错误数等)。

场景二:管理IP地址

ip addr add 192.168.1.100/24 dev eth0
ip addr del 192.168.1.100/24 dev eth0

添加/删除IP地址。临时生效,重启网络或系统后失效。永久配置需修改/etc/network/(Debian)或/etc/sysconfig/network-scripts/(RHEL)。

场景三:管理网络接口

ip link set eth0 up
ip link set eth0 down
ip link set eth0 mtu 1400

启用/禁用接口、设置MTU。

场景四:查看路由表

ip route show
ip route add default via 192.168.1.1
ip route add 10.0.0.0/8 via 192.168.1.1

显示/添加路由条目。

场景五:查看ARP缓存

ip neigh show
ip neigh flush all

显示/清空ARP缓存。

💡 运维经验

  • ip vs ifconfig:ip是iproute2套件的一部分,比传统的ifconfig/route/arp更强大。Debian和RHEL新版本默认都包含iproute2。推荐统一使用ip命令。
  • 临时配置:ip命令的配置是临时的,重启网络服务会丢失。对于测试网络配置很方便,确认后再写入配置文件。
  • 多网卡路由:在多网卡服务器上,可能需要调整路由优先级。ip route show table all可以看到所有路由表。

第五章:权限与用户管理

权限是Linux系统安全的基石。理解文件权限、特殊权限、ACL、SELinux等,才能有效保护系统安全。本章还涵盖用户创建、修改、删除等日常运维操作。

5.1 文件权限管理

chmod

改变文件或目录的访问权限

语法

chmod [options] mode file

权限表示法

数字模式:使用3位八进制数字,分别代表所有者、所属组、其他用户的权限。

  • 4 = r(读)
  • 2 = w(写)
  • 1 = x(执行)

常用组合:

  • 7 = rwx(读、写、执行)
  • 6 = rw-(读、写)
  • 5 = r-x(读、执行)
  • 4 = r--(只读)
  • 0 = ---(无权限)

示例:chmod 755 file(rwxr-xr-x)、chmod 600 file(rw-------)。

符号模式:u所有者、g所属组、o其他用户、a全部;+添加、-移除、=设置。

示例:chmod u+x file(给所有者添加执行权限)、chmod go-rw(移除组和其他的读写权限)。

常用参数

参数 说明
-R 递归修改目录及其内容
-v 显示详细信息
-c 只显示变更的信息
--reference=FILE 使用参考文件的权限

实战示例

场景一:设置可执行权限

chmod +x /usr/local/bin/myscript

给脚本添加执行权限,否则无法直接运行。

场景二:批量设置目录权限

chmod -R 755 /var/www

-R递归修改目录及其内容。755是Web目录的常见权限设置。

场景三:安全权限(600/700)

chmod 600 ~/.ssh/id_rsa
chmod 700 ~/.ssh

SSH私钥必须只能所有者读写,目录也需要安全权限否则SSH会警告。

💡 运维经验

  • Web目录权限:Web目录通常644,PHP文件644,PHP目录755,上传目录403。执行权限只能给必要的脚本。.htaccess等配置文件不应被Web服务器直接访问。
  • sudo权限:使用visudo编辑/etc/sudoers,不要直接编辑。错误语法会导致无法使用sudo。行格式:username ALL=(ALL) ALL
  • umask:新建文件默认权限受umask影响。默认umask 022,所以新建文件权限是644。临时调整:umask 077

chown

改变文件或目录的所有者和所属组

语法

chown [options] owner[:group] file
chown [options] :group file

常用参数

参数 说明
-R 递归修改
-v 显示详细信息
-c 只显示变更信息
--reference=FILE 使用参考文件属性

实战示例

场景一:修改所有者

chown www-data:www-data /var/www/html -R

-R递归修改整个Web目录的所有者和所属组。这是部署Web应用后的常见操作。

场景二:只修改所属组

chown :developers /shared/project

冒号前为空,只修改所属组。等价于chgrp developers /shared/project

场景三:修改用户同时修改组

chown nginx:nginx /var/log/nginx

同时设置所有者和所属组。

chgrp

改变文件或目录的所属组

语法

chgrp [options] group file

常用参数

参数 说明
-R 递归
-v 详细
-c 只显示变更

实战示例

chgrp -R www-data /var/www/html

与chown效果类似,但只改变组,不改变所有者。

5.2 用户管理

useradd/userdel/usermod

创建、删除、修改用户账户

语法

useradd [options] username
userdel [options] username
usermod [options] username

常用参数

命令 参数 说明
useradd -m 创建用户主目录
useradd -s /bin/bash 指定登录Shell
useradd -G group 添加到附加组
useradd -d /home/path 指定主目录
useradd -u UID 指定UID
useradd -e YYYY-MM-DD 账户过期日期
useradd -M 不创建主目录
userdel -r 同时删除主目录和邮件
usermod -aG group 添加到组(不退出其他组)
usermod -l newname 修改用户名
usermod -L 锁定账户
usermod -U 解锁账户

实战示例

场景一:创建系统用户

useradd -r -s /sbin/nologin -M nginx

-r创建系统用户(UID<1000),-s指定不可登录的shell,-M不创建主目录。这常用于运行服务的系统账户。

场景一:创建普通用户

useradd -m -s /bin/bash -G sudo,developers john

创建普通用户john,主目录,bash shell,添加到sudo和developers组。

场景三:修改用户组

usermod -aG docker john

把用户john添加到docker组,-a必须与-G配合使用,否则会离开其他组。

passwd

设置或修改用户密码

语法

passwd [options] [username]

常用参数

参数 说明
-l 锁定账户(不能登录)
-u 解锁账户
-d 删除密码(无密码登录)
-e 强制下次登录改密码
-S 显示密码状态

实战示例

场景一:修改自己密码

passwd

普通用户只能修改自己的密码。

场景二:修改其他用户密码

passwd john

root用户可以修改任意用户密码。

场景三:锁定/解锁账户

passwd -l john
passwd -u john

锁定账户后,用户不能使用密码登录,但仍可能有SSH密钥登录。完全禁用SSH需要修改sshd_config。

id

显示用户和组的信息

语法

id [options] [username]

常用参数

参数 说明
-g 只显示主要组ID
-G 显示所有组ID
-n 显示名称而非数字ID
-u 只显示用户ID

实战示例

id john
# 输出: uid=1000(john) gid=1000(john) groups=1000(john),27(sudo),1002(docker)

第六章:文本处理与管道

Linux的哲学是"小工具,组合用"。文本处理是运维的核心技能,grep、sed、awk被称为Linux三剑客,配合管道可以实现强大的数据处理能力。

6.1 文本搜索

grep

在文本中搜索匹配的行,是使用最频繁的命令之一

语法

grep [options] pattern [file...]

常用参数

参数 说明
-i 忽略大小写
-v 显示不匹配的行
-n 显示行号
-c 计数匹配行数
-r 递归搜索目录
-l 只显示文件名
-L 显示不包含匹配的文件名
-w 匹配整个单词
-x 匹配整行
-A n 显示匹配行及后n行
-B n 显示匹配行及前n行
-C n 显示匹配行及前后n行
-E 使用扩展正则表达式
-f file 从文件读取模式

实战示例

场景一:基本搜索

grep "error" /var/log/nginx/access.log

在日志文件中搜索包含error的行。

场景二:忽略大小写

grep -i "error" /var/log/syslog

-i忽略大小写,匹配Error、ERROR、error等。

场景三:显示行号和上下文

grep -n -C 3 "failed" /var/log/app.log

-n显示行号,-C 3显示匹配行及其前后3行。排查问题时非常有用。

场景四:递归搜索

grep -r "database" /var/www --include="*.php"

递归搜索PHP文件中包含database的文件。--include可以限制文件类型。

场景五:统计匹配数量

grep -c "GET" /var/log/nginx/access.log

-c计数匹配行数。快速统计接口访问量:grep -c "GET /api/user" access.log

场景六:使用正则表达式

grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" /var/log/access.log

-E使用扩展正则,匹配IP地址格式的行。

💡 运维经验

  • 多文件搜索:grep支持同时搜索多个文件。grep pattern file1 file2 file3grep pattern *.log
  • 颜色高亮:grep默认在终端中高亮匹配内容。如果颜色没有显示,使用--color=auto或--color=always。
  • 管道组合:grep是管道大师。常见组合:cat log | grep ERROR | wc -l统计错误数量、dmesg | grep -i error搜索内核错误。
  • 二进制文件:grep默认会尝试匹配二进制文件。使用-I忽略二进制文件,或使用-BINARY files=without-match。

6.2 流编辑器

sed

流编辑器,用于文本替换、删除、插入等操作

语法

sed [options] 'script' [file...]

常用命令

命令 说明
s/pattern/replacement/ 替换
d 删除
p 打印
i\ 在行前插入
a\ 在行后追加
= 打印行号
q 退出

常用参数

参数 说明
-n 静默模式,不打印行
-i 直接修改文件
-i.bak 修改前备份
-e 多个脚本
-r 使用扩展正则

实战示例

场景一:基本替换

sed 's/old/new/' file

将每行第一个old替换为new。默认只替换第一个匹配。

场景二:全局替换

sed 's/old/new/g' file

g表示全局替换,每行的所有匹配都会被替换。

场景三:原地修改

sed -i 's/old/new/g' file

-i直接修改文件。建议先不加-i测试:sed 's/old/new/g' file查看效果。

场景四:删除行

sed '/pattern/d' file

删除包含pattern的行。配合grep -v类似效果。

场景五:打印指定行

sed -n '1,10p' file
sed -n '5p' file

-n静默模式,p打印。显示第1到10行,或第5行。

场景六:多命令组合

sed -i -e 's/old1/new1/g' -e 's/old2/new2/g' file

-e可以添加多个编辑命令。

awk

强大的文本分析工具,适合处理结构化文本

语法

awk [options] 'pattern {action}' [file...]

内置变量

变量 说明
$0 整行
$1,$2,... 第N个字段
NF 字段总数
NR 行号
FNR 当前文件行号
FS 字段分隔符
OFS 输出字段分隔符
RS 行分隔符
ORS 输出行分隔符

实战示例

场景一:打印特定字段

awk '{print $1, $3}' file

打印第1和第3个字段,默认以空格/tab分隔。

场景二:指定分隔符

awk -F: '{print $1, $7}' /etc/passwd

-F指定冒号为字段分隔符,打印用户名和登录Shell。

场景三:条件过滤

awk '$3 > 100 {print $1, $3}' file

只打印第3个字段大于100的行。

场景四:计算统计

awk '{sum+=$1} END {print sum}' file

计算第1列的总和。常用于日志统计。

场景五:格式化输出

awk 'BEGIN {printf "%-10s %-10s\n", "Name", "Score"} {printf "%-10s %-10s\n", $1, $2}' file

BEGIN块初始化,printf格式化输出。

💡 运维经验

  • awk vs grep vs sed:grep用于搜索、sed用于行编辑、awk用于复杂分析。当需要字段提取、计算统计时,awk是首选。
  • 性能:awk比shell循环快得多。处理大日志文件时,用awk替代while read循环。
  • 多文件处理:awk可以处理多个文件。FILENAME变量包含当前文件名,FNR是当前文件的行号。

第七章:进程管理与任务调度

进程是运行中的程序。在服务器运维中,我们经常需要让程序在后台运行、管理定时任务、保持服务持续运行。本章介绍nohup、screen、crontab等实用工具。

7.1 后台进程管理

nohup

使进程忽略SIGHUP信号,即使终端退出进程仍继续运行

语法

nohup command [&]

实战示例

场景一:后台运行程序

nohup python app.py > app.log 2>&1 &

让Python程序在后台运行,即使关闭终端也不会停止。输出重定向到app.log,2>&1将错误也重定向到日志末尾加&让命令在后台执行。

场景二:查看nohup进程

ps aux | grep python
jobs -l

查看nohup启动的进程。jobs命令只能在当前终端查看。

💡 运维经验

  • 输出重定向:nohup默认会创建nohup.out文件保存输出。如果不使用重定向,输出会写入当前目录或主目录。明确指定输出位置是更好的习惯。
  • screen vs nohup:nohup适合简单场景,screen提供完整的终端会话。screen可以" detach"会话,在任何终端重新"attach"。生产环境推荐使用systemd管理长期服务。

screen

终端复用器,创建可分离的持久会话

常用命令

命令 说明
screen -S name 创建命名会话
screen -ls 列出所有会话
screen -r [name] 重新连接会话
screen -d [name] 强制分离会话
Ctrl+a d 分离当前会话
Ctrl+a \ 杀死当前会话
Ctrl+a c 创建新窗口
Ctrl+a n/p 下一个/上一个窗口

实战示例

场景一:创建持久会话

screen -S deploy

创建名为deploy的screen会话。进入后可以运行部署脚本,即使SSH断开也不受影响。

场景二:管理会话

screen -ls
screen -r deploy

列出所有screen会话,重新连接到deploy会话。

场景三:会话分离与重连

# 在screen中按 Ctrl+a d 分离会话
# 重新SSH连接后
screen -r

7.2 定时任务

crontab

定时任务调度器

语法

crontab [options]
crontab -e
crontab -l
crontab -r

时间格式

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

特殊字符:

    • 任意值
  • , 列表值,如1,3,5
    • 范围,如1-5
  • / 步进,如*/5每5分钟

常用示例

# 每分钟执行
* * * * * /path/to/script.sh

# 每天凌晨3点
0 3 * * * /path/to/backup.sh

# 每周日凌晨4点
0 4 * * 0 /path/to/cleanup.sh

# 每月1日凌晨5点
0 5 1 * * /path/to/monthly.sh

# 每5分钟
*/5 * * * * /path/to/monitor.sh

# 多个时间点:每天9点和18点
0 9,18 * * * /path/to/task.sh

实战示例

场景一:编辑定时任务

crontab -e

打开编辑器(通常是vi或nano)编辑当前用户的crontab。保存后自动安装。

场景二:查看定时任务

crontab -l

列出当前用户的所有定时任务。

场景三:删除所有定时任务

crontab -r

删除当前用户的整个crontab。危险操作。

场景四:系统级定时任务

# 系统级cron文件位置
/etc/crontab
/etc/cron.d/
/etc/cron.daily/
/etc/cron.hourly/
/etc/cron.weekly/
/etc/cron.monthly/

系统级任务建议放在/etc/cron.d/目录,格式略有不同,需要指定用户。

💡 运维经验

  • 环境变量:cron执行时使用最小环境,PATH和HOME可能与交互shell不同。使用绝对路径或在脚本开始时设置环境变量。
  • 输出处理:cron任务的输出会发送到本地邮件或被丢弃。建议重定向输出到日志文件以便排查:0 3 * * * /path/to/script.sh >> /var/log/script.log 2>&1
  • 时区问题:cron使用系统时区。如果需要按特定时区执行,设置TZ环境变量:TZ=Asia/Shanghai 0 9 * * *
  • 重叠执行:如果任务执行时间可能超过间隔,设置锁防止重叠:flock -n /tmp/task.lock /path/to/task.sh

第八章:磁盘与存储管理

磁盘空间是服务器最常见的资源瓶颈之一。本章介绍磁盘分区、挂载、RAID、LVM等存储管理技术,以及常见的磁盘问题排查方法。

8.1 磁盘与分区管理

fdisk/parted

磁盘分区工具

fdisk用法

fdisk -l
fdisk /dev/sdb

常用fdisk命令(进入交互模式后)

命令 说明
p 打印分区表
n 创建新分区
d 删除分区
t 改变分区类型
w 写入并退出
q 不保存退出

parted用法

parted /dev/sdb
parted -l

parted支持超过2TB的磁盘(GPT),fdisk只支持MBR(2TB限制)。

实战示例

场景一:查看磁盘分区

fdisk -l

列出所有磁盘和分区信息。

场景二:创建新分区

fdisk /dev/sdb
# 依次输入:n, p, 1, 回车, +100G, w

创建1个100GB的主分区。

8.2 挂载管理

mount/umount

挂载和卸载文件系统

语法

mount [-t type] [-o options] device mountpoint
umount mountpoint|device

常用参数

参数 说明
-t 文件系统类型(ext4,xfs,nfs,cifs等)
-o ro 只读挂载
-o rw 读写挂载
-o remount 重新挂载
-o noatime 不更新访问时间(提升性能)
-o loop 挂载镜像文件

实战示例

场景一:挂载分区

mount /dev/sdb1 /mnt/data

将sdb1分区挂载到/mnt/data目录。

场景二:重新挂载(修改选项)

mount -o remount,ro /mnt/data

将已挂载的目录重新以只读方式挂载。救援场景常用。

场景三:挂载NFS

mount -t nfs 192.168.1.100:/share /mnt/nfs

挂载NFS共享目录。

场景四:挂载ISO镜像

mount -o loop /path/to/image.iso /mnt/iso

以loop设备挂载ISO镜像。

/etc/fstab

静态文件系统表,开机自动挂载配置

格式

# <device> <mount point> <type> <options> <dump> <fsck>
/dev/sdb1    /mnt/data    ext4    defaults    0       0
192.168.1.100:/share /mnt/nfs nfs defaults 0 0

💡 运维经验

  • 挂载选项:生产环境中,重要数据分区建议添加nofail选项(挂载失败不影响开机),以及noatime提升性能。
  • 只读挂载:当文件系统损坏时,尝试以只读挂载只读方式挂载可能可以读取部分数据:mount -o ro,remount /dev/sda1
  • 卸载失败:umount报"device is busy"时,使用lsof +D /mountpoint查找占用进程,或用fuser -mv /mountpoint定位。

附录:运维救火备忘录

本附录汇总最常用的紧急故障处理命令,在紧急情况下可以快速参考。

磁盘问题

问题 排查命令
磁盘满了 df -h
inode耗尽 df -i
查找大文件 du -sh /* 2>/dev/null \| sort -rh \| head -10
查找大目录 du -h --max-depth=1 / \| sort -rh \| head -10
已删除但未释放 lsof \| grep deleted
磁盘IO高 iostat -x 1 5

内存问题

问题 排查命令
内存使用 free -h
OOM杀进程 dmesg \| grep -i "out of memory"
内存泄漏进程 top -o %MEM
进程内存详情 pmap -x PID

CPU问题

问题 排查命令
CPU负载 uptime
实时CPU top -1
高CPU进程 ps aux --sort=-%cpu \| head -10
多核负载 mpstat -P ALL 1 5

网络问题

问题 排查命令
网络连接 ss -tunap
端口占用 lsof -i:PORT
连通性测试 ping host
路由追踪 traceroute host
DNS解析 dig host
TCP抓包 tcpdump -i eth0 port 80

进程问题

问题 排查命令
查找进程 ps aux \| grep name
进程树 pstree -p PID
打开文件 lsof -p PID
线程数 ps -eLf \| grep PID
杀死进程 pkill -9 name

服务问题

问题 排查命令
服务状态 systemctl status service
服务日志 journalctl -u service -n 50
服务重启 systemctl restart service
查看failed服务 systemctl list-units --failed

日志问题

问题 排查命令
系统日志 journalctl -xe
内核日志 dmesg
认证日志 tail -f /var/log/secure
定时任务日志 tail -f /var/log/cron
搜索错误 grep -i error /var/log/syslog

快速健康检查

# 系统整体状态一行命令
echo "=== Load ===" && uptime && echo "=== Memory ===" && free -h && echo "=== Disk ===" && df -h && echo "=== Top5 CPU ===" && ps aux --sort=-%cpu | head -6 && echo "=== Top5 MEM ===" && ps aux --sort=-%mem | head -6

本手册完
祝你的运维之路顺利