ARTICLE DETAIL

资讯详情

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

Linux screen 终端复用从入门到进阶:会话管理、后台任务与故障排查

Linux screen 终端复用从入门到进阶:会话管理、后台任务与故障排查 做运维这几年不知道你有没有遇到过这种场景在服务器上跑一个数据同步脚本预计要跑两三个小时SSH 窗口开着人盯着屏幕不敢动。结果网络抖了一下终端断开重新连上去发现脚本进程已经被 SIGHUP 信号给带走了前面俩小时白等。后来我就养成了一个习惯凡是长任务一律丢进 screen 会话里跑断开、关电脑、甚至换一台电脑连上去任务都还在那儿安安稳稳地跑着。screen 是 Linux 下老牌的全屏窗口管理器和 tmux 并列终端复用工具的两大经典。它最核心的价值就是两件事让会话与终端窗口解耦让任务在后台持续运行不被打断。本文把 screen 从基础到进阶的用法梳理一遍包括创建会话、保持后台运行、命令窗口管理、日志保存、权限控制和故障排查不管你是刚摸 Linux 的新手还是需要频繁操作远程服务器的运维老手这篇都能给你一些可以直接抄作业的用法。1.1 从一次事故说起SSH 断开为什么会搞丢任务很多人第一次接触 screen都是因为吃过上面那种亏。要彻底搞懂 screen 解决了什么问题得先明白 SSH 断开后进程为什么会死。当你 SSH 登录一台服务器终端窗口就挂着一个 shell 会话。你在这个 shell 里执行python train.py这个进程就成了当前 shell 的子进程。SSH 连接断开时终端会被关闭内核会向该终端的前台进程组发送 SIGHUP 信号Hangup挂断信号默认动作就是终止进程。这就是为什么断开 SSH 后任务跟着没了的根本原因。那有没有办法让进程忽略 SIGHUP有比如nohup command 它通过让进程忽略 SIGHUP 来实现扛住断线。这也是很多人最早接触的保活方案但它有几个痛点nohup只能保活单个进程想在同一个会话里切换多个任务做不到。nohup重定向输出只写了nohup.out日志一多就不好看。nohup启动的进程没有前台概念你想重新看它的实时输出只能去 tail 日志文件。screen 的思路完全不一样。它创建一个独立的会话session这个会话有自己的伪终端pty你在这个会话里跑的进程父子关系是挂在 screen 的终端上而不是你本地 SSH 的终端上。SSH 断开时SIGHUP 发给的是本地终端的前台进程组screen 服务器端进程和它管理的会话不在这条链路上自然不受影响。等到你重新 SSH 连上服务器执行screen -r就能把那个会话重新粘回当前终端看到熟悉的画面一切都还在。1.2 screen 与 tmux、nohup 的取舍现在聊终端复用难免被问怎么不用 tmux。我的看法是两者没本质优劣更多是习惯和环境问题。tmux 比 screen 年轻配置语法更友好状态栏信息丰富分屏操作也灵活而且有大量社区配置可以抄。但 screen 也有自己的优势几乎所有主流 Linux 发行版默认就带 screen或者一条命令就能装上而有些精简版系统、老系统装 tmux 反而要多几步。screen 的命令模式快捷键肌肉记忆一旦形成在纯命令行环境下效率很高。screen 支持 ATT 风格的多用户共享会话这在某些教学、协作场景里比 tmux 更顺手。我个人的习惯是简单的单任务保活用nohup就够了需要在多个任务间来回切换、看实时输出、可能还要传给别人看屏幕就用 screen 或 tmux。下面以 screen 为主按创建 - 使用 - 管理 - 排查这条线走一遍。2. 安装与首批命令先把基础动作练熟2.1 各发行版的安装方式虽然很多系统自带 screen但如果没有安装也很简单# Debian / Ubuntu sudo apt install screen # RHEL / CentOS / Rocky sudo yum install screen # Fedora sudo dnf install screen # Arch / Manjaro sudo pacman -S screen # openSUSE sudo zypper install screen # Alpine sudo apk add screen装完验证一下版本screen --version正常会输出类似Screen version 4.08.00 (GNU) 05-Feb-20的信息。如果你登录的是一台内网服务器外网不通可以看看系统安装媒介里是否带了这个包很多发行版的安装 ISO 里就有 rpm 或 deb 包直接本地装就行。2.2 进入 screen 之后的命令入口screen 的操作风格和 vim 有点像有一个命令前缀默认是Ctrla所有管理指令都是先按前缀再按功能键。比如Ctrla然后按c新建一个窗口Ctrla然后按n切换到下一个窗口Ctrla然后按d分离detach当前会话回到原终端Ctrla然后按k杀掉当前窗口这个Ctrla的设计很多人刚接触时会觉得别扭尤其如果你习惯用Ctrla跳到命令行行首在 screen 里会被拦截。解决办法是把前缀键改成Ctrlz或Ctrlb我见过有人改成和 tmux 一致的Ctrlb这个我们放到配置章节单独说。先别急着配快捷键我建议你按下面这个顺序跑一遍体会一下会话和终端分离到底是什么感觉# 1. 创建一个名为 work 的会话 screen -S work # 2. 在会话里跑一个实时输出的小命令 watch -n 2 date # 3. 按 Ctrla 然后按 d 分离会话 # 4. 查看当前所有会话 screen -ls # 5. 重新连接 screen -r work跑完之后你就能理解分离之后watch命令还在这个会话里跑只是不再把画面输出到你当前的终端了重新screen -r之后它又把画面贴回到了你的窗口上。3. 创建会话与后台运行核心操作全流程3.1 创建会话的几种姿势screen 创建会话的方式非常灵活用的最多的有三种。第一种裸创建进去再跑命令screen这会直接进入一个新会话默认名字乱七八糟建议别这么用多了之后分不清谁是谁。第二种指定会话名创建screen -S build_task-S大写 S用来指定会话名称。命名规则建议带上任务名我一般用项目_任务_日期这样的格式例如web_deploy_20250618。这样screen -ls列表里一眼能看出来这个会话是用来干嘛的。第三种直接带着命令创建并启动screen -S migrate_data python migrate.py这种用法在一个命令里完成创建会话 启动任务适合明确知道要跑什么命令的场景。会话创建后migrate.py直接在这个会话里运行你看到的是脚本实时输出。跑完退出后会话会自动结束不需要你手动去关。除了这三种基本姿势还有几个参数是真实运维里经常组合用的-d -m直接以分离模式创建会话常用于脚本中启动后台任务。-r重新连接一个分离的会话。-x以多显示模式接入可以多人同时看一个会话。-p指定窗口编号或窗口名配合-X可以向会话里的窗口发送命令。比如你写一个发布脚本要在后台跑一组测试就可以这样screen -dmS test_runner bash -c ./run_tests.sh 21 | tee test_results.log这里的-dmS组合含义是-d表示分离-m表示如果会话不存在就新建-S指定会话名。命令加在最后screen 会在这个新会话里启动它。脚本执行完会话自己就关掉了不会留下一堆僵尸会话。3.2 分离、重连与管理会话的完整命令先看一张我平时最常用的速查表操作命令说明创建命名会话screen -S 名称进入会话并指定名字创建分离会话screen -dmS 名称创建后不附加常用于脚本列出会话screen -ls查看所有 screen 会话重新连接screen -r 名称附加到一个分离的会话强制重连screen -dr 名称如果会话被占用先分离再重连进入已占用会话screen -x 名称多显示模式接入分离当前会话Ctrla d从会话退出但任务继续跑杀掉会话screen -S 名称 -X quit远端命令行直接关闭会话锁定会话Ctrla x给会话加锁需要密码解锁显示帮助Ctrla ?列出所有绑定键位在管理大量会话时-ls输出里的状态信息值得认真看一下There are screens on: 12567.build_task (Detached) 13790.web_deploy (Attached) 14203.ops_cleanup (Multi) 2 Sockets in /run/screen/S-root.Attached表示有终端正连着这个会话Detached表示会话存在但当前没有任何终端附加Multi表示多人共享接入模式。如果你用-r去连一个 Attached 状态的会话会收到Must be connected to a terminal.或者类似提示这时候用-dr先踢掉旧连接再把自己接上去。因为-dr是先 detach 再 reattach注意这不是强杀进程只是把旧终端踢出会话会话里的任务不受影响。有一种特殊状态叫(Dead)意思是会话的进程已经没有响应但在/run/screen/S-用户名/目录下还留有 socket 文件。处理掉死会话的方法screen -wipe它会自动清理那些失效的 socket跑完再用screen -ls看列表就干净了。3.3 会话内的多窗口管理screen 的会话和窗口是两个概念一个会话里可以开多个窗口每个窗口相当于一个独立的终端标签页。处理多个并行任务时非常有用比如我经常在一个会话里开三个窗口一个跑日志跟踪、一个编辑配置文件、一个执行发布命令。常用快捷键Ctrla c新建窗口Ctrla n/Ctrla p下一个 / 上一个窗口Ctrla 弹出窗口列表方向键选择Ctrla 0~9直接跳到对应编号窗口Ctrla A给当前窗口重命名Ctrla k关闭当前窗口会提示确认Ctrla \关闭所有窗口并退出整个会话给窗口起名字是个好习惯。默认窗口名是当前 shell 命令名比如bash或者python开了三个窗口全是bash切换时容易搞混。按Ctrla A然后输入一个名字回车这个名字会出现在窗口列表里一眼识別。窗口之间复制粘贴也是有技巧的。screen 的复制模式是Ctrla [进入后移动光标选择文本按空格开始选择再按空格复制用Ctrla ]粘贴。说实话这个操作体验比较陈旧我在实际使用中更倾向于在会话里直接用 vim 的寄存器、或者用cat重定向来交换内容screen 的复制模式只在偶尔需要时用一下。3.4 滚动与回看让会话里的终端有记忆screen 刚建好时当你退出了会话里的一个命令或日志滚动太快想往回翻看会发现看不到之前的内容。这是因为默认没有开启滚动缓冲区或者说 buffer 被限制得很小。解决方式在会话里执行也可以写进配置文件Ctrla : # 进入 screen 的冒号命令模式 scrollback 20000 # 设置回滚行数为 20000或者直接用快捷键Ctrla [ # 进入复制/滚动模式在复制/滚动模式里用Ctrlb往上翻页Ctrlf往下翻页q退出。很多教程没提滚动模式下的翻页键用的是Ctrlb和Ctrlf不是方向键方向键在复制模式下移动的是光标而已。这个细节一开始容易懵。如果希望所有新会话都默认保留更多历史输出就把下面这行写进~/.screenrcdefscrollback 20000加上之后每个新会话的滚动缓冲就是 2 万行日志刷屏的时候回看基本够用。4. 高级技巧日志、配置、多用户与自动化4.1 把会话输出完整保存到日志很多时候我们不光要让任务在后台跑还要保留完整的输出日志。screen 有自己的日志机制和nohup的nohup.out相比screen 的日志能力更灵活推荐用这样的组合第一种启动时指定日志文件screen -L -Logfile /var/log/build_20250618.log -S build_task-L开启日志记录-Logfile指定日志路径。注意发行版不同有的老版本不支持-Logfile参数那就需要在会话里手动激活第二种在会话内动态开启Ctrla H # 切换日志记录的开与关第一次按Ctrla H会在当前目录生成一个screenlog.0之类的文件数字对应窗口编号再按一次就停止记录。屏幕右下角会有(logging)之类的提示。第三种使用冒号命令自定义Ctrla : logfile /opt/logs/screen_task.log log onlog on之后当前窗口的输出就会写入指定日志文件。实测下来我最常用的还是-L -Logfile这种启动时指定方式因为路径和文件名可控配合 logrotate 归档很方便。但有个坑要注意如果会话里跑了交互式命令比如 vim-L会把终端控制序列也写进日志日志文件会夹杂大量^[[?2004h之类的乱码。处理办法非交互场景开启全量日志交互场景用 vim 自己的会话恢复功能或者直接别开日志。如果想给日志文件自动加时间戳轮转可以配合 cron 或 systemd timer 定期重命名日志screen 自身不提供内置轮转。生产中我一般让应用自己写日志通过 log4j、logrotate 等screen 只用来兜底记录 stdout 和 stderr 的一次性输出。4.2 screenrc 配置改掉默认快捷键的坑默认的Ctrla前缀键的问题我之前提过很多人不习惯。改配置很简单编辑~/.screenrc添加escape ^Zz这会把前缀键改成Ctrlz。如果你平时用Ctrlz做终端挂起suspend改了之后那个功能就没了所以要权衡。我见过有同行把前缀改成Ctrls的但Ctrls在终端里是流控停止键XOFF一旦误按整个终端会被卡住不推荐。如果你要改成Ctrlb和 tmux 一致escape ^Bb改键要确保字母键本身不被占用为其他快捷键。比如把前缀改成Ctrlb后Ctrlb原本在 bash 里是左移光标的现在在会话内是前缀但 screen 的快捷键体系只在前缀按下后才生效不会影响 shell 内部其他Ctrlb功能除了前缀本身。常用的.screenrc配置我贴一份# 修改前缀键为 Ctrlz escape ^Zz # 默认回滚行数 defscrollback 20000 # 启动时不显示欢迎信息 startup_message off # 设置终端类型避免某些应用显示异常 term xterm-256color # 状态栏显示窗口列表和时间 caption always %{ kc} %-w%{ kW}%n %t%{-}%w % %{ kG}%Y-%m-%d %{ kY}%c # 自动分离时提示 defnonblock on其中startup_message off会跳过每次进入会话时的欢迎说明看着清爽些。defnonblock on的作用是当会话暂时无法接受输出时不让 screen 卡住等待。4.3 多用户共享会话给同事投屏教学screen 允许多个用户同时接入同一个会话这个功能在团队作战时非常实用。比如你在帮同事排查问题直接让他加进来看你的实时操作或者你想演示某个部署过程不需要再录屏把会话共享出去就行。前提是两台机器能共享同一个系统账户比如都是 root或者开启 multiuser 模式。简单场景这么用# 用户 A 创建会话 screen -S demo # 在会话内开启 multiuser 模式 Ctrla : multiuser on # 添加用户 B Ctrla : acladd userB这样用户 B 就可以用同一台机器登录然后执行screen -x demoB 会直接看到 A 的会话内容并且可以交互操作默认 acladd 给的是完全权限。如果不希望 B 能输入命令只能看可以用aclchg userB -w收回写权限只留读权限。需要注意多用户共享的是同一台主机上的同一个系统账号如果是不同账号还需要给/run/screen/S-root目录设置相应权限操作比较繁琐实际工作中很少用这个功能大多数团队有研发协同工具或直接录屏了。但偶尔一次给面试官展示实时操作、或给新同事演示命令流程时这个功能还是挺惊艳的。4.4 在脚本中安全地使用 screen避免僵尸会话堆积在自动化脚本里我们常遇到需要给任务创建一个会话但脚本结束后又希望这个会话能被随时重连的场景。一个常见的坏习惯是不断创建新会话而不回收导致/run/screen/S-root下堆积几十个会话 socketscreen -ls列出来一大片分不清哪个是哪个。推荐的做法是脚本开头先清理旧会话再创建新会话。比如在 shell 脚本里#!/bin/bash SNAMEdaily_backup # 如果存在同名会话先杀掉 if screen -ls | grep -q \.${SNAME}; then screen -S ${SNAME} -X quit fi # 以分离模式创建会话并启动任务 screen -dmS ${SNAME} bash /opt/scripts/backup.sh # 等待几秒确认会话状态 sleep 3 screen -ls | grep ${SNAME}这里注意一点grep 匹配会话名时不要匹配到无关项。比如有两个会话backup和backup_log如果你grep backup会把两个都匹配到。建议 grep 匹配完整的会话 socket 名例如\.${SNAME}\s或者用screen -ls | awk精确匹配。更稳妥的方式是用screen -ls -S 精确名来过滤。在脚本里调用screen -dmS时还有个细节如果当前没有终端比如在 cron 环境里某些旧版本 screen 会报Cannot open your terminal /dev/pts/0 - please check.这类错误。解决办法是加-T xterm指定终端类型或者使用screen -DmS大写 D多试两个组合一般能解决screen -DmS task -T xterm bash /opt/scripts/run.sh4.5 screen 与 systemd、cron 的配合有些人会问有了 systemd为什么还要用 screen 我的理解是两者定位不同。systemd 的 service 适合管理常驻服务、开机自启、异常重启它更适合不需要人看、状态由 systemd 统一管理的场景。screen 则保留了对前台交互的追踪能力你可以随时接进去看到输出还能手动按个键和运行中的程序交互。在实际服务器上长期运行的数据采集、消息消费这类任务我通常建议优先写成 systemd service获得自动重启和日志统一管理能力。但如果是短则几分钟、长则几小时的临时任务比如手动数据订正、一次性的数据库迁移、测试脚本用 screen 反而更灵活。我自己的习惯是需要开机自启、持久的服务 → systemd需要临时跑、可能中断、还要人工盯一眼 → screen一行命令搞定、看输出就行 → nohup tail -fcron 配合 screen 也很常见。比如需要每天凌晨 3 点跑一个只能在某个会话里交互完成的任务可以写 cron 条目0 3 * * * /usr/bin/screen -dmS night_task /opt/scripts/nightly.sh /var/log/nightly.out 21这样每天早上你 SSH 上去执行screen -r night_task就能看到昨晚的任务结果或者看/var/log/nightly.out检查日志。5. 常用场景实操从部署到排查的完整演示5.1 实战一跑一个长任务并随时查看进度假设我要在服务器上解压一个大文件、然后做数据校验流程大概是# 创建会话并重命名 screen -S extract_and_check # 在会话内执行长任务 tar -xzf /data/backup_20250618.tar.gz -C /data/restore/ python3 /opt/scripts/verify_data.py # 按 Ctrla d 分离去做别的事 # 过段时间回来看看 screen -r extract_and_check这里值得强调screen -r连接后画面会直接显示当前窗口最后的内容。如果你的任务已经继续跑很久了屏幕可能已经刷了无数行你可以按Ctrla [进入滚动模式Ctrlb向上翻页查看之前的报错。翻完按q退出滚动模式回到实时输出。这个进入滚动模式 - 往回翻 - 退出 - 回到实时画面的动作是日常看日志最常用的组合一定要在测试环境先练熟。5.2 实战二服务器断线后任务不中断这是最经典的一个应用# 在公司通过 SSH 连服务器 ssh ops10.0.0.5 # 在服务器上创建 screen 会话开始编译或部署 screen -S deploy cd /opt/app ./deploy.sh --env prod # 你切走窗口甚至关闭笔记本带回家 Ctrla d # 分离 # 回到家重新 SSH 连接服务器 ssh ops10.0.0.5 # 查看会话还在不在 screen -ls # 重新附加看到部署脚本还在跑 screen -r deploy这个过程里deploy.sh从头到尾都没有断过即使你的笔记本中途断网、关机、换网络都不影响服务器上的进程。这背后就是 screen 把进程的父子关系从你的 SSH 终端转移到了screen 守护进程而 screen 守护进程本身就是系统中的一个后台进程。5.3 实战三同时观察两个任务的日志在 screen 会话里开两个窗口screen -S monitor # 窗口 0跟踪前端日志 tail -f /var/log/nginx/access.log # 新建窗口 1跟踪后端日志 Ctrla c tail -f /opt/app/backend.log # 来回切换看 Ctrla 0 # 切到窗口 0 Ctrla 1 # 切到窗口 1这种场景里如果你的日志路径是固定的我更推荐用tail -f加多个文件的方式不用切窗口tail -f /var/log/nginx/access.log /opt/app/backend.log但如果需要在一个窗口里查看日志、另一个窗口里执行排查命令比如查看df -h、uptime、ss -tnlp那多窗口的好处就体现出来了。还有一种用法是一个窗口跑top一个窗口跑ping一个窗口跑应用日志出现问题可以快速交叉定位。5.4 实战四远程协助与分享屏幕给同事演示命令时可以这么做# 创建可共享的会话 screen -S share_demo # 在会话里执行需要的操作 vim /etc/nginx/nginx.conf # 开启多用户 Ctrla : multiuser on acladd zhangsan # 告诉同事使用同一账号登录并附加 ssh rootserver screen -x share_demo如果同事只是想看、不想乱动你可以收回写权限Ctrla : aclchg zhangsan -w-w表示 windows窗口操作权收回后对方只能看不能做任何输入。这个权限控制粒度其实比较粗糙但对分享场景够用。5.5 实战五screen 保活监控脚本有些任务你希望它崩溃后自动重启。screen 本身不自带进程守护但它可以在一个会话里将命令循环执行screen -dmS worker bash -c while true; do python worker.py; sleep 5; done这样worker.py崩溃退出后bash -c会在 5 秒后重新启动它。这个和 systemd 的Restartalways原理类似但好处是你可以随时screen -r worker进去看当前输出而且如果想中途干预可以 CtrlC 终止循环一点也不影响主系统配置。另一个靠谱的方案是配合supervisor或systemd做守护screen 只负责看得见守护逻辑交给更专业的工具。但如果你只是临时需要一个小脚本在后台稳定维持上面的 while 循环方案成本最低。5.6 实战六与 vim、git 等工具的协同我在 screen 会话里经常会启动 vim 改配置开到一半想起有个命令要执行不用退出 vim直接Ctrla c # 新建窗口执行命令执行完Ctrla 0 # 切回 vim 所在窗口vim 的状态完全保留光标位置、未保存的修改都还在。这个体验比在终端里来回挂起/恢复Ctrlz / fg要直观得多尤其适合改配置和跑命令交替进行的场景。配合 git 也有妙用。比如你在 screen 会话里跑一个git rebase -i中途需要对比另一个分支的代码可以新建一个窗口执行git diff HEAD...feature_branch看完了切回来继续 rebase互不影响。用 tmux 的同事可能觉得这没啥但只用裸终端的人第一次发现这个操作时感觉是真香。6. 常见问题与排查技巧实录6.1 连接会话时报错Cannot open your terminal这个报错通常出现在你通过 cron、jenkins 的 shell 环境里执行screen -r或者当前没有 TTY 终端时。解决办法screen -r 会话名 # 如果报错加 -T 试试 screen -T xterm -r 会话名如果是脚本环境更推荐用-dmS创建不要尝试附加。附加动作要求你当前环境有可用的终端设备纯函数环境比如 CI 里的某些 executor没有 TTY是不符合使用场景的。6.2 会话还在但 screen -r 连不上常见情况有几种会话处于Attached状态先screen -dr强制分离旧连接。会话处于Dead状态用screen -wipe清理。权限问题切换了登录用户当前用户没有权限附加另一个用户的会话。解决办法要么su到那个用户要么用 root 执行screen -ls看 socket 文件。有一次我遇到一个怪问题进程确实在跑但screen -r一直提示There is no screen to be resumed.后来发现是会话 socket 目录/run/screen/S-root权限被误改导致 screen 找不到对应的 socket 文件目录权限回滚后问题解决。6.3 日志文件里全是乱码和控制字符前面提过一次这里再总结screen -L开启的日志会把终端控制序列一起记下来。如果你看到日志里有大量^[[?2026h、^[[0m这类字符说明是交互式程序的控制序列被录入了。非交互场景脚本、命令直接执行日志是干净的交互式程序就别开 screen 日志让应用自己打日志。如果已经被污染可以用cat -v或sed去掉 ANSI 转义序列sed -r s/\x1B\[[0-9;]*[mK]//g screenlog.0 clean.log6.4 screen 会话太多如何批量清理常用命令# 查询所有会话 screen -ls # 逐条杀掉 screen -S 会话名 -X quit # 批量杀掉所有谨慎使用 screen -ls | awk /\./{print $1} | xargs -I{} screen -S {} -X quit第二条批量命令会杀掉所有 screen 会话生产环境慎用除非你确认没有正在跑的重要任务。更温和的做法先screen -ls | grep 关键词筛选出需要清理的会话名再手动一个个处理。另外screen -X quit发送的是 quit 命令给 screen 进程它会优雅地关闭该会话。如果遇到-X quit无效的顽固会话可以先找到 screen 的进程号ps aux | grep screen然后用kill 进程号或者kill -9强制结束。当然kill -9之后会话里的子进程也会失去父进程可能变成孤儿进程处理时要小心。6.5 常用问题速查表症状排查思路解决命令找不到会话可能被误杀或 socket 异常screen -ls必要时screen -wipe-r提示 attached有旧连接占用screen -dr 会话名会话存在但从列表消失socket 残余screen -wipe或手动删/run/screen/S-*无法输入 / 键盘没反应可能启用了流控或前缀锁检查Ctrls/Ctrlq检查Ctrla x锁定日志乱码终端控制序列混入使用sed清理或干脆不开-L会话自动退出内部命令跑完或手动退出检查命令退出逻辑必要时用while true循环保活多个 screen 进程占用 CPU长时间运行的会话screen -ls定位后手动管理6.6 我的实测避坑经验最后分享几个实实在在的坑。第一个坑误以为screen -r能连接 Attached 会话。实际不行得-dr或-x且-dr会把已有连接踢掉。如果你在服务器上开着一个 screen 会话又从另一台电脑连上去想附加发现被拒千万别以为会话挂了先screen -ls看状态。第二个坑改了前缀键之后Ctrla在 ssh 命令里可能冲突。比如你习惯在 bash 里用Ctrla跳到行首如果在某个 session 里使用 screen 且前缀被改掉就会出现你按Ctrla半天没反应。这种时候记住一句话进到 screen 里默认前缀就是Ctrla除非你明确改了配置没进 screenCtrla才是行首跳转。第三个坑screen 会话里的进程如果启动了守护进程deamon导致主进程退出但会话不退出screen -r进去后你会发现没有 shell 提示符。原因是守护进程占住了伪终端的前台会话这时候Ctrlc可能不管用需要Ctrla k强制杀窗口或者用screen -X quit关闭整个会话。第四个坑在 screen 里运行ssh再嵌套一个 screen这种嵌套场景会导致快捷键层级变复杂。Ctrla先被外层 screen 吃掉内层 screen 收不到除非你用两次前缀外层Ctrla a再发一次前缀给内层。我原则上不建议嵌套 screen有嵌套需求时用 tmux 或直接分多个终端连接。最后一个建议把常用的screen -ls、screen -r、screen -dr这几个命令做到不用思考的程度然后养成一个习惯——任何可能超过 20 分钟的长任务从第一秒就放到 screen 里跑。没跑 screen 前我吃过断线丢任务的亏跑了之后几乎再也没有因为终端断开而重新跑任务。screen 这个工具学习曲线前期有一点点陡但一旦形成肌肉记忆你会觉得它就是 Linux 上任务保活这件事的标准答案。如果后续你还想深入可以研究一下它的hardcopy截图功能、exec命令批量下发、以及-X远程向窗口发送按键这些都是进阶玩法。但就日常工作而言掌握本文这些内容已经足够撑起大部分场景了。
返回列表