Ruby Net::SSH执行cockroach启动远程命令挂起无返回
问题根因
Net::SSH的exec!方法默认会阻塞等待,直到远程命令的标准输出、标准错误流全部关闭、命令返回退出码后才会继续向下执行。你在启动参数里加的--background只是CockroachDB自身的后台运行逻辑,但进程启动阶段不会立刻关闭从SSH会话继承的stdout/stderr文件描述符,导致会话一直卡着等待流关闭,表现为执行挂起。- 直接在命令末尾加
&虽然能让exec!立刻返回,但SSH会话执行完命令退出时,会给当前会话关联的所有后台进程发送SIGHUP挂断信号,CockroachDB还没完成初始化就被系统杀死,自然查不到运行中的进程。
可用解决方案
方案1:重定向流 + nohup 屏蔽信号(改动最小、最稳妥)
把CockroachDB启动命令的标准输入、输出、错误流全部和SSH会话断开,同时用nohup屏蔽会话退出时的SIGHUP信号,既不会阻塞exec!返回,进程也不会被会话退出信号杀死。
修改后的启动命令写法:
s = <<~CMD.squish sudo -S su root -c ' nohup cockroach start --advertise-addr=34.207.235.139:26257 --certs-dir=/home/ubuntu/certs --store=node0015 --listen-addr=172.31.17.244:26257 --http-addr=172.31.17.244:8080 --join=34.207.235.139:26257 --background --max-sql-memory=.25 --cache=.25 >> /var/log/cockroach.log 2>&1 < /dev/null & ' CMD
注意:必须把stdin重定向到
/dev/null、stdout/stderr重定向到日志文件,彻底断开进程和SSH会话流的关联,否则仍可能出现阻塞。
方案2:systemd托管进程(生产环境推荐)
不要直接通过SSH命令后台拉起进程,把CockroachDB配置成系统服务,启动时只需要调用systemctl命令即可,命令会在服务启动请求发出后立刻返回,进程生命周期完全由系统托管,不受SSH会话影响。
服务配置参考:
# /etc/systemd/system/cockroach.service [Unit] Description=CockroachDB node After=network.target [Service] User=root WorkingDirectory=/root ExecStart=/usr/local/bin/cockroach start --advertise-addr=34.207.235.139:26257 --certs-dir=/home/ubuntu/certs --store=node0015 --listen-addr=172.31.17.244:26257 --http-addr=172.31.17.244:8080 --join=34.207.235.139:26257 --max-sql-memory=.25 --cache=.25 Restart=always LimitNOFILE=65535 [Install] WantedBy=multi-user.target
对应的Ruby启动代码:
ssh.exec!('sudo systemctl daemon-reload') ssh.exec!('sudo systemctl start cockroach')
方案3:用Net::SSH异步接口替代exec!
如果不想修改启动命令,可以不用阻塞式的exec!,改用异步exec接口,等进程初始化完成后主动关闭通道,不需要等待所有流关闭:
ssh.exec("sudo -S su root -c 'cockroach start --advertise-addr=34.207.235.139:26257 --certs-dir=/home/ubuntu/certs --store=node0015 --listen-addr=172.31.17.244:26257 --http-addr=172.31.17.244:8080 --join=34.207.235.139:26257 --background --max-sql-memory=.25 --cache=.25;'") do |ch, stream, data| # 需要打印启动日志就保留下面这行,不需要可以删掉 print data if stream == :stdout end # 等待3秒让进程完成初始化,后续逻辑继续执行 sleep 3
额外避坑提示
- 你原有Ruby代码的证书备份行多写了一个右大括号:
mv /home/ubuntu/certs /home/ubuntu/certs.back.#{rand(1000000)}};,末尾多余的}会导致shell执行报错,记得删掉。 - CockroachDB启动需要几秒初始化时间,执行完启动命令后不要立刻查进程,至少等待3-5秒再校验运行状态。
内容的提问来源于stack exchange,提问作者LeandroS
相关产品推荐
相关产品推荐

