如果使用puppet不存在,我想创建目录结构/var/www/apps/example/current/public
。如果它已经存在,我不想清除目录的内容。我该怎么做呢?以下是我到目前为止:
file { "/var/www/apps/example/current/public":
owner => 'deploy',
group => 'users',
ensure => "directory",
purge => false,
recurse => true
}
这给了我
Cannot create /var/www/apps/example/current/public; parent directory /var/www/apps/example/current does not exist
答案 0 :(得分:19)
recurse
参数不允许您创建父目录。它用于递归地对目录内容和子目录强制执行owner
,mode
等属性值。
file { '/var/www':
owner => 'www-data',
recurse => true,
}
事实上,Puppet目前无法自动创建所有父目录。您应该将所有相关目录添加为资源。
file { [ '/var/www/apps',
'/var/www/apps/example',
'/var/www/apps/example/current',
'/var/www/apps/example/current/public', ]:
ensure => directory,
...
}
现有内容将保持不受干扰。无需传递purge
参数。
答案 1 :(得分:10)
exec { "Create ${mydir}":
creates => $mydir,
command => "mkdir -p ${mydir}",
path => $::path
} -> file { $mydir : }
最后一行是为了使其他资源(例如,在$mydir
内创建的文件)可以依赖于File[$mydir]
,就好像可以使用普通的旧file {}
块创建它一样,which it really should。
答案 2 :(得分:0)
木偶不会为你制作父目录,但你可以轻松创建一个类似文件的提供者。作为一个例子,我创建了一个自定义类型和提供程序,基本上运行' mkdir -p'在POSIX系统上:https://docs.puppetlabs.com/puppet/latest/reference/lang_namespaces.html
但是,有一个很好的理由,Puppet默认情况下不这样做。这是因为Puppet并不想对多个目录的权限负责,因为代理以root身份运行。如果您正在配置/ var / www或其他东西,这可能会很糟糕。
recuse file参数实际上是用来管理目录树参数:https://docs.puppetlabs.com/references/latest/type.html#file-attribute-recurse
您可以使用source =>创建目录树并提供服务。 '木偶:///'例如,将recurse设置为true,并且它将使用在所服务的目录树上设置的所有文件模式。
答案 3 :(得分:0)
我试图找到一个好的解决方案,但失败了。所以我自己想出了办法。希望它对其他人有用。
以下函数将生成父目录列表,然后我们可以使用该列表来构建父文件夹。第一个参数是用作搜索父目录的起点的路径;第二个参数是可选的,它用作终止点(不包括)来停止查找:
module Puppet::Parser::Functions
newfunction(:parentdirs, :type => :rvalue, :doc => <<-EOS
Build a list of all its parent directories.
EOS
) do |arguments|
raise(Puppet::ParseError, "parentdirs(): Wrong number of arguments " +
"given (#{arguments.size} for 1)") if arguments.size < 1
$dir_until = arguments.size > 1 ? arguments[1] : nil
$cur = File.dirname(arguments[0])
$result = []
begin
$result.unshift($cur)
$last = $cur
$cur = File.dirname($cur)
end while $cur != $last and !$cur.end_with?('/') and $cur != $dir_until
return $result
end
end
以下是如何使用它的示例:
$my_folder = '/var/www/apps/example/current/public'
$parent_dirs = parentdirs($my_folder, '/var/www/apps')
file { $parent_dirs:
ensure => 'directory',
owner => 'deploy',
group => 'users'
}
file { $my_folder:
ensure => 'directory',
owner => 'deploy',
group => 'anonymous'
}
上述代码将确保文件夹&#39; / var / www / apps / example&#39;和&#39; / var / www / apps / example / current&#39;在创建&var; / var / www / apps / example / current / public&#39;之前创建而&#39; / var / www / apps / example&#39;以上仍然没有被触及。
我只在Windows中测试过它。但它应该在Linux环境中工作。
这不太理想。但它比手动逐一列出所有父母更好。
答案 4 :(得分:0)
如果您使用&#34; define&#34;,您可以使用以下内容:
mymodule::recursive_dir { "My Directory" :
drive => "C:",
path => "/path/to/folder",
}
我定义&#34;定义&#34;在mymodule.rb中:
define mymodule::recursive_dir ($drive, $path) {
$folders = split($path, "/")
$folders.each |$index, $folder| {
$calculated_folder = inline_template("<%= @folders[0, @index + 1].join('/') %>")
$full_path = "${drive}${calculated_folder}"
if (! defined(File[$full_path]) and $full_path != $drive) {
file { $full_path :
ensure => directory,
}
}
}
}
这会拆分路径并创建每个目录,因为它会将路径重新组合在一起,确保不要尝试自己创建驱动器。
答案 5 :(得分:0)
Thank-you to AnthonyY.
I didn't know where to put the code for his function, and as a result of my research ended up rewriting the whole thing using the newer syntax, but keeping his logic.
It took me quite a while to work it all out, so I figured it would be good to post it back here. ...I would have just added it as a comment to his answer, but apparently I need 50 points to do that, not zero.
The code should be saved in it's own file inside your Puppet environment directory as follows:
lib/puppet/functions/parentdirs.rb
...so the full path would be something like this (on Ubuntu server 18.04, using the Puppet packages, not the repo ones):
/etc/puppetlabs/code/environments/testing/lib/puppet/functions/parentdirs.rb
...there seem to be other places you can put it, but this is what I did.
Notice that the file is .rb
, not .pp
(because it's Ruby code, not Puppet).
I got most of my information from https://puppet.com/docs/puppet/5.5/functions_ruby_overview.html and the sub-pages.
The usage is the same as the original function, and somewhat re-explained in the comments
# Returns an array of the parent directories to the given file or directory. This can then be passed to File to create the directory tree require for a dynamic path value.
# Parameter 2 is an optional, higher level of the same path. These higher level directories will not be in the array.
# Example 1: parameter 1 is '/var/www/mysite'; parameter 2 is not given; returns array ['/var', '/var/www']
# Example 2: parameter 1 is '/var/www/mysite'; parameter 2 is '/var'; returns array ['/var/www']
Puppet::Functions.create_function(:parentdirs) do
dispatch :parents do
required_param 'String', :target_dir
optional_param 'String', :dir_until
return_type 'Array'
end
def parents(target_dir, dir_until = '')
cur = File.dirname(target_dir)
result = []
begin
result.unshift(cur)
last = cur
cur = File.dirname(cur)
end while cur != last and !cur.end_with?('/') and cur != dir_until
return result
end
end
答案 6 :(得分:0)
这是做mkdir -p $(dirname $file_path)
的纯木偶解决方案
$file_path = '/tmp/foo/bar/bob.conf' # assumes file_path is Stdlib::Unixpath
# strip leading '/' then split and loop
$dirs = $file_path[1,-1].dirname.split('/').reduce([]) |$memo, $subdir| {
$_dir = $memo.empty ? {
true => "/${subdir}",
default => "${$memo[-1]}/${subdir}",
}
concat($memo, $_dir)
}
file {$dirs:
ensure => directory,
}