ARTICLE DETAIL

资讯详情

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

Linux安装Chrome依赖缺失全解:ldd定位与离线部署

Linux安装Chrome依赖缺失全解:ldd定位与离线部署 在Linux上装Chrome表面上看就是下载一个包、点两下安装的事真动手的人都知道卡住你的从来不是下载速度而是终端里冒出来的一长串libxxx is not installed。我这些年折腾过的机器不算少从Ubuntu 18.04一路到现在的新版本从CentOS 7的内网服务器到ARM架构的国产终端再到深度、UOS这类国产Linux发行版Chrome以及依赖解决这套活儿几乎每隔一段时间就要重来一遍。原因很简单——Chrome是个典型的闭源商业软件它编译时绑定了一批特定版本的共享库而各家Linux发行版的库命名、库版本、拆分粒度都不一样于是同一个deb包在Ubuntu上双击就装好了在别的系统上能给你报出二十行缺失依赖。这篇内容我打算把Linux安装Chrome这件事从头到尾拆开讲为什么会缺依赖、怎么判断自己缺的是哪个、各个发行版分别怎么处理、离线环境怎么办、装完之后启动失败、字体乱码、扩展装不上、无头模式跑不起来这些坑怎么填。不管你是刚在虚拟机里装完Linux系统准备配个浏览器的新手还是要给一批内网机器批量部署的运维看完都能直接照着做。文中涉及的命令我会把参数为什么这么写一并交代清楚不做只给命令不说理由的事。1. 先搞清楚Linux下的Chrome为什么总缺依赖1.1 动态链接库这套机制决定了问题必然存在Linux下的可执行程序绝大多数是动态链接的也就是程序本体里不包含它需要的功能代码而是在运行时去系统的库目录里找对应的.so文件。你可以把它理解成一份菜谱和一个公共厨房菜谱Chrome主程序上写着需要面粉、鸡蛋、黄油做饭的时候再去厨房/usr/lib、/lib、/usr/lib/x86_64-linux-gnu这些目录里拿。厨房里少一样这顿饭就做不成程序也就起不来。Chrome依赖的库大概分几类图形渲染相关的libgbm、libdrm、libxcomposite、libxdamage文本排版相关的libpango、libcairo、libfreetype音频相关的libasound2网络与安全相关的libnss3、libnspr4还有系统集成相关的libsecret、gnome-keyring。这些库在不同发行版里由不同的软件包提供包名可能差异很大——Debian系叫libasound2RHEL系叫alsa-libDebian系叫libgtk-3-0RHEL系叫gtk3。这就是为什么你从网上抄一条安装命令在别人的机器上跑得好好的到你这里直接报无法定位软件包。更麻烦的是版本约束。Chrome的deb包在control文件里写死了它依赖的包名和最低版本号比如libnss3 ( 2:3.26)。如果你系统里的libnss3版本比这个低apt就会告诉你依赖不满足。而有些老系统比如还在跑的CentOS 7本身仓库里的库版本就偏低光靠系统源根本装不上得额外挂第三方源或者手动编译这是后话。1.2 官方包明明自带依赖列表为什么还是报错很多人有个误解既然deb/rpm包里写了依赖那安装工具不应该自动把依赖装好吗这个逻辑本身没错apt install ./xxx.deb或者dnf install ./xxx.rpm确实会自动去仓库拉取依赖。但它能自动解决的前提是——你的软件源里得有这些包而且版本得满足要求。实际踩坑的场景往往有三类。第一类是源不可用或者源里的包被裁剪过典型的就是各种精简版系统、容器镜像、以及内网隔离环境仓库里压根没有libgbm1这个包apt只能干瞪眼。第二类是包名对不上Chrome官方只针对Debian/Ubuntu和RHEL/Fedora出包你要是装在Slackware、Alpine、openSUSE上依赖名完全是另一套体系自动解析直接失效。第三类是架构不匹配你拿的是amd64的包结果机器是arm64的这时候报的错五花八门有时候是依赖找不到有时候干脆是无法执行二进制文件。注意看到依赖报错时先别急着一条条手装先确认自己的软件源是完整可用的。源有问题的话你补再多单包也是白费劲。1.3 不同发行版的生态差异比想象中大Debian/Ubuntu这一系是Chrome支持最好的官方直接提供deb包双击或者apt安装都行依赖关系也基本能自动解决。RHEL/CentOS/Fedora这一系官方也给rpm包但CentOS 7这类老系统要留意它的默认仓库包版本偏旧可能需要启用EPEL。Arch系走的是AUR社区维护的PKGBUILD会帮你处理依赖实际体验反而最省心因为Arch用户习惯了自己解决依赖。国产Linux发行版是这几年问得比较多的场景。深度Deepin、统信UOS、openKylin这些系统底层大多是Debian系的血统所以deb包通常能装但因为仓库做了定制某些库的包名或者版本会被调整偶尔需要手动补一两个包。另外ARM平台的国产终端飞腾、鲲鹏、麒麟用的是arm64架构你要下的是arm64版本的包而不是x86_64的这是新手最容易搞错的一点。至于企业微信Linux版、豆包Linux客户端这类桌面应用它们和Chrome一样都依赖同一批图形库所以你如果已经装好了别的Linux桌面应用Chrome的依赖大概率也能顺利补上反过来也一样。2. 装之前先摸清家底三条命令确认系统信息2.1 看清架构、发行版和库版本动手装之前先花十秒钟把系统底细摸清楚能省掉后面一半的返工。三条命令足够uname -m # 看CPU架构x86_64 / aarch64 / armv7l cat /etc/os-release # 看发行版ID和版本号 ldd --version # 看glibc版本决定你能用多新的Chromeuname -m输出x86_64就是常见的64位Intel/AMD平台输出aarch64或arm64就是ARM 64位输出armv7l是32位ARM。这一步决定了你要下载哪个架构的安装包下错了后面全是无用功。/etc/os-release里的ID和VERSION_ID两个字段最关键。IDubuntu、VERSION_ID22.04这种一看就明白如果是IDuos或者IDdeepin说明是国产定制发行版底层大概率是Debian系包管理用apt但仓库地址和部分包名可能是定制的。ldd --version输出的是glibc版本。这个数字有讲究新版Chrome对glibc有最低版本要求太老的glibc会导致Chrome能装上但一启动就崩。比如glibc 2.17CentOS 7那一代就跑不了最新版Chrome这也是为什么很多人被迫去用Chrome 109这一代老版本。2.2 架构选择与版本取舍的实际判断架构这一块除了x86_64和arm64还有些特殊情况。部分国产ARM终端跑的是arm64但系统库目录布局跟标准Debian不完全一样这种情况建议优先用发行版自己的软件商店或仓库里的Chromium而不是硬装Chrome官方包兼容性反而更好。版本取舍上如果你用的是较新的系统Ubuntu 20.04以上、Debian 11以上、Fedora 33以上直接用最新的稳定版就行没必要折腾老版本。但如果是内网老机器、或者系统被锁死在老版本上不能升级那Chrome 109这一类相对老的稳定版就是务实选择——它对glibc和依赖库的要求低能塞进更多环境里。代价是缺少一些新特性安全性上也建议只在隔离环境里用。有个细节容易被忽略下载页面给的包文件名里带current的是当前最新版每次下载都是当天的版本如果你要给一批机器做统一部署最好把某一次下载的包留档用同一个文件装所有机器避免出现A机器装的是120版、B机器装的是121版导致的行为不一致。2.3 仓库可用性与离线包的提前准备公网环境下先更新一次源索引这一步经常被跳过然后出问题sudo apt update # Debian/Ubuntu系 sudo dnf makecache # RHEL/Fedora系更新完再装包能避免仓库里有这个包但本地索引是旧的导致的找不到。如果你的机器压根没网或者公司网络限制严格那就得走离线路线。基本思路是在一台能联网的、系统和目标机器尽量一致的机器上把所有依赖包下载下来拷过去再装。Debian系用apt-get download配合dpkg-scanpackages做本地仓库RHEL系用yumdownloader --resolve或者dnf download --resolve把依赖树一次性拉全。这部分命令我在第4章会展开讲先记住一个原则离线安装最怕的是漏包宁可多下一个也别到现场发现少一个。多下的包最多占点硬盘少下的包就是一次白跑。3. 分发行版实操从下载到把浏览器跑起来3.1 Debian/Ubuntu/Deepin/UOSdeb包的标准姿势这是最常见也最顺的一条路。拿到deb包之后推荐用apt来装而不是dpkg因为apt会把依赖一起处理sudo apt install ./google-chrome-stable_current_amd64.deb注意包名前有个./这是告诉apt安装这个本地文件而不是去仓库里找同名包。加上./之后apt会先解析这个deb的依赖去仓库里把缺的依赖下载安装好再装Chrome本体一步到位。如果你手快用了dpkgsudo dpkg -i google-chrome-stable_current_amd64.deb那大概率会看到依赖关系未满足的报错然后需要补一条sudo apt -f install-f是 fix broken 的意思它会扫描dpkg记录里处于半配置状态的包把缺的依赖补上。这条命令可以反复执行直到依赖全部满足。装完之后用google-chrome --version验证一下能打印出版本号就说明主程序没问题了。国产系统上如果遇到某个依赖在默认源里找不到先试试换成本系统的完整源有些精简镜像只挂了基础源再不行就去Debian官方源或者对应架构的源里找同名包手动下载安装。装的时候用--force-depends要谨慎强行忽略依赖可能导致程序能装但一跑就崩只在确认那个依赖对当前用途无影响时才用。3.2 RHEL/CentOS/Fedora/麒麟rpm包与dnf处理RHEL系的做法类似推荐用dnf installCentOS 7及更早用yumsudo dnf install ./google-chrome-stable_current_x86_64.rpm本地rpm文件同样可以带路径直接装dnf会自动解析依赖。如果报依赖缺失用这个命令补sudo dnf install -y $(rpm -qpR google-chrome-stable_current_x86_64.rpm | grep -v ^/)这条命令的意思是把rpm包里声明的依赖列出来除了以斜杠开头的文件路径依赖其余全部交给dnf去装。这是个比较暴力的补依赖方式正常情况下用不上但在仓库包名跟依赖名对不上的时候很管用。CentOS 7这类老系统要特别提醒一句默认仓库里的libnss3、libgbm等库版本可能不满足新版Chrome的要求这时候要么启用EPEL要么就得考虑用老一点的Chrome版本。硬扛新版的结果是装上了但启动报错排查起来更费时间。3.3 Arch/ManjaroAUR方式反而最省事Arch系用户直接走AURyay -S google-chrome # 或者 paru -S google-chromeAUR里的PKGBUILD是社区维护的依赖关系人家早就调好了你基本不需要管依赖问题。这也是为什么很多人说Arch装Chrome最容易——不是因为Arch有什么魔法而是因为有人替你把这个活干了。如果不想用AUR也可以下载deb包手动解包后运行思路和第3.4节一样。3.4 通用兜底方案解包后直接运行遇到发行版既没有deb也没有rpm包或者依赖实在补不齐的情况还有个万能办法——把deb当成压缩包解开直接跑里面的可执行文件。mkdir -p /tmp/chrome-extract dpkg -x google-chrome-stable_current_amd64.deb /tmp/chrome-extract解开之后主程序在/tmp/chrome-extract/opt/google/chrome/目录下。你可以把它整个目录复制到一个固定位置比如/opt/chrome/然后直接运行sudo mv /tmp/chrome-extract/opt/google/chrome /opt/chrome sudo ln -s /opt/chrome/chrome /usr/local/bin/chrome这时候运行chrome如果缺库会明确告诉你缺哪一个。这是解包法最大的好处报错信息直接指向具体库名方便逐个补齐。顺手把桌面快捷方式也补上否则只能从终端启动。新建/usr/share/applications/google-chrome.desktop[Desktop Entry] Version1.0 NameGoogle Chrome Exec/opt/chrome/chrome %U Terminalfalse TypeApplication Icon/opt/chrome/product_logo_128.png CategoriesNetwork;WebBrowser;Exec指向你实际的程序路径Icon指向图标文件路径保存之后在应用菜单里就能搜到。这个写法对所有发行版基本通用是个很实用的小技巧。4. 依赖缺失逐个击破报错日志与包名对照4.1 典型报错与对应包名速查依赖报错看着吓人其实翻来覆去就那么几个。下面是Debian系和RHEL系的包名对照照着补就行缺失的库文件Debian/Ubuntu包名RHEL/CentOS包名作用libnss3.solibnss3nss网络安全服务libnspr4.solibnspr4nspr可移植运行时libatk-1.0.so.0libatk1.0-0atk无障碍工具包libatk-bridge-2.0.so.0libatk-bridge2.0-0at-spi2-atk无障碍桥接libcups.so.2libcups2cups-libs打印支持libdrm.so.2libdrm2libdrm直接渲染管理libxkbcommon.so.0libxkbcommon0libxkbcommon键盘布局libXcomposite.so.1libxcomposite1libXcomposite合成扩展libXdamage.so.1libxdamage1libXdamage损伤区域扩展libXrandr.so.2libxrandr2libXrandr屏幕旋转缩放libgbm.so.1libgbm1mesa-libgbm缓冲管理libpango-1.0.so.0libpango-1.0-0pango文字排版libcairo.so.2libcairo2cairo2D图形libasound.so.2libasound2alsa-lib音频libatspi.so.0libatspi2.0-0at-spi2-core无障碍libxshmfence.so.1libxshmfence1libxshmfence共享内存栅栏libgtk-3.so.0libgtk-3-0gtk3图形界面无头模式headless跑自动化脚本的话还要额外补libxss1RHEL叫libXScrnSaver、fonts-liberation、xdg-utils这几个否则会出现能启动但截图空白、或者直接报错的怪现象。一口气补Debian系常用依赖的命令大概长这样sudo apt install -y libnss3 libnspr4 libatk1.0-0 libatk-bridge2.0-0 \ libcups2 libdrm2 libxkbcommon0 libxcomposite1 libxdamage1 \ libxrandr2 libgbm1 libpango-1.0-0 libcairo2 libasound2 \ libatspi2.0-0 libxshmfence1 libgtk-3-0 libsecret-1-0装完再跑一次Chrome看还有没有新的报错缺什么补什么。4.2 用ldd定位到底缺哪个库比一条条猜更高效的办法是用ldd直接看主程序依赖哪些库、哪些没找到ldd /opt/google/chrome/chrome | grep not found输出的每一行not found就是一个缺失的库。拿到库文件名之后用下面两条命令查它属于哪个包# Debian/Ubuntu系 apt-file search libnss3.so # RHEL/CentOS系 dnf provides */libnss3.soapt-file需要先装并更新索引sudo apt install apt-file sudo apt-file update但它查文件归属包的能力非常实用值得提前装好。还有个进阶工具patchelf可以修改可执行文件的动态库搜索路径。这个方法一般用不上但在极端情况下比如某个库装在非标准路径程序找不到能救命patchelf --set-rpath /opt/custom/lib /opt/chrome/chrome提示ldd本质上是让系统加载器去解析依赖对于不可信的可执行文件不建议直接跑。Chrome官方包没问题来路不明的二进制要谨慎。4.3 没有外网时怎么把依赖凑齐内网机器的离线安装是最考验经验的一块。Debian系的思路是在联网机器上把所有deb下到同一个目录做成一个本地源拷到目标机器后从本地源安装。# 联网机器上 mkdir /tmp/debs cd /tmp/debs apt-get download libnss3 libnspr4 libatk1.0-0 ... # 把所有需要的包列进去如果你要下载的是带依赖树的完整集合可以用apt-rdepends递归列出所有依赖再逐个下载。下完之后在目录里生成索引cd /tmp/debs dpkg-scanpackages . /dev/null | gzip -9c Packages.gz把整个目录拷到目标机器在/etc/apt/sources.list里加一行deb [trustedyes] file:/tmp/debs ./然后sudo apt update sudo apt install google-chrome-stable就能从本地源装了。[trustedyes]是跳过签名校验本地源没必要走完整签名流程。RHEL系的对应做法是yumdownloader --resolve --destdir/tmp/rpms libnss3 nss ...或者用dnf download --resolve --alldeps。把rpm拷到目标机器后用sudo rpm -ivh *.rpm或者建个本地仓库用createrepo生成元数据再通过dnf --repofrompath指向本地目录安装。这两种方式我都用过如果依赖数量不多十几个以内直接rpm -ivh一把梭最省事如果依赖很多且可能反复装建本地仓库更规范。5. 装完之后的收尾启动、字体、扩展与无头模式5.1 root下启动和沙箱相关的报错怎么处理很多人在服务器或者容器里用root身份跑Chrome会看到这样的报错Running as root without --no-sandbox is not supported.原因在于Chrome的沙箱机制需要用户命名空间等内核特性支持root身份下直接跑会被安全策略拦住。解决办法有两个。第一个是加参数跳过沙箱google-chrome --no-sandbox但要清楚--no-sandbox意味着放弃了浏览器的进程隔离保护如果用它去访问不可信的网页风险是实打实的。所以这个参数建议只在隔离的测试环境、跑自动化脚本时用日常浏览别加。第二个办法是新建一个普通用户来跑Chrome这也是更推荐的做法sudo useradd -m chromerun sudo -u chromerun google-chrome容器环境下还有一类报错跟/dev/shm太小有关表现是页面加载一会儿就崩。可以在启动时加--disable-dev-shm-usage或者给容器更大的共享内存docker run --shm-size1g ...这个坑很隐蔽因为报错信息往往不直接提共享内存容易往别的方向排查。5.2 中文字体缺失导致的乱码和方块系统里没有中文字体时Chrome打开中文网页会显示成一堆方块。这在精简版系统、容器镜像里特别常见。补字体很简单# Debian/Ubuntu系 sudo apt install -y fonts-noto-cjk fonts-wqy-zenhei # RHEL系 sudo dnf install -y wqy-zenhei-fonts google-noto-sans-cjk-fonts装完之后刷新字体缓存fc-cache -fv用fc-list :langzh可以确认系统中文字体是否已经识别。Linux下还有一个跟中文相关的经典坑是解压zip文件时中文文件名乱码那个是编码识别的问题跟字体没关系但经常一起被问到顺手说一下unzip -O CP936 file.zip指定GBK编码或者用unzip -O gbk就能正常解出中文名。7z用户可以用7z x -mcp936 file.zip。5.3 离线安装crx扩展的两种方式企业内网环境装浏览器扩展是个刚需但没有扩展商店可用的时候怎么办。第一种方式最直接把.crx文件拖到chrome://extensions/页面上。不过新版Chrome对非商店来源的crx限制越来越严拖拽可能直接被拒绝尤其是较新的版本会提示无法从该网站添加扩展程序。第二种方式更稳也更能绕过限制把crx当成zip解压然后用加载已解压的扩展程序。mkdir myext cd myext unzip ../someext.crx # crx本质就是带头的zip然后在chrome://extensions/页面右上角打开开发者模式点加载已解压的扩展程序选中刚才解压出来的目录。这种方式的好处是稳定缺点是每次启动会提示正在使用开发者模式扩展企业批量部署时可以用组策略关掉这个提示。企微、办公类插件这类企业常用的扩展基本都是这么离线装进去的。有些扩展还有配套的原生消息宿主native messaging host需要单独部署那个要在系统里注册一个json清单文件指向本地可执行程序配置位置在~/.config/google-chrome/NativeMessagingHosts/或者系统级的/etc/opt/chrome/native-messaging-hosts/这个比较进阶篇幅有限就不展开了。5.4 无头模式与chromedriver的配套做爬虫或者自动化测试的多半会用到headless模式google-chrome --headless --disable-gpu --dump-dom https://example.com--dump-dom把页面DOM打印到标准输出简单验证用得着。要截图就用--screenshot/tmp/out.png --window-size1920,1080。注意headless模式对依赖的要求跟有界面模式不完全一样缺libxss1或者字体时会以各种奇怪的方式失败——截图是空白的、文字是方块、或者直接报错退出。配chromedriver的时候版本号必须和Chrome主版本一致。Chrome是120.xchromedriver就得是120.x差一个主版本号就会报session创建失败。这个错误信息通常是session not created: This version of ChromeDriver only supports Chrome version XXX看到就说明版本对不上去下对应版本即可。google-chrome --version chromedriver --version两条命令的输出主版本号一致才行。另外chromedriver的路径要能让脚本找到要么放进/usr/local/bin/要么在代码里显式指定路径。6. 常见问题速查与踩坑心得6.1 问题速查表现象大概率原因处理方式装完运行报一堆 lib 缺失依赖包没补齐ldd 定位后逐个补装报 Running as root without --no-sandboxroot身份启动加 --no-sandbox 或建普通用户页面加载一会儿就崩/dev/shm 太小加 --disable-dev-shm-usage中文全是方块缺中文字体装 fonts-noto-cjk 并 fc-cache双击图标无反应缺桌面项或权限补 .desktop 文件检查可执行权限扩展拖不进去新版限制非商店来源解压后开发者模式加载chromedriver 报版本不支持版本号不匹配下载同主版本驱动安装时报无法定位软件包源索引过期或缺源apt update 或换完整源RPM 装完提示依赖不满足仓库版本偏低启用 EPEL 或用老版本Chrome离线机器缺个别依赖依赖树没下全yumdownloader --resolve 重下6.2 几个我实际踩过的坑第一个坑是以为apt update过就不用再更了。有次在内网机器上装Chrome报某个库找不到我确认仓库里有这个包折腾半天才发现是软件源索引是半年前的缓存apt update一下立刻就装上了。从那以后我养成了装任何新软件前先更新索引的习惯虽然多花十秒但能少走很多弯路。第二个坑是依赖装齐了但程序还是起不来。这种情况往往不是库的问题而是库的版本太老。表现是启动瞬间退出终端里留下一句含糊的报错。这时候用google-chrome --version试试如果连版本号都打不出来说明是glibc层面的问题基本只能换版本。判断glibc版本用ldd --version对照Chrome官方说明里的最低要求看。第三个坑是复制粘贴失灵。Chrome在某些桌面环境下会出现复制内容粘贴不出来或者剪贴板只在浏览器内部有效。这类问题多半跟桌面环境的剪贴板管理器和Chrome的集成有关换个桌面环境、或者用--enable-featuresUseOzonePlatform --ozone-platformwayland之类的参数切换渲染后端有时能解决。这种问题很难有通用答案只能针对具体环境调。第四个坑是关于磁力链接和自定义协议处理器的。Chrome里点了某个协议链接没反应是因为系统里没有注册对应的协议处理器。这个要在.desktop文件里加MimeTypex-scheme-handler/xxx;然后update-desktop-database刷新缓存。企业内网应用经常用到自定义协议跳转这个点值得记一下。最后一个提醒如果你是在虚拟机里装Linux再装Chrome注意给虚拟机分配足够的显存和内存。Chrome是个吃内存的大户只有2G内存的虚拟机上跑开三四个标签页就开始卡这不是安装的问题是资源不够。我一般建议虚拟机至少4G内存起步装完Chrome之后体验会正常很多。整套流程走下来Linux装Chrome这件事其实没什么玄学核心就三句话搞清楚自己的架构和发行版把依赖按包名对照表补齐装完之后注意沙箱、字体、版本匹配这几个收尾点。真正花时间的从来不是技术难度而是各种环境差异带来的意外。上面这些命令和对照表我用了很多次覆盖面算是比较全了你按自己的环境挑对应的部分用就行。
返回列表