ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Linux系统管理实战:从用户权限到运维脚本的完整进阶指南

Linux系统管理实战:从用户权限到运维脚本的完整进阶指南 开门见山说个事如果你只会cd、ls、cp这些命令那还停留在“会用 Linux”的阶段而真正让 Linux 发挥价值、也是工作中拉开差距的是“把 Linux 管好”的能力——用户权限怎么控、磁盘存储怎么挂、进程之间怎么协作、多台机器怎么共享网络、以及怎么把日常重复操作固化成脚本。这篇《Linux基础下》就是围绕这五块展开的。适合刚学完基础命令、准备进入系统管理和运维方向的人看也适合那些面试前想系统梳理一遍 Linux 核心知识点的同学。内容会有不少实操细节都是我在日常维护服务器时踩过坑之后总结出来的。1. 从“会敲命令”到“管好系统”用户、权限与sudo机制1.1 权限模型读懂了它你就读懂了半个LinuxLinux 是个多用户操作系统这个“多用户”不是概念上的而是设计上的一切资源都围绕“用户”来分配。文件有属主、属组进程有运行身份服务有启动账号。理解权限本质上是理解三个问题我是谁uid/gid、我能访问什么rwx、我能让谁替我执行什么sudo/setuid。一条文件权限信息长这样-rw-r--r-- 1 root root 1234 Mar 8 10:00 app.conf从左往右拆第一个字符是文件类型-普通文件、d目录、l软链接、b/c设备文件后面九位分成三组分别是属主u、属组g、其他人o的权限每组三位是r读、w写、x执行。目录的x比较特殊它表示“能否进入这个目录”没有x权限的话即使有r也进不去。我见过不少新手把权限理解为“按用户名精确匹配”其实 Linux 的权限检查是有固定顺序的先看你是不是文件的属主是就直接套用属主权限不是再看你是不是文件属组的成员是就套用属组权限都不是才走“其他”权限。这个顺序意味着如果你是属主但属主权限是rw-哪怕你的用户也在属组里、属组有r-x你也不能执行因为第一条匹配就结束了。除了基础的 rwx还有三个特殊位setuid数字表示 4、setgid2、sticky1。setuid最典型的就是/usr/bin/passwd普通人能改密码靠的就是这条文件带上了 setuid 位执行时临时以 root 身份运行。sticky位体现在/tmp目录上drwxrwxrwt里的t表示在这个目录下只有文件属主或 root 才能删除自己的文件大家都能建文件但不能互删。1.2 sudo的配置与坑不是所有root都是rootsu是切到另一个用户代价是你得知道那个用户的密码sudo是“用其他身份执行命令”通常是 root但只需要输入自己密码就行。生产环境我强烈不建议用su - root长期切到 root 操作一个手误可能就是删库跑路真心想用 root 应该通过 sudo 按需提权。sudo 的配置在/etc/sudoers一定用visudo改它会在保存前做语法检查避免写错导致 sudo 整个不可用。常用写法就几种# 给用户 wang 所有命令的 sudo 权限 wang ALL(ALL:ALL) ALL # 给 wheel 组所有成员 sudo 权限且不需要密码 %wheel ALL(ALL:ALL) NOPASSWD:ALL # 只允许指定命令 ops ALL(root) /usr/bin/systemctl, /usr/bin/journalctl第三个写法在运维里很有用让普通用户能重启某个服务但给不了 shell权限边界控制得干净。这里有个实际坑很多人配置了 NOPASSWD 之后发现脚本里sudo还是提示要密码十有八九是 sudoers 里前面有一条Defaults requiretty或者规则顺序覆盖问题。sudoers 是按从上到下匹配的后配置的规则可能被前面更宽的规则盖住。记住一个原则更具体的规则放在前面更宽松的规则放后面同级别规则后面的生效。1.3 新建用户背后的完整流程我之前看人创建用户就一个useradd testuser然后用不了因为连家目录都没有。完整地建一个能登录、能管理、环境干净的用户建议这样useradd -m -G wheel -s /bin/bash testuser passwd testuser-m创建家目录并复制/etc/skel下的模板文件-G wheel把用户加入管理组-s指定登录 shell。创建命令背后的文件变化关系到你对系统的理解/etc/passwd用户基本信息包括 uid、gid、家目录、shell/etc/shadow密码哈希和过期策略只有 root 能读/etc/group组信息和组内成员我看过很多面试题让人解释/etc/passwd里密码字段为啥是x其实就是因为真实密码在 shadow 里passwd 文件是全局可读的不能放哈希。日常管理用户很少需要用usermod改大项但有个细节容易被忽略用户 A 要加入用户 B 的附属组来协作文档时A 必须重新登录一次组权限才会生效。偶尔遇到画面明明刚把用户加入组登录进去组还是进不去于是怀疑配置写错。其实 Linux 的组缓存目前只生效在会话创建的时刻。2. 存储实战分区、文件系统与NAS挂载2.1 Linux如何“看到”一块新磁盘Windows 插个 U 盘自动分配盘符Linux 则完全不一样——它把一切都抽象成文件。磁盘设备在/dev/下比如sda、sdb、nvme0n1需要用lsblk查看块设备关系这是排查磁盘问题的第一工具。lsblk # NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT # sda 8:0 0 100G 0 disk # ├─sda1 8:1 0 1G 0 part /boot # └─sda2 8:2 0 99G 0 part /新磁盘拿到手步骤是分区或直接建文件系统、挂载。如果只是当数据盘整块用可以省掉分区直接格式化mkfs.xfs /dev/sdb mkdir -p /data mount /dev/sdb /data这里选 xfs 还是 ext4取决于场景xfs 擅长大文件和高吞吐是 RHEL/CentOS/Rocky 系的默认ext4 老牌稳妥小文件场景和旧工具链兼容性更好。SSD 上两者差异在新内核里已经没那么明显别为了“性能极致”陷入玄学稳定大于一切。分区工具我用得最多的是fdisk和parted。超过 2T 的盘必须用parted GPT 分区表fdisk默认 MBR 到 2T 就到顶了。这块面试也常考。2.2 挂载NAS存储从手动 mount 到开机自动挂载处理 Linux 服务器时很大概率要挂网络存储最常见的两种协议是 NFSLinux 之间和 CIFS/SMB和 Windows 或 NAS 设备对接。命令并不难真正的坑在挂载选项上。# NFS 方式假设 NAS 导出的目录是 /volume/share apt install -y nfs-common # Debian/Ubuntu yum install -y nfs-utils # RHEL/Rocky mount -t nfs4 -o rw,vers4.1 192.168.1.10:/volume/share /mnt/nas # CIFS 方式NAS 通常需要账号密码 apt install -y cifs-utils mkdir -p /mnt/nas mount -t cifs //192.168.1.10/share /mnt/nas -o usernamenasuser,passwordxxx,uid1000,gid1000几个实际经验NFS 默认用root_squashroot 在 NFS 服务端会被压制成 nobody所以客户端用 root 写的文件服务端打开一看属主是 nobody这是特性不是故障。CIFS 挂载时一定要指定uid/gid或/etc/fstab里的uid选项否则文件全归 root普通用户只能干瞪眼。挂载 NAS 的_netdev选项很重要它告诉系统“这是网络设备等网络起来后再挂”不加的话开机时网络没准备好挂载会失败系统甚至可能卡在等待。开机自动挂载配置在/etc/fstab里典型一行192.168.1.10:/volume/share /mnt/nas nfs4 defaults,_netdev,noatime 0 0写完 fstab 建议先执行mount -a验证语法否则配置写错重启后系统会进入 emergency mode那种局面在机房远程操作时特别痛苦。千万别把所有鸡蛋放进 fstab能自动挂载的盘自己测过再往里写。2.3 磁盘空间排查三板斧“服务器磁盘满了”是我处理过最多的告警之一。排查三板斧df -h看文件系统整体使用率du -sh *看当前目录下谁吃空间lsof L1看已删除但还被进程占用的文件。第三个命令很多人不知道某个进程删了日志文件但没释放句柄df看到空间没回来du却找不到大文件。这时候lsof L1 | grep deleted能找到那个还握着文件句柄的进程重启它或清空句柄就释放空间了。再提供一个冷知识点df -h和df -i的区别。-h看数据块-i看 inode。当磁盘“没满”但建不了新文件时多半是 inode 耗尽——小文件太多把 inode 表占满了。碰到这种就往 /tmp 或日志目录查删一批小文件df -i的数字马上降下来。3. 进程管理看穿系统里正在发生什么3.1 ps、top与信号机制进程管理是 Linux 系统管理的核心地盘。日常查看进程两条命令足矣ps aux # 所有进程CPU/内存排序看 ps -ef # 进程树父子关系更清晰 top -c # 动态刷新按 P 按 CPU 排、按 M 按内存排但“看”只是第一步真正控制进程靠的是信号。kill不只是“杀死”的意思它是发信号。常用信号有SIGTERM15默认请求进程正常退出、SIGKILL9内核直接强制终结进程没有任何机会清理资源、SIGHUP1终端挂断nginx 用它重载配置收得更平滑、SIGUSR1/2自定义业务信号。实操经验能用kill -15就不要用kill -9。原因很简单数据库或应用在收到 SIGTERM 时能做收尾刷缓存、关连接、写日志。直接 SIGKILL 的话进程状态可能残留在共享内存或文件锁里服务能拉起来但丢数据、锁卡死是常有的事。先说一句kill -9像搬家时直接把房子炸了东西全砸在里面kill -15才是正常退租。批量操作时用pkill或killall但得小心后者是按名字匹配的比如killall java会把机器上所有叫 java 的进程全干掉。所以线上环境我推荐先pgrep进程查询配合正则确认目标再 kill别拿生产环境练手。3.2 进程间通信入门管道、共享内存与SocketLinux 面试题里有一类必考进程间通信方式有哪些。理解它的本质是搞明白“进程之间为什么需要通信”以及“通信双方的亲密程度不同方案就不同”。管道pipe内存里的一条单向数据流适合父子进程或同家族进程比如ps aux | grep nginx抓管道两端就是两个进程在协作。信号signal轻量级异步通知适合“我告诉你一声”的场景不适合传大量数据。共享内存shared memory效率最高多个进程直接读写同一块内存但需要自己控制并发一般配合信号量使用。消息队列message queue内核维护的消息链表比共享内存安全天然有边界每条消息有长度适合应用层通信但会有拷贝开销。Socket套接字适用范围最广既能走本机也能跨机器。你访问网站、连数据库底层都是 Socket。实际业务开发中我接触最多的是 Socket 和消息队列。命令行的 grep/awk 组合依赖最多的则是管道。作为系统管理员不必急着学所有底层机制但要清楚管道是命令行的粘合剂Socket 是服务间通信的主流共享内存是追求极致性能时的选择。3.3 给进程改名字一种实际可用的做法“修改进程名称”这个话题网上资料不算多场景却很真实你起了一堆 Python 脚本或 Java 进程全在进程列表里叫python3没法区分谁是谁。解决办法有两个层面高级一点的用 Python 直接修改进程名称原理是改写argv[0]和借助PR_SET_NAMEimport ctypes import sys def set_proc_name(new_name: str): # 修改 /proc/self/commtop/ps 里会显示 libc ctypes.CDLL(libc.so.6) libc.prctl(15, new_name.encode()[:15], 0, 0, 0) # 15 PR_SET_NAME # 修改 argv[0] 以让 ps -ef 里的命令显示也改变 if len(sys.argv) 1: sys.argv[0] new_name set_proc_name(my_worker_node)或者用 systemd 启动服务时直接定义好服务名[Unit] DescriptionMy Worker [Service] ExecStart/usr/bin/python3 /opt/worker/main.py一个更简单但实用的做法是启动脚本时带一个特征参数或改进程comm字段。我自己的经验是不要等到进程起来了再改而是在启动脚本里就设计好标识比如systemd服务名、shell 脚本的$0后期排查日志时能立刻定位到是什么进程、属哪个服务。直接用prctl改名字时留意进程名最长 15 个字符取太长会被截断这是我在监控脚本里发现名称不全时才注意到的。4. 网络配置与共享上网的实用解法4.1 静态IP配置以Rocky Linux 10为例过去的 RHEL 系用ifcfg-*配置文件路径/etc/sysconfig/network-scripts/ifcfg-ens33。后来 NetworkManager 全面接管现在更推荐用nmcli尤其是 Rocky Linux 10 这种新版本网络配置已经默认走 NetworkManager。# 查看连接 nmcli connection show # 修改现有连接为静态IP nmcli con mod ens33 ipv4.method manual \ ipv4.addresses 192.168.1.100/24 \ ipv4.gateway 192.168.1.1 \ ipv4.dns 223.5.5.5 8.8.8.8 nmcli con up ens33一定先nmcli connection show看连接名字很多系统里网卡叫ens33但连接名可能叫Wired connection 1。如果用前者去配置命令会直接报错“找不到连接名”这是新手第一次用 nmcli 时最容易踩的坑。静态 IP 配置好后立即ping网关、ping外部域名验证。我之前遇到过 IP 配好了、网关通、就是解析不了域名排查发现是 DNS 没生效——systemd-resolved的 stub 文件没关联上把/etc/resolv.conf手动建好指向systemd-resolved后解决。4.2 让Linux做NAT共享上网公司网段不够用或者实验室内网需要统一出口时完全可以让一台 Linux 服务器做 NAT 共享上网其他机器把网关指到它。这个做法在生产环境中也能顶替部分路由器功能。前提是这台机器有两个网卡外网口能上公网和内网口连局域网设备然后开启内核转发并配置 iptables 规则# 开启转发立即生效并持久化 echo net.ipv4.ip_forward1 /etc/sysctl.conf sysctl -p # 防火墙放行转发和 NAT firewall-cmd --permanent --add-masquerade firewall-cmd --reload # 习惯用 iptables 的可以这样 iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT iptables -A FORWARD -i eth0 -o eth1 -m state --state ESTABLISHED,RELATED -j ACCEPT然后局域网内的其他机器把 IP 设为同一网段、网关指向这台机器的内网 IPDNS 指向外网 DNS 或配置的本地 DNS 都可。这里最容易犯的错是只加了 NAT 规则忘了开 sysctl 的转发结果内网机器连网关能通、但包到 Linux 上就被丢弃一条sysctl -w net.ipv4.ip_forward1就能解决却经常被忽略大半天。检查时用ping 内网网关 - ping 网关机器外网IP - ping 公网IP - ping 域名逐段定位是哪一段断了问题就在哪一层。4.3 网络排查的常规步骤网络问题的定位思路我总结成“从下往上”链路 - 地址 - 路由 - DNS - 应用。ip addr # 网卡IP是否存在、UP还是DOWN ip route # 默认路由是否正确 ping -c 4 网关 # 二层/三层通不通 ping -c 4 8.8.8.8 # 公网通不通不要猜先确认真实IP通不通 ss -lntp # 本机监听端口列出进行中的 TCP 状态确认服务是否在监听 traceroute 目标地址 # 找出丢包点在哪一跳 dig short 域名 # 解析是否正常排查习惯比命令重要得多。很多人一上来就ping www.xxx.com不通就认为网络断了其实 ping 域名失败可能是 DNS 问题可能是 ICMP 被防火墙丢也可能是中间链路 MTU 问题。我的做法是先把“纯 IP 连通性”和“DNS 解析”拆开ping 8.8.8.8通而ping 域名不通问题就聚焦在解析层查/etc/resolv.conf和 DNS 服务器状态即可。别混在一起效率会高很多。5. 运维脚本与定时任务把重复劳动交给机器5.1 Shell脚本的真正价值Shell 脚本是 Linux 管理员绕不开的“胶水”。它不需要像 Python 那样考虑依赖和库天生就是命令的组合器。判断一个运维脚本写得好不好的标准很简单可读、可控、可重跑。写脚本最底层的习惯#!/usr/bin/env bash set -euo pipefail # 遇到错误退出、变量未定义报错、管道中出错即失败这三行是我所有脚本的固定开头。set -e防止脚本在某些命令失败后继续执行到更危险的地方set -u防止变量拼错导致莫名其妙的错误值set -o pipefail防止管道命令“前面失败了前面无伤大雅”的假象。没写这三行之前我的备份脚本因为某个tar命令静默失败等到恢复数据时才发现备份是坏的——从那以后这三行成了铁律。5.2 定时任务cron的写法与排查定时任务用crontab -e编辑当前用户的任务格式是五个时间字段加命令# 分 时 日 月 周 命令 */5 * * * * /usr/local/bin/check_health.sh /var/log/health.log 21 0 2 * * * /usr/local/bin/backup.sh /var/log/backup.log 21cron 有几个不太友好的点我吃过亏老朋友也踩过cron 环境变量极其精简脚本里的PATH可能只有/usr/bin:/bin导致脚本里调用的命令找不到。解决方法是脚本头部显式定义export PATH/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin。cron 不会自动把输出发到邮件一般都要自己重定向到日志文件并且按日期切分。想确认任务是否执行查/var/log/cron即可很多问题其实是脚本执行了但报错日志全被冲掉了。5.3 常用运维命令的组合拳命令单独学很容易难的是组合。下面这些是我用得最频繁的组合敲多了就自然成为肌肉记忆# 查找占用8080端口的进程PID并强制结束 fuser -k 8080/tcp # 查看所有监听端口的对应进程 ss -lntp | awk {print $6} # 日志里统计接口请求次数与TOP IP awk {print $1} /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20 # 找到大于10G的文件 find / -type f -size 10G -exec ls -lh {} \; # 把当前目录所有普通文件按大小排序展示 find . -maxdepth 1 -type f -printf %s %p\n | sort -n | tail -10 # 批量重命名备份文件 for f in *.conf; do cp $f $f.bak_$(date %Y%m%d); done这些都涉及到管道把不同的小工具串起来数据从一个命令流转到下一个命令。理解了管道思想awk grep sed xargs sort uniq就会像乐高积木一样在手里自由搭。我始终觉得脚本是“把你自己犯过的错固化下来”的工具流程里有一步容易漏、容易错就把它写进脚本每次自动跑比记在笔记里可靠得多。运维的很多价值不是“操作快”而是“不用操作”。最后再分享一个个人心得想真正掌握 Linux光看是不行的去虚拟机里开两台机器一台做 NAT一台做客户端把《Linux基础下》里的内容完整过一遍比看十篇博客都有用。遇到问题时优先看man文档和系统自带日志比如/var/log/messages真能告诉你绝大多数故障的真相。Linux 是越用越熟的别怕敲错命令——只要别在生产环境不假思索地复制执行就大胆去试吧。
返回列表