先直接说结论:Python程序员学Linux命令,不是去背一份"命令大全",而是围绕自己每天的开发场景,把最常用的几十条命令练成肌肉记忆。这篇文章我只讲Python开发中真正会用到的那些命令,每条都配了实际场景和踩坑记录。
你写Python的时候是不是也有这种感觉:本地IDE里跑得稳稳当当的代码,一上服务器就各种报错;爬虫跑到一半进程没了;部署完服务连日志都不知道去哪看。这些问题的根子往往不在Python代码本身,而是你对运行环境缺少基本的掌控能力。Linux命令就是掌控这台机器的钥匙。
这篇文章适合三类人:刚转Python开发、第一次接触服务器的初学者;已经写了几年Python但一直靠运维同事帮忙查环境问题的开发;以及想把自己从"会写代码"提升到"能独立部署维护"的全栈方向的人。我会从环境管理讲起,一路覆盖文件操作、进程管理、日志排查和部署传输,最后给一份速查表。
1. 环境管理:Python版本、虚拟环境、PATH,这三个问题能坑掉半天时间
1.1 搞清楚"which python"到底指向哪里
很多Python程序员的第一道坎,是在服务器上敲python发现版本和本地完全不一样。这个问题九成出在PATH上。
举个例子,你在服务器上执行:
bash复制which python3
/usr/bin/python3
这个路径说明你用的很可能是系统自带的Python版本,比如Ubuntu 18.04自带的3.6。但你的项目用了f-string调试特性,或者用了3.10才有的match语法,跑起来直接SyntaxError。
这个时候你第一个该查的是PATH:
bash复制echo $PATH
看输出的路径顺序,系统会从左到右逐个查找可执行文件,找到第一个就停下。所以如果你在/usr/local/bin里装了个Python 3.11,但PATH里/usr/bin排在前面,系统还是会用旧版本。想强制切换,有几种做法:
- 直接把新版Python的路径放到PATH最前面
- 用绝对路径调用,比如
/usr/local/python3.11/bin/python3 - 用
update-alternatives配置默认版本(Debian/Ubuntu系列)
我最推荐的方式是永远用虚拟环境隔离,不要系统级切换。虚拟环境会把解释器路径固定死,而且不会污染系统环境。
1.2 虚拟环境:Python程序员的第二个家
虚拟环境解决的问题很简单:A项目依赖Django 3.2,B项目依赖Django 4.2,两个项目都在同一台机器上,装到一起必然冲突。用venv隔离后,每个项目有自己独立的一套包。
创建和激活的完整流程:
bash复制# 创建虚拟环境(在项目目录下执行)
python3 -m venv venv
# 激活虚拟环境
source venv/bin/activate
# 激活后,命令行前面会出现 (venv) 前缀
这里注意一个细节:创建虚拟环境时,python3用的是哪个版本,虚拟环境里就是哪个版本。所以创建前先which python3确认版本。
我踩过最惨的一个坑:在服务器上创建了venv,然后用sudo pip install装包,结果包全装到了系统Python里,虚拟环境怎么import都报ModuleNotFoundError。后来才想明白,sudo会把环境变量切到root用户,而venv是当前用户创建的,root用户下$VIRTUAL_ENV根本不存在。所以记住:激活虚拟环境后,装包千万别加sudo。
1.3 pip和python版本不对应的问题
pip和python版本不对应,是另一个高频翻车点。你可能会遇到这种情况:python3已经激活了虚拟环境,但执行pip install requests却装到了一个莫名其妙的位置。
排查思路:
bash复制# 看当前pip指向哪个解释器
which pip3
# 直接用python -m pip,保证pip跟着当前python走
python3 -m pip install requests
推荐后面这种写法。python -m pip的意思是"让python自己去找pip模块",这样永远不会出现pip和python版本错位的问题。以后再有人在群里问"为什么pip装了我还是import不到",直接把这条命令甩给他。
Python脚本的头两行还有一种经典写法:
python复制#!/usr/bin/env python3
写env python3而不是直接写死/usr/bin/python3,是为了让你的脚本在虚拟环境中执行时,能自动使用虚拟环境里的解释器。这个细节在写部署脚本、定时任务脚本时特别重要。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 文件与文本处理:跟代码、日志、数据文件打交道的基本功
2.1 别再用ls翻页了,less解放双眼
初学者看服务器文件列表,习惯用ls -l一条条刷屏。文件少还行,一旦目录里几千个文件,刷屏根本看不过来。
bash复制ls -lh
-h参数会把文件大小显示成人类可读的K/M/G格式,而不是一串字节数。想看文件内容,用less代替cat:
bash复制less app.log
less支持上下翻页、按/搜索关键词、按q退出。对于动辄几百MB的日志文件,less是唯一能流畅打开的方式。cat直接读大文件会把终端卡死,我见过有人用cat读一个1G的日志,终端直接无响应,最后只能关掉重连。
2.2 find和grep:定位文件与代码的双刃剑
你记得某个Python文件里写过一段处理Excel的逻辑,但项目分了好几层目录,文件名也记不清了。find帮你按条件找文件,grep帮你按内容找代码。
bash复制# 在项目里找所有.py文件
find . -name "*.py"
# 在项目里找所有.py文件,并且排除venv目录
find . -name "*.py" -not -path "./venv/*"
# 在代码里搜哪个文件用了requests库
grep -rn "import requests" --include="*.py" .
这里-r是递归搜索子目录,-n是显示行号,--include限定文件类型。配合起来定位代码极快。
还有一个容易被忽略的组合拳:find配合xargs。比如要找所有包含"DEBUG"的.py文件并统计每个文件的匹配次数:
bash复制find . -name "*.py" -not -path "./venv/*" | xargs grep -c "DEBUG"
xargs会把前一个命令的输出作为参数传给后一个命令。为什么要用xargs?因为有些命令不支持直接接一堆文件路径的参数,xargs帮你批量传参。写Python爬虫时,处理几千个URL文件列表,这条命令能当简易版任务分发器用。
2.3 tail和head:日志文件的头和尾
排查Python服务问题时,最常用的命令大概率是tail。
bash复制# 查看文件最后100行
tail -n 100 app.log
# 实时跟踪日志文件
tail -f app.log
-f参数是follow的意思,会持续输出文件新追加的内容。你在本地起Flask服务测试接口时,开着tail -f就能实时看到每次请求的访问日志。Head则反过来看文件开头,适合查看日志文件是否以某种启动信息开头。
有一次我在排查一个定时微博爬虫为什么半夜没跑,就是用tail -f盯着日志,发现凌晨3点一到,内存占用飙升然后进程被系统杀掉。后来用free -h一查,是服务器内存本身不够,逻辑上一条命令就定位了问题。
2.4 处理文本数据:awk和sed虽然不是Python,但比Python快
处理结构化的文本数据时,很多人第一反应是写Python脚本。确实Python更灵活,但如果你只是想把日志里某一列字段抽出来,或者想把所有/替换成-,使用awk和sed效率高得多,还不用写文件。
bash复制# 提取日志中每行第3列的内容
awk '{print $3}' app.log
# 把所有2024-01-01替换成2024/01/01
sed 's/2024-01-01/2024\/01\/01/g' app.log
awk默认按空格切分每一行,$1是第一个字段,$0是整行。sed的s/旧/新/g是替换命令,g是全局替换。
你可能会说,这不就是正则表达式吗?对,sed和awk的核心就是正则。Python里re模块的语法跟它们是同源。我的建议是:临时查看、简单加工用sed/awk,需要复杂逻辑再写Python。工具选对了,效率提升是数量级的。
2.5 磁盘和内存:为什么你的Python程序突然跑不动了
代码本身没错,但程序一跑就卡死。这种时候先别在代码里加日志了,先看机器状态。
bash复制# 查看磁盘空间
df -h
# 查看当前目录占了多少空间
du -sh *
# 查看内存使用情况
free -h
一个典型的场景:数据分析脚本处理几十个G的CSV文件,写到一半报"No space left on device"(磁盘空间不足)。用df -h一看,根分区100%满了。
还有一个我很常用的组合:用du -sh *看当前目录下哪些子目录最占空间,然后直接定位到大文件。有次我发现~/.cache占了20多个G,全是各种包管理器留下的缓存,一条rm -rf ~/.cache/pip就清干净了。注意du -sh的-s是汇总当前目录整体大小,*是展开所有子目录,这样能一次列出所有子目录的大小排序。
3. 让Python脚本真正跑起来:前台、后台、守护进程之间的那点事
3.1 前台运行:最朴素的姿势
你直接在终端里执行python3 myscript.py,这就是前台运行。它的特点是:输出直接打到终端,Ctrl+C可以随时中断。适合开发调试阶段,因为你能实时看到print出来的内容。
但这种运行方式有两个致命缺陷:一是终端关闭或ssh断开,进程就跟着挂了;二是如果脚本要跑几个小时,你就得一直占着终端窗口。这时候就要用后台运行。
3.2 nohup:让脚本在ssh断开后继续跑
Python爬虫往深了写,一次性跑几个小时很正常。你不能一直开着电脑挂着ssh,更不想程序因为断网而中断。nohup就是干这个的。
bash复制nohup python3 spider.py > spider.log 2>&1 &
这条命令拆开看:
nohup:no hang up,挂起也不中断。即使终端窗口关了,进程照样跑。> spider.log:把标准输出重定向到文件。2>&1:把标准错误输出也重定向到同一个地方。&:放到后台执行。
这样执行后,终端会输出一个PID(进程ID),比如[1] 23456。这个数字就是进程号,后面要杀掉或查看它都要用。
我踩过的一个坑是:只写了nohup python3 spider.py &,没有重定向输出。结果程序运行时打了一堆warning刷屏,终端关闭后还是提示磁盘占用满了。原因就是没重定向,输出堆积到了nohup.out文件里。所以日志重定向一定要带上。
3.3 ps、kill和top:查看并管理你的Python进程
脚本后台跑起来之后,你可能会遇到以下需求:
- 想知道脚本还活着没有
- 感觉脚本卡死了,想强制结束
- 脚本占用了太多CPU或内存,想看看情况
对应命令:
bash复制# 查看所有包含python的进程
ps aux | grep python
# 用前面记录的PID结束进程
kill 23456
# 结束不了的时候,强制杀死
kill -9 23456
# 实时查看系统资源占用
top
ps aux输出一长串信息,格式是:用户、PID、CPU占用、内存占用、虚拟内存、物理内存、终端、状态、启动时间、CPU时间、命令。grep python是筛出和python相关的行。
top命令进去后按q退出,按P按CPU排序,按M按内存排序。看哪个进程吃资源最狠,一目了然。还有一个更直观的htop,有颜色和树状结构,但需要安装(apt install htop或yum install htop)。
这里有个细节:kill -9是发SIGKILL信号,进程没有机会做任何清理操作,直接消失。如果脚本有未保存的中间结果,kill -9会造成数据丢失。优先用kill PID(SIGTERM),给Python进程机会执行finally或atexit里的清理逻辑。实在没反应了再上kill -9。
3.4 定时任务:crontab里跑Python的注意事项
把Python脚本挂到crontab定时执行,是部署常用姿势。但坑也不少。我直接给一个安全模板:
bash复制* * * * * cd /path/to/your/project && /usr/bin/python3 /path/to/your/project/script.py >> /path/to/your/project/cron.log 2>&1
有几点必须注意:
- 一定要
cd到项目目录再执行。否则脚本里用了相对路径,比如open("data.csv"),会因为当前目录不对而找不到文件。 - Python建议用绝对路径,比如
/usr/bin/python3。因为crontab的环境变量比终端少很多,直接写python3可能找不到命令。 - 输出重定向到日志,方便排查为什么没跑成功。
注意:如果你用的是venv虚拟环境,crontab里的python要指向虚拟环境里那个路径,比如/home/user/myproject/venv/bin/python3,而不是系统Python。这个坑我踩过两次,每次都是"crontab确实执行了,但Python脚本import失败"这种诡异现象。
3.5 timeout:给脚本上个保险丝
有时候你会遇到一种情况:某个API调用久久不返回,代码没报错但就是卡住了。这时候一个简单又实用的命令是timeout:
bash复制timeout 300 python3 myscript.py
这样myscript.py最多跑300秒,超时自动终止。不管是爬虫卡在某个请求,还是数据处理死循环,都不用你盯着手动杀。
配合退出码还能做更精细的控制:timeout 300 python3 myscript.py || echo "timeout or error"。就算script执行失败或超时,你也能在日志里立刻感知到。
4. 线上翻车怎么救:日志、管道与排错实战
4.1 别对着空终端发呆了,先把日志捞出来
对Python程序员来说,最痛苦的事情不是代码报错,而是代码在服务器上报错,你却不知道报了什么错。所以线上排错的第一步,永远是找到日志。
如果你用systemd管理Python服务,那日志在journald里:
bash复制# 查看某个服务的完整日志
journalctl -u mypy-service
# 只看最近100行,并且持续跟踪
journalctl -u mypy-service -n 100 -f
如果你用nohup或crontab方式跑脚本,日志就在文件里:
bash复制tail -n 200 spider.log
grep -n "Traceback" spider.log
Traceback就是Python的报错堆栈。用grep搜到异常关键词,定位到出错行号,再回代码里看前后逻辑。80%的运行时报错都能用这种思路解决。
4.2 管道符:把多个命令串成一条流水线
Linux管道的魅力在于组合。单个命令能做的事有限,但用|串起来之后,威力翻倍。我给你写几个实战组合:
bash复制# 统计日志里出现了多少次ERROR
grep "ERROR" app.log | wc -l
# 看日志里所有出现的错误类型,去重并统计次数
grep "ERROR" app.log | awk '{print $2}' | sort | uniq -c | sort -nr
# 找出最近10分钟被修改的.py文件
find . -name "*.py" -mmin -10
第二条命令拆解一下:先筛出所有ERROR行,然后取第2列(错误类型),排序,去重并计数,最后按数字倒序排列。这样你一眼就能看出哪种错误最多,优先修哪个。
sort | uniq -c的组合在统计场景中极常用,包括分析访问日志IP、统计爬虫抓取数据的重复率。写Python代码时可以用collections.Counter实现同样的效果,但处理几百MB的日志,一条shell命令会比Python快很多。
4.3 tee:边看边存,两不耽误
调试脚本时,既想在终端实时看输出,又想同时存一份到文件里。用tee:
bash复制python3 myscript.py | tee output.log
这样输出会同时打到屏幕和文件。等脚本跑完,你可以直接去翻日志,不用重新跑一遍。注意tee默认会覆盖(truncate)已有文件,如果想追加写,用-a参数。
4.4 一个完整的线上排错案例
我把这些命令串起来,演示一个真实排错流程。
现象:Flask服务部署在服务器上,curl访问某个接口返回500,但本地跑没有这个问题。
排查步骤:
bash复制# 1. 先看服务进程还在不在
ps aux | grep gunicorn
# 2. 看服务日志最后50行
tail -n 50 /var/log/myservice/app.log
# 3. 如果日志里没有错误信息,查系统journal
journalctl -u myservice -n 50
# 4. 用grep过滤出和异常相关的所有行
grep -n "Exception\|Error" /var/log/myservice/app.log | tail -n 20
# 5. 如果服务已经挂了,尝试前台启动,直接看输出
cd /opt/myservice && /opt/myservice/venv/bin/python3 app.py
我遇到过的情况是:前台直接报ModuleNotFoundError: No module named 'oracle'。原因很明确,这个Python环境没有装Oracle驱动包。但为什么之前没事?因为那台服务器的系统Python里装了,而venv创建后忘了装。
这种问题你自己用命令排查,两分钟就能定位。如果不懂命令,就只能截图发给运维等回复,一来一回半小时没了。
4.5 生产环境不是本地,print大法要慎用
很多Python程序员习惯用print调试,这没问题。但生产环境的日志一堆print刷屏,反而会掩盖真正的报错信息。所以在写正式部署的服务时,建议用Python的logging模块控制日志级别,或者给print加上开关。
Linux命令虽然有tail -f跟踪输出,但如果你的print每秒钟刷几十行,日志文件很快就会涨到几百MB,磁盘空间也会被占满。所以日志级别的管理是生产级Python项目必修课,别等线上磁盘满了再来后悔。
5. 从开发机到服务器:代码传输、部署与网络排查的最后一公里
5.1 scp:最直白的远程文件复制
本地代码改完了,要传到服务器上。最直接的方式是scp:
bash复制# 把本地文件推送到服务器
scp local_file.py user@server_ip:/path/to/target/
# 把服务器上的文件拉回本地
scp user@server_ip:/path/to/remote/app.log ./logs/
# 复制整个目录,-r是递归
scp -r ./myproject user@server_ip:/opt/
第一次连接会提示确认指纹,输入yes回车,然后输入密码。如果配置了SSH密钥,可以直接免密登录,在实际部署时更省事。
scp的正确姿势是"先拷贝到服务器临时目录,确认文件完好,再移动到项目目录"。不要直接scp到项目目录,万一传一半断开,就会留下一个残缺文件,下次启动服务直接报语法错误。
5.2 rsync:增量同步,部署必备
scp每次都是全量传输,文件大了效率很低。rsync只传有差异的部分。
bash复制rsync -avz --progress ./myproject/ user@server_ip:/opt/myproject/
参数解释:-a归档模式,保持文件权限、时间戳;-v输出详细信息;-z传输时压缩;--progress显示进度。
我部署Django或Flask项目时,都用rsync同步代码。本地改一行代码,服务器上只需传这一个文件,几秒钟完成,还不用全量打包。
注意一个容易踩的坑:最后有没有斜杠效果差别巨大。rsync -avz dir/ user@host:/target/是把dir目录下的内容同步到target里;如果写成dir不带斜杠,则会把dir目录本身放进去,变成target/dir。这个细节记错会导致目录层级错乱。
5.3 tar:打包压缩,不能不会
服务器之间迁移项目、备份数据,tar是最通用的格式。
bash复制# 打包并压缩
tar -czvf myproject.tar.gz myproject/
# 解压
tar -xzvf myproject.tar.gz
参数中c是创建归档,x是解压,z是gzip压缩,v显示过程,f指定文件名。组合起来就是你的记忆口诀:czvf压缩,xzvf解压。
还有一个技巧:查看压缩包里有什么文件而不解压:
bash复制tar -tzvf myproject.tar.gz
在下载一个陌生tar包之前,先看内容,避免解压出一堆乱七八糟的文件。
5.4 systemd:让Python服务开机自启
nohup适合临时跑脚本,但如果这是一个24小时在线的Web服务,最好把它托管给systemd。先创建一个service文件:
bash复制sudo vim /etc/systemd/system/myservice.service
内容示例:
ini复制[Unit]
Description=My Python Service
After=network.target
[Service]
User=root
WorkingDirectory=/opt/myproject
ExecStart=/opt/myproject/venv/bin/python3 /opt/myproject/app.py
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
写好后启动并设置开机自启:
bash复制sudo systemctl daemon-reload
sudo systemctl start myservice
sudo systemctl enable myservice
这样进程挂了会自动重启,重启间隔3秒,非常稳定。后面想看日志用journalctl -u myservice -f,想重启服务用sudo systemctl restart myservice。
注意ExecStart里用的是/opt/myproject/venv/bin/python3,而不是python3。因为systemd运行环境更干净,不会加载你shell里的PATH配置,用绝对路径才不会找不到解释器。
5.5 网络排查:端口占用、接口连通性、DNS解析
Python服务跑起来了,但外部访问不了。我们要一步步排查:
bash复制# 看哪个进程占用了8000端口
ss -tlnp | grep 8000
# 或者用netstat(旧版本系统)
netstat -tlnp | grep 8000
# 本地测试接口能否访问
curl -I http://127.0.0.1:8000/health
# 从外部访问一下(在另一台机器上)
curl -I http://server_ip:8000/health
常见的情况:
- 服务没起来:
ss -tlnp查不到8000端口,检查日志。 - 服务起来了但外部访问不了:可能是防火墙拦了,或者云平台安全组没放行。
- curl超时:ping一下服务器IP,排除网络不通的问题。
这些排查思路对Python后端、爬虫Scrapy服务的日常运维都很重要。爬虫抓某网站失败,先curl -I一下目标网站,判断是网站挂了还是你的代码被反爬了。
5.6 快速查看系统架构
写Python代码时如果需要安装特定架构的包,或者编译扩展模块,搞清楚服务器架构就很重要:
bash复制uname -m
输出可能是x86_64、aarch64、armv7l之类。之前帮同事排查过一次问题:他在本地x86的Windows上开发时下载了某个预编译的whl包,传到服务器是ARM架构,Python直接报"architecture not supported"。用uname -m一看就知道原因了。
6. 高频命令速查与疑难杂症排查链路
6.1 一张表存下最高频的命令
我把前面讲过的命令整理成一份速查表,项目部署时贴在电脑旁或者记在笔记里,随用随查:
| 场景 | 命令 | 说明 |
|---|---|---|
| Python版本 | python3 --version |
查看当前Python版本 |
| 解释器路径 | which python3 |
确认python到底指向哪里 |
| 查看PATH | echo $PATH |
排查命令找不到的问题 |
| 创建虚拟环境 | python3 -m venv venv |
项目隔离 |
| 激活虚拟环境 | source venv/bin/activate |
进入环境 |
| 卸载虚拟环境 | deactivate |
退出环境 |
| 安装包 | python3 -m pip install xxx |
推荐写法 |
| 冻结依赖 | pip freeze > requirements.txt |
导出依赖 |
| 查看文件大小 | du -sh * |
定位大文件 |
| 磁盘空间 | df -h |
检查分区用量 |
| 内存使用 | free -h |
排查内存不足 |
| 实时日志 | tail -f app.log |
跟踪日志输出 |
| 查找代码 | grep -rn "import requests" --include="*.py" . |
定位代码 |
| 后台运行 | nohup python3 app.py > app.log 2>&1 & |
服务挂后台 |
| 查看进程 | ps aux | grep python |
拿到PID |
| 结束进程 | kill PID |
优先用SIGTERM |
| 强制结束 | kill -9 PID |
最后手段 |
| 限制运行时间 | timeout 300 python3 app.py |
防止卡死 |
| 远程传文件 | scp file user@host:/path |
单文件推送 |
| 增量同步 | rsync -avz ./dir/ user@host:/path/ |
高效部署 |
| 查看端口占用 | ss -tlnp | grep 8000 |
检查服务监听 |
| 查询服务日志 | journalctl -u myservice -f |
systemd日志 |
| 查看架构 | uname -m |
确认CPU架构 |
6.2 排错链路:按照这个顺序走,省一半时间
我总结了几个高频问题的最短排查链路,按顺序执行就行:
问题1:远程Python脚本报错ModuleNotFoundError
- 确认虚拟环境是否激活:终端前是否有
(venv)前缀 - 确认python路径:
which python3 - 确认pip安装位置:
python3 -m pip show 包名 - 确认运行目录:是否
cd到了项目目录
问题2:服务突然挂了
- 看进程还在不在:
ps aux | grep python - 查日志:
tail -n 50 app.log或journalctl -u 服务名 -n 50 - 看内存和磁盘:
free -h、df -h - 如果是内存不足,考虑优化代码或加swap
问题3:端口访问不了
- 服务是否监听:
ss -tlnp | grep 端口 - 本机访问:
curl -I http://127.0.0.1:端口 - 外网访问:
curl -I http://IP:端口 - 如果本机能通外网不通,查防火墙和安全组
6.3 把Linux命令和Python结合:用python执行shell命令
有些场景需要在Python脚本里调用Linux命令,有几种方式:
python复制import subprocess
# 执行命令并获取输出
result = subprocess.run(["ls", "-lh"], capture_output=True, text=True)
print(result.stdout)
# 带管道的方法,注意shell=True有注入风险,参数可控时才用
result = subprocess.run("ps aux | grep python", shell=True, capture_output=True, text=True)
print(result.stdout)
尽量用参数列表形式,避免shell=True拼接字符串,防止命令注入。批量部署时,可以写一个Python脚本循环调用rsync或scp,比手动一条条执行高效得多。
还有一个经常用到的技巧:用os.environ读取Python脚本运行时环境变量。比如你在systemd里设置了Environment=PYTHONUNBUFFERED=1,Python脚本里就可以读这个值来判断当前是否跑在生产环境。
6.4 我自己的命令行习惯:减少敲键盘次数
最后分享几个让我日常效率提升很多的习惯:
第一,给常用命令设别名。在~/.bashrc或~/.zshrc里加几行:
bash复制alias python=python3
alias ll='ls -lh'
alias act='source venv/bin/activate'
alias logs='tail -f app.log'
这样ll直接看文件大小,act一键激活虚拟环境。改完后执行source ~/.bashrc生效。
第二,用history查看之前敲过的命令。想复用又不想重打一遍:
bash复制history | grep "scp"
找到编号后,!编号即可重新执行。或者Ctrl+R反向搜索历史命令,输入关键词自动补全。
第三,写复杂的部署流程时,直接写成Shell脚本或Python脚本,而不是每次手动敲。比如我有个deploy.sh,内容就是rsync代码、重启服务、查看日志三步,一个脚本搞定。部署这种事,写进脚本之后,人和人之间的效率差距就体现出来了。
