带Python入门班这些年,每次开课第一件事不是讲语法,而是让大家坐下来,先花一个晚上把Linux基本命令过一遍。总有同学问“我是学Python的,为什么要先学Linux”,我通常只回一句:你以后写的脚本,大概率要跑在Linux服务器上。第26期第一课就是这么安排的,这篇文章把那堂课的核心内容整理出来,专门讲Python学习者必须吃透的那批Linux命令,以及它们和Python开发之间的实际关系。
内容面向零基础和刚转行的新手,也欢迎写了段时间Python、但一直没系统学过命令行的同学对照查漏。学完至少能做到:在Linux服务器上自由穿梭目录、查看日志、管理文件、排查进程,并且能在Python脚本里调用命令去完成自动化任务。
1. 为什么Python学习者必须先过Linux命令这道坎
1.1 开发环境与部署平台的绑定关系
很多人写Python都在Windows上,因为安装方便、图形界面顺手,但真实世界的Python应用部署在哪儿?绝大多数是Linux服务器。不管是Web后端、数据处理脚本还是定时任务,最终跑起来的环境基本都是Linux。哪怕你只是给自己写个小工具,最后想放到云服务器上定时执行,也必须通过命令行登录、上传文件、跑脚本。
这里有个不太容易被新手理解的现实:开发环境和部署环境的鸿沟。你在Windows上写的代码,即使Python语法完全兼容,到了Linux上也可能遇到路径分隔符不一样、换行符不一样、依赖装不上、权限不足等各种幺蛾子。所以如果早早就熟悉Linux命令,等于提前把环境差异这个最大的坑填上了。
我经常跟学员打比方:Python语法是游泳的动作,Linux命令是泳池里的水。动作练得再标准,不下水永远游不起来。先掌握命令,后面的部署、排错、自动化才有基础。
1.2 自动化脚本的本质是命令行的程序化
很多同学学Python就是想做自动化,比如批量处理文件、定时抓数据、监控服务器状态。但仔细想想,这些需求的原始形态是什么?是命令行操作。
批量重命名文件,你手动操作是右键重命名,但服务器上没有右键,只有mv old new。定时抓数据,你手动操作是打开浏览器、复制粘贴,但服务器上只有curl加grep。所以自动化脚本写来写去,本质上是把一串命令行操作固化成了代码。
如果你连命令行本身都不熟,写出来的脚本就非常别扭。最常见的情况是:在Python里明明可以用subprocess调用现成的grep或find三秒解决一件事,却非要自己写几十行Python去遍历文件、匹配字符串、处理异常,最后性能还差得远。
还有一个更实际的原因:排查问题。脚本跑挂了,第一件事是看日志,而看日志的基本功就是tail、grep、less这些命令。就算你的Python代码写得完美无缺,只要服务器上出了问题,整个人还是要钻进命令行里去诊断。所以命令行不是可学可不学,而是Python开发者的生存技能。
1.3 学习时机:指数级回报的早期投资
有人觉得Linux命令可以边用边学,没必要专门花时间。这话对一半,但对于初学者来说,边用边学等于每次都要在搜索引擎上现查,而且查到的命令写法五花八门,根本不知道哪个是对的、哪个能跑、哪个会把自己系统弄坏。
第26期课程里,我把Linux命令放到第一课,核心原因就是回报率。这批命令撑死了就这么几十条,集中一个晚上过一遍,后面所有课程里只要遇到服务器操作、脚本运行、项目部署,你都不会被环境卡住。相反,如果拖到写项目时才补,既影响进度又会打击信心,因为你会在同一时间面对语法、框架、部署三个新知识点的冲击。
还有一个心理层面的理由。命令行上手以后会给人很强的掌控感,而这种掌控感对于初学者建立信心特别有帮助。很多人第一次用Linux命令删掉一个文件、启动一个服务,都会有一种“我好像真的能操作这台机器了”的感觉。这种正向反馈,远比看两章语法书来得直接。
2. 高频必备命令详解:怎么用才不算白学
2.1 目录穿梭三件套:pwd、cd、ls
刚上手Linux,先把三个命令练成肌肉记忆:pwd、cd、ls。
pwd是打印当前工作目录,你迷路的时候一敲就知道自己在哪。cd是切换目录,配合绝对路径和相对路径两种玩法。ls是列出当前目录下的文件和文件夹,日常用得最多。
新手必须理解一个概念:绝对路径和相对路径。绝对路径是从根目录/开始写全,比如/home/user/project。相对路径是从当前位置开始算,比如cd ..回到上一层,cd ../..上两层,cd project进入当前目录下的project文件夹。~代表当前用户的家目录,cd ~一键回家,.代表当前目录。
ls有几个参数值得死记硬背:ls -l能看详细列表,包括文件权限、属主、大小、修改时间;ls -a查看隐藏文件;ls -lh显示人类可读的大小单位。我基本只用一个组合:ls -lh。因为人在服务器上最关心的就是文件多大、什么时候改的、有没有权限。
很多发行版里ll就是ls -l的别名,直接用没问题。但有的服务器上ll不存在,所以只认ls -l才稳妥。
2.2 文件操作的四个核心命令:touch、cp、mv、rm
文件操作是每天都要干的活,新手期建议先背熟四个:touch、cp、mv、rm。
touch用于创建空文件,也可以更新已有文件的时间戳。cp是复制,复制单个文件直接cp 源文件 目标文件,复制整个目录必须加-r参数递归复制,很多人第一次忘了-r,报错“cp: omitting directory”,这是最常见的入门错误。mv是移动或重命名,同一个目录下mv old.txt new.txt就是重命名,跨目录就是移动,这个命令不会复制,操作很快。rm是删除,删文件直接rm file,删目录要加-r,如果目录里有内容系统会跟你确认,不想确认就加-f强制。
这里必须放一个深刻警告:rm -rf这个组合是危险动作。rm -rf /在某些系统上会把整个系统删掉,这真的不是玩笑。我的习惯是,任何带-rf的命令执行前,先停两秒看一眼路径,再敲回车。尤其不要顺手在命令末尾多打一个空格然后补个错的路径。
顺便说一个操作细节:删除之前用ls确认一下目标是否存在、是不是你要删的东西。很多事故都发生在“我以为这个目录是临时缓存,结果它是最新的源代码”这种状态里。与其删错再找备份,不如删前两秒钟多看一眼。
2.3 文本查看与关键字检索:cat、head、tail、grep
服务器上排查问题、检查配置、看日志,全靠文本命令。
cat 文件把整个文件内容一次性打到屏幕上,适合看小配置文件。文件一大,直接cat会把屏幕刷爆,所以大文件要用less,支持翻页和搜索,按q退出。head -n 20看前20行,tail -n 50看最后50行,最实用的是tail -f,它会持续跟踪文件末尾新增的内容,调试日志时一用就是半天。
grep是文本检索的核心工具。基本用法是grep 关键词 文件,比如想从一个日志文件里找所有包含“ERROR”的行:grep ERROR app.log。常用参数包括-i忽略大小写、-n显示行号、-v反向匹配(输出不包含关键词的行)、-E支持正则表达式。
grep不只是单独用,它最擅长和管道配合。管道符|把前一个命令的输出传给后一个命令继续处理。看一个实际场景:应用日志持续刷屏,我只想看包含“ERROR”的那几行,并且希望这些行一直跟着最新输出,那就用tail -f app.log | grep ERROR。这一条命令的价值,顶得上打开图形化日志工具点半天鼠标。
wc -l可以统计行数,常用来快速评估日志规模。sort和uniq配合能统计去重后的内容数量,比如grep ERROR app.log | sort | uniq -c | sort -rn可以按出现次数从高到低列出不同的错误类型。
2.4 权限与身份:chmod、chown、sudo
Linux是个多用户系统,每个文件都有属主和属组,权限分三类:读r、写w、执行x。用ls -l查看文件时,第一列那10个字符就是权限描述。比如-rw-r--r--,第一个字符-说明是普通文件(d是目录),后面9个字符每3个一组,分别是文件属主、属组成员、其他人的权限。
改变权限用chmod,两种方式都有用。数字法最常用:读=4,写=2,执行=1,三者相加得到一个0到7的数字,三个数字分别代表属主、属组、其他人。chmod 755 file表示属主有全部权限,属组和其他人有读和执行权限,这是可执行文件的经典配置。chmod 644 file表示属主可读写,其他人只读,适合普通数据文件。
修改属主用chown,比如chown user:group file。日常场景里,一个共享目录里文件全属于另一个用户,你没法改文件内容,就得找管理员执行chown。
遇到操作被拒绝,第一反应是看一下自己的身份和文件属主。whoami查看当前用户,id查看用户ID和所属组。如果确实需要管理员权限,就在命令前面加sudo,比如sudo apt install nginx。但sudo不是万能钥匙,它只是暂时以root身份执行,适合少数管理操作,不建议养成什么命令都挂sudo的习惯,容易出安全事故。
2.5 进程与资源排查:ps、top、df、free
Python脚本跑挂了、服务器负载高了、磁盘满了,这些是上线之后几乎每天都会遇到的状况,所以必须会看进程和资源。
查看进程,ps -ef或ps aux都能列出当前系统所有进程,列里包含PID(进程号)、CPU占用率、内存占用率、命令。想确认某个Python程序是不是在跑,用ps -ef | grep python一搜就知道。如果按名字搜到一条grep自己的进程也别慌,那是管道机制产生的,很常见。
动态监控资源用top,默认每几秒刷新一次,按CPU占用排序显示所有进程。按q退出。内存状况看free -h,单位是人性化的G和M。磁盘状况看df -h,一眼就能看到各分区总量、已用、可用和使用率。磁盘满了是运维里最高频的事故之一,当服务器突然读写变慢、程序报“No space left on device”时,先跑一下df -h就能确认是不是磁盘问题。
结束进程用kill PID,这是优雅终止,进程可以处理善后;如果进程僵死,kill -9 PID强制杀死。我见过很多同学在进程已经完全卡死时只用kill,等了很久也没反应,最后才发现要加-9。另外要注意,kill后面跟的是PID,不是程序名,很多人第一次都卡在这里。
3. Python与Linux命令协同实操:学会在脚本里调用命令
3.1 为什么脚本里要调外部命令:工具箱思维
Python中有个很重要的分工思维:能用系统现成的命令解决问题,就别重复造轮子。Linux命令本身是几十年沉淀下来的工具箱,grep、find、awk、sed每一个都经过极端优化,处理文本、扫描文件的速度往往比你自己写的纯Python循环快得多。
举个实际例子。你要统计一个几十万行日志里每种错误类型出现的次数。用纯Python读文件、切字符串、做计数循环,代码写几十行,运行要几秒甚至更久。可如果先调用grep把错误行筛出来,再用sort和uniq -c统计,代码量和时间都只是前者的零头。这就像你明明有洗衣机,却非要手搓衣服。
所以我教项目的第一课就是:Python里调外部命令是合法且推荐的思路,关键是用对方式。
3.2 subprocess是正解,尽量别用os.system
Python调用外部命令有两个常见选择:os.system()和subprocess模块。os.system简单粗暴,传入字符串命令,执行完只返回命令退出状态码,拿不到命令输出,而拿输出是高频需求,所以它基本不适合写脚本。
正确选择是subprocess。看下面这个对比:
import os import subprocess # 不推荐:拿不到输出,参数处理容易出问题 os.system('ls -l') # 推荐:能捕获输出,还能拿到退出码 result = subprocess.run(['ls', '-l'], capture_output=True, text=True) print(result.stdout) print(result.returncode)subprocess.run接收一个列表,第一个元素是命令名,后续是参数。capture_output=True表示捕获标准输出和标准错误,text=True表示按文本模式解码而不是输出字节串。
还有一种写法是把整条命令作为字符串传进去,加shell=True:
result = subprocess.run('ls -l | grep py', shell=True, capture_output=True, text=True)shell=True可以让你直接使用管道、通配符这些Shell特性,但有个安全前提:如果命令里拼了外部输入,千万别用shell=True,比如subprocess.run(f'rm -rf {user_input}', shell=True)这种写法是严重的安全漏洞。正确做法是用列表传参,让系统帮你转义,避免注入风险。
3.3 三个能直接抄作业的自动化脚本
下面给三个我在课上演示过的实战脚本,都不长,但很能代表“Python + Linux命令”的组合用法。
第一个:实时查看日志里新增的ERROR数量。
import subprocess result = subprocess.run( ['grep', '-c', 'ERROR', '/var/log/app.log'], capture_output=True, text=True ) count = int(result.stdout.strip()) print(f'当前日志中的ERROR总数: {count}')如果服务器上日志路径固定,这个小脚本比手动打开日志去数行数高效太多,配合cron定时任务就能变成一个简单的异常监控。
第二个:检查磁盘使用率,超过80%就告警。
import subprocess result = subprocess.run(['df', '-h', '/'], capture_output=True, text=True) lines = result.stdout.strip().splitlines() header = lines[0].split() data = lines[1].split() usage = data[4].rstrip('%') print(f'磁盘总量: {data[1]},已用: {data[2]},使用率: {usage}%') if int(usage) > 80: print('磁盘使用率超过80%,需要清理') else: print('磁盘状况正常')这段脚本直接解析df -h的输出,从第5列提取使用率百分比。真实项目里你还可以把结果通过邮件或即时通讯工具发出去,就变成一个完整的告警机器人。
第三个:批量给目录下的文件添加后缀。
import subprocess result = subprocess.run(['find', '.', '-name', '*.log'], capture_output=True, text=True) for path in result.stdout.strip().splitlines(): new_path = path + '.bak' subprocess.run(['mv', path, new_path]) print(f'已重命名: {path} -> {new_path}')这里用find找到所有.log文件,再用Python逐个执行mv加后缀。好处是逻辑清晰,而且比写纯Python的os.walk遍历代码短得多。实际生产环境中,这类脚本只要确保文件路径不含特殊字符,就能直接复用。
4. 避坑指南:新手最常遇到的6类问题与排查思路
4.1 command not found:命令去哪了
报错command not found是最基础的坑。原因通常就三类:命令没安装、命令不在当前用户的PATH里、命令拼写错误。
没有安装就用系统包管理器装,比如apt install或yum install。想知道一个命令是否存在,用which 命令名,它会显示命令所在路径。比如which python3有输出说明Python已安装且配好了PATH。
还有一种容易被忽略的情况:装好了但要用新开的终端窗口才生效。很多安装过程会修改配置文件,这些配置只在重新登录或者新开Shell时才加载。如果你刚装完命令就报找不到,先开一个全新终端再试。
4.2 文件就在眼前,路径却老是找不到
这个问题在初学Linux时特别让人崩溃。明明ls能看到文件,但Python脚本里面写相对路径却找不到,原因基本是“当前工作目录”和“你眼睛看到的目录”不是同一个。
在终端里,你看到/home/user/project下有文件,但Python脚本可能是跑在/home/user之下,它用的是自己的当前工作目录,而不是脚本所在目录。这非常反直觉。
我的习惯是:所有涉及文件路径的脚本,第一行就用cd到脚本所在目录,或者显式用绝对路径。在Python里可以这样做:
import os os.chdir(os.path.dirname(os.path.abspath(__file__)))这段代码把当前工作目录切到脚本文件所在目录,之后再写相对路径基本不会迷路。如果你手动在终端里处理文件,那就记住:用pwd确认自己到底在哪,再判断路径对不对。
4.3 中文乱码:终端编码与Python编码双重排查
中文乱码分两个层面。第一层是终端层面,Linux终端默认字符集如果不对,中文就显示成问号或乱码。常见解决方式是检查环境变量,手动设置UTF-8:
export LANG=C.UTF-8这个设置对当前终端进程有效,要永久生效就写到用户配置里。字符集不对还会导致Python脚本打印中文时报编码错误,因为输出到终端时编码方式不匹配。终端层面处理好了,很多问题直接消失。
第二层是Python读写文件的编码问题。文件本身可能是GBK或UTF-8,你在open()的时候需要明确指定编码。比如读取历史遗留的GBK日志:open('log.txt', encoding='gbk', errors='ignore')。很多人默认只写open('file'),遇到文件编码不对就只有报错,所以养成习惯,读写文件时显式声明编码。
4.4 换行符引发的崩溃:CRLF与LF
Windows写出来的文本文件,每行末尾是\r\n(CRLF);Linux下是\n(LF)。如果你在Windows里用编辑器写了Python脚本传到Linux上运行,偶尔会出现奇怪的语法错误,排查半天发现是换行符问题。
这种错误很隐蔽,因为你在Vim里看文件内容明明正常,但Python解析器读到的行尾多了个回车符。处理办法很简单:
sed -i 's/\r$//' script.py这条命令把每行末尾的\r去掉,转换完之后脚本就能正常跑了。更彻底的办法是从源头解决:在Windows编辑器里把换行符默认设置为LF,或者用带“转换换行符”功能的编辑器保存文件。我自己写脚本的习惯是统一在Linux上用vim或nano,避免这个坑。
4.5 端口被占用与僵死的进程
启动Web服务时,最经典的报错是Address already in use,意思是端口已经被别的进程占了。新手第一反应是改端口,但更好的是先找到占用端口的进程,看看它是不是你之前启动后忘了关的服务。
查端口占用的命令是ss -tlnp | grep 8080,ss是看Socket状态的工具,-tlnp显示监听端口并带上进程信息。或者用lsof -i :8080。找到PID后,如果确实需要释放端口,就kill PID。
如果进程变成僵尸进程或者怎么都杀不掉,大概率是它有子进程未清理,或者处于不可中断的内核状态。这时候可以先kill,等几秒,不行再kill -9。注意别乱杀系统进程,判断标准是进程名和启动命令你认不认识。
4.6 提升效率的两个小习惯:Tab补全与命令历史
最后给新手两个零成本但收益极高的小习惯。
第一个是Tab补全。敲命令时按Tab,系统会自动补全命令名、文件名和路径。你敲cd /ho再按Tab,它自己补成/home。目录下文件多的时候,这套补全能把打错字概率降到极低。第二个是命令历史。按键盘上方向键上可以翻出之前的命令,不用重新打一遍长命令。history可以查看所有历史记录,Ctrl+R进入反向搜索模式,输入关键字就能找到以前敲过的命令。
这两个习惯看似不起眼,但实际用起来能省非常多时间。我带班时观察过,敢用Tab补全的同学,在终端里的操作速度是经常敲完整命令的同学的两倍以上,而且出错率低很多。
5. 刻意练习路径与我的个人心得
5.1 每天30分钟的场景化练习法
Linux命令不难,难的是记住它们并且知道什么时候用。我的建议是用场景驱动来练:不要背命令清单,而是给自己设任务,每天解决一个真实问题。
比如第一天的任务是“在服务器上创建目录结构并复制文件”,你就得用到mkdir -p、cp -r、mv;第二天的任务是“查看某个服务今天有没有报错”,你就得学会tail -f、grep、less;第三天的任务是“磁盘快满了,找出最大的文件”,你会用到df -h、du -sh、find。每天30分钟,这几天下来就能覆盖绝大多数高频命令,而且印象会特别深。
别追求什么都会。很多命令是低频冷门命令,真用到的时候再查完全来得及。真正需要形成肌肉记忆的只有三类:目录操作、文件操作、文本检索。这三类滚瓜烂熟,你日常的使用体验就已经和熟练运维相差无几。
5.2 几个越早明白越好的使用习惯
带完这么多期班,我最大的感受是:初学者对命令行的恐惧,九成来自“怕把系统弄坏”。实际上,你只要不碰危险的rm -rf,不乱用sudo,大部分命令在这个用户权限下能造成的伤害非常有限。所以别怕,放手去试。
另一个是配置一个模糊查找的习惯。很多命令你记得大概,但记不住完整参数,在终端里man 命令名可以查看手册,按q退出。不怕查手册,是专业素养的一部分,而不是技术不行。
最后分享一个我个人的小习惯:凡是超过三步的操作,我都写成脚本存下来,而不是依赖手动敲。比如启动服务、查看日志、清理缓存,都放到一个tools/目录下,需要时一条命令搞定。这既是命令行能力的体现,也是Python自动化思维的延伸。当你开始把重复性工作反复“脚本化”的时候,就说明你真正把命令行的武器攥在手里了。