ARTICLE DETAIL

资讯详情

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

Python程序员必修的Linux命令实战指南

Python程序员必修的Linux命令实战指南 1. 先想清楚为什么Python写得好Linux命令还是躲不掉先说个我自己的经历。有一段时间我主要是写Python爬虫和数据处理脚本在Windows的PyCharm里跑得飞起当时真觉得Linux命令跟我没什么关系。结果第一次把脚本部署到云服务器上直接在项目目录里敲python xxx.py跑了几秒钟就崩了——报错信息七零八落本地完全没有复现。折腾了一下午最后发现是路径分隔符、编码、还有文件权限三个问题叠在一起。那一刻我才明白写Python的人躲不开Linux命令不是因为它流行而是因为你写的代码最后大概率要跑在Linux上。你随便打开一个招聘需求看看Python后端、爬虫、数据分析、自动化运维几乎都会写熟悉Linux基本操作。这背后的逻辑很简单互联网公司的服务端百分之八九十是Linux系统Docker容器里的基础镜像绝大多数也是Linux甚至你做树莓派或者嵌入式项目底层跑的还是Linux。Python本身是跨语言的、跨平台的但部署环境几乎默认就是Linux。你可以不擅长系统管理但不能不会用命令行把自己写的代码在目标环境里跑起来、调明白、查清楚问题。我见过一些刚开始工作的同事对Python语法、框架都挺熟但一碰到服务器就慌不知道怎么看进程在不在不知道日志去哪找不知道端口被谁占了。其实这些都不是高深运维知识只是没有养成用命令行干活的思维习惯。命令行跟图形界面最大的区别在于它是可编程的、可组合的。你可以一条命令查文件、一条命令过滤日志、一条命令批量改名再把这些串成流水线。IDE是给你看代码用的终端才是让你在真实环境里处理问题的。这篇文章我就按Python程序员日常工作的实际路径来梳理命令不讲那种背了也没用的命令手册只讲你写代码、跑服务、查问题、部署上线时真正碰得到的高频场景。你不用全背先把思路掌握用到的时候自然会想起来去哪查。核心就一句话命令是工具不是考试题。2. 文件与进程操作你的Python代码跑在哪里你的眼睛就看到哪里2.1 定位文件别只靠文件管理器ls、find、locate各有各的定位进场第一件事是搞清楚我在哪、这目录里有什么。ls是最基本的但很多时候我们用的是它的变体ls -l看权限、大小、修改时间ls -a看隐藏文件比如.venv、.gitignore这类对Python项目特别重要的隐藏文件ls -lh把文件大小显示成人能读懂的 K/M/G 格式。我个人的习惯是直接ls -lah极少用裸的ls。要找文件find才是真正的瑞士军刀。比如我想在项目里找出所有两天内改过的 Python 文件find /home/wang/projects -name *.py -mtime -2-mtime -2表示修改时间在两天以内-mmin -30可以精确到三十分钟内改过。配合-size还能找大文件比如找出大于 100M 的日志find /var/log -type f -size 100Mlocate用的是预建索引查系统内文件极快但新创建的文件可能不在索引里需要updatedb刷新。我一般把find当作主力因为它在项目目录里灵活、可控而且能和后面的-exec、xargs配合做批量操作。2.2 内容检索用grep代替肉眼扫日志这可能是Python程序员最该先掌握的命令之一。项目里加了一堆调试日志想看看遗留的print和DEBUG标记都散在哪grep -rn TODO\|FIXME --include*.py .-r递归目录-n显示行号--include*.py只搜 Python 文件。搜索的时候我喜欢再带上-l只打印文件名或者带-c统计每个文件命中多少行这样不会一下子被刷屏。日常查日志用得最多的是tail -f app.log | grep ERROR这是经典的只观察错误行的写法等于给日志装了一个筛子。有个小坑是grep 默认按行匹配如果你的 Python 日志是多行的 traceback最好先grep -A 5 Traceback带上错误后面几行否则只能看到半截堆栈。2.3 进程管理ps、top、kill三件套跑了python main.py之后服务到底起来没有端口有没有监听内存是不是爆了这三件事天天都在问。先看进程列表ps aux | grep pythonps aux会显示所有用户的进程配合grep python就能看到你的 Python 进程和 PID。只看与被查进程是否存活也可以直接pgrep -af python。想看动态资源占用用top进去以后按P按 CPU 排序、按M按内存排序这个操作在排查到底是哪个进程把机器吃满了的时候非常实用。有htop的机器上体验更好但公网服务器不一定装了所以top的基本操作必须会。杀进程也有讲究不要一上来就kill -9。kill默认发的是 SIGTERM15是请你保存后退出进程有机会做清理。只有它确实没反应了才轮到kill -9SIGKILL强制了断。命令是kill 12345 # 温和退出 kill -9 12345 # 强制杀掉我之前遇到过用 PyTorch 训练模型卡死直接kill -9了进程结果留下了几个 G 的临时文件和一个损坏的 checkpoint。所以能用 15 就别先上 9就像吵架先给台阶、再掀桌顺序不能反过来。2.4 文件权限为什么./script.py总报 Permission deniedPython 脚本要直接执行光写代码没用还要让它有执行权限。写完一个脚本后通常要chmod x script.py ./script.py而且文件第一行最好有 shebang#!/usr/bin/env python3这样系统才知道用哪个解释器运行它。另一个常见问题是服务跑在www-data用户下但日志目录权限是root的导致 Python 写日志直接整个进程崩溃。这时候看ls -l的输出或者直接看/var/log/你项目/的属主和属组再chown -R调整即可。这些在本地 Windows 开发时几乎不会遇到一到服务器上就会变成连环坑。3. vim 与 git写 Python 前必须啃下的两块硬骨头3.1 vim服务器上没有 PyCharm你的文本编辑器就是它说实话vim 的学习曲线确实让很多人一开始想放弃。但在服务器上用vim改配置文件、看代码、临时写脚本是绕不开的场景。你总不能在每台服务器上都装一个图形化开发环境也不可能把文件下载到本地改完再传回去——那样效率太低。先理解 vim 的底层逻辑它是模式化编辑器。日常使用不贪多只需要记住三块普通模式打开文件默认在这个模式所有按键像快捷键dd删一行、yy复制一行、p粘贴、u撤销插入模式按i进入可以像普通编辑器一样打字按Esc返回普通模式末行模式按:进入:wq保存退出:q!不保存退出/关键词搜索我最常用的场景是在服务器上改配置文件、给脚本加一行注释、快速查看日志文件片段。真的只需要知道i、Esc、:wq、dd、y、p、/、u这几个键位就能应付大部分需求。vim还有一个功能在外面被低估——当你用git diff查看代码改动的时候vimdiff 能并排对比两个文件。现在很多编辑器和 IDE 都内置了 vim 模式比如 VSCode 的 Vim 插件我一直在用就是因为它让我的肌肉记忆能跨工具生效。vimmers 之间流传一句话vim 的学习曲线是陡但就陡一次。我的建议是不要一上来就去配一堆插件先学会原汁原味地改文件、保存、搜索够用两周之后再去碰.vimrc。配置文件路径是~/.vimrc最简单的几行就能显著提升体验set number syntax on set tabstop4 set shiftwidth4 set expandtabPython 社区强烈建议缩进是四个空格所以这几行对写 Python 非常友好。3.2 git 日常流程版本控制不是存草稿而是留证据git 大概是程序员最不能跳过的工具了。我不是来讲完整教程我只想说清楚在你写 Python 项目时最高频的几条通路。日常开发几乎是这个循环git status # 看工作区状态 git diff # 看还没加进暂存区的改动 git add 文件名 # 加入暂存区 git commit -m fix: 修复配置读取编码问题 git push # 推到远端这里我见过最多的错误是永远只会git add .然后一次性把无关文件全部提交进去最后队友看 diff 看到崩溃。一个小习惯每次提交之前先git status和git diff --stat确认一下改动范围把已训提交拆小。写清楚 commit message 就像给未来的自己留了一张便利贴。分支操作有几个命令值得细说。git branch 分支名创建分支git checkout 分支名切换分支git merge 分支名合并。注意不要在主分支上直接改代码我的做法是每次需求都开分支测试通过再合并回主分支。合并时如果出现冲突用git diff看两个版本的差异然后打开文件手工解决——这个环节不是机器能替你决定的必须人肉看懂两边的意图。3.3 用 git 查历史事情搞砸了之后它是你的时光机线上代码出 bug怎么快速知道是哪一次提交引入的两个命令组合使用。git log --oneline看提交历史git blame 文件名查看每一行代码最后被谁、在哪个提交里改过——这个命令在定位这行到底是谁写的时特别好用。更深层一点的绝活是git bisect通过二分查找快速定位引入 bug 的提交。原理很简单告诉 git这个提交是好的、那个提交是坏的它会自动在中间切提交让你测试几次之后就能锁定元凶。我实际用下来一个 500 次提交的项目大概反复十次以内就能找到那个出问题的 commit。vim 和 git 配合最爽的场景是git diff之后直接看代码。我习惯在终端里git diff查看改动如果改动太多就git diff 文件名 | less分页看看到哪个文件想深入就用 vim 打开原文件。这种命令行管道配合的方式其实比打开 IDE 再切标签页的效率高不少。4. 环境与依赖管理装 Python、建虚拟环境、装包的正确姿势4.1 在 Linux 上安装 Python不同场景的不同选择Linux 系统自带的 Python 版本不一定能满足你的需求Ubuntu 20.04 默认可能就是 Python 3.8而项目需要 3.11。常用有三种方式我按自己的推荐顺序给你排一下pyenv多版本管理的首选。安装后pyenv install 3.11.5然后pyenv local 3.11.5在项目目录里固定版本以后再也不用担心系统 Python 被搞坏。系统包管理apt install python3Debian/Ubuntu或yum install python3CentOS/RHEL。胜在简单缺点是版本通常偏旧而且容易跟操作系统的内部工具混在一起。源码编译确实是最正统的方式wget下载源码、tar -zxvf解压、然后./configure --prefix/usr/local/python3.11、make make install。但编译耗时、依赖多环境复杂的服务器上还容易因为缺 zlib、openssl 这类开发包而失败新手不太推荐。我自己主力用 pyenv但有一点需要提醒pyenv 通过修改 PATH 来实现版本切换所以你的 shell 配置文件.bashrc或.zshrc里必须加好初始化脚本否则会出现命令找不到 pyenv的尴尬。我踩过的坑是当时改完.bashrc没有立刻source ~/.bashrc然后一脸懵地在当前会话里打字发现 pyenv 不存在实际上换个新终端就好了。4.2 虚拟环境此生必须养成的好习惯Python 依赖管理最大的痛就是版本冲突。项目 A 需要 Django 3.2项目 B 需要 Django 4.2如果都装在系统环境里最后肯定有你哭的一天。所以 2018 年之后我用任何项目都会先建虚拟环境基本命令cd /path/to/myproject python3 -m venv .venv source .venv/bin/activate激活之后终端提示符前面会出现(.venv)这时候pip install的一切都装在项目的.venv目录里。退出环境用deactivate。注意.venv目录体积不小所以一定要写进.gitignore别顺着git add .一起提交上去。如果你想用conda管理 Python 环境和依赖那是另一个流派尤其适合做数据科学的人因为能一次性装好 numpy、pandas、scipy 这些编译好的库省时省力。conda create -n myenv python3.10创建环境conda activate myenv激活。我个人的区分方式是普通 Web 项目和爬虫用venv就够了涉及机器学习和复杂科学计算的直接用 conda反正别裸装到系统环境里就行。4.3 pip 的实用参数装包比你想象的更可控pip 大家都用但很多人只用过pip install 包名。这里有几个日常用得上的参数pip install -r requirements.txt # 按文件批量安装 pip install --upgrade 包名 # 升级包 pip install --user 包名 # 只装到当前用户目录不影响系统 Python pip list # 列出当前环境所有包 pip freeze requirements.txt # 冻结当前环境版本信息一个很大的坑是国内网络环境下pip install默认从官方 PyPI 下载偶尔会慢到你想砸电脑。解决办法是配置镜像源比如 Linux 下在~/.pip/pip.conf中加入[global] index-url https://pypi.tuna.moj.edu.cn/simple trusted-host pypi.tuna.moj.edu.cn这样装包速度快了不止一个档次。每次装了新包之后最好立刻pip freeze requirements.txt保持依赖清单最新否则过几天你自己都忘了装过什么。这个习惯帮我在换机器、部署新环境的时候少掉了无数根头发。5. 日志查看与故障排查终端命令才是真正的调试工具5.1 看日志先学会跟读再学会检索Python 服务出问题第一步永远是看日志。高频命令无非这几个tail -f app.log # 实时跟踪日志输出 tail -n 100 app.log # 看最后 100 行 less app.log # 大日志文件分页查看按 G 到末尾按 g 到开头我见过不少新手拿着一百多 MB 的日志文件直接vim打开卡得整个终端都动不了然后怀疑是机器坏了。好一点的思路是先用wc -l看行数再grep筛选关键词、less分页浏览。日志里找ERROR、Traceback是最基本的但更聪明的做法是找时间窗口grep 2025-01-15 10:2 app.log这段日志只匹配2025-01-15 10:20 到 10:29这一个小时的情况比从头翻到尾高效得多。5.2 systemd 服务日志journalctl 是你的新朋友如果你的 Python 服务是用 systemd 管理的这是现在 Linux 服务的主流管理方式那看日志的姿势就要换成journalctl。我以前还傻乎乎地在/var/log/里找应用日志后来才知道 systemd 会把 stdout/stderr 自动收集到这个统一日志系统里journalctl -u myapp.service --since 1 hour ago journalctl -u myapp.service -f # 实时跟踪 journalctl -u myapp.service --since 2025-01-15 10:00 --until 2025-01-15 10:30这三个参数组合起来基本就能实现按服务、按时间段、按实时流三档切换。诊断重启类问题的时候先systemctl status myapp看进程状态和最近的日志再判断是代码异常还是 OOM 等资源和环境问题。5.3 端口、连接与系统调用当日志正常却行为异常时最难的一类问题是日志里干干净净该打印的 print 都打印了但服务就是响应慢或者连不上。这时候就要跳出 Python 代码从系统层面查找。先看端口监听状态ss -tlnp | grep 8000如果 8000 端口被别人占了就会看到占用进程的 PID 和名字再配合ps就能找到真凶。如果端口是通的但请求还是超时可能是连接数满了用ss -s看当前连接汇总。更深一层lsof -i :8000能列出打开这个端口的所有进程特别适合排查明明是别人的进程占用了我的端口这种历史难题。最狠的工具其实是strace。它跟踪一个进程的所有系统调用等于给程序开了一个显微镜。比如一个 Python 进程疑似卡在某个 IO 上你可以strace -p 12345 -e tracefile,network这样就能看到它到底是卡在读取某个文件、还是卡在等待网络请求。当年我排查一个爬虫程序无症状卡死最后就是用 strace 发现它在反复重试打开一个不存在的 cookie 文件疯狂循环。这类问题光看 Python 日志根本无从下手因为 Python 解释器把异常吞掉了但操作系统层面的行为骗不了人。5.4 一个真实案例FastAPI 服务端口起不来的完整排查链路这些命令组合并用的一个典型场景是服务起不来报端口被占用。我完整走一遍你以后遇到类似的就直接照抄systemctl status myapi看服务状态提示Address already in use。ss -tlnp | grep 8000找到占用端口进程的 PID发现是另一个旧版本的 Python 进程还活着。ps aux | grep 旧进程名确认进程详情原来是一次部署时新旧代码同时启动旧的没退干净。kill 旧PID先温和退出等几秒还没消失再用kill -9。重新systemctl start myapi再journalctl -u myapi --since 1 min ago确认启动日志正常。这个链路其实只要第一步做对了后面基本都是顺藤摸瓜。但如果第一步直接pkill python把整个机器上所有 Python 进程全杀了那才叫灾难。所以排查的过程也是最小干预原则一步一步缩小范围而不是上来就放大招。6. 远程操作与网络调试部署和联调离不开的看家本领6.1 ssh 与文件传输把远程服务器当成你电脑的延伸部署代码的第一关就是连上服务器标准姿势是ssh 用户名服务器地址如果端口不是默认的 22加-p 端口号。第一次连接时会让确认 host key 指纹这是正常的安全机制确认一遍就行。比较安全的习惯是提前配置好密钥登录而不是每次输密码。把本地的公钥~/.ssh/id_rsa.pub放到服务器的~/.ssh/authorized_keys里之后就能免密登录了。注意本地私钥文件的权限不要太宽松chmod 600 ~/.ssh/id_rsa否则 ssh 会因为权限过于开放而拒绝使用该密钥。传文件用scp或rsync我一般情况用rsync因为它支持增量传输和断点续传传大文件或大量小文件时稳得多rsync -avz ./deploy/ 用户名服务器:/opt/myapp/6.2 curl不打开浏览器也能调试接口写了 Python 后端接口最直接的验证方法不是跑到浏览器里点来点去而是用curl在终端里模拟请求。我最常用的几个参数curl http://127.0.0.1:8000/api/health # GET 请求看返回内容 curl -i http://127.0.0.1:8000/api/health # 连同响应头一起看 curl -X POST -H Content-Type: application/json -d {name:test} http://127.0.0.1:8000/api/create-i会输出 HTTP 状态行和响应头调试 302 跳转、跨域、缓存问题的时候几乎必用。想同时看请求耗时可以curl -o /dev/null -s -w 耗时: %{time_total}s\n http://127.0.0.1:8000/api/health这个写法不输出响应体、只输出耗时统计非常适合做快速性能冒烟测试。6.3 网络连通性ping、dig、tracepath 的分工接口超时了到底是域名解析失败、网络不通、防火墙拦截还是服务本身的问题需要按层排查。ping测网络通不通dig看 DNS 解析结果tracepath看经过的路径。比如dig example.com ping -c 4 example.com tracepath example.com我的一般流程是先用dig确认域名解析到自己预期的 IP不通就查 DNS 配置通了就ping看丢包情况丢包严重就用tracepath判断是不是中间链路的问题。如果这几层都没问题再回到服务本身看日志。沿着这个层级排查基本不会把时间浪费在错误的层面。需要注意公网生产环境里ping和traceroute的大流量探测要谨慎别在敏感时段拿生产机器去跑压力探测。6.4 安全底线权限、密钥、服务账号远程操作多了之后安全习惯必须刻进肌肉记忆。我的几个底线原则第一不用 root 跑应用服务单独建一个低权限用户需要管理员权限时用sudo第二SSH 尽量禁用密码登录、改用密钥认证私钥绝不出本机第三服务监听的地址要明确如果只需要本机访问就绑127.0.0.1暴露公网的接口越少越好。这些不是锦上添花的运维洁癖而是你在生产环境工作必须有的自我保护意识。7. 把重复操作变成脚本终端命令的组合艺术7.1 管道、重定向与通配符命令的积木玩法单个命令是工具组合起来才是生产力。管道符|把左边命令的输出变成右边命令的输入重定向把输出写进文件通配符*.py让命令一次匹配一堆文件。一个经典组合是统计当前目录下 Python 代码行数find . -name *.py -exec cat {} \; | wc -l这里的{}是find找到的每个文件的占位符\;表示命令结束。写反了或者少了反斜杠都会直接报错。理解了组合之后你就可以把查找文件筛选内容统计这些原子操作拼成一条流水线。7.2 find 与 xargs 搭配批量操作的经典姿势批量文件操作是另一个高频场景。比如说项目里有一堆临时文件想清理find /tmp/ -name *.tmp -type f | xargs rm -f有个我得专门提醒的坑如果文件名包含空格直接xargs rm -f会把my file.tmp当成两个文件处理。稳妥的做法是让 find 自己执行删除find /tmp/ -name *.tmp -type f -delete-delete参数是最稳妥的没有文件名的头疼问题。具体场景下的命令选择不光是哪个能跑通的问题而是哪个在极端文件名下也不会出错的问题这往往要踩过坑才会重视。7.3 sed 与 awk文本处理的看家本领写 Python 的人可能会觉得 sed、awk 跟 Python 的 re、pandas 重叠了但这两个命令在终端里处理日志和配置文件时效率优势巨大。比如全局替换某个配置项sed -i s/127.0.0.1/0.0.0.0/g settings.py-i表示原地修改s/旧值/新值/g是全局替换。再比如从访问日志里提取每个 URL 的状态码和耗时可以用 awk 按列切awk {print $7, $9, $10} access.log日志格式不同列的含义也不同这需要你先看一眼日志长什么样再决定取第几列。awk 本身是一门迷你语言我不建议一开始就深学记住按列提取 简单统计的用法就足够日常需求了。7.4 crontab 定时任务让 Python 脚本自己跑起来很多 Python 程序是定时任务型的比如每天凌晨抓取数据、每周发送报表。这时候 crontab 是标配工具。crontab -e打开当前用户的定时任务配置每行一个任务格式是分 时 日 月 周 命令# 每天凌晨 2 点 30 分执行爬虫脚本 30 2 * * * cd /opt/myproject /opt/myproject/.venv/bin/python spider.py /var/log/spider.log 21我吃了好几次亏后总结出两个必写项一是命令里必须用绝对路径尤其要显式指定虚拟环境里的 Python因为 cron 环境跟你的终端环境不一样PATH 基本是空的二是要把输出重定向到日志文件因为 cron 里的错误输出默认会发到邮箱而你几乎不会去查那个邮箱。如果不重定向脚本跑了等于白跑出了问题也找不到任何痕迹。定时任务写完之后等一分钟观察下有没有执行是基本操作。高效但常被忽略的验证方式是先用一个立即执行的命令测试脚本本身能正常跑再测试脚本在 cron 的环境里也能正常跑最后才谢天谢地的相信是 cron 在正常干活。可以顺手在任务里加一句date输出下次看日志的时候就知道任务有没有被触发。最后再说一点个人习惯命令的复杂度要和风险成正比。在本地实验环境你可以随意rm -rf测试、随意kill -9但在生产环境所有批量、危险的操作之前先停两秒想一想这个命令匹配的范围是什么我有没有先ls看一遍匹配结果养成先列出再删除、先查看再修改的习惯比记住再多命令都管用。写 Python 也好敲 Linux 命令也好说到底都是处理代码、数据、环境、进程这几件事的交互。你不需要成为运维专家但你需要让终端成为你随身的工具箱——这也是我这些年逐渐从只在 IDE 里点鼠标变成喜欢在命令行里把活干完的原因。工具不需要多华丽需要的是你在关键时刻拿得出来、用得稳。
返回列表