资讯动态

Screen终端复用:Linux远程任务不中断的保活神器

发布时间:2026/10/14 3:50:26 来源:尧图企业网站定制
上次给一台线上服务器跑数据迁移前面都挺顺利脚本跑到三分之一时 SSH 窗口卡住几秒后直接掉线。重新连上服务器等我的只有一条迁移失败日志——命令行里起的进程跟着连接一起没了。那次之后凡是登服务器干耗时活我都会先敲screen -S work再开工。screen 是 Linux 上最常用的终端会话复用工具核心作用是把正在跑的任务和眼前的终端窗口解耦SSH 断了、窗口关了、电脑休眠了任务照常在后头跑下次连接随时恢复界面。这篇文章不按 man 手册顺序念而是按真实使用路径展开先解决日常 80% 的需求再补充窗口管理、日志、脚本自动化这些进阶玩法最后把踩过的坑梳理给你。适合所有要远程操作 Linux 的人尤其是部署、运维、跑数据脚本以及任何不愿意因为一条网线把任务弄丢的场景。1. 为什么需要 screen先从那次掉线说起1.1 一条断掉的 SSH 连接到底带走了什么我当时做的其实是一件很普通的事本地打包、rsync 到服务器、解压、执行迁移脚本。前几步都是秒级操作最后那步需要在服务器上跑二十来分钟我就直接在 SSH 窗口里等了。中途看了一眼手机回来发现终端右上角的连接状态变成了断线图标重新登录后进程列表里干干净净脚本留下的日志停在三分之一处。这个场景的教训是**挂在 SSH 会话里的命令本质上和这个会话是一条命。**当 SSH 连接断开系统会向这个会话发送挂断信号SIGHUP前台进程组里的命令都会收到这个信号默认行为是直接终止。不是说断线了任务还在那头继续跑绝大多数情况下进程已经没了。很多人第一次意识到这一点都是拿一次真实的发布事故换来的。1.2 screen 把任务转移到了哪screen 的做法是在你的物理终端和真正跑命令的 shell 之间插一层守护进程。你敲的每条命令其实是在 screen 创建的伪终端pty里执行的这个伪终端归 screen 的独立守护进程管理不挂在你 SSH 会话下。SSH 断开只是你这边看不见了守护进程和它管理的任务完全不受影响。用生活里的场景类比直接开 SSH 跑任务相当于你把一台机器放在工位上亲自盯着人走了机器就停screen 相当于你把任务放进了一个带独立电源的托管柜你随时可以离开回来开柜子继续操作。柜门开不开不影响机器转机器停了你也别怪柜门——这个区别后面会反复用到。1.3 screen这个名字其实挺直白很多人第一反应以为 screen 是屏幕锁定或者截屏其实它的字面意思就是屏幕。早期的 Unix 终端是一块实实在在的字符屏幕screen 在它之上模拟出了好几个虚拟屏幕每个虚拟屏幕都能跑独立的程序。它最初的定位就是字符终端下的全屏窗口管理器只是后来因为它能把会话和终端拆开才被广泛用在远程任务保活上。理解这层关系之后你就会明白为什么 screen 里不叫标签页而叫窗口window一个会话session下可以有多个窗口每个窗口对应一个独立的 shell 环境和运行任务。这正是它比单纯后台运行更强的地方——不只保住任务还能把任务组织成多个可切换、可命名、可回看的界面。2. 五分钟上手创建、分离、恢复、销毁2.1 第一个 screen 会话怎么建最简单的用法screen直接回车你会感觉屏幕闪了一下然后出现一个跟原来很像的 shell。其实你已经在一个新建的 screen 会话里了只是界面变化不明显。为了让后续管理方便我更推荐带名字启动screen -S deploy-S 后面跟的是一个会话名用来标记这个会话是干什么用的。启动之后你可以正常敲命令也可以跑任何长时间任务它就是一个普通 shell。如果你只是想某个命令在后台跑不想进去交互可以用这一条screen -dmS build ./run.sh-d表示分离状态启动-m表示强制新建会话-S build指定名字后面直接跟要执行的命令。执行完这一条命令已经在后头跑了你连界面都不用进去。2.2 分离与恢复核心中的核心在 screen 会话里按Ctrla d先按 Ctrla再按 d界面会退回原来的 shell并提示类似[detached from 12345.deploy]。这个过程叫分离detach关键点在于分离只是把你的视线移开会话里的任务继续跑。回头想恢复的时候先看看有哪些会话screen -ls输出会列出会话的编号、名字和状态。恢复就一条命令screen -r deploy或者直接用列表里的编号screen -r 12345。如果你只有一个会话screen -r也能直接恢复。这里我最想强调的是分离不是退出它更像是合上笔记本盖任务还在服务器上运行。如果你因为断线或其他原因screen -r提示会话已经被标记为 Attached那就用强制接管screen -dr deploy-d会先把那个已经挂着的客户端剥离再重新附加。后面排障部分我还会详细讲这种情况。2.3 退出一个会话的正确姿势有时任务跑完了这个会话就没用了。正确的退出方式是在会话窗口里输入exit或者按Ctrla k确认后窗口关闭。也可以不进入会话从外部直接结束它screen -S deploy -X quit注意这里-X quit是真关闭不是分离。新手最容易把分离和退出搞混——按Ctrla d分离任务还在按Ctrla k或exit窗口和里面跑的程序就都结束了。注意Ctrla d是分离Ctrla k是关闭窗口exit是退出 shell。分离不会终止任务关闭和退出会。3. 窗口管理一个会话里同时开好几个终端3.1 窗口的创建与切换screen 的进阶能力从窗口管理开始。在同一个会话里你可以开出多个虚拟终端每个终端跑各自的任务。最基本的窗口操作我整理了一张表操作快捷键说明新建窗口Ctrla c创建并切换到新窗口下一个窗口Ctrla n按编号向后切换上一个窗口Ctrla p按编号向前切换跳转到窗口Ctrla 0~9按编号直接跳转窗口列表Ctrla 列出所有窗口回车选择关闭当前窗口Ctrla k结束当前窗口及里面进程创建多个窗口之后最直观的感受就是在同一个会话里一个窗口跑编译一个窗口编辑配置再开一个窗口监控日志切换就是一下的事。而且这些窗口都属于同一个会话主会话断了所有窗口和任务都还在服务器上。3.2 给窗口起名避免这个窗口是干嘛的窗口多了之后容易乱。默认每个窗口只有一个编号过一阵你自己都记不清 3 号窗口是干嘛的。这时可以用Ctrla A给当前窗口起名字比如输入migrate窗口标题栏就能显示出来。配合Ctrla w查看窗口列表整个会话里有什么任务一目了然。我的习惯是窗口名跟任务名对齐。跑数据库迁移就叫 migrate看日志就叫 log调试就 debug。这种习惯在维护多个线上服务时会非常省心尤其是隔天回来恢复会话不需要进每个窗口确认一次。3.3 分屏让两个窗口同时出现在眼前Ctrla S大写 S可以把当前区域水平切成上下两块Ctrla |竖线切成左右两块。分屏之后用Ctrla Tab在不同区域之间跳转在每个区域里都可以正常操作窗口。不想看某个分屏了用Ctrla X关闭当前区域想退出所有分屏用Ctrla Q合并回单窗口。分屏配合窗口切换很灵活你先在 1 号窗口跑服务再开 2 号窗口跟着写请求分屏之后左边看服务日志右边敲测试命令两边同时动非常顺手。要说明的是分屏只是把同一个会话里的窗口分散到不同区域窗口本身还是那些窗口任务状态不受影响。3.4 把会话共享给同事screen 的多用户共享能力很有意思。当你的会话已经在运行让同事用同一台服务器执行screen -x deploy他会直接附加到你的会话里你们看到的是同一个界面谁都能输入和操作。这在远程协作看输出时很有用两个人一边看日志一边讨论。但也正因如此共享会话有风险两边同时敲键盘会互相干扰。我的建议是开共享前先说好谁主导不需要参与的时候用Ctrla x把会话锁住具体见 4.4 节避免误操作。4. 进阶技巧日志、回滚、复制与自动化注入4.1 让 screen 自动记录会话日志没人盯着屏幕的任务跑完之后怎么复盘screen 可以直接把会话里的所有输出写成文件。启动时加-Lscreen -L -S backup ./backup.sh它会在当前目录生成一个类似screenlog.0的日志文件。如果你在会话运行过程中想临时开启日志按Ctrla H再按一次关闭。日志对排错非常有用尤其是那种半夜跑的脚本第二天进会话看历史或者直接翻screenlog.0就能定位问题。有个坑要提前说默认日志是无脑覆盖式的如果同一会话里开了一堆窗口输出全写进同一个文件会乱。所以我在.screenrc里习惯配置独立的日志文件名甚至能用日期变量这部分我在第 7 节给出配置模板。4.2 回看输出复制模式与滚动缓冲区screen 每个窗口都有滚动缓冲区默认记录最近 1000 行可以通过配置放大到几万行。想回看刷屏内容时按Ctrla [进入复制模式然后用方向键或Ctrlu/Ctrld上下翻页空格开始选择再按一次空格结束选择最后按Ctrla ]把选中的内容粘贴回 shell。这个模式本质上是个内建的视图层你操作的是缓冲区里的文本不会影响当前正在跑的程序。我的使用场景通常是脚本输出了一屏报错我直接按Ctrla [往回翻到报错开头选中关键字段复制到编辑器里分析。滚动缓冲区大小我一般设成 20000 行日志刷得再快也够用。4.3 在脚本里遥控 screen 会话有时候你想在另一个终端里往某个 screen 会话的某个窗口发送命令而不是手动附加进去。可以用-X参数# 向 deploy 会话的第 0 个窗口发送命令并回车 screen -S deploy -p 0 -X stuff $ls -la\r-p 0指定窗口编号stuff表示向该窗口直接输入按键序列\r是回车。这个能力是把 screen 接进自动化的关键写一个监控脚本定时检查某个会话状态或者在外部触发重跑任务。比如我用 cron 每天凌晨执行一个脚本脚本内部就是先screen -ls检查会话是否存在存在就往会话里发一条新的指令。这里要特别提醒stuff发送的是字面按键如果窗口里的程序正在对话框等待输入发送的内容也会被吃进去。所以自动化时最好明确在哪个窗口、发什么内容避免误操作正在交互的程序。编写脚本时用$命令\r这种写法可以正确带上回车键。4.4 离开时的锁屏如果几个人共享一个会话或者你担心离开期间有人碰到你的终端可以用Ctrla x锁定会话。screen 会要求输入密码才能继续操作密码默认取系统用户密码也可以单独在.screenrc里用password指令设置。我的习惯是只要是共享会话离开一定上锁。共享是方便但脚本误触一下可能就把线上程序停了这把锁能省掉很多个深夜电话。5. screen 与 nohup、tmux 的选型对比5.1 nohup 为什么解决不了回来接着干的问题很多老教程会告诉你跑长任务用nohup command 。nohup 确实能屏蔽 SIGHUP 信号让进程在退出登录后继续运行。但它只解决了一半问题任务确实在跑但你没有会话界面可回输出要么重定向到文件要么就丢了。想再看任务进度只能开新进程去看日志想临时往任务里输入点什么就更不可能。screen 把运行中的任务和可操作的界面一起保住了。这也是我很多场合不用 nohup 的原因nohup 适合丢出去就不管的临时任务screen 适合跑起来了我还要回去继续操作的任务。两者不冲突我后面会给实际组合用法。5.2 screen 和 tmux 怎么选tmux 是这些年更时髦的终端复用工具功能上跟 screen 高度重合。我给一份基于实际使用的对比维度screentmux预装程度几乎所有主流发行版都有BusyBox 也有精简版多数需要单独安装配置复杂度语法较老但功能足够配置直观社区模板多分屏体验支持快捷键稍繁琐拆分灵活操作顺手状态栏需自己配 hardstatus自带漂亮状态栏插件生态少而稳插件和主题丰富学习曲线命令少容易上手概念略多但很好理解老服务器兼容性好救援模式也能用内核太旧时安装麻烦我的真实感受是两者都能解决会话保活这个核心问题差别主要在手感。screen 胜在到处都有、环境再破也能用tmux 胜在现代化、分屏和配置更舒服。你如果主要在自己的一两台服务器上用装 tmux 没问题如果维护着一批老机器、最小化系统、甚至救援环境screen 几乎是唯一不需要纠结就能用的选择。5.3 我的组合拳我自己在服务器上跑任务的组合一般是这样短任务直接前台跑纯后台不发话的用nohup ... 凡是我还要回去看、回去操作的长任务一律进 screen 会话screen -S weekly-backup # 进入会话启动脚本 ./backup_all.sh Ctrla d脚本开始跑之后我分离走人第二天screen -r weekly-backup回来界面还停在原来的位置可以继续写下一步命令。如果需要跟别人联调就开共享会话不用时锁屏。这个组合拳在生产环境用了很久稳定性一直可以。6. 实战排查那些年我踩过的 screen 坑6.1 误杀会话exit 不是 detach某次维护服务A 同学以为自己按了Ctrla d只是暂时离开结果任务全丢了。后来他跟我复盘才发现他实际按的是Ctrla k确认关闭窗口然后整个会话就结束了。这类问题的本质是detach分离和 kill结束在人机交互上容易混淆快捷键的确也离得很近。要避免这个坑我的建议是刚上手的前几天手指离开键盘之前默念一遍离开是 d结束是 kexit 也是结束。如果已经出现了会话不见了但任务很重要的情况别太指望能找回正常结束的会话进程会收到终止信号基本没有恢复途径。所以关键还是预防供长任务专用的会话每次操作前确认这个键是分离还是结束。6.2 断线后无法 attach一堆 Attached 状态SSH 掉线之后你可能会遇到screen -r提示 There is a screen on ... (Attached)可明明你已经看不到界面了。这是因为客户端断线时screen 的状态标记没能正确清除服务端还认为有人连着。此时用强制接管screen -dr deploy或者更彻底一点screen -D -R deploy-D -R会先把旧的连接踢掉再重新附加。要注意如果旧连接上正有一个同事在操作这个命令会把对方踢下线。所以共享会话里执行强制接管前先确认不是别人还在用。很多时候先screen -ls看一下状态比直接闷头敲命令更安全。6.3 会话列表越来越乱命名规范和清理跑过几个项目之后screen -ls的列表会变得很长尤其是不加-S创建的会话编号是一串随机数字根本不知道哪个是哪个。我的规范很简单会话名 项目-环境-用途比如web-prod-build、db-migrate-test。这样一眼就能定位。对于已经没用的会话及时清理# 列出所有会话 screen -ls # 关闭指定的一个 screen -S 12345 -X quit # 也可以写小脚本把名字包含 .test. 的会话全部关掉 screen -ls | grep \.test\. | awk {print $1} | xargs -I{} screen -S {} -X quit清理时同样要分清关掉和分离。如果你只是想暂时离开别用-X quit那等于把整个会话结束掉。定期看一下列表该清的清能省很多找会话的时间。6.4 退格键、Ctrla 冲突和乱码最常见的 screen 配置问题有三个。第一某些终端里退格键变成^H删除不了字符需要在.screenrc里加termcapinfo xterm* ti:te第二Ctrla默认是 screen 的命令前缀而这在 Bash/Emacs 里也有功能比如跳回行首。如果你在会话里需要把Ctrla透传给当前程序可以按Ctrla a连按两下前缀键。如果不想接受这个设计就把前缀换成别的键escape ^Bb换成Ctrlb之后所有原来的前缀操作都要用新前缀这个配置我放在最后一部分的完整模板里。第三乱码问题多半是 locale 或 UTF-8 没设置可以在.screenrc里加defutf8 on并把会话环境的 LANG 设成 UTF-8。7. 我的 .screenrc 配置和使用心得7.1 一份能直接抄的 .screenrc好用和难用很多时候就差在一个.screenrc。下面这份配置我是实际在用的基本覆盖了前面的各种习惯# 关闭启动时的欢迎提示 startup_message off # 修正部分 xterm 终端的清屏和退格问题 termcapinfo xterm* ti:te # 滚动缓冲区 20000 行 defscrollback 20000 # 默认 UTF-8 defutf8 on # 底部状态栏显示窗口列表、时间和用户名 hardstatus alwayslastline %{bW}%-w%{rW}%n %t%{-}%w % %{gW}%u %{yW}%c # 把命令前缀从 Ctrla 换成 Ctrlb想改回去就注释这行 escape ^Bb # 新窗口默认使用登录 shell shell -bash # 日志文件名带日期避免所有窗口写进同一个文件 logfile /tmp/screen_%Y%m%d_%c.log逐行解释一下hardstatus那行是状态栏样式%n是窗口编号、%t是窗口名%u是用户、%c是时间看着复杂但配一次就够。escape ^Bb我强烈建议用一段时间它能避免和很多终端编辑的默认按键冲突用不惯再改回去。日志文件名里的%Y%m%d会按日期展开这样每天的日志分开存配合-L启动非常清爽。7.2 平时我是怎么把 screen 用顺的最后讲一点实际使用感受。我习惯登录服务器之后第一件事就是screen -S work所有临时任务都放进这个会话里再在这个会话下开不同窗口管理不同工作。离开就按Ctrla d分离回来screen -r work继续一整天的工作上下文都还留着不用重新翻文件找状态。长任务自动化方面我经常把 screen 和 cron 配合例如凌晨的备份脚本脚本里用screen -dmS backup ./backup.sh启动然后把日志写到独立文件。第二天我只需要screen -ls看看会话还在不在再进会话确认结果整个过程非常省心。如果你还没试过 screen 的日志和远程注入我建议今晚找个不那么重要的任务先跑一遍感受一下关了窗口任务照跑、回来界面还原的体验。这个工具带来的安全感只有真正在断过一次线之后才会懂得。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑