很多Python程序员写代码的时候思路清晰,一进终端就手足无措。其实Linux命令不是背出来的,而是“用”出来的。这篇文章我不会罗列几百条命令,而是挑出Python开发、调试、部署过程中真正高频用到的那批,告诉你每条命令解决什么问题、怎么把多个命令串起来用。无论你是刚转Python的脚本党,还是已经写了几年业务代码的老手,只要需要在服务器上跑程序、看日志、调进程、排查bug,这套命令都值得你收藏起来慢慢消化。
1. 先搞明白:为什么Python程序员离不开Linux命令行?
先别急着记命令,先弄清楚一个问题:为什么偏偏是Linux?我在一线写Python也有不少年头,接触过各种项目,最终几乎所有生产环境都跑在Linux上。原因其实不复杂,Python生态很多底层库,比如网络、并发、系统调用相关的,在Linux上表现最稳定,部署工具链也默认围绕Linux设计。你可以在Windows上写代码,但上线那一刻,大概率还是要和Linux终端打交道。如果连基本的命令都不熟,那部署、排查基本寸步难行。
1.1 不是“学Linux”,而是“用Linux”
很多教程喜欢从文件系统目录结构讲起,讲权限位、inode、软硬链接,说实话特别容易劝退。我的经验是:别把Linux当一门课程来“学”,把它当成工具箱来“用”。你想要完成什么任务,就去找对应命令。比如“我想看看程序日志最后几行”对应tail,“我想知道谁在占用8080端口”对应ss或lsof,“我想让脚本在后台跑不被打断”对应nohup。任务驱动的记法,比抄笔记牢得多。
Python程序员有个天然优势:你已经非常熟悉“函数输入输出”的逻辑。Linux命令本质上也是这样,一条命令接收标准输入,处理后输出到标准输出,还能用管道把一个命令的输出接到另一个命令的输入上。把这些命令想成一个个小函数,串起来就是一条流水线,这样理解起来会轻松很多。
1.2 三条主线:文件、进程、日志
我对团队的同事说过,日常开发运维中,90%的终端操作可以归到三条线:第一是文件,比如查看目录、复制部署、批量替换代码;第二是进程,比如启动Python服务、查看后台进程、停止异常任务;第三是日志,比如实时查看输出、搜索报错关键字。这篇文章后面的内容基本就是围绕这三条线展开。先把主线抓出来,后面碰到陌生命令,你也能猜出它大概属于哪一类,心态就不慌了。
为什么我推荐先掌握这三条主线,而不是去看完整命令手册?因为主线是连起来的,一个任务的完成往往是跨类别的。举个例子:你改了一个Python脚本,想重新部署,可能需要先找到目录(cd),修改文本(sed),然后重启服务(systemctl restart),最后看日志验证(tail -f)。如果每个命令单独记忆,你很难把它们串成解决问题的流程。所以后面每一章我都会用场景把命令串起来讲。
1.3 你用的可能不是同一个Shell
这里插一句很容易被忽略的背景。很多人在Windows上用CMD或者PowerShell,到了服务器上却发现命令对不上。原因是你接触到的其实不是Linux本身,而是Shell,也就是解释“命令”这个语言的程序。Linux上最常见的是bash,macOS新版默认是zsh。两者语法大体相近,alias、脚本基本通用,不用担心太多。我的建议是:统一在终端里用bash习惯,写脚本时第一行写成#!/bin/bash,这样换环境也不会翻车。毕竟我们后面要用的很多组合技,依赖的是Shell的工作方式。
别怕在终端里试命令。我第一次接触Linux时,满屏的英文输出也吓人,但慢慢发现试错成本其实很低。最多就是删错文件、误杀进程,只要重要数据有备份,大胆敲反而学得快。尤其Python程序员写代码本身就习惯了“跑一下看报错再改”,这套循环搬到终端上也成立。
2. 日常操作必会:文件、目录与文本处理命令
如果说哪类命令最常被用到,那一定不是炫酷的系统调试,而是最基础的文件和文本操作。很多Python项目的坑,往往不是代码逻辑,而是文件权限不对、路径搞错、目录占满。把这些命令练熟,能避开大量低级问题。
2.1 文件命令的高频组合
先说说每天都会用到的几个,别小看它们,正是因为每天都在用,一旦用错代价也最大:
ls -lh按人类可读的大小显示当前目录的文件,-a可以看到隐藏文件,比如.venv、.env。千万别小看隐藏文件,很多部署事故就是漏传了.env。cd -在当前目录和上一次目录之间来回切换。我在多个项目目录间跳转时经常用,比重新敲一遍路径省事。cp -r递归复制目录,部署代码前备份老版本时必用。mv移动或重命名,我习惯用它来改备份文件名,比如mv app.py app.py.bak。rm -rf这个命令杀伤力极大,请务必反复确认目录再执行。我见过太多人把变量写错,导致误删整个项目目录的事故,建议在重要机器上最好不要裸用。du -sh .venv查看某个目录占了多少空间。Python项目里的虚拟环境动不动几个GB,磁盘满的时候先查它。
还有几个和Python密切相关的用法。find . -name "*.py"可以递归找文件,老式但可靠。如果你的服务器上装了ripgrep,也可以用rg --files -g '*.py',速度更快。另外ln -s /data/static /home/user/static创建软链接,在部署场景里很常用,比如把大体积的静态文件放在独立磁盘,然后链接到项目目录里,这样项目目录本身不会瞬间膨胀。
2.2 grep、sed、awk 三件套
别看现在编辑器很强大,到了服务器上没有图形界面,文本过滤就靠这三个。我平时最常用的是grep:
grep -n "Traceback" app.log | tail -50 grep -r "TODO" --include="*.py" .第一句是找日志中报错的行并显示行号,第二句是递归搜索项目里的待办标记。注意grep -R和-r的区别,我一般用-r,它不会进入符号链接目录,避免在虚拟环境里绕圈,搜索结果也更干净。
sed主要用于批量替换。比如把某个环境配置里的域名换掉:
sed -i 's/old-domain.com/new-domain.com/g' config.py这类操作不能只看一眼就确认,最好先不加-i跑一遍,确认替换结果正确再真正写入文件。我自己就在生产环境上做过一次直接替换,结果把注释里的历史文案也改了,虽然影响不大,但深刻体会到“先看再做”有多重要。
awk更偏重结构化文本。比如日志里每一行是“时间 级别 消息”,想提取第二列:
awk '{print $2}' app.log | sort | uniq -c这条命令可以统计各日期的日志条数,快速判断是否有异常高峰。老实说awk功能很强大,但我们不必追求精通,掌握取出某一列、按条件过滤就够用了。真正的复杂解析,直接用Python写脚本反而更清晰。不要把时间浪费在背awk的正则上,能用Python实现的东西,就留给Python。
2.3 权限和属主:别一见到Permission denied就用sudo
新手最容易犯的错,就是遇到权限问题直接sudo python xxx.py。这样虽然能跑起来,但后患无穷:生成的缓存文件、日志文件全都变成root所有,下次普通用户运行又会出错,最后只能一路sudo到底。正确做法是先搞清楚是谁在访问哪个文件:
whoami查看当前用户。ls -l查看文件属主和权限。比如-rw-r--r-- 1 user group表示只有属主可写。id看用户组。- 如果确实需要让当前用户可读可写,用
chown user:group file修改属主。 - 给脚本加执行权限用
chmod +x script.py,注意这里的可执行其实是对Shell而言,不代表Python能直接运行,还需要shebang或python指定。
我处理过一个典型场景:某个项目总是出现PermissionError,结果是离职同事留下的文件属主不对,导致部署账号无法覆盖。后来我在部署脚本里统一加了一句chown -R deploy:deploy /data/project,这个问题再也没出现过。不要滥用chmod 777,那是给自己挖坑。权限问题看起来麻烦,但排查起来其实很有套路,先看用户再看组,最后看文件位。
3. Python专属:虚拟环境、进程管理与服务部署
进入正题,这部分和Python的关系最直接。很多Python程序员本地跑得好好的,一到服务器上就各种乱,大多数是虚拟环境和进程管理出了问题。
3.1 虚拟环境(venv)的命令操作法
现在Python官方推荐用venv,我建议在项目根目录固定创建.venv:
python3 -m venv .venv source .venv/bin/activate激活之后,注意确认当前用的是哪个Python:
which python # 预期输出 /data/project/.venv/bin/python如果显示的是系统路径,说明激活没生效,或者你所在的目录不对。退出虚拟环境用deactivate。这些是最基础的,但真正容易翻车的是cron或systemd里忘了用虚拟环境的Python。比如在定时任务里写python,结果用的是系统Python,导致找不到项目依赖。解决办法后面会说,这里先记住一个经验:在非交互式环境里,不要依赖source activate,直接写虚拟环境的绝对路径/data/project/.venv/bin/python最可靠。
安装依赖时,我习惯先把项目需要的包写进requirements.txt,然后:
pip install -r requirements.txt升级某个包时用pip install --upgrade,排查依赖冲突用pip check。命令行操作虚拟环境和IDE里配置,本质上是一样的,但在服务器上你只有命令行,所以这套必须形成肌肉记忆。另外建议把pip升级到新版本,老版本pip在解析复杂依赖时容易出幺蛾子,会浪费你很多时间。
3.2 后台运行、查看与停止进程
本地跑开发服务,直接python app.py就行,但服务器上你希望关掉SSH后程序继续跑。最原始的方式是:
nohup python app.py > app.log 2>&1 &nohup让进程忽略挂断信号。> app.log把标准输出写入文件。2>&1把错误输出也合并进来,否则报错信息你看不到。- 最后的
&表示放到后台。
这种做法适合临时验证,但生产环境还是建议用systemd,见下一节。平时查看进程:
ps -ef | grep python这条命令会列出所有Python进程,包含PID、父进程、启动时间等信息。如果想要精确匹配,用pgrep -f app.py只输出PID:
pgrep -f "python app.py"停止进程,我推荐按PID精确操作:
kill <pid>如果进程没反应,等几秒再kill -9 <pid>。kill -9是强制销毁,不到万不得已不要用,因为有可能导致数据库写入中断、文件损坏。很多时候我们只想“重跑一次”,那就先杀旧进程再启动。注意:pkill -f app.py虽然方便,但会匹配到命令行里含有app.py的其他进程,比如你刚好在编辑同一个文件,容易误伤。所以还是用pgrep先看,再精确kill更稳妥。
3.3 systemd:把Python服务变成开机自启的守护进程
线上服务如果还靠 nohup,一旦服务器重启,服务不会自动恢复。这就得用systemd了。写过一次.service文件之后就一劳永逸。
假设项目目录是/data/myapp,虚拟环境Python在/data/myapp/.venv/bin/python,入口脚本是app.py。创建配置文件:
[Unit] Description=My Python App After=network.target [Service] User=deploy WorkingDirectory=/data/myapp ExecStart=/data/myapp/.venv/bin/python app.py Restart=always RestartSec=3 Environment="PYTHONUNBUFFERED=1" [Install] WantedBy=multi-user.target写好后放到/etc/systemd/system/myapp.service,然后执行:
sudo systemctl daemon-reload sudo systemctl enable --now myapp查看状态:
systemctl status myapp实时日志:
journalctl -u myapp -f这套配置里几个细节值得展开。User=deploy可以避免服务用root运行,运行出的文件权限更干净;Restart=always让进程崩溃后自动拉起,但注意如果你的代码启动失败后一直崩溃,systemd会不断尝试重启,这时候需要看StartLimitIntervalSec相关配置,或者临时systemctl stop服务调整代码再启动;PYTHONUNBUFFERED=1确保print输出不经过缓冲实时进入journald,这样你调试日志时不需要等很久才看到内容。
相比本地开发服务器,生产环境部署更是要有systemd或容器工具来托底。学会这一套,你能节省大量排查时间。尤其当你管理的机器超过几台,手工nohup加ps查进程的效率会低到让人崩溃。
4. 文本流与管道:让Python脚本和Linux命令互相配合
很多Python程序员没有意识到,你的Python脚本可以成为命令行流水线中的一环。这种能力特别适合日志分析、批量处理文件的场景。
4.1 标准输入输出与重定向
Linux一切皆文件,标准输入、标准输出、标准错误都是文件。Python脚本默认也可以从标准输入读取数据。比如我写一个统计IP频率的小脚本count_ip.py:
import sys from collections import Counter counter = Counter() for line in sys.stdin: ip = line.strip().split()[0] if ip: counter[ip] += 1 for ip, cnt in counter.most_common(10): print(f"{ip}\t{cnt}")然后配合命令行使用:
cat access.log | python count_ip.py或者省掉cat:
python count_ip.py < access.log这两种方式都行。管道把前一个命令的标准输出接到后一个命令的标准输入。Python脚本只要按行读sys.stdin,就能和任意Linux命令组合,完全不需要打开文件、处理路径。这是很多老工程师喜欢命令行数据分析的原因。反过来,如果脚本有输出,你可以用>保存到文件,用>>追加。注意2>&1的使用,它把标准错误也重定向到同一文件,排查出错信息时非常重要。
4.2 xargs:批量把参数传给Python脚本
如果要对每个找到的文件执行Python处理,xargs就派上用场了。基础用法:
find . -name "*.log" | xargs -n1 python process_log.py-n1表示每次只传一个文件路径给Python脚本。如果文件数量多,可以用-P4并行执行4个进程,加快处理。这个组合在批量压缩、批量校验图片、批量重命名时都很好用。
有两点容易踩坑。第一,如果文件名里有空格,直接接xargs会拆错参数。这时用find . -name "*.log" -print0 | xargs -0 ...,以空字符分隔,才能正确处理。第二,如果Python脚本本身已经支持一次接收多个文件,可以不用-n1,直接xargs python process_log.py,效率更高。这取决于脚本怎么实现,要灵活判断。刚接触xargs时,我总觉得它难以理解,后来把它想成“把前面的结果作为后面的参数列表”,配合几个小样例跑一遍,就通了。
4.3 watch 与 cron:让脚本定时运行或持续观察
开发调试时,我想盯着某个变化,比如看目录里文件数量有没有增长,可以用:
watch -n 2 'ls -l /data/upload | wc -l'-n 2表示每2秒刷新一次。这个命令适合观察脚本运行产生的临时文件、队列长度等。如果想把脚本做成定时任务,用cron:
crontab -e在里面加一行:
*/5 * * * * /data/myapp/.venv/bin/python /data/myapp/cleanup.py >> /data/myapp/cleanup.log 2>&1注意两点:第一,Python要用绝对路径,最好直接指向虚拟环境里的解释器;第二,cron执行时的环境变量和你SSH登录时不一样,路径PATH可能很短,所以脚本内部如果需要外部命令,最好也写绝对路径。我见过太多人写的定时任务明明手动执行没问题,到了cron里却报“ModuleNotFoundError”或者找不到文件,原因多半是没有用绝对路径或没有激活虚拟环境。写cron时养成“全绝对路径”的习惯,能少踩很多坑。
5. 排查问题必会:日志、网络与性能排查命令
程序上线后,最考验功力的就是排查问题。在服务器上你没法用IDE断点调试,一切全靠日志和系统状态。这些命令是你定位问题的探照灯。
5.1 实时看日志的正确姿势
最简单的命令就是:
tail -f app.log它会持续跟踪文件新增内容。如果日志文件很大,又想找关键字,可以用:
grep -n "ERROR" app.log | tail -100或者用less打开大文件,操作更顺滑:
less app.logless里按/搜索关键字,按n跳转到下一个结果,按G去文件末尾,按g回开头。对于几百MB的日志,它也不会卡死,比我见过的一些图形编辑器强得多。如果服务由systemd管理,看日志更优雅:
journalctl -u myapp -f --since "10 minutes ago"-f表示跟随,类似tail -f。加上--since可以只看最近十分钟的记录,减少刷屏。日志是程序员的眼睛,我强烈建议从一开始就养成在关键业务路径上打日志的习惯,到排查问题时你会感谢自己。尤其Python自带print很直观,但生产环境更建议用logging模块,带上时间戳和级别,配合grep过滤效率会高很多。
5.2 端口占用与网络连接排查
Python服务启动时报“Address already in use”,基本就是端口被占了。先看谁在监听:
ss -tlnp | grep 8080-t显示TCP,-l只显示监听,-n显示数字端口,-p显示进程。如果系统没有ss,可以用老的netstat:
netstat -tunlp | grep 8080想知道某个端口被哪个进程占用的更直观方式:
lsof -i:8080会列出进程PID和名称。杀掉占用进程,建议用PID kill,而不是瞎猜。有时候端口被占是上一个Python进程没杀掉,可以用ps -ef | grep python找出来。排查网络问题时,我还会用curl -v http://127.0.0.1:8080/health看看接口返回,-v打印详细请求过程,能快速看出连接是否正常、返回了什么状态码。如果接口返回超时,再配合ping或者telnet检查网络链路,不过大多数时候还是端口和进程的问题。
5.3 内存、CPU与磁盘定位
Python服务经常是吃内存大户。先看整体资源:
free -h df -hfree -h看内存剩余量,df -h看磁盘剩余。如果磁盘满了,日志和临时文件都会写不进去,后续需求全崩。更详细看进程占用:
top -ctop里按P按CPU排序,按M按内存排序,q退出。如果服务器上有htop,交互体验更好,能看到彩色直方图。但基础机器不一定有,所以我更常用一条命令:
ps -eo pid,%cpu,%mem,cmd --sort=-%mem | head -20这条命令直接列出占用内存最高的前20个进程,一眼就能看出来是不是某个Python进程内存泄漏。遇到进程被系统杀掉,表现是“Killed”,大概率是内存不足触发OOM。这时候不要只盯着代码,先用free -h确认内存,再用上面的ps命令排查是哪个进程吃掉大量内存。如果确认是Python脚本内存消耗过大,可以考虑用生成器代替列表推导、分批处理大数据、或者增加机器内存。排查性能问题不是想当然,数据摆在那里,问题往往一目了然。
6. 效率工具与组合技巧(个人经验)
到了这一节,假设基本命令你已经上手了。下面分享一些我平时积累的效率做法,不是标准答案,但实测下来很香。
6.1 用alias定制自己的高频命令
我个人强烈推荐在~/.bashrc里加alias。比如:
alias py='python3' alias act='source .venv/bin/activate' alias gp='git log --oneline --graph --all' alias jc='journalctl -u'加完后source ~/.bashrc生效。alias的好处是少敲几个字符,但别走火入魔。不用刻意背别人配置,结合自己项目习惯加几条最常用的就行。要注意alias只在交互式Shell里生效,如果你把alias写进脚本,脚本可能找不到命令,所以脚本里还是老老实实用全名。
6.2 使用history与Ctrl+R快速复用
输入过100条长命令后,不想再敲一遍。几个技巧:
- 输入
history查看所有命令记录。 - 用
Ctrl+R进入反向搜索,输入关键字,它会实时匹配历史命令,再按一次Ctrl+R继续往上翻,命中后回车执行。 - 用
!!代表上一条命令,比如sudo !!可以用管理员权限重跑上一条命令,虽然我不建议随便sudo,但偶尔确实方便。 - 用
!abc代表最近一条以 abc 开头的命令,比如!py会补全成最近的python开头的命令。
这些技巧不复杂,但能明显改善终端使用体验。我见过一些人还在用鼠标复制粘贴命令,其实在命令行里早就一秒回放历史了。特别是Ctrl+R,用顺手之后几乎离不开。
6.3 推荐几个现代命令行替代品
老命令当然可靠,但效率工具能让你舒服很多:
tldr:命令帮助学习,比如tldr tar会给出常用场景示例,比翻完整man手册省时间。通常用官方脚本或包管理器安装即可。fzf:一个模糊查找工具。配合history和文件路径使用,比如history | fzf可以交互式筛选历史命令。ripgrep(rg):替代grep -r,速度更快,默认忽略.gitignore中的文件,不会在.venv目录里翻个底朝天。
安装这些工具要注意服务器权限,不要因为装一个方便工具就张手sudo到底。我的经验是:个人常用的折腾可以在本地,生产环境尽量保持最小化,少装无关软件。工具终究是辅助,基础命令才是兜底。
6.4 常见问题速查表
最后把高频故障整理成一张表格,方便你贴在终端旁边:
| 现象 | 常见原因 | 排查/解决命令 |
|---|---|---|
| Permission denied | 文件属主或权限不对 | ls -l file,用chown调整属主 |
| Command not found | 命令不在PATH中,或虚拟环境未激活 | echo $PATH,which python |
| Port already in use | 进程未退出或被其他服务占用 | ss -tlnp | grep 8080,kill对应PID |
| No space left on device | 磁盘写满 | df -h,du -sh /data/*定位大目录 |
| 进程被Killed | 内存不足触发OOM | free -h,ps -eo pid,%mem,cmd --sort=-%mem |
| 定时任务报ModuleNotFoundError | cron未使用虚拟环境Python | 修改crontab,使用.venv/bin/python绝对路径 |
| 日志不输出 | print缓冲导致 | 设置PYTHONUNBUFFERED=1,或用flush=True |
这张表基本覆盖了我被问到最多的场景。排查的原则始终是先定位再处理,不要一上来就重启服务或乱杀进程,否则问题会反复出现。
我个人在实际操作中最大的体会是:Linux命令的价值不在于你背了多少,而在于你能不能用一条命令快速定位问题。刚入行那会儿我也害怕终端,总觉得黑框框很吓人,后来发现只要带着具体任务去敲,进步远比想象中快。最后分享一个小技巧:每次新建Python项目,我会在终端里先敲一遍mkdir -p logs data、python -m venv .venv、source .venv/bin/activate这三条命令,让文件夹结构、虚拟环境和终端状态从一开始就干干净净。这个习惯帮我避开了很多环境混乱的坑,也推荐你试试。