如何使用 Chef 递归更改目录上的所有者和组?

Posted

技术标签:

【中文标题】如何使用 Chef 递归更改目录上的所有者和组?【英文标题】:How to recursively change the owner and group on a directory with Chef? 【发布时间】:2014-07-18 06:31:59 【问题描述】:

resource_directory 只有 2 个可用的操作:createdelete

我需要递归更新目录的所有者和组。

我该怎么做?

使用简单的resource_execute?

execute "chown-data-www" do
  command "chown -R www-data:www-data /var/www/myfoler"
  user "root"
  action :run
end

【问题讨论】:

您是在创建目录还是只是在更改现有目录? resource_directory将让您设置mode,您可以使用它来设置粘性位并使其下的所有内容都继承自该位。另请参考:tickets.opscode.com/browse/CHEF-690 关于为什么他们从未添加递归 chmod。您的执行语句可能是最简单的方法 不确定是覆盖目录还是只是更改权限,但您可以使用directory 资源和recursive true 选项。 @jarsever 无关用户,类似问题。使用目录资源,递归操作不会编辑目录中所有文件的所有者。文档说只有叶节点是 chowned。 @jarsever 递归选项是指定如果需要也创建父目录 【参考方案1】:

您可以将默认操作设置为空,然后将可能搞砸的资源通知烫发修复者:

execute "chown-data-www" do
  command "chown -R www-data:www-data /var/www/myfoler"
  user "root"
  action :nothing
end

resource "that may screw up perms" do
  stuff "one two three"
  notifies :run, execute "chown-data-www"
end

如果父文件夹已经是正确的权限,则可以使用更多选项来执行操作:运行但不是。您可以更改它以包含更深/有问题的文件/目录,或使用类似于this的查找命令

execute "chown-data-www" do
  command "chown -R www-data:www-data /var/www/myfoler"
  user "root"
  action :run
  not_if '[ $(stat -c %U /var/www/myfolder) = "www-data" ]'
end

编辑:修复以反映下面的评论

【讨论】:

在最后一节中,我猜你的意思是:not_if "stat -c %U /var/www/myfolder |grep www-data"【参考方案2】:

https://***.com/a/28283020/11822923

Answer 满足我的需要,但 grep 命令存在问题,即使用户是 apache2apach,grep 退出代码将是 0,但我需要用户完全是 @987654328 @(CentOS 7.7 上的 Apache Web 服务器用户)。

这是我的食谱:

node["apache"]["sites"].each do |sitename, data|
  document_root = "/content/sites/#sitename"

  directory document_root do
    action :create
    mode "0755"
    recursive true
    owner "apache"
    group "apache"
  end

  execute "chown_to_apache_user" do
    command "chown -R apache:apache /content"
    user "root"
    action :run
    not_if '[ $(stat -c %U /content/) = "apache" ]'
  end

  template "/etc/httpd/conf.d/#sitename.conf" do
    source "vhost.erb"
    mode "0644"
    variables(
      :document_root => document_root,
      :port => data["port"],
      :domain => data["domain"]
    )
    notifies :restart, "service[httpd]"
  end

end

比较:

P.S.:还要检查group

node["apache"]["sites"].each do |sitename, data|
  document_root = "/content/sites/#sitename"

  directory document_root do
    action :create
    mode "0755"
    recursive true
    owner "apache"
    group "apache"
  end

  execute "chown_to_apache_user" do
    command "chown -R apache:apache /content"
    user "root"
    action :run
    not_if '[ $(stat -c %U /content/) = "apache" ] && [ $(stat -c %G /content/) = "apache" ]'
  end

  template "/etc/httpd/conf.d/#sitename.conf" do
    source "vhost.erb"
    mode "0644"
    variables(
      :document_root => document_root,
      :port => data["port"],
      :domain => data["domain"]
    )
    notifies :restart, "service[httpd]"
  end

end

【讨论】:

【参考方案3】:

我会使用带有action :create 的普通资源目录。 根据文档:

:create
Default. Create a directory. If a directory already exists (but does not match), update that directory to match

https://docs.chef.io/resource_directory.html

【讨论】:

【参考方案4】:

如果这是一次性修复权限,您的最短路径可能只是刀 ssh。 (我只是在自己的搜索中结束后才这样做的。)

knife ssh 'name:*' "sudo chown -R $user:$group /full/path/to/directory"

knife ssh 'name:*' "sudo chmod -R 770 /full/path/to/directory"

如果我从头开始设置,我想我需要设置directory 路径和一行适当的权限(注意:将权限显式应用于路径中的每个父级)

%w[ /foo /foo/bar /foo/bar/baz ].each do |path|
  directory path do
    owner 'root'
    group 'root'
    mode '0755'
  end

然后将每个 file 创建为一个食谱文件。

【讨论】:

【参考方案5】:

我们可以编写一个厨师资源,它遍历您的目录层次结构并为它找到的每个文件创建一个文件或目录资源,然后将其设置为管理这些文件的所有者和组。但是,您不会喜欢这样,因为如果您在该目录中有一千个文件,那么您将获得一千个厨师资源,并且您的收敛速度会很慢。

如果你愿意,事实上,你可以推出自己的代码,它的作用类似于我在票证 tickets.opscode.com/browse/CHEF-690 中写的,@name 引用了它,但我不推荐它。

如果您试图防止“篡改”并修复用户和组属性的随机损坏,那么您的解决方案可能是正确的。您将始终在每次厨师收敛时执行该命令,并且资源将始终显示为正在更新,但该命令将尽可能快地运行(chown -R 基本上是收敛和幂等的,因为它在尝试设置权限之前检查权限)。你不会得到关于固定烫发的报告,这是唯一的缺点。

如果您只是尝试在构建服务器时修复一次权限,那么您应该在其中抛出一个 not_if 条件来检查根目录是否具有正确的权限,您不会每次都运行它。这将为您提供幂等行为,并且不会在每次运行时都执行该命令,但不利的一面是,如果该目录结构下的某个文件的权限将来被某人或某事破坏,那么它将不会得到纠正。

这里有一个单一资源的可能用例,其行为类似于 chown -R 然后报告它修复的内容(以及已更改权限的文件数组),这对于 SOX 和 PCI-DSS 报告等情况很有用,但是我们目前不涉及该用例。

tl;dr 是你的解决方案很好,如果你喜欢,你可以添加一个 not_if 保护

【讨论】:

您可以运行 chown--verbose 以列出它正在执行的所有操作(更改或已经正确的“保留”所有权)。 与 chmod 相同,您可以拨打 --verbose 以获取所有更改的列表。我想通过一个相当基本的正则表达式,您可以很好地处理chownchmod 输出语法,以便报告/测试权限的应用,因为它们非常相似。 我想知道使用本机平台工具会比尝试针对每个平台的文件权限怪癖和 ACL 等优化 Ruby 快多少?

以上是关于如何使用 Chef 递归更改目录上的所有者和组?的主要内容,如果未能解决你的问题,请参考以下文章

如何按名称更改目录的用户和组权限?

如何更改linux文件目录拥有者及用户组

如何使用 Chef 更改文件?

在Linux系统中,如何更改文件的访问权限

Linux常用命令——chown

如何取消Access 用户和组权限