先说结论:在Linux 8.3上装Oracle 19c RAC,Grid Infrastructure跑到ssh互信检查时卡住报INS-06006,这个报错本身不一定是OpenSSH的锅,但确实是OpenSSH版本越新越容易踩的坑。我那次是在客户内网环境,不能随便打OS补丁、不能改sshd_config、防火墙策略也动不了,前后折腾了一个多小时,最后用一个“偷梁换柱”的思路把scp的调用临时包装了一层,直接绕过OUI的检测逻辑,装完以后再把文件恢复原样。这篇文章就把整个排查过程、原理和操作步骤完整写出来,给同样卡在这关的人一个参考。
如果你也是DBA、运维或者正在搭RAC环境的新手,这篇文章适合你。我会先讲清楚INS-06006到底在检查什么、为什么Linux 8.3上容易翻车,再给常规排查路线,然后重点拆解“临时替换scp”这个偏方怎么落地,以及装完以后怎么回滚——这个方案有风险,不能在生产环境留后门,所以每一处权限、恢复命令我都会写得非常细。
1. 先把INS-06006讲明白:OUI到底在检查什么
1.1 错误日志去哪找
安装Oracle 19c RAC时,Grid Infrastructure的图形界面(gridSetup.sh)在“SSH connectivity”这一步有个自动化功能:输入两遍密码,OUI会自动把各节点的密钥分发好、建立互信。如果这个自动过程失败了,界面就弹出INS-06006,字面意思是“Passwordless SSH connectivity is not established between the following node(s)”,中文就是节点之间没有建立无密码ssh连接。
这个报错出现后,大部分人第一反应是手动去配ssh互信,配完重试还是报错,就开始怀疑人生。其实解决问题的第一步不是反复重试,而是先找到OUI的详细日志。我建议按下面顺序找:
# 1. 安装日志所在目录 $ORACLE_BASE/cvutrace/ $INVENTORY/logs/ # 2. 关键文件通常是这些 installActions*.log installProfile*.log oui*.log实际操作中,$INVENTORY/logs/installActions2025-xx-xx.log里会有最完整的错误上下文。用grep直接搜关键字:
grep -i "INS-06006\|ssh\|scp\|exit code" installActions2025-xx-xx.log日志里能看到OUI执行了哪个命令、命令的退出码、stderr输出。很多时候报错根因就藏在最后几行里,比看界面上的错误提示有用得多。
1.2 OUI验证ssh互信的三个步骤
OUI自动设置互信时,内部动作大致分三步:
第一步,在本节点生成RSA密钥对,命令类似ssh-keygen -t rsa -b 2048 -N "" -f ~/.ssh/id_rsa。如果密钥文件已经存在,它会复用旧的,这里常见问题就是历史残留的密钥格式或权限不对。
第二步,通过scp把本节点的公钥(id_rsa.pub)复制到目标节点的~/.ssh/authorized_keys,或者通过ssh user@node "cat >> ~/.ssh/authorized_keys"方式追加。此时需要密码认证,OUI会把你填的密码交给ssh/scp工具去用。
第三步,验证环节最要命。OUI会以ssh -o BatchMode=yes user@node "command"的方式执行远程命令,BatchMode=yes表示“不进行任何交互,认证失败直接退出”。如果前两步建立的互信有问题,这里就会返回非零退出码,然后界面就炸了。
这第三步是理解整件事的关键:OUI在验证阶段用的是BatchMode,意味着它不希望看到任何交互提示,包括host key确认、密码输入、警告信息等等。而在Linux 8.3这种OpenSSH 8.2p1环境下,首次ssh到新主机名时默认会提示“Are you sure you want to continue connecting (yes/no)?”,这个提示在BatchMode下会被直接判死。
1.3 Linux 8.3上的隐藏变化
RHEL/CentOS 8.3自带的OpenSSH版本是8.2p1,和老系统常见的OpenSSH 7.4(RHEL 7)相比,有几个直接影响OUI判断的变化。
第一个是host key确认行为没有本质变化,但known_hosts的格式和管理方式更敏感了。如果之前用root或其他用户ssh过这些节点,known_hosts里可能已经有了旧的主机公钥,切换到grid用户或oracle用户时,指纹不一致就会报“REMOTE HOST IDENTIFICATION HAS CHANGED”。
第二个是scp命令默认仍然走传统的SCP协议,但会输出一行deprecation警告,大致是“Warning: use of the SCP protocol is deprecated”。这个警告本身不致命,但它会混入scp的输出流里。OUI的cvu脚本有时做正则匹配,额外输出会干扰判断,导致明明文件已经拷过去了,还是返回失败。
第三个坑藏在系统级安全策略里。Linux 8.x默认开启了系统级crypto-policy,某些老算法(比如ssh-dss、部分弱MAC算法)被默认禁用。如果你手工生成的互信里用了旧算法,ssh验证时算法协商就会失败。这类问题在日志里表现为no matching key exchange method found之类的关键字。
2. 常规排查先走一遍:大部分问题不靠换scp解决
2.1 手动验证互信的三板斧
遇到INS-06006,至少在折腾“替换scp”这种偏方之前,下面这三组命令必须跑一遍,因为多数报错其实是基础互信没配好。
以节点node1和node2为例,用安装用户(一般是grid)在两台机器上分别执行:
# 1. 重新生成密钥(注意备份旧的) ssh-keygen -t rsa -b 2048 -N "" -f ~/.ssh/id_rsa # 2. 把公钥复制到对方机器,包括localhost和主机名 ssh-copy-id -i ~/.ssh/id_rsa.pub node1 ssh-copy-id -i ~/.ssh/id_rsa.pub node2 ssh-copy-id -i ~/.ssh/id_rsa.pub localhost # 3. 逐个验证免密登录 ssh -o BatchMode=yes node1 hostname ssh -o BatchMode=yes node2 hostname这里有个新手最容易忽略的细节:OUI检查的是“双向互信”,也就是node1能免密ssh到node2,同时node2也要能免密ssh到node1。前者只把node1的公钥放到了node2,后者还得把node2的公钥放到node1。我见过不少人只做了一侧就跑去重试安装,当然继续报INS-06006。
另外,互信还要覆盖localhost。Oracle的cvu脚本有时会用ssh localhost做本机检查,而很多人只配了主机名的互信,localhost被漏掉了。建议直接写个小循环验证:
for host in localhost $(hostname) node1 node2; do ssh -o BatchMode=yes -o ConnectTimeout=3 $host hostname done2.2 权限、SELinux与主机名解析的坑
互信配完还是失败,下一步一定是查.ssh目录权限和属主。OpenSSH对权限有硬性要求,权限过宽直接拒绝使用authorized_keys。正确的配置是:
chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys chown -R grid:oinstall ~/.ssh注意点是:如果曾经用root给grid装过互信,或者手工用root拷贝过authorized_keys,文件的owner很可能是root冒号root,sshd直接不认。
还有一个在Linux 8.x上特别容易忽略的东西:SELinux的file context。即使权限、属主全对,如果SELinux的context不对(比如authorized_keys是从/tmp复制过来的,带了tmp_t标签),sshd仍然会拒绝读取。修复命令:
restorecon -R -v ~/.ssh或者检查SELinux状态:
getenforce # 输出的如果是Enforcing,就得留意context问题主机名解析也是大头。RAC要求/etc/hosts里配置好所有节点的真实内网IP和主机名,不能依赖DNS,而且主机名要和hostname命令输出一致。很多环境下,hostname返回的是短主机名,但/etc/hosts里写的是FQDN,ssh解析后找不到匹配,也会导致互信验证失败。稳妥的做法是/etc/hosts同时写上短名和全名:
192.168.1.11 node1 node1.example.com 192.168.1.12 node2 node2.example.com2.3 日志怎么读:区分ssh失败和scp失败
如果手动互信三项都通了,OUI还是报错,那就必须老老实实读日志,判断到底是ssh阶段失败还是scp阶段失败。
打开installActions日志,关注两种典型现场。第一种是ssh阶段失败,日志里会出现ssh: connect to host node2 port 22: Connection refused或者Permission denied (publickey,gssapi-keyexch,password)。如果是Connection refused,优先去查防火墙和sshd服务状态;如果是Permission denied,回到互信本身。
第二种是scp阶段失败,日志里会出现scp: /home/grid/.ssh/authorized_keys: No such file or directory一类的错误。这类错误通常不是scp命令本身的问题,而是目标端的.ssh目录不存在或权限不对,或者scp的non-interactive模式无法处理host key确认。
判断清楚阶段之后,再用ssh -vvv和scp -v手动模拟一次OUI的执行命令,观察输出里卡在哪一个环节:
ssh -vvv -o BatchMode=yes node2 hostname scp -v ~/.ssh/id_rsa.pub node2:/home/grid/.ssh/test_pub3. 临时替换scp的完整实操
3.1 什么时候才值得上这个“偏方”
说实话,替换系统命令属于风险操作,我不建议你在一开始就试。但有一种场景下它确实是最快的解法:手动互信已经完全验证通过,ssh node1 hostname、ssh node2 hostname、ssh localhost hostname全部免密成功,但OUI的自动互信检查依然报INS-06006,日志里能看到scp或ssh命令返回非零退出码,但你手动跑同样的命令却一切正常。
我当时面对的情况就是这样:客户环境限制多,不能重装openssh,不能改sshd_config,不允许停防火墙,也不允许随便打OS补丁。OUI每次都在scp阶段返回失败,日志里只有一个模糊的scp exited with code 1,而手动执行scp就是成功的。这种“手动正常、脚本调用失败”的典型原因,多半是OUI脚本解析scp输出或交互逻辑与新版OpenSSH的行为不兼容。
在这种受限场景下,与其继续跟OUI较劲,不如临时给scp套一层“壳”,让它适配OUI的调用方式。但要强调:这只是安装期间的临时救急手段,装完大库之后必须立刻恢复原文件、移除所有临时脚本和密码痕迹。
3.2 用户级wrapper脚本的实现方式
我的做法是分两层,先试用户级,不修改系统文件,失败再上系统级。
用户级的意思是:在grid用户自己的~/bin目录下放一个名叫scp的脚本,然后把这个目录放到PATH的最前面。OUI在验证互信时是通过PATH查找scp命令的,所以只要PATH优先,就会找到我们包装过的版本。
这个脚本的核心逻辑是:不用系统默认的scp去跟OUI的expect交互,而是用sshpass把密码自动喂给真正的scp。脚本内容大概长这样:
# 文件路径: /home/grid/bin/scp #!/bin/bash exec /usr/bin/sshpass -p 'Grid@2025' /usr/bin/scp "$@"注意几个关键点。第一,密码绝对不能出现在脚本里被别人看到,所以脚本权限要收紧:
chmod 700 /home/grid/bin/scp chown grid:oinstall /home/grid/bin/scp第二,PATH要在~/.bash_profile里设置,确保grid用户通过图形终端或者OUI启动时继承到:
export PATH=/home/grid/bin:$PATH第三,sshpass这个工具在最小化安装的Linux 8.3上通常没有,需要先确认:
which sshpass rpm -qa | grep sshpass如果没装,而且你手头有root权限、能访问本地yum源,可以安装:
yum install -y sshpass如果连软件源也用不了,就用expect来替代,下面会单独讲。
3.3 系统级替换与回滚步骤
用户级wrapper有一个软肋:如果OUI脚本在某个环节调用了/usr/bin/scp这种绝对路径,用户级的PATH scheme就失效了。我当时第一次重试,日志里仍然报scp错误,用strace跟踪OUI进程才发现它调用了绝对路径。这时候才决定动系统文件。
系统级操作分七步,每一步都不能省:
# 1. 备份原始scp cp -a /usr/bin/scp /usr/bin/scp.bak # 2. 编写wrapper脚本覆盖到/usr/bin/scp cat > /usr/bin/scp <<'EOF' #!/bin/bash # 仅用于安装Oracle 19c RAC期间临时替代,安装完成后必须恢复 exec /usr/bin/sshpass -p 'Grid@2025' /usr/bin/scp.bak "$@" EOF # 3. 加上执行权限,保持属主不变 chmod 755 /usr/bin/scp chown root:root /usr/bin/scp # 4. 检查SELinux context是否需要修复 restorecon -v /usr/bin/scp第4步容易被忽略,因为直接新写的文件context可能不对,导致即便有执行权限也被SELinux拦住。执行完restorecon之后,用OUI重试互信检查。
确认安装通过后,回滚操作是终局:
# 5. 恢复原始scp mv /usr/bin/scp.bak /usr/bin/scp # 或者 cp -a /usr/bin/scp.bak /usr/bin/scp # 6. 删除临时文件,清理密码痕迹 rm -f /home/grid/bin/scp sed -i '/\/home\/grid\/bin/d' ~/.bash_profile # 7. 验证scp功能恢复正常 scp ~/test.txt node2:~回滚操作我建议在Grid Infrastructure的root.sh和orainstRoot.sh跑完之后再做。虽然理论上装完GI之后OUI不再需要scp了,但保险起见,等到两个root脚本执行完成、集群正常启动之后再恢复。
3.4 依赖工具缺失时的备选:expect脚本
如果内网环境装不了sshpass,还有一条路:用系统自带的expect写交互脚本。expect在Linux 8.3上默认可能也没有,但有些基础环境会装上。检查:
which expect如果有,wrapper脚本可以改成罩住scp的交互行为:
#!/bin/bash # 文件路径: /usr/bin/scp # 用expect自动应答密码 exec expect -c " set timeout 30 spawn /usr/bin/scp.bak {*}\$argv expect { \"*yes/no*\" { send \"yes\r\"; exp_continue } \"*password:*\" { send \"Grid@2025\r\" } \"*Password:*\" { send \"Grid@2025\r\" } } expect eof "这个方案的好处是不装额外软件包,坏处是expect对scp的交互输出依赖比较强,不同OpenSSH版本提示语可能不一样,容易匹配不上。建议先用小文件手动测试几次,确认expect脚本稳定了再交给OUI用。
4. 其他靠谱替代方案与选型对比
4.1 手工配置互信后跳过自动互信
在真正去替换scp之前,其实还有一个非常容易被忽略的选项:OUI在ssh互信步骤时,如果你已经手工做好了互信,可以直接选择跳过“自动设置互信”的选项。
我记得gridSetup.sh界面里有个复选框,大致是“Set up SSH connectivity automatically”之类的字样。如果你把这个勾去掉,OUI就单纯验证现有互信,而不去做自动生成密钥、自动scp分发那套动作。既然我们的互信手动验证已经全部通过了,那只要它不再自动搞事,检查通常就能过。
这个方案比替换scp安全得多,也是我后来复盘时觉得应该优先尝试的。我当时没这么干是因为界面卡在检查结果上,重试按钮一直弹错,没注意到有跳过自动配置的勾选。建议卡在这里的朋友,先尝试这个方案,不行再上scp替换。
4.2 修改ssh客户端配置规避host key确认
如果日志明确指向host key确认问题,也就是“Host key verification failed”,还有更温和的办法:在grid用户的~/.ssh/config里写死对目标节点的策略。
cat > ~/.ssh/config <<'EOF' Host node1 node2 StrictHostKeyChecking no UserKnownHostsFile /dev/null LogLevel ERROR ConnectTimeout 10 EOF这个方法通过对客户端做配置,让ssh和scp在连接目标节点时不再要求host key确认,也不写入known_hosts,从而避免OUI在BatchMode下被交互提示卡死。它对系统文件完全无侵入,回滚也简单,删掉这个config文件即可。
它的局限性是:如果OUI日志显示失败原因根本不是host key确认,比如是scp输出解析或者算法协商失败,那这个配置就帮不上忙。
4.3 方案对比与选型建议
| 方案 | 复杂度 | 风险 | 适用场景 |
|---|---|---|---|
| 手工互信+跳过自动配置 | 低 | 低 | 绝大多数INS-06006 |
| 修改ssh客户端config | 低 | 低 | 明确为host key确认失败 |
| 临时替换scp(sshpass) | 中 | 高 | 手动互信通过但OUI自动逻辑不兼容 |
| 临时替换scp(expect) | 中 | 中 | 无法安装sshpass的受限环境 |
| 打OpenSSH补丁或调整sshd_config | 高 | 中 | 客户允许变更系统安全配置 |
我的建议是:第一优先手工互信+跳过自动配置;第二优先修改客户端config;最后才用替换scp。替换scp是救场用的,不是常规手段,它能解决“OUI自动逻辑与新版OpenSSH不兼容”这一类壳层问题,但也可能在安装过程中引发其他隐性故障,所以操作时一定要留好备份和回滚脚本。
5. RAC安装排障实录:常见问题速查
5.1 高频报错与排查方向
这次排障过程中,陆陆续续踩了几个典型的坑,我把它们整理成速查表,方便你遇到类似问题时快速对号入座。
| 日志关键字 | 可能原因 | 排查动作 |
|---|---|---|
| Permission denied (publickey) | authorized_keys权限/属主不对,或密钥算法不匹配 | 检查.ssh目录权限,确认属主是grid:oinstall,重新生成Ed25519或RSA密钥 |
| Host key verification failed | known_hosts指纹冲突 | 清理~/.ssh/known_hosts,或配置StrictHostKeyChecking no |
| Connection refused | sshd未启动或防火墙阻断 | 检查systemctl status sshd、firewall-cmd规则 |
| no matching key exchange method | crypto-policy禁用了旧算法 | 生成新密钥或修改系统crypto-policy后再试 |
| scp exited with code 1 | OUI与scp交互不兼容 | 手动跑scp确认功能正常,然后考虑临时替换scp方案 |
| Bad configuration option | ssh_config里有当前版本不认的参数 | 逐行检查~/.ssh/config,注释掉可疑项 |
我印象最深的是一次环境里报“no matching key exchange method”,当时在ssh命令后面手工加-o KexAlgorithms=diffie-hellman-group14-sha1能通,但OUI没法传这个参数,最后是重新生成了RSA密钥并调整了系统crypto-policy级别才解决。
5.2 安装前把互信一次配对的检查清单
吃了几次亏以后,我在RAC安装前的互信步骤收敛成了一个固定清单,每次按顺序执行,基本能避免90%的INS-06006:
- 确认
/etc/hosts配置正确,短主机名和FQDN同时写上,节点IP必须内网互通。 - 清理历史互信残留,删除
~/.ssh下的旧文件,或者完整备份后重新生成。 - 用grid用户和oracle用户分别执行
ssh-keygen -t rsa -b 2048 -N "",生成新密钥对。 - 在节点间互相执行
ssh-copy-id,包括localhost、短主机名、FQDN。 - 执行双向、多主机的BatchMode验证脚本,确认所有组合都免密成功。
- 检查
~/.ssh和authorized_keys权限,确认属主正确。 - 执行
restorecon -R -v ~/.ssh修复SELinux context,并getenforce确认状态。
5.3 一些碎碎念的实战心得
说实话,INS-06006报错最迷惑的地方在于:OUI的界面提示太笼统了,永远只告诉你“互信没建立”,但不告诉你具体是ssh失败还是scp失败,更不会告诉你它执行了什么命令。所以我的第一原则永远是找日志,而不是反复重试。确定失败阶段之后,再动手解决问题,否则就是在猜。
如果最后真的走到替换scp这一步,我提醒三个红线:一是必须备份原文件,备份完先验证备份文件可用;二是脚本里的密码必须严格限制读取权限,装完立刻清理;三是回滚动作放在集群启动成功之后执行,别图省事提前恢复,否则root.sh阶段可能又需要scp。
还有一个容易被忽略的心理因素:当你用偏方把安装流程推过去之后,一定要在业务空窗期做一次彻底的复盘,把当时的临时配置、临时脚本、残留密码全部清除干净。我当时装完以后,第二天还专门登录所有节点,逐个确认/usr/bin/scp恢复成了原始状态、~/.bash_profile里没有多余的PATH设置。这个动作看似多余,但能在将来某次安全审计时救你一命。
最后再分享一个小技巧
整个过程中让我最意外的是,真正卡住OUI的往往不是密钥或权限这类“硬配置”,而是软件交互层面的变化。OpenSSH每个版本都在调整输出和交互行为,而Oracle的cvu脚本里写死了对老版本的预期,这中间的空档就造成了大量莫名其妙的INS-06006。
如果你也遇到类似情况,建议先在测试环境里跑一遍strace -f -e trace=network,execve -o /tmp/oui_strace.log ./gridSetup.sh,看看OUI到底调了哪些ssh和scp命令、传给它们什么参数。有些时候,你会发现它调用了一个你完全没想到的命令,比如用rcp或者带特殊参数的scp -o SomeOption。那时候就能对症下药,而不是盲猜。
我个人的体会是:替换系统命令这种偏方,能用,但一定要清楚它的代价和边界。它救急能力很强,但绝不能当作长期方案留在机器上。装好RAC、集群正常跑起来之后,把系统恢复干净,再回头梳理OUI与OpenSSH版本差异,才是上策。