
SerenityOS 命令行截图工具 shot 使用指南参数详解与源码级原理【免费下载链接】serenityThe Serenity Operating System 项目地址: https://gitcode.com/GitHub_Trending/se/serenityshot是 Serenity Operating System 内置的命令行截图工具可完成全屏、多屏、区域截取、延时截图并支持输出到剪贴板或直接交给 PixelPaint 编辑。本文以 shot 的手册页 为核心结合 shot.cpp 源码逐参数拆解其行为并对照 GUI 版 Screenshot 应用说明二者的关系让读者既能上手实操也能理解底层实现。概述shot 是什么shot是 SerenityOS 用户态的命令行截屏程序位于/bin/shot。它不依赖图形界面即可完成截图但仍运行在 GUI 会话中通过 WindowServer 获取屏幕位图。与图形化应用Screenshot相比shot提供更丰富的参数组合延时、指定屏幕、区域选择、剪贴板输出、直接编辑等。从 Userland/Utilities/CMakeLists.txt 可以看到shot被注册为系统 Utility出现在第 244 行的内置命令清单中其链接依赖为LibFileSystem、LibGfx、LibGUI、LibIPC、LibURL等库印证了它同时使用 GUI 基础设施连接 WindowServer、Clipboard与图像编码PNGWriter的实现路径。有趣的是图形化应用 Screenshot 在用户点击OK后并不会自行截图而是通过Core::Process::spawn(/bin/shot...)把参数转交给shot执行。换句话说shot是 SerenityOS 截图功能的统一底层实现GUI 只是它的前端封装。基本用法Synopsis$ shot [--clipboard] [--delay seconds] [--screen index] [--region] [--edit] [output]output是可选的输出文件名。当省略时shot会自动生成带时间戳的默认文件名// Userland/Utilities/shot.cpp#L119-L121 if (output_path.is_empty()) { output_path Core::DateTime::now().to_byte_string(screenshot-%Y-%m-%d-%H-%M-%S.pngsv); }即形如screenshot-2026-09-09-03-19-30.png保存在当前工作目录。该功能由LibCore/DateTime的时间格式化实现格式占位符与strftime一致。参数详解Options短选项长选项参数默认值说明-c--clipboard无关闭将截图写入剪贴板而非文件-d--delayseconds0截图前等待的秒数-s--screenindex-1全部屏幕指定要截取的屏幕索引-r--region无关闭交互式框选区域后截图-e--edit无关闭截图后自动在 PixelPaint 中打开这些参数在源码中由LibCore::ArgsParser解析对应的声明位于 shot.cpp与手册页一一对应。-c, --clipboard输出到剪贴板不写文件直接把位图写入系统剪贴板// Userland/Utilities/shot.cpp#L157-L160 if (output_to_clipboard) { GUI::Clipboard::the().set_bitmap(*bitmap); return 0; }使用GUI::Clipboard::set_bitmap来自LibGUI/Clipboard.h。此时output参数会被忽略。注意剪贴板模式不能与-e组合生效——代码中剪贴板分支先于 PNG 编码与编辑分支执行并直接return。-d seconds, --delay seconds延时截图等待指定秒数后再抓屏适合需要先布置窗口、打开菜单等场景。源码实现非常简单// Userland/Utilities/shot.cpp#L143 sleep(delay);delay的类型是无符号整数unsigned delay 0由 ArgsParser 解析为非负整数负值或非数字输入会导致参数解析失败。注意延时发生在区域选择完成之后若同时使用-r会先完成框选、再进入倒计时。-s index, --screen index选择屏幕SerenityOS 支持多显示器multi-head。screen默认值为-1表示截取所有屏幕拼接后的完整画面// Userland/Utilities/shot.cpp#L144-L148 Optionalu32 screen_index; if (screen 0) screen_index (u32)screen; auto shared_bitmap GUI::ConnectionToWindowServer::the().get_screen_bitmap(crop_region, screen_index);screen 0时仅截取索引为index的显示器screen -1默认时screen_index为空WindowServer 返回整张虚拟桌面位图屏幕索引从0开始与系统显示器编号一致。抓屏通过GUI::ConnectionToWindowServer::get_screen_bitmap(crop_region, screen_index)LibGUI/ConnectionToWindowServer.h以 IPC 方式向 WindowServer 请求位图这也是shot依赖LibIPC的原因。-r, --region框选区域截图开启交互式区域选择屏幕上会出现一个全屏半透明遮罩SelectableLayover按住鼠标左键拖拽框选松开即截取该区域按Esc取消。相关实现位于 shot.cpp 的SelectableLayover类窗口类型为GUI::WindowType::Popup带 Alpha 通道并全屏显示set_fullscreen(true)保证遮罩本身不会出现在截图中光标切换为十字准星Gfx::StandardCursor::Crosshair拖拽时以Gfx::IntRect::from_two_points实时计算选中矩形并绘制绿色十字参考线与透明选区松开鼠标mouseup_event后窗口关闭区域矩形存入crop_region按Esckeydown_event则清空区域并关闭随后主流程检测到空区域直接输出cancelled...并退出shot.cpp。框选结果作为crop_region传给get_screen_bitmap由 WindowServer 裁切对应区域。-e, --edit在 PixelPaint 中编辑截图后自动调用 PixelPaint 打开图片便于快速标注// Userland/Utilities/shot.cpp#L169-L170, L181-L182 if (edit_image) output_path Core::DateTime::now().to_byte_string(/tmp/screenshot-%Y-%m-%d-%H-%M-%S.pngsv); ... if (edit_image) TRY(Core::Process::spawn(/bin/PixelPaintsv, Array { output_path }));关键行为截图文件被固定保存到/tmp/下带时间戳的 PNG通过Core::Process::spawnLibCore/Process.h以独立进程启动/bin/PixelPaint并传入文件路径-e与output参数互斥一旦开启编辑模式用户提供的output文件名会被覆盖为/tmp/...路径同样地-e与-c互斥剪贴板分支优先返回。输出行为细节文件写入截图像素数据先由Gfx::PNGWriter::encodeLibGfx/ImageFormats/PNGWriter.h编码为 PNG 字节流再写入输出文件// Userland/Utilities/shot.cpp#L162-L179 auto encoded_bitmap_or_error Gfx::PNGWriter::encode(*bitmap); ... auto file_or_error Core::File::open(output_path, Core::File::OpenMode::Write); auto file *file_or_error.value(); TRY(file.write_until_depleted(encoded_bitmap.bytes()));若 PNG 编码失败或目标文件无法打开例如目录不存在、无写权限shot会分别输出Failed to encode PNG或Could not open path for writing: ...并返回退出码1。PNG 编码器的正确性由 Tests/LibGfx/TestImageWriter.cpp 中的图像写入测试覆盖。终端超链接输出在支持 ANSI 超链接的终端即stdout为 TTY中shot会把输出路径打印为可点击的file://超链接同时打印主机名// Userland/Utilities/shot.cpp#L184-L204 if (isatty(STDOUT_FILENO)) { auto full_path_or_error FileSystem::real_path(output_path); ... auto url URL::create_with_file_scheme(full_path_or_error.value(), {}, hostname); out(\033]8;;{}\033\\, url.serialize()); ... } out({}, output_path);非 TTY 环境如管道重定向只输出纯路径文本链接使用 OSC 8 转义序列ESC ]8;;URL ESC \由LibURL构造file://URL。失败与取消路径场景行为退出码-r框选时按Esc输出cancelled...0WindowServer 返回空位图输出Failed to grab screenshot1PNG 编码失败输出Failed to encode PNG1文件无法写入输出Could not open ...1实战示例# 1. 截取整个桌面保存为默认时间戳文件名 $ shot # 2. 指定输出文件截取全部屏幕 $ shot my-desktop.png # 3. 5 秒后截取可先布置好界面 $ shot --delay 5 desktop.png # 4. 只截取第二块显示器 $ shot --screen 1 monitor2.png # 5. 框选区域后截图 $ shot --region region.png # 6. 截图直接进剪贴板可在其他应用中粘贴 $ shot --clipboard # 7. 截图后立即在 PixelPaint 中打开编辑 $ shot --edit # 8. 组合延时 3 秒 框选 $ shot --delay 3 --region annotated.png与图形化 Screenshot 应用的关系SerenityOS 还提供图形化截图应用 Screenshot对应源码 Userland/Applications/Screenshot提供四种模式Whole desktop整屏、Selected area框选、Edit in Pixel PaintPixelPaint 编辑、Select Folder自定义保存目录默认Pictures文件夹。两者在实现上是前端 后端关系GUI 应用点击 OK 后将用户选择翻译为shot的参数并通过Core::Process::spawn调用/bin/shotMainWindow.cpp选中Selected area → 追加-r选中PixelPaint 编辑 → 追加-e选中剪贴板 → 追加-c用户选择的保存目录作为output位置参数传入。GUI 版本把截图功能封装为更友好的界面而shot命令行工具则提供了脚本化、可组合的能力。二者面向同一套 WindowServer 抓屏机制。小结shot是 SerenityOS 截图生态的核心命令行工具参数虽少但覆盖了延时、多屏、区域、剪贴板、外部编辑等常见截图需求。结合源码可以看到其实现依赖 WindowServer 的get_screen_bitmapIPC 接口、LibGfx的 PNG 编码器以及LibGUI的剪贴板与窗口基础设施GUI 版 Screenshot 应用同样只是它的薄封装。若需在脚本或自动化流程中截屏shot是最直接的选择。参考文件索引手册页shot(1)命令行实现Userland/Utilities/shot.cpp构建注册与链接依赖Userland/Utilities/CMakeLists.txtGUI 截图应用手册Applications/Screenshot(1)GUI 截图应用源码Userland/Applications/Screenshot/main.cpp、MainWindow.cppPNG 编码器测试Tests/LibGfx/TestImageWriter.cpp【免费下载链接】serenityThe Serenity Operating System 项目地址: https://gitcode.com/GitHub_Trending/se/serenity创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考