聊到Linux入门,咱们得先搭个顺手的环境。现在都2024年了,Linux内核最新已经到6.8版本(今年3月刚发布的),你要是还在纠结装双系统或者搞虚拟机,那真的有点“复古”了。简单来说,对于绝大多数开发者和运维新手,我首推WSL2(Windows Subsystem for Linux 2)。它不仅能让你在Windows上无缝跑一个完整的Linux内核,而且性能损耗极低,文件互访也方便。
咱们现在的Bash(也就是你打开终端时默认的那个Shell)主流版本是5.2(2022年9月发布的),虽然Shell脚本有个通用的POSIX标准,但Bash 5.2在交互体验和脚本安全性上确实做了不少优化。
以前咱们用VMware或者VirtualBox,不仅占内存,而且网络配置、文件共享能把人折腾死。WSL2基于Hyper-V技术,轻量得不像话。
C:\盘下摸鱼,可以直接在WSL里cd /mnt/c访问到。既然环境提到了Bash 5.2,咱们直接上手写个最简单的脚本,感受一下。别怕,这东西比你想的简单。
打开你的终端(WSL2或者MacOS的Terminal都行),输入 bash --version,确认一下版本。然后咱们创建一个文件:
在文件里写入以下内容:
保存退出后,记得给这个脚本执行权限(这是新手必踩的坑,忘了加权限就跑不起来):
你会看到输出。这里用到了$BASH_VERSION这个内置变量,这就是Bash 5.2环境给你提供的现成信息,不用你自己去查系统文件。
别在Windows的C盘根目录直接跑你的Shell脚本项目。 虽然WSL2能访问/mnt/c,但那边的文件权限(NTFS)和Linux的权限(ext4)处理逻辑不一样,容易导致脚本里的chmod失效或者Git显示一堆文件改动。建议把代码放在WSL2的家目录(~ 或者 /home/你的用户名)下,那里才是Linux的原生地盘,跑起来最稳。
---
搞定了环境,咱们来聊聊Linux里最核心的生存技能——“找文件”和“管权限”。其实,Linux里一切皆文件,你要是不会操作文件,那基本寸步难行。
ls 这个命令大家都认识,但很多人只会敲个 ls。这就好比你进了一家图书馆,只会在门口看一眼就走。咱们得学会看细节。
比如,查看当前目录下所有文件的详细信息(包括隐藏文件,即以.开头的文件):
-l:长格式显示,能看到权限、所有者、大小。-a:显示所有文件,包括.bashrc这种隐藏配置。-h:人性化显示大小,把1024字节显示成1K,看着不累。输出大概长这样:
看那个 drwxr-xr-x 没?这就是权限位。第一个字符d代表是目录,-代表是文件。后面9个字符分三组:rwx(所有者)、r-x(组用户)、r-x(其他用户)。
权限控制是Linux的安全基石。咱们经常遇到“Permission denied”(权限拒绝),这时候新手容易直接 sudo rm -rf,这是大忌!
修改权限用 chmod。有两种写法,一种是数字,一种是字母。我推荐新手用字母,不容易出错。
假设你有一个脚本 deploy.sh,你想让所有者能读写执行,其他人只能读和执行:
避雷经验提醒:chmod 777 是很多新手的噩梦。这相当于告诉系统:“谁来都能动这个文件”,非常不安全。在现在的安全强化趋势下,系统对权限校验越来越严格,咱们要养成最小权限原则。
当你需要干管理员才能干的事(比如装软件、改系统配置),就得用 sudo。它不是命令,而是个前缀,意思是“以超级管理员身份运行”。
光说不练假把式,咱们来个实战。假设你要给团队里的 dev 用户组创建一个共享目录,大家都能写,但别人看不见。
你会看到类似 drwxrwx--- 的输出,这就对了。
没事别用 root 登录。 现在的Linux发行版(包括最新的内核趋势)都在弱化 root 直接登录,转而推崇 sudo。如果你平时操作都用 root,哪天手滑敲了个 rm -rf /,系统就真成砖了。用 sudo 能让你在执行危险命令时多思考一秒钟,这一秒可能救你的饭碗。
---
服务器跑起来了,怎么知道它有没有偷懒?有没有被攻击?这就需要咱们掌握进程监控和网络操作。这不仅是运维的活儿,开发调试的时候也离不开。
ps 是查看当前瞬间的进程快照。最经典的搭配是 ps aux。
a:显示所有用户的进程。u:以用户为主的格式显示。x:显示没有控制终端的进程(比如后台服务)。这里有个面试考点梳理:ps aux | grep nginx 的执行逻辑是什么?
其实,就是先让 ps aux 把系统里所有进程列出来,然后通过管道 | 传给 grep,grep 再从中过滤出包含 nginx 字样的行。
避雷经验点:你会发现结果里往往有一行是 grep --color=auto nginx,这是 grep 命令本身。怎么去掉?加个正则技巧:
这样 grep 找的是 nginx,但它自己进程里显示的是 [n]ginx,就匹配不上自己了。
如果你想实时盯着进程,那就用 top 或者它的升级版 htop。top 就像Windows的任务管理器,默认按CPU占用排序。按 q 退出,按 M 按内存排序。
现在的应用离不开网络。curl 是命令行里的浏览器,用来发请求。
比如,测试一下你的后端接口是不是通的:
以前我们查端口用 netstat,但现在它有点老了。根据现在的运维标准,推荐用 ss (Socket Statistics)。它更快,而且直接读取内核数据。
-t:TCP协议。-u:UDP协议(这里没用,但习惯带上)。-l:监听状态。-n:以数字显示端口和IP,不解析域名(更快)。如果你想看是哪个进程占用了8080端口,杀掉它:
咱们写个简单的逻辑,模拟监控Nginx是否运行,如果挂了就重启。
不要在生产环境随便用 kill -9。 -9 信号(SIGKILL)是强制杀死,进程连清理现场(比如关闭文件句柄、释放锁)的机会都没有。这就好比你直接拔电源,而不是点“关机”。除非进程已经僵死(Zombie)或者完全不响应,否则先用普通的 kill (发送SIGTERM),给它个体面的死法。
---
这一章是Shell脚本的精髓,也是最能体现你“技术含量”的地方。咱们常说的“文本处理三剑客”就是 grep、awk 和 sed。配合管道 |,你能把一堆杂乱无章的日志玩出花来。
管道就像流水线上的传送带。左边命令的输出,直接变成右边命令的输入。
比如:我想知道当前目录下有多少个文件?
ls -l 列出文件,wc -l 数行数。这一串组合拳,比写个循环去数要快多了。
grep 负责按条件过滤。
面试常考:如何用 grep 统计日志中 "ERROR" 关键词的出现次数?
如果说 grep 是过滤器,awk 就是处理机。它特别擅长处理列状数据(比如CSV或者日志)。
假设有个日志文件 access.log,内容是 IP 时间 请求路径,我们要统计哪个IP访问最多:
这行命令是经典中的经典,能列出访问量前10的IP。
sed 主要用来替换文本,而且是不打开文件直接改(或者输出到新文件)。
比如,你想把配置文件里的 localhost 批量换成 127.0.0.1:
关键点:sed -i 很危险,改错了就找不回来了。建议先备份,或者先用不带 -i 的命令看看输出对不对。
咱们来个综合实战。假设我们要从Nginx日志里找出今天访问量最高的5个页面(URL),并且排除掉静态资源(图片、css、js)。
这个脚本里的 \ 是换行符,为了让命令看起来清晰。这就是Linux的魅力,把简单的工具组合起来,解决复杂的问题。
脚本里尽量用绝对路径。 比如写 grep 的时候,虽然系统能找到,但在Cron定时任务里跑的时候,环境变量可能没加载,导致 command not found。写 /bin/grep 或者 /usr/bin/awk 虽然麻烦点,但更稳。另外,处理文本时,注意文件编码,Windows下编辑的脚本传到Linux里经常因为换行符(\r\n vs \n)报错,用 dos2unix 工具修一下就好。
Shell脚本编程入门:变量、条件判断与循环语法
简单来说,Shell脚本就是把你平时在终端敲的一堆命令,按顺序写到一个文件里,让系统自动帮你跑。咱们现在主流的服务器环境,用的Shell基本都是 Bash 5.2(2022年9月发布的稳定版),虽然Linux内核都更新到6.8了(2024年3月发布),但Shell脚本的语法标准还是遵循 POSIX Shell 规范,所以你学会了这些,在绝大多数Linux发行版上都能跑得通,不用担心兼容性问题。
很多新手一上来就被Shell的语法劝退,其实核心就三块:变量、判断、循环。
这是新手最容易踩的坑。在Shell里,赋值的时候等号两边绝对不能有空格。
除了自己定义的变量,系统还内置了一些特殊变量,面试特别爱问,记一下:
$0:脚本本身的名字$1 ~ $9:传入脚本的第1到第9个参数$#:传入参数的个数$?:上一条命令的执行结果(0代表成功,非0代表失败)Shell里的条件判断用 if 语句,但那个中括号 [ ] 其实是一个命令,所以两边必须留空格,不然Shell会懵逼。
常用的判断条件还有 -d(是不是目录)、-eq(数字相等)、-ne(数字不等)。
当你需要重复做一件事,比如批量重命名文件,循环就派上用场了。最常用的是 for 循环。
💡 经验总结:写脚本的时候,养成在开头加上 #!/bin/bash 的习惯,这叫Shebang,它告诉系统用哪个解释器来执行。另外,如果你打算把脚本给别人用,或者跑在严格的环境里,建议加上 set -e,这样一旦脚本里某条命令报错了,脚本会立刻停止,防止错误像滚雪球一样越滚越大。
---
作为全栈工程师,服务器运维是躲不掉的。最烦人的就是磁盘被日志塞满,或者数据没备份导致背锅。咱们用Shell脚本结合 cron 定时任务,就能把这些脏活累活全自动化了。
Nginx或者应用跑久了,日志文件动不动几个G。咱们写个脚本,自动删掉7天前的 .log 文件。
光清理不行,重要的数据还得备份。咱们写一个备份 /data 目录的脚本,并且加上日期戳,防止覆盖。
脚本写好了,怎么让它每天自动跑?这就得用到 cron 了。在终端输入 crontab -e 编辑定时任务。
📖 学习建议:千万别直接把命令扔进 cron 就不管了。cron 执行的时候环境变量和你在终端里不一样,所以脚本里尽量用绝对路径(比如写 /bin/tar 而不是 tar)。还有,一定要测试脚本在终端能跑通了,再放进 cron,不然到时候报错你都不知道,因为 cron 默认是不给你发邮件提示的(除非你配置了)。
---
写了这么多年脚本,我见过太多人因为一些细节翻车。这一章咱们聊聊那些让你加班到半夜的“坑”,以及现在云原生时代(K8s、Docker)下,Shell脚本该怎么写才显得专业。
`bash
file="my document.txt"
# 错误:rm 会试图删除 my 和 document.txt 两个文件
# rm $file
# 正确:
rm "$file"
`
grep 把自己也搜进去了:面试常考 ps aux | grep nginx。你会发现结果里有一行是 grep nginx 本身。怎么去掉?`bash
# 方法一:加个 grep -v grep 过滤掉自己
ps aux | grep nginx | grep -v grep
# 方法二:用正则的中括号技巧(更优雅)
ps aux | grep [n]ginx
# 原理是 grep 在搜 [n]ginx 时,进程名是 grep [n]ginx,正则匹配不上自己
`
$? 的时效性:$? 只能保存上一条命令的结果。如果你在判断前加了个 echo,那 $? 就变成了 echo 的结果(通常是0)。面试官特别喜欢问:“怎么统计日志里ERROR出现了多少次?”
直接用 grep 的 -c 参数就行,简单粗暴。
现在大家都用Docker和K8s了,在容器里跑Shell脚本,跟在物理机上不一样。现在的趋势是 轻量化 和 减少依赖。
以前我们喜欢在脚本里用 awk、sed 做复杂的文本处理,但在容器里,为了追求镜像小,基础镜像(比如 alpine)可能连这些工具都没有,或者版本很老。
改造建议:
cut 或 awk。SIGTERM 信号,不然你发停止命令,容器停不下来。🔧 实战技巧:在写自动化运维脚本时,如果逻辑特别复杂(比如涉及到复杂的API调用、JSON解析),别硬用Shell死磕。虽然Shell能写,但代码会很难看且难维护。这时候划清界限,用Python或者Go写工具,Shell只负责调用和串联,这才是2024年最主流的做法。