1. 先搞清楚:Solaris 上“版本”和“位数”为什么不能一句话带过
有一类机器很难绕开,就是机房里那些还在跑 Solaris 的老设备。它们可能是十几年前上线的数据库主机,也可能是某套专业设备的控制节点。接手这种机器时,第一件事要确认两件事:这台机器到底是什么版本,以及它到底是 32 位还是 64 位。听起来像一条命令就能解决,实际上 Solaris 查看系统版本与位数这件事,比 Linux 上的cat /etc/os-release复杂得多。
原因在于 Solaris 的版本信息分散在好几个地方,每处回答的都是不同问题。/etc/release讲的是发行版装的是什么介质、什么时候装配的;uname -a讲的是内核跑的是什么;isainfo讲的是这套系统在指令集层面支持什么。三者不一致的情况很常见,尤其是那些打过补丁、升过级、或者跑在逻辑域和 Zone 里的机器。如果你只用一条命令下结论,后面装软件、打补丁、编译模块时大概率要返工。
这篇内容面向三类人:第一类是刚接手 Solaris 环境、需要快速摸清家底的运维同学;第二类是要在 Solaris 上部署中间件、数据库、监控代理,必须先确认目标平台位数的交付工程师;第三类是需要写跨平台脚本、要在 SPARC 和 x86 两边都跑通的老手。下面这些命令和判断方法,都是可以直接复制粘贴用的,配合实际输出示例和容易踩坑的地方一起讲。
2. 查版本:四类命令的分工与适用场景
2.1 cat /etc/release:发行版身份的唯一权威出处
判断一台 Solaris 装的是什么发行版,最直接的办法就是看/etc/release。这个文件由安装介质在系统装配阶段写入,内容是人可读的一段文本,包含发行版名称、更新级别、平台类型和装配日期。它不依赖任何命令是否存在,哪怕系统处于最小化安装、命令路径被破坏的状态,cat一下也能看到。
$ cat /etc/release Solaris 10 1/13 s10x_u11wos_24a X86 Assembled 16 January 2013上面这段输出有几个关键信息。Solaris 10是大版本,1/13表示这版介质是 2013 年 1 月发布的更新,s10x_u11wos_24a是内部装配标识,其中u11暗示它包含 Update 11 的内容,末尾的X86明确了平台是 x86 而不是 SPARC。装配日期16 January 2013是介质打包时间,不是系统安装时间,别把它当成机器上线日期记录进台账。
Solaris 11 之后输出格式变了,多了一行 SRU 相关的内容,版本号也更细:
$ cat /etc/release Oracle Solaris 11.4 X86 Assembled 07 August 2018这里11.4是 GA 大版本号。但要注意,/etc/release反映的是安装时的介质版本,后续通过pkg update打的 SRU 补丁不会改写这个文件。所以一台机器/etc/release写 11.4,实际可能已经打到 11.4.42 了。想知道真实的补丁级别,得去看包管理系统,这一点在第 2.3 节展开。
提示:
/etc/release在全局区和非全局区里都存在,但非全局区里的这个文件是从全局区继承过来的,不代表该 Zone 自身有独立内核。看到它只能说明宿主安装了什么,不能说明当前 Zone 的实际运行环境。
2.2 uname -a 与 uname -X:内核视角的信息集合
uname是每个 Unix 都有的命令,但 Solaris 的uname有它自己的脾气,字段含义和其他系统不完全一样。日常最常用的是uname -a,一次打印全部字段:
$ uname -a SunOS dbnode01 5.10 Generic_147148-26 i86pc i386 i86pc从左往右依次是:系统名(SunOS)、主机名、内核 release(5.10)、内核版本(Generic_147148-26,这是一个补丁级别标识)、硬件平台(i86pc)、指令集架构(i386)、平台标识(i86pc)。SPARC 机器上会类似这样:
$ uname -a SunOS spnode01 5.10 Generic_147440-19 sun4u sparc SUNW,SPARC-Enterprise跟 Linux 比,Solaris 的uname -a里那个i386或者sparc字段最容易误导人。很多人看到i386就认为系统是 32 位,这是错的。这个字段在 x86 平台上固定输出i386,跟系统是不是 64 位没有关系,原因在第 3.2 节详细说。同理,i86pc是硬件平台标识,不是位数标识。
如果想按字段分开看,uname -X会输出更结构化的内容:
$ uname -X System = SunOS Node = dbnode01 Release = 5.10 KernelID = Generic_147148-26 Machine = i86pc BusType = <unknown> Serial = <unknown> Users = <unknown> OEM# = 0 Origin# = 1 NumCPU = 8这个格式对脚本解析比较友好,尤其Release和KernelID两个字段,可以直接awk -F'= ' '/^Release/{print $2}'抠出来。NumCPU在较老的版本上可能显示不准(虚拟化环境里尤其明显),别拿它当 CPU 核数的权威数据,要看核数用psrinfo -p。
单独使用各个开关时:
| 开关 | 输出内容 | 典型值 | 用途 |
|---|---|---|---|
uname -r | 内核 release | 5.10 / 5.11 | 判断大版本 |
uname -v | 内核版本 | Generic_147148-26 / 11.4.0.15.0 | Solaris 11 上是 SRU 号 |
uname -m | 硬件平台 | i86pc / sun4u / sun4v | 判断物理平台 |
uname -p | 指令集架构 | i386 / sparc | 不能用来判断位数 |
uname -i | 平台实现 | i86pc / sun4u | 与-m类似 |
uname -n | 主机名 | dbnode01 | 写脚本命名输出文件 |
Solaris 11 之后uname -v的语义发生了实质变化,从“内核补丁标识”变成了“发行版 SRU 号”,比如输出11.4.0.15.0。这意味着同一批脚本在 Solaris 10 和 11 上解析uname -v的逻辑不能通用,写跨版本脚本时必须用uname -r先分流。
2.3 showrev 与 pkg:补丁级别和装配信息的补充
showrev是一个老资历的综合信息命令,showrev -a会把主机、版本、内核架构、应用架构、补丁列表全打印出来。它在 Solaris 10 上信息很全,到了 Solaris 11 部分字段会显示<unknown>或者被裁剪,但仍然值得跑一下,因为它给的Kernel architecture和Application architecture两行,是快速判断内核位数和应用位数的直观依据。
$ showrev Hostname: dbnode01 Release: 5.10 Kernel architecture: i86pc Application architecture: i386 Kernel version: Generic_147148-26这里Kernel architecture和Application architecture的差别很关键。前者描述内核跑在什么平台上,后者描述默认编译出来的应用程序是几位。在 x86 的 64 位系统上,这两个字段可能都显示不带位数的名字,单看文字判断不出位数,所以还是要回到isainfo,第 3 节专门讲。
真正想知道打过哪些补丁,Solaris 10 用showrev -p配合grep:
$ showrev -p | grep 147148 Patch: 147148-26 Obsoletes: Requires: Incompatibles: Packages: ...Solaris 11 换了包管理体系,补丁概念被 SRU 取代,对应的做法是查entire这个元包:
$ pkg list entire NAME (PUBLISHER) VERSION IFO entire 1.4.5.0.0.1.15.0 i--也可以直接看内核包:
$ pkg info kernel | grep -i version Version: 1.4.5.0.0.1.15.0这行的版本号就是当前系统的真实 SRU 级别,比/etc/release可靠得多。实际做资产盘点时,我一般要求同时记录/etc/release的介质版本和pkg list entire的运行版本,前者说明这台机器当初是怎么装的,后者说明它现在是什么状态,两者对不上是常态,对上了反而说明这台机器很久没维护。
3. 查位数:isainfo 是标准答案,uname 是干扰项
3.1 isainfo 四个参数,各回答一个不同的问题
Solaris 判断位数只用一条命令就够,就是isainfo。它有几个开关,含义差别很大,很多人混着用,导致结论互相打架。
$ isainfo -b 64-b输出的是系统支持的最大位数,只打印 32 或 64。这是最常用的一个,判断“这台机器能不能跑 64 位程序”看它就行。注意它回答的是“支持”,不是“当前默认”。
$ isainfo -k sparcv9-k输出的是内核自身的位数标识。SPARC 上可能是sparc(32 位内核)或sparcv9(64 位内核);x86 上基本只会看到amd64,因为 Solaris 10 之后的 x86 版本只提供 64 位内核。这个参数在排查“硬件是 64 位但系统跑着 32 位内核”的情况时特别有用,SPARC 平台上这种情况是真实存在的。
$ isainfo -v 64-bit sparcv9 applications vis2 vis 32-bit sparc applications vis2 vis v8plus div32 mul32-v是最详细的一个,把系统能运行的应用类型和对应的指令集扩展全部列出来。输出里出现64-bit ... applications就说明支持 64 位应用,后面缩进的那一行是该架构支持的指令集特性,比如vis、sse4.2、avx之类。这些特性对性能调优和二进制兼容性判断有用,比如某个第三方库要求sse4.2,就可以在这里确认目标机器是否具备。
$ isainfo -kv 64-bit sparcv9 kernel modules-kv是两个开关的组合,输出内核位数加内核模块类型。装驱动、装内核模块之前必须确认这一项,32 位内核模块往 64 位内核上装,加载时会直接报架构不匹配,错误信息还很含糊,容易浪费半天时间。
还有一个不常用但很实用的-n,它输出当前平台的原生架构名:
$ isainfo -n sparcv9这个值可以直接拿来做脚本里的判断变量或者目录命名,比解析uname -m靠谱。
3.2 uname -p 和 uname -m 为什么永远显示 i386 和 i86pc
这是 Solaris 上最常见的一类误判。在 x86 的 64 位 Solaris 上执行:
$ uname -p i386 $ uname -m i86pc看到i386就断定“这是 32 位系统”,是新手最容易犯的错。原因在于这两个字段的含义根本不是位数:-m是硬件平台的家族名,-p是处理器架构的兼容标识,它们在 x86 平台上被固定成i86pc和i386,目的是保持历史兼容性,让那些老脚本不至于因为平台名变化而失效。Solaris 的 x86 版本从 10 开始就只提供 64 位内核了,uname -p依然雷打不动地输出i386。
SPARC 平台同理,uname -p输出sparc,-m输出sun4u或sun4v,都不带位数信息。sun4v是较新的虚拟化平台架构,sun4u是老一代物理平台,这个区别在做硬件兼容性判断时有用,但跟 32/64 位是两码事。
注意:如果你看到某份文档或者某个人说“用
uname -p看位数”,可以直接跳过这条建议。这个字段在 Solaris 上从来就不是干这个用的。
3.3 硬件、内核、应用三层的位数可能各不相同
Solaris 上“这台机器是几位”这个问题,严格来说要分三层回答,三层可以不一致:
第一层是硬件能力,也就是 CPU 本身支持什么。这一层用isainfo -b看,现代机器基本都是 64。第二层是内核位数,用isainfo -k看,SPARC 上装 32 位内核是有可能的,x86 上从 Solaris 10 起没有 32 位内核可装。第三层是应用默认位数,用getconf LONG_BIT看:
$ getconf LONG_BIT 64这个值反映的是编译器默认生成的程序位数。在 64 位系统上一般是 64,但在某些经过特殊配置的环境里可能是 32。三层都对齐了才叫“完全 64 位环境”,任何一层不一致都要在交付文档里写清楚,否则后面装软件时会出现“明明系统是 64 位,为什么装不上 64 位版本”的困惑。
还有一个更细的检查方法,直接看某个可执行文件是 32 位还是 64 位:
$ file /usr/bin/ls /usr/bin/ls: ELF 64-bit LSB executable AMD64 Version 1 ...或者用 Solaris 自带的elfdump:
$ elfdump -e /usr/bin/ls | head -5输出里会有ELFCLASS64或ELFCLASS32字样。这个方法在排查“某个二进制到底能不能在目标机上跑”时最直接,比查系统版本更快。装第三方软件之前,先file一下安装包里的主程序,比看安装文档靠谱。
4. 一套可以直接抄走的采集流程
4.1 手工执行:三条命令得出完整结论
如果只是临时登上一台机器,用下面三条就能得出结论,顺序不要乱:
第一步,cat /etc/release,确认发行版大版本和平台类型,是 Solaris 10 还是 11,是 SPARC 还是 X86。这一步决定后面所有命令的语法差异。
第二步,uname -a,拿内核 release 和内核版本。5.10和5.11是分水岭,决定了补丁体系是showrev -p还是pkg。
第三步,isainfo -b加isainfo -kv,确认支持的最大位数和内核模块位数。这两个值决定了你能装什么版本的软件、什么架构的驱动。
三条命令的输出合起来,一份最小可用的机器档案就有了。实际执行时我习惯顺手把getconf LONG_BIT和zonename也带上,前者补充应用默认位数,后者确认当前是不是在 Zone 里。如果zonename输出的是全局区名字而不是global,那说明你现在处在非全局区里,看到的很多信息是继承来的,需要特别注意,这一点在第 5 节展开。
4.2 写成脚本:一次采集,一次落表
批量盘点几十上百台机器时,手工敲命令不现实。写个采集脚本,用sh而不是bash,因为 Solaris 10 上默认的/bin/sh是 Bourne shell,很多 bash 语法不支持,脚本跑到一半报语法错误比不跑还烦。
#!/bin/sh # 采集 Solaris 版本与位数信息,输出到临时文件 HOST=`uname -n` OUT=/var/tmp/sysinfo_${HOST}_`date +%Y%m%d`.txt { echo "===== collect time =====" date echo "===== /etc/release =====" cat /etc/release echo "===== uname -a =====" uname -a echo "===== uname -X =====" uname -X echo "===== uname -v =====" uname -v echo "===== isainfo -b =====" isainfo -b echo "===== isainfo -n =====" isainfo -n echo "===== isainfo -kv =====" isainfo -kv echo "===== isainfo -v =====" isainfo -v echo "===== getconf LONG_BIT =====" getconf LONG_BIT echo "===== zonename =====" zonename 2>/dev/null || echo "not a zone aware system" echo "===== virtinfo =====" virtinfo -a 2>/dev/null || echo "virtinfo not available" } > ${OUT} 2>&1 echo "output written to ${OUT}"几个细节值得说。isainfo在 Solaris 7 之前不存在,如果机器老到那个程度,脚本里要加一个存在性判断,用isalist替代。virtinfo是 Solaris 11 才有的命令,在 10 上会报错,所以用2>/dev/null ||兜住,避免输出里出现一堆报错信息干扰阅读。zonename在非 Zone 系统上也可能不存在,同样处理。
重定向用> ${OUT} 2>&1而不是逐个echo >>,这样脚本运行期间只打开一次文件,效率高,也不会因为中途某条命令报错导致文件写坏。
4.3 档案里还要顺手记下来的几项旁证
光有版本和位数还不够,做资产台账时下面几项建议一起采集,后面排查问题会感谢自己。
prtconf | head -20能看到系统配置和硬件平台型号,SPARC 机器上会打印出机型关键字,这个对查硬件手册、找驱动很有用。psrinfo -p看物理 CPU 数量,psrinfo -v看每个 CPU 的状态和主频,虚拟化环境里这两个值可能和uname -X里的NumCPU不一致,以psrinfo为准。swap -l和df -h记录存储布局,ifconfig -a记录网络配置,这些都是接手一台陌生机器时的基础信息。
还有一个经常被忽略的:pkginfo | wc -l,统计已安装的软件包数量。如果一台机器装了几百个包,说明它不是最小化安装,跑着业务软件;如果只有一百出头,很可能是干净的系统盘。这个数字还能反过来验证/etc/release的真实性,因为最小化安装和完整安装的介质版本往往不同。
5. 虚拟化与分区环境下的版本判断
5.1 Zone 里看到的版本,可能是宿主的版本
Solaris Zones 是操作系统级虚拟化,非全局区共享全局区的内核。这意味着在一个非全局区里执行uname -a,看到的SunOS ... 5.10 ...是宿主内核的信息,不是这个 Zone 自己的。/etc/release同样是安装 Zone 时从全局区复制过来的,后续宿主升级不会自动同步。
这种情况在做资产盘点时会造成误判。假设全局区已经升到 Solaris 11.4,某个非全局区是在 11.3 时期创建的,那么在这个 Zone 里cat /etc/release看到的还是 11.3 的文本,但实际跑的内核是 11.4 的。准确的做法是在 Zone 里执行pkg list entire,看它自己安装的包版本,这才是这个 Zone 的真实软件级别。
品牌区(Branded Zone)更特殊。为了兼容老应用,系统提供了模拟旧版本运行环境的品牌区类型,比如模拟 Solaris 8 或 10 环境的品牌区。在这种 Zone 里执行uname -a和cat /etc/release,看到的全是模拟出来的假象,故意让你以为这是一台老机器。判断方法是在全局区里用zonecfg -z <zonename> info查看brand字段,一眼就能看出它是什么类型的 Zone。
$ zonecfg -z legacyapp info zonename: legacyapp brand: solaris10 ...看见brand: solaris10就说明这个 Zone 是在模拟 Solaris 10 环境,你在里面查到的版本信息只能用于应用视角,不能用作系统盘点依据。
5.2 逻辑域和虚拟化平台上的额外一层
SPARC 平台上的逻辑域(Logical Domain)是硬件级分区,每个域有独立的固件和操作系统实例,uname -a看到的是这个域自身的信息,相对可靠。但要知道当前机器是不是逻辑域,得用ldm list或者virtinfo:
$ virtinfo -a DOMAINROLE|impl=LDoms|control=true|io=true|root=true这行说明当前系统是一个逻辑域的控制节点。如果是control=false,说明是一个受控域。在受控域里执行ldm命令会失败,别以为是命令坏了。
virtinfo的输出还能区分物理机和虚拟化环境。物理机上执行通常报virtinfo not available或者返回空,逻辑域上返回上面那行结构化的内容。做容量规划和性能分析时,这个信息直接影响对 CPU 和内存数字的解读,因为逻辑域分到的资源是宿主编排分配的,跟物理机独占资源不是一回事。
6. 常见误判场景与排查速查表
6.1 几个特别容易踩的坑
第一个坑是拿uname -p的输出当位数结论,前面已经说过,这里再强调一次。i386是历史遗留的兼容标识,在 64 位 x86 系统上照样输出这个值,任何基于这个字段做位数判断的脚本都是错的。
第二个坑是拿/etc/release的装配日期当系统安装日期。那个日期是介质打包时间,所有用同一版介质装出来的机器,这个日期都一样,跟机器什么时候上线毫无关系。要查真正的安装时间,可以看根文件系统里某个早期文件的创建时间,或者查系统日志的最早记录。
第三个坑是在 Solaris 11 上继续用showrev -p查补丁。Solaris 11 的补丁体系已经改成 SRU,showrev -p在 11 上输出不完整甚至为空,看到空输出别急着下“这台机器没打过补丁”的结论,换pkg list entire再看一遍。
第四个坑是忽略了内核模块位数。装第三方驱动时只看isainfo -b显示 64 就放心装,结果驱动是给 32 位内核编译的,加载时报错。正确做法是同时看isainfo -kv,两边的架构名必须一致。SPARC 上尤其要注意sparc和sparcv9的区别,x86 上则是i386和amd64的区别。
第五个坑是跨版本写脚本时不判断uname -v的语义。Solaris 10 上uname -v是内核补丁号,11 上是 SRU 号,同一个脚本在两代系统上解析出来的结果完全不是一回事。稳妥的写法是先看uname -r,5.10和5.11走两个分支。
6.2 速查表:症状、原因、处理
| 症状 | 可能原因 | 确认方法 | 处理 |
|---|---|---|---|
uname -p显示 i386,怀疑是 32 位 | 该字段是兼容标识,不表示位数 | isainfo -b看是否为 64 | 以 isainfo 为准,忽略 uname -p |
/etc/release版本与预期不符 | 介质版本不等于当前补丁级别 | pkg list entire | 以包管理器的版本为准 |
showrev -p输出为空 | Solaris 11 已改用 SRU 体系 | uname -r确认是 5.11 | 改用pkg list entire |
| 64 位系统装 64 位软件失败 | 内核是 32 位,或模块架构不匹配 | isainfo -kv | 换对应架构的安装包 |
| Zone 里查到的版本和宿主不一致 | 非全局区的 release 文件未同步 | zonename确认在 Zone 内 | 以pkg list entire为准 |
| Zone 里显示很老的版本 | 品牌区模拟旧环境 | 全局区执行zonecfg -z <name> info | 查看 brand 字段确认 |
virtinfo命令不存在 | 系统版本较低或非虚拟化环境 | uname -r | 用ldm list或直接忽略 |
| 脚本在 Solaris 10 上报语法错误 | 用了 bash 专有语法 | 检查 shebang | 改用 sh 兼容写法 |
6.3 踩过几次坑之后的几条经验
脚本兼容性别偷懒。我见过太多在测试机上用 bash 写得好好的采集脚本,搬到生产环境的老 Solaris 10 上直接报syntax error,原因就是用了[[ ]]或者数组。Solaris 10 的默认 shell 是 Bourne shell,写脚本老老实实用[ ]、用反引号或者$()(这个 Bourne shell 也支持),别碰 bash 扩展语法。
判断位数只看isainfo,不要混用多个命令互相印证,越印证越乱。uname系列命令里的架构字段是历史包袱,getconf LONG_BIT反映的是编译器默认值,只有isainfo -b和isainfo -kv是直接回答“支持什么”这个问题的。三个值不一致时,以 isainfo 为准。
做台账时把“介质版本”和“运行版本”分两栏记。这一条是从实际盘点返工里总结出来的。只记/etc/release,半年后根本不知道这台机器打没打过 SRU;只记pkg list entire,又不知道它当初是拿哪个版本装的。两栏配合,才能看出这台机器的维护轨迹。
最后一个小技巧,如果只想快速知道一台机器能不能装某个 64 位软件,不用查一堆版本,直接跑isainfo -b和file <软件主程序>,两边一个是 64 一个是 ELF64,基本就能装。剩下的兼容性问题,等安装程序自己报错再说,比提前把所有版本信息查一遍效率高得多。