Ruby实现Chef Knife后台并行查询并获取结果(不显示标准输出)
嘿,我看你是想把Chef Knife的角色和环境查询放到后台并行执行,解决Windows下查询耗时久的问题,但现有代码没达到预期效果对吧?我来帮你捋清楚问题所在,再给你调整后的可行方案。
先说说你现有代码的问题
你当前的代码里,chef_role = knife search role ':' -i...和chef_env = knife search environment '*' -i...这两行已经在主线程里同步执行完了,后面的线程只是引用已经计算好的变量,等于线程啥实际的查询工作都没做,自然实现不了并行。而且线程块里的逻辑只是返回search变量,完全没触发新的查询操作。
修正后的并行实现代码
下面是调整后的代码,真正让两个Knife查询在后台并行执行,同时不阻塞主线程处理用户输入:
# 启动两个后台线程,分别执行角色和环境的Knife查询并处理结果 role_thread = Thread.new do begin # 执行查询并捕获输出,2>&1确保错误信息也能被捕获 search_result = `knife search role '*:*' -i 2>&1` if $?.success? # 检查命令执行是否成功 search_result.split.map { |item| { name: item } }.sort_by! { |obj| obj[:name] } else puts "角色查询失败:#{search_result}" [] # 返回空数组避免后续逻辑报错 end rescue => e puts "角色查询发生异常:#{e.message}" [] end end env_thread = Thread.new do begin search_result = `knife search environment '*' -i 2>&1` if $?.success? search_result.split.map { |item| { name: item } }.sort_by! { |obj| obj[:name] } else puts "环境查询失败:#{search_result}" [] end rescue => e puts "环境查询发生异常:#{e.message}" [] end end # 这里可以先处理用户的其他输入,完全不会被查询阻塞 puts "请输入你的项目名称:" project_name = gets.chomp # 当需要用到角色和环境结果时,等待线程完成并获取结果 chef_role = role_thread.value chef_env = env_thread.value # 后续逻辑:让用户从查询结果中选择 puts "\n可用角色列表:" chef_role.each_with_index do |role, idx| puts "#{idx + 1}. #{role[:name]}" end puts "\n可用环境列表:" chef_env.each_with_index do |env, idx| puts "#{idx + 1}. #{env[:name]}" end
关键逻辑说明
- 线程的正确用法:每个线程单独执行Knife查询和结果处理,两个查询会并行运行,大大节省总耗时。
Thread#value方法:这个方法会自动等待线程执行完成,并返回线程块的最终结果,比手动调用join再取结果更简洁。- 错误处理:加入了
begin...rescue和命令执行状态检查,避免Knife命令出错导致整个程序崩溃,同时能给出明确的错误提示。 - 非阻塞主线程:启动线程后,主线程可以先处理用户的其他输入(比如项目名称),等需要用到角色/环境数据时再等待线程结果,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Stromweld
相关产品推荐
相关产品推荐

