简体   繁体   English

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

[英]Returning multiple custom facts with puppet Facter

I'm trying to add the users on a system as puppet facts. 我试图将用户添加到系统中作为p事实。 I'm not a ruby programmer and the following code properly generates the users, but their uid is all the same (the uid of the last entry in the password file). 我不是一个红宝石程序员,下面的代码可以正确生成用户,但是他们的uid都是相同的(密码文件中最后一个条目的uid)。 If uid was out of scope, I would expect an unknown symbol error, if Facter.add was only getting called once at the end, I would expect there to be only one user, the last one, same as the uid. 如果uid超出范围,那么我会期望出现未知的符号错误,如果Facter.add在最后只被调用一次,则我希望只有一个用户,最后一个与uid相同。 I don't understand how one can iterate without the other one doing so as well... 我不明白一个人如果没有另一个人也不能如此反复...

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

In poking around, I found someone else with nearly the identical problem and this was the solution (which did work for me as well): 在四处寻找时,我发现其他人几乎有相同的问题,这就是解决方案(对我也很有效):

require 'etc'

Etc.passwd { |user|

    Facter.add("user_" + user.name) {
      setcode {
        user.uid
      }
    }
}

...however I don't understand what the difference is. ...但是我不明白有什么区别。 It acts like calls to the Facter.add block are getting buffered and run all at once at the end of the loop, and Etc loaded up all of passwd so user.uid indexes into the array and timing is irrelevant. 它就像对Facter.add块的调用被缓冲并在循环结束时一次运行一样,并且Etc加载了所有passwd,因此user.uid索引进入数组,并且计时无关紧要。 That would be a bizarre thing for a procedural language to be doing though... 但是,对于程序语言而言,这将是一件奇怪的事情。

You are right to say the following: 您正确地说以下话:

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

is nearly equivalent to: 几乎等同于:

require 'etc'
Etc.passwd { |user|
  print uid
}

In fact these two ruby snippets will produce exactly the same result. 实际上,这两个红宝石片段将产生完全相同的结果。

The only difference is that the last method uses another way of iterating through the passwd file. 唯一的区别是,最后一种方法使用另一种遍历passwd文件的方式。 It uses a closure which receives a parameter user as an input. 它使用一个闭包来接收参数user作为输入。 This user is the only user that exists in the scope of the anonymous function. user是匿名功能范围内的唯一user

Now, about your problem with the difference between your two methods: 现在,关于您的两种方法之间的差异问题:

When you reference variables inside a ruby closure that don't belong to the closure itself (ie outer variables) the reference to the symbol of that variable within that (outer) scope is stored inside the closure's code. 当您在ruby闭包内部引用不属于该闭包本身的变量(即外部变量)时,对该变量的符号在(外部)范围内的引用将存储在闭包的代码内。 Since in the first method you reuse the same symbol within the same scope, uid references the last known value of uid when the closure's code is called after all facts have been added. 由于在第一个方法,你重复使用相同的范围内,同样的符号, uid引用的最后已知值uid时已添加的所有事实后封闭的代码被调用。 This is known as the outer variable trap . 这称为外部变量陷阱

One way to work around this problem is by having each uid exist in its own scope. 解决此问题的一种方法是让每个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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM