☰
Linux基础指令进阶:从文件权限到Shell脚本实战
2026/10/8 14:41:09 网站建设 项目流程

上一期把ls、cd、cat这些最基础的指令过了一遍,这期顺势往上走一层。标题叫“Linux基础指令(2)”,其实我已经刻意回避了那些“一查手册就知道”的内容,挑的都是在日常运维、写脚本、排查故障时真正高频使用、但新手容易踩坑的指令。你如果正处在从“会用Linux”到“能用Linux干活”的阶段,或者准备面试被问linux常用命令,这一篇应该能帮你把指令串成一个可以解决实际问题的工具箱,而不是死记命令名。

这次覆盖的指令大概分成五块:文件删除与重命名、用户与权限、系统信息与时间校准、软件安装与gcc编译、进程操作与Shell脚本。每一块我都会先说清楚为什么需要这些指令,再给出可以直接抄的实操命令,最后附上我踩过的一些坑。内容偏务实,不追炫技,适合在虚拟机、云主机或者嵌入式板子上反复验证。

1. 文件操作进阶:删除、重命名与批量处理

ls和cd是进门的钥匙,真正开始干活之后,你马上会遇到“怎么删文件”“怎么改文件名”“怎么同时处理一堆文件”这种问题。文件名里带空格、批量改后缀、误删一个目录,这些场景几乎每天都在发生,所以文件操作值得单独拿出来精讲。

1.1 删除文件夹:rm -rf 的边界与安全替代方案

删除文件用rm,删除空目录用rmdir,但实际使用中绝大多数人在删非空目录时都会用这一条:

rm -rf directory_name

-r表示递归,把目录里的所有内容一层层删完;-f表示强制,不逐个询问。这个组合好用,但也是Linux里最出名的“高危指令”。我刚入行时有一次想删临时目录,手滑在rm -rf后面多打了个空格和星号,差点把当前目录下的所有项目文件清掉。那之后我给自己定了几条规矩:

  • 尽量不用rm -rf处理带通配符的路径,真要删一批文件,先ls确认通配符匹配到的内容。
  • 删除前先cd到目标目录的父目录,用相对路径反复看一眼,再执行删除。
  • 给rm设置别名,让它默认带-i交互确认,虽然每次删除都要按一下y,但安全系数高得多:
alias rm='rm -i'

删除时遇到“rm: cannot remove 'xxx': Operation not permitted”,多数情况是文件属性被锁定了,比如设置了chattr +i防删除标志,用lsattr查看,chattr -i解除后再删。还有一种情况是文件系统以只读方式挂载,mount输出里能看到ro字样,重新挂载为读写(rw)再操作。

如果不想请“大力士”,也可以装trash-cli把删除变成“扔进回收站”。命令是trash file,在用户主目录下会生成.local/share/Trash目录,误删后可以直接trash-restore找回。这在远程服务器上特别实用,毕竟没有图形界面的回收站,多一层保险多一条后路。

1.2 重命名文件:mv 比你想象的更强大

mv的字面意思是“移动”,但它同样承担着重命名的工作。单个文件重命名很简单:

mv old_name.txt new_name.txt

把文件从当前目录移动到/data/logs目录,并顺手改个名,一行也能搞定:

mv access.log /data/logs/access_$(date +%F).log

这里顺手用命令替换生成带日期的文件名,是运维里很常见的操作。等日志文件积累到一定程度,你会频繁需要这种“按日期归档”的能力。

批量重命名是另一个高频需求。假设有一堆report_20240101.txt这样的文件,你想统一改成backup_report_20240101.txt,用Shell循环:

for f in report_*.txt; do mv "$f" "backup_$f" done

文件名里带空格时,for循环里必须用双引号把变量包起来,否则空格会被当成分隔符拆散,这是我吃过亏的地方。更复杂的批量替换(比如把.txt改成.log,还要处理文件名中的特定单词)可以借助rename命令,Debian系的rename用的Perl语法,功能很猛,但语法需要单独学习,不建议新手一上来就啃。

复制文件的cp也需要在这里一起说。cp -r递归复制目录,cp -a保留属主、权限、时间戳等元属性,cp -p只保留时间戳。如果你要同步代码到服务器,rsync比cp更强,但那是后话,先把cp的参数记住,日常拷文件够用了。

复制或移动时注意:目标路径不存在时,mv会把源文件改名为目标文件名;目标路径是已存在的目录时,会把源文件放进这个目录。这个逻辑想清楚,很多“文件怎么不见了”的疑问就解开了。

2. 用户与权限:新建用户、权限和 sudo 那些事

Linux是典型的多用户系统。你看一台服务器,上面可能同时跑着好几个服务、好几个开发者账号,权限划分不清就会有人不小心把别人的项目目录改了,或者把不该读的配置文件读了。这个章节围绕“怎么建一个账号”“怎么控制它能做什么”展开。

2.1 新建用户与用户组:adduser 和 useradd 有什么区别

创建用户的指令有两个:useradd和adduser。很多教程混着用,但它们根本不是一回事。

  • useradd是系统底层命令,参数非常“硬”,不加参数的话连家目录都不会创建。
  • adduser是Perl写的一个交互式友好脚本,底层调用useradd,但会自动创建家目录、设置密码、创建同名用户组,还会问一堆问题,对新手极其友好。

所以我推荐交互场景下直接用adduser:

adduser zhangsan

执行后会依次让你设置密码、填写用户信息,家目录/home/zhangsan会自动建好,默认Shell是/bin/bash,登录名也能正常使用。

如果你在脚本里需要静默创建用户,才用useradd加参数:

useradd -m -s /bin/bash -G sudo lisi

-m创建家目录,-s指定Shell,-G把用户加入附加用户组。这里把lisi加入了sudo组,它就有权限执行管理员命令了,这正是下一小节要聊的授权控制。

Linux把用户信息写在/etc/passwd,密码散列在/etc/shadow,用户组在/etc/group。用户ID叫UID,root的UID是0。看到/etc/passwd里每个用户后面有一串数字,那个就是UID。为什么要提这个?因为面试题里常问“如何查看用户属于哪些组”或者“如何修改用户UID”,答案就落在这些文件里。查看用户属于哪些组用id zhangsan,修改密码用passwd zhangsan,锁定账号用passwd -l zhangsan,一把钥匙一把锁。

2.2 文件权限:chmod、chown 和数字权限位的含义

创建好用户,紧接着的问题是:这个用户能碰哪些文件?Linux用一个很朴素的模型管理权限:每个文件都有属主(user)、属组(group)、其他人(other)三类身份,每类身份有读(r=4)、写(w=2)、执行(x=1)三个权限位,用数字相加表示。

最常用的数字权限是755和644。chmod 755 script.sh表示属主可读可写可执行,属组和其他人只能读和执行,这适合脚本文件。chmod 644 file.txt表示属主可读写,其他人只读,适合普通配置文件。递归修改整个目录用-R:

chmod -R 755 /data/www chown -R www-data:www-data /data/www

chown改属主和属组,-R一起递归。一个非常常见的实战场景是:网站目录权限错乱,nginx或apache报403或403 Forbidden。排查思路通常是ls -l看目录权限,然后确认运行进程的用户是谁,再把目录属主改成那个用户,权限设为755,文件设为644。这套组合在Linux运维面试里出现频率极高,背下来不亏。

补充两个冷门但有用的权限位:SetUID(4)、SetGID(2)、Sticky Bit(1)。比如/tmp目录就是drwxrwxrwt,最后的t表示Sticky Bit,只有文件属主和root能删除这个目录里的文件,防止用户互相删临时文件。chmod +t /tmp可以给目录加这个位,chmod u+s file设置SetUID。掌握这些,遇到ls -l输出里出现格格不入的s或t时就知道发生了什么。

2.3 sudo 与权限失控时的恢复思路

普通用户执行管理员操作,靠sudo。为什么不用su直接切到root?因为su需要root密码,而且一登录就是全部权限,风险敞口太大。sudo的核心思想是“最小授权”加“操作审计”,每次执行都需要当前用户的密码,同时可以用sudo -l查看当前用户被授予了哪些命令权限。

配置sudo权限的中心文件是/etc/sudoers,用visudo编辑。常用的授权行格式是:

zhangsan ALL=(ALL:ALL) NOPASSWD:ALL

表示用户zhangsan可以从任意主机登录,以任意身份执行任意命令,且不需要输密码。实际生产环境不建议给这么大的权限,更稳的写法是只授权特定命令:

zhangsan ALL=(root) /usr/bin/systemctl, /usr/bin/apt

一旦把sudo权限配错,比如把自己从sudo组里踢出去,root密码又忘了,恢复思路一般是重启进入单用户模式或使用恢复内核,挂载根文件系统后修改/etc/sudoers。这个操作细节因发行版和引导方式差异很大,但原理都是“绕过正常登录验证,直接修改配置文件”。我建议你在自己的虚拟机里练一遍这个恢复流程,因为几乎每个做运维的人都会碰上至少一次“唯一管理账号被锁死”的危机。

3. 系统信息与时间:先弄清你在哪儿、现在几点

排查问题之前要先把环境摸清楚。系统是什么发行版、内核什么版本、CPU和内存多大、磁盘还剩多少、时间准不准,这些信息直接决定后续操作方案。这个部分不是单纯罗列命令,而是告诉你到哪一步去看哪个输出。

3.1 查看系统信息:uname、os-release 和硬件概况

三条命令立刻定位一台Linux的身份和内核:

uname -a cat /etc/os-release uname -r

uname -a输出完整内核信息,包括主机名、内核版本、硬件架构。cat /etc/os-release告诉你发行版的准确名称和版本号,比如Ubuntu 24.04还是Debian 13。内核版本单独用uname -r看,因为很多驱动和软件需要匹配内核版本才能编译安装。

硬件资源用三件套:

lscpu # CPU型号、核数、架构 free -h # 内存总量和用量,-h是human-readable,自动带单位 df -hT # 磁盘分区占用,-T显示文件系统类型

排查“我的服务器怎么这么卡”时,第一眼就是看这三个的输出。如果free -h显示可用内存不足1G,但之前没人部署过大应用,那大概率是某个进程在偷吃内存,顺着上一节的ps指令往下查。如果df -h显示根分区使用率99%,不用怀疑,很多莫名其妙的问题都是磁盘写满导致的,先清理日志、再用du -sh /*逐级找大文件。

3.2 查看与同步时间:date、timedatectl 和 chrony

服务器时间不准是隐蔽的灾难。日志时间对不上、HTTPS证书验证失败、分布式系统里的数据对不上时间戳,全是这个原因。查看当前时间用:

date date '+%Y-%m-%d %H:%M:%S'

第二条是格式化输出,写脚本生成日志文件名时特别好用。date +%F等价于date '+%Y-%m-%d',date +%s输出Unix时间戳(从1970年1月1日0点起算的秒数),这两个变形很常见。

现代系统用timedatectl统一管理时间和时区:

timedatectl # 查看系统时间、时区、NTP状态 timedatectl list-timezones | grep Shanghai # 查时区 timedatectl set-timezone Asia/Shanghai # 设置时区

网络同步时间,传统方案是ntpdate,现代方案推荐chrony。安装以后:

apt install chrony -y systemctl enable --now chrony chronyc sources -v

chronyc sources -v输出里能看到当前同步的NTP服务器和对时偏差。如果系统时间比真实时间慢了十几秒,执行chronyc makestep可以强制立即校准。很多云主机默认开了NTP同步,但如果你跑的是嵌入式板子,没有RTC电池或者没有网络,时间会非常不靠谱,脚本里涉及时间计算时要格外小心。

排查时间问题时,先看timedatectl里的“System clock synchronized”是不是yes,如果是no,说明NTP同步没生效,或者本地时间被手动改过导致同步被抑制。把问题定位到“时区不对”还是“同步失败”,比直接敲date盯着屏幕有用得多。

4. 软件安装与 gcc:让你的系统具备编译能力

面试题里常问“在Linux系统安装python用的什么命令”“怎么下载gcc编译器”,其实背后是一个软件包管理体系的问题。Debian系(Ubuntu、Debian、Deepin、统信UOS)用apt,RedHat系(CentOS、Rocky、Fedora)用yum和dnf。这套命令不背下来也能用,但理解了“源”的概念和一键安装的原理,遇到装不上的报错就不会抓瞎。

4.1 apt 与 yum:包管理器的使用逻辑

在Debian系上安装gcc最简单的是:

apt update apt install gcc -y

apt update是刷新软件源索引,不是升级软件。很多新手一执行apt install就报“无法定位软件包”,十有八九是忘了先update。-y是跳过确认直接安装,脚本里必加。

安装完用gcc --version验证,能看到版本号就说明编译器已经就位。但实际搞开发时,光有gcc还不够,因为编译一个C程序可能需要头文件、连接器等工具链成员,Debian系为这个准备了“全家桶”:

apt install build-essential -y

一次装好gcc、g++、make、libc-dev等常用编译工具。面试题如果再问“linux下载gcc编译器”,你直接答apt install gcc(Ubuntu/Debian)或者yum install gcc(CentOS)就行,再补一句“生产环境建议安装build-essential”,比只甩一条命令更显经验。

RedHat系的对应用法是:

yum install gcc -y # 老版本CentOS dnf install gcc -y # 新版Fedora/RHEL

区别在于dnf是yum的下一代,依赖解析和性能更好。平时遇到的“安装软件还得先解决依赖”的麻烦,包管理器已经在后台替你处理掉了。

4.2 源码安装:configure、make、make install 的常规流程

用包管理器装软件是走大路,用源码编译是走小路,但嵌入式Linux开发里经常要走小路。源码安装三连击:

./configure --prefix=/usr/local/software make make install

configure脚本会检查环境、生成Makefile;make按Makefile里设定的规则编译源码;make install把编译好的文件复制到系统目录,--prefix可以指定安装路径,避免污染系统默认目录。

这个流程的坑很多。比如编译时报错error: xxx.h: No such file or directory,一般是缺少对应的-dev包。Debian系统一用apt install libxxx-dev补上头文件。再比如make到一半报错,很多时候是系统GCC版本太老或缺少依赖,先apt build-dep xxx把编译依赖补齐,再重新执行make clean && make。

个人体会:不是万不得已,别在生产服务器上源码安装大型软件。源码编译最大的麻烦是“版本依赖地狱”,你装的A依赖B的2.0,系统里的B是1.4,编译A时各种报错。优先用发行版官方源里的软件包,实在需要新版本,再用checkinstall替代make install生成deb或rpm包,这样以后卸载和升级都方便。一个小技巧:源码目录编译完且确认可运行后,把目录整体打包备份,以后换机器直接拷贝解压就能用,省去重复编译。

5. 进程管理与 Shell 脚本:把命令串起来干活

指令说一千道一万,最终是为了干活。这一个部分把你前面学的命令串联起来,讲到进程的查看与终止,再做几个简单的Shell脚本,让机器自动处理批量操作。这也是嵌入式linux、linux运维故障案例、linux面试题背后最常出现的考察点。

5.1 进程查看与结束:ps、top、kill 的合理姿势

查看当前系统有哪些进程在跑,最常用的是:

ps aux ps -ef

两种格式输出略有差别,但核心字段一致:进程PID、CPU占用、内存占用、启动命令。想找某个特定的进程,用grep过滤:

ps aux | grep java

执行后输出里会出现两行Java进程和一行grep java本身,后者是ps的PID,不用理会。这种“管道+过滤”的组合是Linux里最常用的排查模式,面试必问。

动态观察进程资源占用,用top,它每几秒刷新一次,按P按CPU排序,按M按内存排序。更现代的替代品是htop,界面更友好,但需要额外安装。

结束进程用kill,这里有一个新手最容易搞错的概念:kill -9不是唯一选项,甚至不是首选。Linux进程收到信号后可以有机会做清理工作,比如保存状态、关闭文件描述符。kill默认发送的是TERM信号(编号15),相当于礼貌地请求进程退出;kill -9发送的是KILL信号,直接由内核强制终止,进程没有机会做任何善后。所以不要一上来就kill -9,先给进程一个优雅退出的机会。如果15秒后还没有退出,再考虑强制。

kill 12345 # 发送TERM信号 kill -9 12345 # 强制杀死 pkill -f java # 按进程名匹配并终止

排查“哪个进程占了cpu”用组合:先top看到PID,再ls -l /proc/PD目录查到启动命令的完整路径。/proc文件系统里每个数字目录对应一个进程,这里面藏着大量信息,面试题如果问到“如何根据PID找到进程工作目录”,答案就是pwdx PID或ls -l /proc/PID/cwd。

5.2 进程间通信的朴素实现:管道、重定向与信号

“进程间通信”听起来很玄,但你其实每天都在用,只是没意识到。管道|把前一个命令的标准输出接到后一个命令的标准输入,这就是两个进程之间最朴素的通信方式。重定向>把输出写到文件,>>是追加写入。tee把输出同时送进屏幕和文件:

命令 | tee output.log

信号是另一个层面的通信:你在终端按Ctrl+C,本质是给前台的进程组发送了INT信号;kill -TERM 12345是明确给指定进程发信号。理解了这个,你在脚本里用trap捕获信号做优雅退出时就不会发懵。

5.3 写第一个实用的 Shell 脚本

Shell脚本可以用一串指令完成反复操作。新建一个文件run.sh,第一行写解释器声明:

#!/bin/bash

然后写入以下内容:

#!/bin/bash LOG_DIR="/home/user/logs" DATE=$(date +%Y%m%d) # 把旧的log文件加上日期后缀 cd "$LOG_DIR" || exit 1 for f in *.log; do mv "$f" "${f%.log}_${DATE}.log" done echo "日志归档完成:$(ls)"

一个典型场景:网站每天产生大量访问日志,每天定时归档一次。把上面内容保存后执行chmod +x run.sh,然后./run.sh运行。chmod +x是赋予执行权限,不加这一句直接运行会报“Permission denied”,这是新手最常踩的坑。

脚本里再进阶一点,可以统计日志中某个关键词出现次数,这也是运维面试的经典题:

grep -c "ERROR" access.log cat access.log | grep "ERROR" | wc -l sort access.log | uniq -c | sort -nr | head -10

sort | uniq -c | sort -nr | head这条链式处理,输出频率最高的内容,几乎出现在每一份linux面试题里。可以用一行命令完成“统计IP访问次数并输出Top10”,这个技巧背下来,面试时直接写出来会非常加分。

6. 运维故障排查:最容易踩的五个深坑速查

经验总是一坑一坑踩出来的。最后整理几个我见过最多、也最容易复现的Linux操作错误,做成速查表,你实际工作中遇到类似报错,先对照着排查一遍。

故障现象可能原因快速排查解决思路
apt install报“无法定位软件包”没有先执行apt update,软件源索引过期apt update刷新索引后重新安装
删除文件提示Permission denied文件权限不足或文件被锁定ls -l、lsattr用属主身份登录或chattr -i解锁
sudo执行命令报“不在sudoers文件中”用户不在sudo组或未授权id 用户名用root账号执行visudo添加用户
系统时间总是慢几分钟NTP同步未开启或时区错误timedatectl设置正确时区并启用chrony/NTP同步
磁盘明明没写多少内容,占用却很高日志文件或临时文件一直增长df -h、du -sh /*清空日志、删临时文件、定位大文件

再补充一个高频坑:rm -rf删目录时,如果目录是挂载点,你删的其实是挂载点目录下的空壳,真正的数据还在磁盘上,看起来“删不掉”或者“删了半天空间没变”。先df -h看挂载点,再umount卸载后重新操作。这个细节没人提醒的话,自己排查能浪费半天。

防火墙也是一个常被忽略的模块,不过“基础指令2”先不展开端口管理,只提醒一句:遇到网络连不上的问题,优先查service firewalld status或ufw status,别急着怪程序。这一条在云主机和公司内网服务器上都踩过无数次。

个人小建议:把上面这些命令整理成自己的速查笔记,按“文件、用户、系统、软件、进程”五个分类放好。遇到问题时先按分类找命令,再根据输出联想排查路径。Linux的学习不是背命令,而是建立“遇到问题→猜测原因→用命令验证→调整操作”的闭环。今天这篇的指令,足够你把这个闭环跑起来了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询