ARTICLE DETAIL

资讯详情

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

Linux核心指令精讲:权限、用户、进程与软链接实战

Linux核心指令精讲:权限、用户、进程与软链接实战 每个人都会经历从会敲命令到真正开始用 Linux 干活的转变。系列第一篇里我们搞定了文件系统的基本操作cd、ls、cp、mv、rm以及用 less 和 cat 看文件内容用 man 查帮助。这些指令足够你日常浏览目录但离像个管理员一样思考还差一段距离。这篇【2】我要聊的是真正让 Linux 变得稳的那批指令权限、用户、文本处理、压缩、进程监控、软链接和 PATH。它们不一定花哨但每一个都是生产环境里天天要用到的东西也是新手最容易出事故的雷区。为什么要专门写这一批基础指令因为 Linux 的入门门槛不是说你会几个命令就完事了而是你的思维模式要切换到一切皆文件、权限即安全、组合即效率的频道上来。这篇文章不会带你背命令字典而是把每个指令背后为什么这么设计实际使用时该注意什么讲透并配上可以直接照做的实操步骤。适合刚学完 Linux 基本操作、开始接触服务器运维的初学者也适合那些想把零散命令整理成体系、准备面试的人。我尽量用大白话把原理说清楚遇到坑也会直接指出来这些都是我自己在服务器上踩过的。1. 权限管理数字其实比符号更好用1.1 先搞懂 r/w/x 的本质才能理解三位数字Linux 权限这块最劝退新手的就是那串-rwxr-xr--。但如果你把它拆开看其实超级简单。它一共分四段第一段是一个字符表示类型-是普通文件d是目录l是软链接。后面三段每三个一组分别代表属主u属组g其他用户o的权限。每组的三个位置依次是 r读、w写、x执行。这里最需要动脑子的是r/w/x 对文件和目录的含义不一样。对文件来说r 表示能查看内容w 表示能修改内容x 表示能执行这个文件。但对目录来说语义完全变了r 表示能列出目录里有什么ls 一下w 表示能在目录里新增或删除文件x 表示能进入这个目录cd 进去。很多人被目录权限搞晕就是因为没想通这一点。我自己最常用的记忆法是目录的 x 是通行证没有 x 你就进不了门r 是目录清单有 x 没 r你能进去但不知道里面有什么w 是维护权能不能在里面放东西、删东西就看它。理解了这层再看chmod 755chmod 644就不会瞎猜了。1.2 实操快速把项目目录权限改到安全状态数字法就是把 r、w、x 分别当成 4、2、1三个权限相加得到一个 0 到 7 的数。r4w2x1rwx7rw-6r--4-wx3。chmod 755的含义是属主 7、属组 5、其他人 5。755 太常用了基本所有网站的目录、脚本、可执行程序都用它属主什么都能干其他人和属组只能读和执行不能写。我处理一个项目的标准流程是# 先看当前权限 ls -l project/ # 目录统一 755文件统一 644 find project/ -type d -exec chmod 755 {} \; find project/ -type f -exec chmod 644 {} \; # 如果有脚本需要执行权限单独给 chmod x project/run.sh为什么这么折腾而不是直接chmod 755 project/ -R因为生产环境里目录和文件的权限语义不同目录需要 x 才能进入文件通常不需要 x。你把所有文件都给了 755等于每个文本文件都可执行这个习惯非常差。批量改权限时我强烈建议目录、文件分开处理。还有配置文件、私钥这类敏感文件权限要收到 600 或 400别偷懒。1.3 经常翻车的权限细节chown、umask、递归改完权限就该改属主属组了这个不用怀疑直接用chown -R www-data:www-data /var/www/html # -R 递归属主:属组 连在一起很多新手的误区是只改属主不改属组。在 Nginx 或者 PHP-FPM 的场景下进程是用www-data用户跑的你文件属主写的 root属组写的 root那进程可能连读都读不了。这时候正确的做法是把属组改成和进程一致并且把权限里的组权限留够。还有chown是可以只改属主或者只改属组的chown root file只改属主chown :root file只改属组这一个小细节能救命。再说umask。它是创建新文件时默认权限的减数。系统默认一般是 022意思就是文件创建后最大权限 666 减去 022 得 644目录最大权限 777 减去 022 得 755。为什么新文件不是 644 以上因为任何新文件都不该默认带执行权限这是安全底线。如果你发现系统里新创建的文件权限不对先查 umaskumask # 临时改成 027 试试 umask 027我把这章放在第一位的另一个原因是Linux 排障时权限问题占了半壁江山。网站打不开先看目录权限程序启动失败先看日志文件权限SSH 登录不了先看.ssh目录权限是不是 700、authorized_keys是不是 600。养成这种条件反射后面省很多事。2. 用户与用户组建号、给权、改密的完整套路2.1 useradd 和 adduser 的区别要分清初期最容易困惑的是useradd和adduser到底用哪个。这里有个经验总结在 CentOS/RHEL 系里useradd就是底层命令在 Debian/Ubuntu 系里adduser是个对用户更友好的封装脚本它会引导你设置密码、创建家目录、填用户信息。我自己的习惯是脚本里用useradd因为它参数明确、行为可控手动操作时反而喜欢adduser省事。但useradd有个巨坑默认情况下它不创建家目录。很多新手在 Ubuntu 上执行useradd zhangsan然后发现没有/home/zhangsan一脸懵。这不是系统坏了是缺参数。正确做法useradd -m -s /bin/bash -G devops -c Zhang San zhangsan拆解一下-m创建家目录-s指定登录 shell 为 bash-G把用户加入附属组 devops-c是备注。如果不加-s /bin/bash系统可能给用户分配sh登录以后命令行难受得想哭。如果忘记加-G后面可以用usermod -aG devops zhangsan补上注意一定要带-aappend不然用户会被从之前的组里踢出去。2.2 实操验收一个能登录、能 sudo 的新用户创建完用户之后还要过一遍验收流程我也是踩过坑才总结出来的# 1. 先确认用户信息 id zhangsan # 2. 设置用户密码密码不会显示在屏幕上 passwd zhangsan # 3. 验证家目录、shell、所属组 ls -ld /home/zhangsan grep zhangsan /etc/passwd # 4. 把用户加进 sudo 组 usermod -aG wheel zhangsan # CentOS 用 wheel usermod -aG sudo zhangsan # Ubuntu 用 sudo这里有一个我自己从业以来反复看到的事故给用户加了 sudo 权限但用户执行sudo时报错 zhangsan is not in the sudoers file。原因就是加错组了或者忘记带-a导致用户原有的组被清掉。还有如果你改了/etc/sudoers别直接编辑用visudo它会在保存时做语法检查能防止你把整个 sudo 配置搞坏导致 root 都无法授权。关于 su 和 sudo我的态度很明确多用 sudo少用 su。su是切换用户su -切换成 root 并加载 root 的环境变量意味着你拿到的是一个完整 shell后续操作没有任何审计记录。sudo 是单条命令提权执行什么写得很清楚。团队协作时sudo 配 sudoers 规则可以让一部分人只允许执行特定命令比如只允许重启某个服务这比把 root 密码发给大家靠谱得多。2.3 密码过期与用户删除的细节用户管理不只是建号还有养号和销号。密码策略这块和系统安全强相关。用chage可以设置密码过期时间chage -M 90 zhangsan # 密码 90 天后必须改 chage -l zhangsan # 查看密码过期策略强制用户下次登录改密码的写法是chage -d 0 zhangsan这样用户一登录就会收到 You are required to change your password immediately 的提示。这个指令在给临时账号、外包同事建号时特别好用。删除用户的完整姿势是userdel zhangsan # 删用户 userdel -r zhangsan # 连同家目录和 mail spool 一起删-r会把家目录一起清掉但不会把用户之前创建的文件也删干净。如果你删用户前没检查他名下还有什么文件find / -user zhangsan扫一遍不然会留下大量无主文件后面运维会很难受。3. 文本处理基础grep、sort、uniq、wc 的组合拳3.1 grep 不只是查函数它逐行工作凡是靠文本输出信息的系统都能用 grep 过滤。你写 Nginx 配置、看日志、查进程、查环境变量几乎每一步都可能用到 grep。它的本质是一行一行读输入只要这一行匹配你给的模式就打印出来。grep root /etc/passwd会输出所有包含 root 的行就这么简单。常用的参数我列个速查参数作用示例-i忽略大小写grep -i error app.log-v反向匹配排出掉匹配行grep -v ^# nginx.conf-E扩展正则支持 | 和 grep -E error|failed app.log-w精确匹配整个单词grep -w error app.log不会匹配errors-c只统计匹配行数grep -c failed app.log-l只列出包含匹配内容的文件名grep -l error *.log-r递归搜索目录grep -r listen /etc/nginx/我碰到最多的新手问题是以为 grep 的参数放在文件名后面也行比如grep error app.log -i。语法上 Ubuntu 的 GNU grep 确实能解析但为了统一和不出错规矩点写grep -i error app.log。另一个老坑是搜中文日志终端乱码匹配不到中文关键词。这种情况可以先查日志文件的编码再把终端编码调一致不然 grep 进去就是一堆乱码。3.2 实操统计访问日志里的 Top 10 IP这个场景我敢说你迟早会遇到老板丢给你一个 access.log说看看这几天哪个 IP 访问量最大、是不是攻击。shell 里的处理思路特别经典就是用管道把几个命令串起来grep 2025-06-01 access.log | awk {print $1} | sort | uniq -c | sort -rn | head -10我详细解释一下每个环节的意图。awk {print $1}是取每行第一个字段在 Nginx 默认日志格式里第一个字段就是客户端 IP。sort把相同 IP 的行排到相邻位置这一步是为uniq -c做准备的uniq只有相邻的行才能去重统计。sort -rn里的-r是倒序-n是按数值而不是字典序排序这一步很多人会漏漏了的话 100 会排在 20 前面。最后head -10只取前 10 行。这里最容易翻车的是没理解uniq只能处理相邻行。如果你直接grep ... | awk ... | uniq -c结果会一团糟同一个 IP 可能被统计成好几条。所以标准套路就是sort | uniq -c | sort -rn三个命令一步都不能省。练熟这一串后面处理日志效率会高很多。3.3 管道与重定向把命令串成流水线管道的概念我倾向于用流水线来类比grep是第一个工位把粗加工的原料放进传送带awk是第二道工序从传送带取货处理一下sort是第三个工位专门负责排好顺序。每个命令不需要关心前一个命令内部怎么实现只需要从标准输入读、往标准输出写就能自由组合。这就是 Unix 哲学小而专组合用。重定向是一个独立的重点会把前一个命令的输出写到文件里覆盖原文件是追加。2和2处理错误输出21是把标准错误也合并到标准输出里。我推荐大家一开始就把日志落盘的习惯养好nohup ./start.sh /var/log/myapp.log 21 这行命令将脚本的普通输出和错误输出写到同一个日志文件。如果不写21程序报错的信息不会出现在日志里你排查时只看到输出正常结束但程序根本没跑起来很容易被误导。4. 压缩归档tar 打包、gzip 压缩别搞混4.1 tar 的字母参数拆开理解tar 这个名字源自很久以前的磁带归档工具它的本质是打包把一堆文件拼成一个文件而 gzip 才是压缩把文件体积变小。你平时看到的.tar.gz就是先 tar 打包再 gzip 压缩两件事合在了一起。理解了这一点你再看tar -czvf就完全不慌了每一个字母都有明确含义-ccreate打包创建-z用 gzip 压缩生成.tar.gz-vverbose把处理过程打印出来-f指定归档文件名这个参数后面必须马上跟文件名所以一条常用命令tar -czvf backup.tar.gz /var/www/html意思就是把/var/www/html打成一个包再压缩命名为backup.tar.gz。解压的命令对应是tar -xzvf backup.tar.gz。-x是 extract解包-z还是要解 gzip-v、-f同理。如果想解压到指定目录用-Ctar -xvzf backup.tar.gz -C /tmp/restore/4.2 实操备份与恢复项目目录我举个例子把一个网站项目备份到另一个磁盘顺便加时间戳tar -czvf /backup/www_html_$(date %Y%m%d).tar.gz /var/www/html这里用date %Y%m%d生成日期字符串拼进文件名这样每天备份不会覆盖前一天的结果。恢复的时候关键是搞清楚备份包里第一层目录是什么tar -tzvf backup.tar.gz | head -5 # 查看包内容清单先确认路径结构 tar -xzf backup.tar.gz -C /var/www/有个坑必须提醒不要在你的备份目标目录就是包内目录的子路径时把该目录整个打包进去。举个例子你在/var/www/下运行tar -czf backup.tar.gz /var/www/html而 backup.tar.gz 就放在/var/www/里那么下一次打包含有上一次的包包越来越大。正确做法是把备份文件放到独立目录或者把-C切到上级路径再做相对路径打包。还有一个细节tar 解压时遇到同名文件会静默覆盖这既是优点也是风险。我一般会在恢复前用tar -tzvf看一眼内容确认无误必要时先临时备份旧目录再解压新的。4.3 zip 的乱码与路径坑tar 是 Linux 上的主场但当你从同事那里收到 Windows 打的 zip 包时还是会用到 zip/unzip。我的经验是把 unzip 的细节掌握好因为坑实在太多。先说乱码。Windows 默认的 zip 工具中文文件名用的是 GBK 编码Linux 默认按 UTF-8 解压中文文件名就会变成乱码。解决办法是明确指定编码unzip -O gbk files.zip这个参数在不同版本的 unzip 上行为不完全一样如果你的 unzip 版本不支持-O可以装 p7zip 用7z x files.zip替代兼容性更好。另一个问题是解压会破坏目录结构的控制权zip 包内如果包含../../../这类路径解压时可能覆盖意外位置。生产环境我很少直接用unzip而是先列出来检查一下unzip -l files.zip | head -30看看里面有多少层嵌套、有没有可疑的绝对路径再决定是全部解压还是只解压指定文件。5. 进程与系统监控看清机器在忙什么5.1 ps进程快照怎么看服务器卡了、进程挂了、端口被占了第一时间想到的指令就是ps。它给的是某一瞬间进程快照最常见的两种写法是ps -ef和ps aux。我习惯用ps -ef信息密度高且列含义清晰ps -ef # UID PID PPID C STIME TTY TIME CMD # root 1 0 0 Jun15 ? 00:00:05 /usr/lib/systemd/systemd关键列记住几个PID 是进程号PPID 是父进程号CMD 是启动命令。比如你想看 Nginx 的进程树ps -ef | grep nginx会看到 1 个 master 进程和几个 worker 进程它们的 PPID 指向 master。这对排查进程关系非常重要。如果想看更详细的资源占用用ps aux输出里会有%CPU、%MEM和VSZ/RSS。查哪个进程最吃内存ps aux --sort-%mem | head -10--sort-%mem的含义是按内存占用降序排列这条命令基本能定位性能瓶颈。5.2 top负载高的时候先看哪几列top是一个交互式监控工具打开后默认每几秒刷新一次信息。第一次看到它的界面会有点懵但关键是先看三块最上面的load average三个数分别代表过去 1 分钟、5 分钟、15 分钟的系统负载如果你是多核机器负载超过核数就说明可能过载然后是%Cpu(s)那行重点看us用户态和wa等待 I/O如果wa很高说明磁盘读写可能是瓶颈最后是进程列表按P按 CPU 排序按M按内存排序按1看每个 CPU 核的负载情况。top 本身不会告诉你问题根因它只负责指出哪里不对劲。看到某个进程 CPU 飙到 200%你还要结合lsof -p 进程号看它打开哪些文件或者strace -p跟踪它的系统调用才能定位到具体原因。不过作为基础指令top 是我们出发去追查问题的第一站。5.3 怎样温和地让进程退出kill -15 与 kill -9这个知识点值得用单独一节讲因为太多人一上来就kill -9这是我在生产环境最反感的行为。kill本身是发信号不是直接把进程杀掉。默认kill pid发的是 SIGTERM也就是信号 15作用是请你优雅退出进程有机会清理临时文件、关闭连接、保存状态。而kill -9 pid发的是 SIGKILL内核直接强杀进程没有任何机会做善后。对数据库、消息队列这类有状态的进程kill -9相当于拔电源很可能导致数据损坏。我的处理顺序是先kill pid15等几秒看进程是否还在还在再用kill -9 pid。还有一个参数看进程状态ps -ef输出里的 STAT 列Z表示僵尸进程这时候你杀不掉它因为僵尸进程已经被父进程的退出状态接管需要杀掉它的父进程或者让 init 回收。看到一堆 Z 状态大多是因为它们的父进程没有正确 wait 子进程返回这通常是程序 bug不是系统问题。5.4 nohup 后台运行的正确打开方式服务器上跑一个需要常驻的后台任务、训练脚本或者服务最朴素的方式是nohup 命令 。nohup的意思是即使终端断开、HUP 信号触发进程也不会退出。是把命令放到后台执行。但真正专业的写法是要把日志重定向的nohup python train.py train.log 21 echo $!最后的$!是刚才后台进程的 PID。为什么建议立刻 echo $!因为你要在后续 kill 它的时候有据可查。如果忘了记 PID只能pgrep -f train.py再查。很多人都用 nohup 跑 Python 训练脚本到了第二天发现服务器重启了模型没跑多半就是忘了加 nohup 或者没有重定向错误日志。6. 软链接与 PATH把常用命令收进自己的口袋6.1 一句话讲清软链接和硬链接的区别我见过很多人在面试里被这个问题问住其实就是一句话软链接是一个指向文件路径的指针硬链接是同一个文件的另一个目录入口。ln -s /original /link创建软链接它独立存在指向的是路径硬链接ln /original /link不创建新文件只是给同一个 inode 增加了一条路径所以修改任意一边另一边也会变因为本来就是同一个文件。实际使用中 90% 的场景都是软链接因为它是路径级的。比如把项目当前版本软链到 www 目录ln -s /data/releases/v2.3.1 /var/www/myapp下次新版本上线直接删掉软链接建新的指向业务无感切换。这就是发布系统里常用的symlink 切换法。6.2 突发问题ln -s 删除时加不加斜杠软链接删除这件事是我见过新手事故高发区。如果你创建了/data/releases/v2.3.1的软链/var/www/myapp现在要删掉这条软链重新指向正确命令是rm /var/www/myapp没有斜杠。如果你手滑写成rm -rf /var/www/myapp/很多版本的 rm 会把它当目录处理继续往里追最后删除的可能是软链指向的真实目录里的内容。为什么因为路径末尾的斜杠让内核路径解析时直接跟随软链进入真实目录然后-rf就开始递归删了。这个坑我真心建议各位记到烂熟删软链接永远不要带结尾斜杠。如果你实在不放心先ls -ld看一眼它到底是不是软链。真要清理整套目录时也别用rm -rf link/而是先删软链再删真实目录。6.3 定制自己的 PATH 环境变量PATH 就是shell 去哪些目录里找可执行命令的搜索路径。你敲nginx能执行是因为/usr/sbin/nginx所在目录在 PATH 里。which nginx可以查到具体路径。那如果你把脚本放在/opt/scripts想在任何目录下直接敲名字运行就需要把它加进 PATH。临时生效export PATH/opt/scripts:$PATH永久生效把这个 export 写进~/.bashrc或~/.bash_profile然后source ~/.bashrc这里的source就是让当前 shell 重新读取并执行配置文件相当于热加载。有一个我强调过很多次的小细节把自定义路径加在$PATH前面还是后面决定了它的优先级。放在前面shell 会先搜索你的目录这适合你想覆盖系统同名命令的场景放在后面系统自带命令优先。我的习惯是自定义工具目录放后面避免不小心遮蔽了系统命令。如果哪天你把 PATH 改坏了出现command not found连ls都找不到不要慌/bin/ls 这类绝对路径依然有效直接用/bin/ls找到.bashrc修复即可。这也是为什么我建议改 PATH 之前先备份一份原值比如echo $PATH ~/path.backup手欠的时候能快速回滚。这些指令平时不起眼但在紧急时刻就是让你少流汗的那把钥匙。把这几组指令练熟你在服务器上就不再是会打字母的路人而是真正手里有家伙的操作者了。
返回列表