无 root 环境用 chrome-linux64.zip 部署 Chrome 与自动化测试实践
简介Chrome浏览器Linux 64位离线安装包面向需要在无外网或受限网络环境下安装浏览器的用户也可用于团队内部统一浏览器版本特别适合运维人员或IT管理员快速批量部署。压缩包内含132个文件总大小143.36MB核心组件以pak资源文件、info元数据、so动态库和json配置为主覆盖主程序、启动脚本、依赖库及默认配置解压即可使用或手动整合到系统环境。该版本为124.0.6318.0稳定分支经充分测试适合日常办公与Web应用调试。需要注意的是此离线包不含chromedriver自动化工具如需进行自动化测试需另行下载对应版本以满足Selenium等自动化测试框架的调用需求。目前已有632人学习/下载文件结构典型清晰可帮助Linux管理员与开发者快速完成离线部署获得高速、安全的网页浏览体验同时避免在线下载受网络波动影响。1. chrome-linux64.zip 是什么内网、CI 和无 root 机器上最顺手的 Chrome 分发形态第一次见到 chrome-linux64.zip 这个包多半不是在自家电脑上装浏览器而是在一台只有内网源、没有 root 权限、连桌面环境都没有的服务器上需要跑一个真实的 Chrome。apt 装不上、yum 换源失败、sudo 都不在你手里唯一能指望的就是这样一个解压就能跑的 Linux 64 位 Chrome 压缩包。这篇笔记讲清楚三件事它为什么能解压即用、在无 root 环境里怎么把它部署成一条可用命令、以及把它接进自动化测试时你会撞上的那些坑。适合做 Selenium 测试、维护 CI 镜像、在封闭网络里配浏览器的人照着复现。2. 解压即用的前提Chrome 的目录结构与依赖边界理解 zip 包为何不需要安装器2.1 程序自包含与配置外置Chrome 的“绿色软件”设计Chrome 和很多 Linux 图形程序不一样它天生就是“自包含”的。所有程序文件——可执行文件、动态库、资源文件、语言包——都放在同一个目录树里运行时需要的用户数据写到~/.config/google-chrome和~/.cache/google-chrome。它不往/usr里乱丢文件不要求系统里注册什么服务也不依赖注册表式的全局配置。正是这个设计让它能被整体打包成一个 zip搬到另一台 Linux 机器上解压只要系统提供了它需要的少数共享库就能直接跑起来。这和 Windows 下那些“便携版”软件的思路一模一样。用过 CrystalDiskInfo 免安装 zip 包的人应该很熟悉解压就是一个完整的安装动作删掉目录就是彻底卸载系统里不留垃圾。Chrome 在 Linux 上的 zip 分发本质就是这种绿色软件形态。解压后目录里会有主程序chrome、一堆私有动态库和资源子目录你不需要搞清楚每个子目录的职责但必须记住一条纪律解压之后不要把chrome这个可执行文件单独拷走要带着整个chrome-linux64目录一起移动。程序运行时是按相对路径找它的库和资源的拆散了就是玄学崩溃报错还往往不在第一时间指向这个原因。2.2 deb/rpm 安装器只做了四件事而 zip 包全部绕过用 apt 安装 google-chrome-stable 时deb 包做的事情可以归结为四件把文件按 FHS 规范散布到/usr/bin、/usr/lib、/usr/share注册 desktop 文件让桌面环境能发现它写入 update-alternatives 把默认浏览器指向它配置 apt 源用于后续更新。这四件事在无头服务器和测试容器里前三件都是多余的。zip 分发包要做的事情少得多解压到一个固定目录告诉 shell 这个目录里的chrome在哪。这不需要 root因为用户自己的~/.local/bin本来就在 PATH 里。实际维护中这两种方式差异最大的是“版本可控性”apt 装出来的版本跟着源走源更新了你的 Chrome 就悄悄变了zip 包则把版本彻底锁死在你下载的那个瞬间。对比项deb/rpm 安装chrome-linux64.zip 解压是否需要 root需要不需要安装位置/usr 系统目录用户自定义目录版本固定跟随发行版源难精确控制下载哪个版本就是哪个更新方式apt upgrade 连带重新下载替换目录可复现性依赖源快照不同机器有差异同一 zip 解压结果一致工作流上还有一个隐性差别zip 部署不干扰系统里已有的浏览器。很多服务器镜像预装了 Firefox 或其他 Chromium 衍生版apt 装 Chrome 可能会触发替代优先级变更牵扯出一堆连锁反应。zip 包则完全隔离在你自己的目录里想用哪个版本就用哪个不会跟系统里的其他浏览器打架。2.3 zip 版依赖什么用 ldd 摸清系统库边界“解压即用”不等于“零依赖”。Chrome 启动时会动态链接一批系统共享库这些库在桌面发行版里默认装好但在最小化服务器镜像里常常缺失。最直接的检查手段是 lddldd ~/apps/chrome-linux64/chrome | grep not found这条命令有输出就说明缺库。常见的缺失项集中在三类NSS 密码学相关如libnss3.so、libnssutil3.soGTK/ATK 图形栈如libgtk-3.so、libatk-bridge2.0-0音频与硬件加速相关如libasound.so、libgbm.so。缺哪类就补哪类用发行版的包管理器装对应包名即可。Debian/Ubuntu 上通常是libnss3、libatk-bridge2.0-0、libgtk-3-0、libasound2、libgbm1这几个。还有一条硬边界是 glibc。新版 Chrome 对 glibc 版本有最低要求老发行版会在加载阶段直接报GLIBC_2.XX not found这类错误。遇到这种情况别想投机去找与你系统年代接近的旧版 Chrome zip。Windows 上 Win7 用户停留在 Chrome 109 是同一逻辑操作系统太老新浏览器不伺候。判断方法很简单——ldd --version | head -1看一下目标机器的 glibc 版本再和你要下载的 Chrome 版本要求对照能省下解压后才发现跑不起来的尴尬。2.4 官方为何也发 zipChrome for Testing 与可复现测试如果你以为 zip 分发只是第三方镜像的野路子那就错了。Google 官方为自动化测试专门维护了一条 Chrome for Testing 产品线所有版本都以 zip 形式分发命名就是chrome-linux64.zip这种风格。它的定位很明确让测试环境拿到一个版本固定、行为可复现的 Chrome而不是跟着自动更新跑的那个“最新稳定版”。这就是chrome-linux64.zip在一线自动化测试里真正值钱的地方。apt 装出来的 Chrome 版本受源更新时间影响今天构建和下周构建可能拿到不同的小版本zip 包把版本号写在文件名里、写在你下载的 URL 里拿到的东西完全一致。CI 里最怕的不是报错是昨天能过、今天不能过且查不出原因。zip 分发至少把“浏览器”这个变量锁死了剩下的问题才值得花时间去查。3. 用 chrome-linux64.zip 在无 root 服务器上部署下载校验、解压路径与启动参数3.1 先确认平台与 glibc再选 zip 包动手前花一分钟确认目标机器的平台省得下错包白折腾。Linux 下这个 zip 要求 CPU 架构是 x86_64ARM 机器aarch64需要的是另一个命名和构建的包不要混用。uname -m # 期望输出 x86_64 ldd --version | head -1 # 记下 glibc 版本号选 Chrome 版本时用它做参照确认这两项之后再决定下载哪个大版本。判断标准很朴素目标机器的 glibc 越老选的 Chrome 版本就要越旧。我一般会在 Chrome for Testing 的发布说明里查一下版本对应的系统要求或者更简单——先在目标机器上解压一个候选版本跑--version报 GLIBC 错就降级换旧版。版本选择这事没有捷径试一次就记住了。3.2 下载与 SHA256 校验内网传输最容易在这步翻车下载 zip 取决于你的网络环境。能访问外网的机器直接用 Chrome for Testing 的公开 JSON 端点拿版本和下载地址完全隔离的内网机器就在一台能上网的机器上下载好再通过内网传输工具拷贝进去。# 从 Chrome for Testing 的 JSON 端点获取 linux64 的下载地址和哈希 curl -s https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions-with-downloads.json \ | python3 -c import json, sys data json.load(sys.stdin) for item in data[channels][Stable][downloads][chrome]: if item[platform] linux64: print(URL:, item[url]) print(SHA256:, item[sha256]) 这段脚本做的事情很简单从官方 JSON 中筛出 Linux 64 位 Chrome zip 的下载地址和 SHA256。注意这个端点默认返回的是“最新稳定版”信息如果你在项目里固定了某个版本需要换成对应版本的 JSON 端点或者在输出里手动指定版本号再拼 URL。下载完成后校验是必须的一步尤其是内网传输场景。zip 文件在网络里跑一圈后字节翻转并不罕见而 Chrome 的 zip 解到一半报 CRC 错误比重新下载更浪费时间。# 用官方给出的 sha256 校验本地文件 echo 上一步拿到的 sha256 chrome-linux64.zip | sha256sum -c - # 内网传输中断时用断点续传而不是重头再来 wget -c --tries3 --timeout30 -O chrome-linux64.zip URL # 校验通过后再解压 unzip chrome-linux64.zip -d ~/apps/注意sha256sum -c的输出是“OK”才算通过。看到“FAILED”不要犹豫重新下载不要试图修复一个哈希对不上的压缩包。3.3 解压规划与 PATH 链接不碰 /opt 也能全局可用没有 root 权限时最稳的落点是用户主目录。解压到~/apps然后让这个目录里的chrome可执行文件暴露到 PATH 中mkdir -p ~/apps unzip chrome-linux64.zip -d ~/apps/ # 确认解压出来的顶层目录名 ls ~/apps/chrome-linux64/ # 直接运行可执行文件验证能输出版本号 ~/apps/chrome-linux64/chrome --version解压动作本身没有魔法就是把目录树放到指定位置。真正要养成习惯的是“带着目录跑”——不要只把chrome这个可执行文件拷到~/.local/bin它运行时需要同目录下的库和资源文件。想让命令全局可用用软链接而不是拷贝mkdir -p ~/.local/bin ln -s ~/apps/chrome-linux64/chrome ~/.local/bin/google-chrome echo export PATH$HOME/.local/bin:$PATH ~/.bashrc source ~/.bashrc软链接的好处是升级方便。下次换版本时解压新 zip 到新目录改一下软链接指向即可旧目录整个删掉不会留散落文件。如果解压过程中报错先检查 zip 是否下载完整再确认磁盘空间df -h ~/apps一眼就能看到是不是把家目录塞满了。3.4 三个必加启动参数与一个安全禁区部署完成后真正决定能不能跑起来的是启动参数。无头服务器、容器和 root 用户这三个场景分别对应三个参数参数解决什么什么时候用--headlessnew没有显示器也能渲染页面服务器或 CI 里做抓取、截图、自动化测试--no-sandbox绕过 SUID 沙盒启动限制root 用户或容器内无 user namespace--disable-dev-shm-usage避免 /dev/shm 空间不足导致崩溃Docker 容器或其他共享内存受限环境--user-data-dir指定独立的用户数据目录并发跑多个实例、不想污染默认配置--no-sandbox是这几个参数里最需要克制的一个。root 下不加它 Chrome 直接拒绝启动但沙盒是 Chrome 对抗渲染进程漏洞的重要防线关掉等于裸奔。我的习惯是只在明确可信的环境里用它——一次性 CI 容器、隔离的测试机——并且能建普通用户跑就建普通用户从根上绕开这个问题。另一个容易忽略的是--user-data-dir同一台机器上并发跑多个 Chrome 实例时不给每个实例指定独立目录它们会争抢同一个配置锁表现就是启动一个后另一个起不来。4. 把 zip 版 Chrome 接进自动化测试版本固定、ChromeDriver 匹配与无头运行4.1 为什么测试环境要用 zip 固定版本而不是 apt 装最新做过自动化测试的人应该都有这种经历脚本在本地跑得好好的上 CI 就莫名其妙挂了查半天发现是 Chrome 昨晚自动升级了。apt 装 Chrome 等于给自己装了一个“会变的版本”它和你的测试脚本之间的契约随时可能断。ChromeDriver 对 Chrome 版本尤其敏感大版本号对不上就直接拒绝工作报错信息直白得让人想摔键盘。zip 分发的价值就在这里版本是你在下载时选定的不随源更新漂移。Chrome for Testing 存在的意义就是把“固定版本”变成规范。生产上我一般会给项目建一个“版本台账”某个版本的chrome-linux64.zip和对应的chromedriver-linux64.zip放在一起测试脚本里写死这个版本。升级是主动动作而不是被动事故。这套做法配合 CI 的缓存还能让每次构建的浏览器环境完全一致排查问题的时候少一个变量。4.2 用一条命令让 ChromeDriver 与 Chrome 版本对齐ChromeDriver 和 Chrome 的匹配规则是版本号前三段必须一致。手动查版本再找驱动太累直接写进脚本自动对齐CHROME_BIN$HOME/apps/chrome-linux64/chrome CHROME_VER$($CHROME_BIN --version | awk {print $3}) echo Chrome 版本: $CHROME_VER # 用版本号拼出 ChromeDriver 的下载地址Chrome for Testing 的 URL 规则 DRIVER_ZIPchromedriver-linux64.zip curl -LO https://storage.googleapis.com/chrome-for-testing-public/${CHROME_VER}/linux64/${DRIVER_ZIP} unzip -o $DRIVER_ZIP -d ~/apps/ # 确认驱动和浏览器版本前三段一致 ~/apps/chromedriver-linux64/chromedriver --version说明chrome --version的输出形如 “Google Chrome 124.0.6367.60”awk {print $3}取第三段就是完整版本号。这个版本号正好是 Chrome for Testing 下载路径的组成部分所以能无缝拼出对应驱动的地址。解压后把chromedriver也暴露到 PATHSelenium 就能自动发现它。注意 Windows 和 Linux 的 chromedriver 二进制不通用别在 Linux 服务器上解压 Windows 的驱动然后怀疑人生。4.3 Selenium 最小联动示例binary_location、无头参数与用户数据目录二进制就位之后写一个最小可跑的 Selenium 脚本验证整条链路。Python 是测试圈最常用的语言示例也用它from selenium import webdriver from selenium.webdriver.chrome.options import Options opts Options() # 关键告诉 Selenium 用哪个 Chrome 可执行文件而不是系统默认路径 opts.binary_location /home/ci/apps/chrome-linux64/chrome opts.add_argument(--headlessnew) opts.add_argument(--no-sandbox) opts.add_argument(--disable-dev-shm-usage) # 独立用户数据目录避免与真实浏览会话互相干扰 opts.add_argument(--user-data-dir/tmp/chrome-profile-test) driver webdriver.Chrome(optionsopts) try: driver.get(https://example.com) print(标题:, driver.title) print(URL:, driver.current_url) finally: driver.quit()binary_location是 zip 部署场景里最关键的配置项。Selenium 默认会去/usr/bin/google-chrome之类的位置找浏览器zip 包不在那里不指定就报找不到浏览器。headlessnew是新一代无头模式行为和真实浏览器更接近不像旧 headless 那样容易被网站识别。quit放在finally里能确保即使断言失败Chrome 进程也会被回收不会在 CI 机器上留下一堆僵尸进程。跑完这个脚本后顺手看一眼进程ps aux | grep chrome | grep -v grep | wc -l正常退出后这个数字应该是 0。如果不为 0说明有 Chrome 进程没被回收多半是--user-data-dir没有生效多个进程互相等待锁。这是无头测试里很隐蔽的坑进程越积越多最终把 CI 机器的内存吃光。4.4 在 Dockerfile 里固定版本CI 镜像不“漂移”的写法容器里部署 zip 版 Chrome最怕 Dockerfile 里写“装最新版”。构建一次得到一个版本两周后重新构建又得到另一个缓存层还会掩盖这个变化。固定版本的正确姿势是把它写成一个显式的 ARG# Dockerfile 片段 ARG CHROME_VERSION124.0.6367.60 ARG CHROME_ZIPchrome-linux64.zip RUN curl -LO https://storage.googleapis.com/chrome-for-testing-public/${CHROME_VERSION}/linux64/${CHROME_ZIP} \ unzip ${CHROME_ZIP} -d /opt \ ln -s /opt/chrome-linux64/chrome /usr/local/bin/google-chrome \ rm ${CHROME_ZIP}版本号用 ARG 声明之后升级就是改一行再重新构建镜像是可再生的。删掉 zip 是为了让镜像层瘦一点。这里有个 Docker 的细节如果CHROME_VERSION变了但前面的 RUN 层没有变化Docker 会复用旧缓存导致新版本没生效。遇到这种情况要么在构建时加--no-cache要么把版本号写进一个 COPY 的文件里强制打破缓存。CI 用的镜像我一般会显式加--no-cache保证每次构建都是真实执行。5. 避坑linux64 zip 版 Chrome 的 5 个高频翻车点与排查命令5.1 root 下启动就报 SUID sandbox 错误现象root 用户直接执行chrome --headless报错 “Running as root without --no-sandbox is not supported”进程秒退。原因Chrome 的 SUID 沙盒需要普通用户权限体系配合root 用户下这条链路失效Chrome 出于安全考虑拒绝启动。这个设计不是 bug是保护机制。解决可信环境加--no-sandbox启动更稳妥的做法是建一个专用普通用户用它的身份跑 Chrome这样沙盒正常工作也不需要关闭安全防线。我自己的 CI 镜像里就跑在ci用户下只有极少数特殊场景才允许 root 加--no-sandbox。5.2 缺 libnss3.so 等系统依赖zip 包不背这个锅现象./chrome启动时报 “error while loading shared libraries: libnss3.so: cannot open shared object file”。原因zip 包自包含的是 Chrome 自己的私有库NSS、GTK 这类系统级依赖带不了。最小化服务器镜像没装图形库就会这样。解决先用 ldd 摸清缺口再补。Debian/Ubuntu 上通常是libnss3、libatk-bridge2.0-0、libgtk-3-0、libasound2、libgbm1这几个包。补完再跑一遍ldd chrome | grep not found输出为空才算过。这一步需要 root 或 sudo和 zip 部署本身不需要 root 是两回事别混为一谈。5.3 容器里 /dev/shm 太小导致白屏或崩溃现象测试脚本在容器里跑页面加载到一半崩溃截图是白屏日志里能看到/dev/shm相关字样或渲染进程异常退出。原因Docker 默认/dev/shm只有 64MBChrome 的共享内存机制在这个容积下不够用。多个标签页并发时尤其明显。解决最省事的是给 Chrome 加--disable-dev-shm-usage让它把临时文件写到/tmp如果项目允许也可以在docker run里加--shm-size1g从根上放宽限制。两种做法我优先改容器参数因为更接近真实浏览器行为截图和渲染结果更可靠。5.4 Chrome 与 ChromeDriver 版本错位日志说得很直白现象启动 WebDriver 时日志报 “This version of ChromeDriver only supports Chrome version 124”但你的 Chrome 是 125。原因Chrome 和 ChromeDriver 分别安装各自来源不同步。最常见的是 Chrome 用 zip 部署了旧版本而 ChromeDriver 是 apt 或 pip 自动拉的新版。解决让两者来自同一个版本线。先用chrome --version确认浏览器版本再按 4.2 的方法下载对应版本的chromedriver-linux64.zip替换。升级时先升 Chrome再升驱动保持版本前三段一致。这条规则是 Chrome 自动化里少有的“死规矩”别挑战它。5.5 zip 包损坏或伪加密EOCD 找不到与莫名要密码现象unzip chrome-linux64.zip报 “invalid zip archive: could not find EOCD”或者解压时提示输入密码。后者常见于第三方下载站拉回来的包——文件的加密标志位置 1但内容其实没加密叫伪加密。原因EOCD 是 zip 的结尾记录文件末尾被截断或传输损坏就会找不到它。伪加密则是打包工具或分发站故意设置的标志位目的是让你以为需要密码。解决先看文件大小和 SHA256和官方值不一致就重新下载。伪加密的包用 7z 试空密码7z x -p chrome-linux64.zip如果 7z 能正常列出内容说明确实是伪加密解出来就能用。真加密且没有密码的包没有后悔药回到官方来源重新下载是最便宜的解决方式。下载 Chrome 永远只认官方端点或你信任的内部镜像能避开这一类问题。6. 验证部署是否可用版本、依赖与真实渲染截图三条命令部署完 Chrome 别急着写测试脚本先用三条命令确认它真的能用。第一条验版本第二条验依赖第三条验渲染链路。# 1. 版本检查确认程序能启动且版本符合预期 ~/apps/chrome-linux64/chrome --version # 2. 依赖完整性没有任何 not found 才算过了系统库这一关 ldd ~/apps/chrome-linux64/chrome | grep not found || echo 依赖完整 # 3. 真实渲染无头模式访问页面并截图验证完整渲染链路 ~/apps/chrome-linux64/chrome \ --headlessnew \ --no-sandbox \ --disable-gpu \ --window-size1280,720 \ --screenshot/tmp/page.png \ https://example.com ls -lh /tmp/page.png第三条命令里--screenshot是含金量最高的验收方式它能证明 Chrome 不止启动了还完成了网络请求、DOM 构建、排版和光栅化这一整条链路。文件成功生成后续 Selenium 脚本大概率能通。如果卡在这一步多半是字体或 GPU 的问题——无头渲染缺字体不会报错只会让截图的文字变成方块这时候装上 fonts-liberation 或 fonts-noto-cjk 再试。截图生成后把它拉回本地打开看一眼确认排版正常。有条件的话在带显示环境的机器上打开chrome://version对比命令行参数和版本信息检查有没有不符合预期的 flag。我自己的习惯是把这三条命令写进部署脚本末尾作为安装成功的断言。有一次在新拉的 CI 机器上部署版本和依赖都过了截图文件也成功生成但图片是全黑的——一查是/dev/shm太小加上--disable-dev-shm-usage就正常了。所以验证一定要看产出内容不能只看退出码。这些年在测试环境里折腾下来chrome-linux64.zip已经成了我部署浏览器的事实标准一个解压命令、一个版本号、一把 SHA256从零到可用不超过三分钟升级就是改一个数字。遇到老系统先用ldd --version摸清边界再决定用哪个大版本比硬装新版再处理兼容问题省心得多。希望帮到你。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联
返回资讯列表 →