Ruby 使用puppet Facter返回多个自定义事实

Ruby 使用puppet Facter返回多个自定义事实,ruby,puppet,facter,Ruby,Puppet,Facter,我试图将用户添加到系统中作为傀儡事实。我不是ruby程序员,下面的代码正确地生成了用户,但是他们的uid是相同的(密码文件中最后一个条目的uid)。如果uid超出范围,我会预期出现未知符号错误,如果Facter.add最后只被调用一次,我会预期只有一个用户,即最后一个用户,与uid相同。我不明白一个怎么可以迭代而另一个却不这么做 File.open("/etc/passwd", "r") do |passwords| while pw_entry = passwords.gets u

我试图将用户添加到系统中作为傀儡事实。我不是ruby程序员,下面的代码正确地生成了用户,但是他们的uid是相同的(密码文件中最后一个条目的uid)。如果uid超出范围,我会预期出现未知符号错误,如果Facter.add最后只被调用一次,我会预期只有一个用户,即最后一个用户,与uid相同。我不明白一个怎么可以迭代而另一个却不这么做

File.open("/etc/passwd", "r") do |passwords|
  while pw_entry = passwords.gets
    user, pw, uid, gid, gecos, home, shell = pw_entry.split(/:/)

    Facter.add("user_" + user) do
      setcode do
        uid
      end
    end
  end
end
在闲逛时,我发现其他人有着几乎相同的问题,这就是解决方案(对我来说也很有效):


…但是我不明白有什么区别。它的行为就像对Facter.add块的调用得到缓冲,并在循环结束时一次运行,Etc将所有passwd加载到数组中,因此user.uid索引和计时无关。但是,对于过程语言来说,这是一件奇怪的事情…

你说得对:

File.open("/etc/passwd", "r") do |passwords|
  while pw_entry = passwords.gets
      user, pw, uid, gid, gecos, home, shell = pw_entry.split(/:/)
      print uid
  end
end
几乎相当于:

require 'etc'
Etc.passwd { |user|
  print uid
}
事实上,这两个ruby片段将产生完全相同的结果

唯一的区别是,最后一个方法使用另一种迭代passwd文件的方式。它使用一个闭包,该闭包接收一个参数
user
作为输入。此
用户
是匿名函数范围内唯一的
用户

现在,关于您的两种方法之间的差异问题:

当您引用ruby闭包中不属于闭包本身的变量(即外部变量)时,对该(外部)范围内该变量符号的引用存储在闭包的代码中。由于在第一种方法中,您在相同的范围内重用相同的符号,
uid
在添加所有事实后调用闭包的代码时,引用
uid
的最后一个已知值。这就是我们所知道的

解决此问题的一种方法是让每个
uid
存在于自己的范围内

def addUserFact(passwd_entry)
  user, pw, uid, gid, gecos, home, shell = passwd_entry.split(/:/)   
  Facter.add("user_" + user) do
    setcode do
      uid
    end
   end
end

File.open("C:/cygwin/etc/passwd", "r") do |passwords|
  while pw_entry = passwords.gets
    addUserFact(pw_entry)
  end
end
def addUserFact(passwd_entry)
  user, pw, uid, gid, gecos, home, shell = passwd_entry.split(/:/)   
  Facter.add("user_" + user) do
    setcode do
      uid
    end
   end
end

File.open("C:/cygwin/etc/passwd", "r") do |passwords|
  while pw_entry = passwords.gets
    addUserFact(pw_entry)
  end
end