如何使用 Chef 在本地移动/复制文件

Posted

技术标签:

【中文标题】如何使用 Chef 在本地移动/复制文件【英文标题】:How to move/copy files locally with Chef 【发布时间】:2013-10-13 19:33:13 【问题描述】:

我还没有遇到可以在本地复制/移动文件的 Chef 资源。比如我想下载jetty hightide并解压。完成后,将所有文件复制到特定文件夹中,如下所示:

# mv /var/tmp/jetty-hightide-7.4.5.v20110725/* /opt/jetty/

顺便说一句,jettyhightide 解压缩后会为您提供一个文件夹,其余文件位于该文件夹内。因此unzip jetty-hightide-7.4.5.v20110725.zip -d /opt/jetty/ 没有用,因为它会创建一个目录/opt/jetty/jetty-hightide-7.4.5.v20110725/*,而我真正想要的是/opt/jetty/*。因此,我正在 Chef 中寻找本地复制/移动资源。

【问题讨论】:

您能帮我解决以下问题吗? ***.com/questions/39105976/mv-resource-in-chef/… 您说“复制所有文件”,但随后显示“mv”命令,该命令移动个副本 【参考方案1】:

我通过使用bash 资源使其工作,如下所示:

bash "install_jettyhightide" do
  code <<-EOL
  unzip /var/tmp/jetty-hightide-7.4.5.v20110725.zip -d /opt/jetty/
  mv /opt/jetty/jetty-hightide-7.4.5.v20110725/* /opt/jetty/
  cp /opt/jetty/bin/jetty.sh /etc/init.d/jetty
  update-rc.d jetty defaults
  EOL
end

但我真的希望有一种厨师的方式来做这件事。在本地复制/移动文件将是系统管理员需要做的最通用的任务。

【讨论】:

“厨师”的做事方式看起来更像@CAMOBAP 示例中的“每个目录”示例——为每个目录和每个文件生成一个资源。这实际上对性能来说很糟糕。您所做的实际上是正确的,并且是 bash 资源的用例。您可以添加 not_ifcreates 来检查是否正在创建 /etc/init.d/jetty/jetty.sh 以使其更具幂等性。 注意:chef-client 中现在有 archive_file 资源,它比大多数这些 roll-your-own-execute-resource 方法更好【参考方案2】:

您可以试试ark 食谱。这会为您提取文件,然后您会注意到 execute 资源。

【讨论】:

+1 我强烈推荐这本食谱。简化归档文件的处理。还支持源安装。 是的,我知道方舟。但仅将其用于复制/移动将是一种矫枉过正的做法。我的主要目的是复制/移动文件而不是安装它们 vi .tar/.zip 存档。我真的很想知道为什么 opscode 不考虑创建一种复制/移动文件的厨师方式。 是的,我有点同意。但是他们不能启动一个支持everything的产品。 Ark 也适用于简单的解包,即使没有 ./configure && make && make install dance。 现在在 chef-client 中内置了一个 archive_file 资源。【参考方案3】:

如何复制单个文件

第一种方式

我使用file 语句复制文件(编译时检查)

file "/etc/init.d/someService" do
  owner 'root'
  group 'root'
  mode 0755
  content ::File.open("/home/someService").read
  action :create
end

这里:

"/etc/init.d/someService" - 目标文件, "/home/someService" - 源文件

您也可以将::File.open("/home/someService").read 包装在lazy 块中

...
lazy  ::File.open("/home/someService").read 
...

第二种方式

用户remote_file 语句(运行时检查)

remote_file "Copy service file" do 
  path "/etc/init.d/someService" 
  source "file:///home/someService"
  owner 'root'
  group 'root'
  mode 0755
end

第三条路

你也可以使用 shell/batch

对于每个目录

Dir[ "/some/directory/resources/**/*" ].each do |curr_path|
  file "/some/target/dir/#Pathname.new(curr_path).basename" do
    owner 'root'
    group 'root'
    mode 0755
    content lazy  IO.read(curr_path, mode: 'rb').read 
    action :create
  end if File.file?(curr_path)
  directory "/some/target/dir/#File.dirname(curr_path)" do
    path curr_path
    owner 'root'
    group 'root'
    mode 0755
    action :create
  end if File.directory?(curr_path)
end

这只是想法,因为这个例子中的子路径没有被正确处理。

【讨论】:

很好的答案!我特别喜欢上面的“第一种方式”,因为如果不更改文件内容,它将不会更新文件。值得一提的是,如果源文件是由 Chef 管理的,那么 ::File.open 必须 包裹在一个惰性块中,否则 Chef 在编译时会找不到文件。 lazy 属性仅适用于 Chef >= 11.6, >= 10.28(我相信)。 需要指出的是,使用远程文件可以绕过 Chef 要求该文件在编译时存在的问题。 请补充说明remote_filefile的区别还在于file是在编译时执行的,而remote_file是在时执行的>运行时间。因此,当您需要在运行时处理文件时 - remote_file 是一个很好的解决方法。 请务必注意,对于二进制文件,您需要将其更改为IO.read(curr_path, mode: 'rb'),否则可能会损坏目标文件。 remote_file 对我有用,因为它允许我自动跟踪文件增量。谢谢!【参考方案4】:

我知道这个问题已经得到解答和讨论,但这是我在创建文件时使用的方法。

    首先将文件包含在说明书的文件/默认文件夹下 然后在您的食谱上使用 cookbook_file 资源

例如:

cookbook_file "/server/path/to/file.ext" do
  source "filename.ext"
  owner "root"
  group "root"
  mode 00600
  action :create_if_missing
end

来自厨师文档:https://docs.chef.io/resources/cookbook_file/

cookbook_file 资源用于从 将食谱中 files/ 目录的子目录复制到指定的 位于运行 chef-client 或 chef-solo 的主机上的路径。

【讨论】:

这篇文章是关于将目标机器上已经存在的文件移动到目标机器上的另一个位置。 cookbook_file 无法做到这一点。 cookbook_file 用于将文件从说明书复制到目标机器,而不是目标机器的本地。 我在 Ansible 上使用 copy 模块做了一些操作,谢谢。【参考方案5】:

在 CHEF 中本地复制文件

file "C:/Users/Administrator/chef/1.xml" 

do         --->       tar content lazy 



IO.read("C:/Users/Administrator/chef-repo/cookbooks/2.xml")

 -->src

action :create

end

【讨论】:

非工作代码,这个想法已经在上面的先前答案中)【参考方案6】:

除了您已经完成并接受它的方式之外,如果您只想像最初要求的那样运行一个命令(复制或移动),而不是运行一个命令块,那么您可以使用 @987654321 @资源:

execute "copy_core" do
    command "mv /var/tmp/jetty-hightide-7.4.5.v20110725 /opt/jetty"
    user "root"
end

也许这会帮助其他人在未来看到这个。

【讨论】:

这里警告:如果没有添加保护,这将在每次厨师运行时一次又一次地运行 mv,如果目标中的文件已被修改,任何更改都将丢失。 @Tensibai,他只是问如何在 Chef 中执行“mv”命令。这完全取决于你把这个块放在哪里。您可以随时在块中添加not_if File.exist?("/opt/jetty") ,这样如果它已经被复制就不会重做。 警告是针对此问题/答案的未来读者。 (解决 XY 问题并不总是最好的办法)【参考方案7】:

我实际上会使用类似以下的内容(注意“binread”),因为这适用于文本文件和二进制文件。使用“读取”会在二进制文件中产生令人惊讶的结果,特别是如果您同时使用 unix 和 windows 系统。

file destination do
  content IO.binread(source)
  action  :create
end

【讨论】:

这实际上非常重要,如果您使用默认读取方法,处理 Java Keystore 文件之类的文件将会中断。【参考方案8】:

如果您的配方已经绑定到 Windows,您可以使用嵌入式 PowerShell 脚本,如下所示:

# Copy files from "C:/foo/lib" to "C:/foo"
powershell_script "copy_lib" do
  code <<-EOH
    $ErrorActionPreference = "Stop"
      Get-ChildItem -Path "C:/foo/lib" -File | Foreach-Object 
        Copy-Item -Path $_.Fullname -Destination "C:/foo" -Force
      
  EOH
end

# Delete "C:/foo/lib" folder
powershell_script "delete_lib" do
  code <<-EOH
    $ErrorActionPreference = "Stop"
    Remove-Item -Path "C:/foo/lib" -Recurse
  EOH
end

【讨论】:

以上是关于如何使用 Chef 在本地移动/复制文件的主要内容,如果未能解决你的问题,请参考以下文章

将文件从 Chef 客户端节点复制到工作站

如何将文件从 HDFS 复制到本地文件系统

Vmware中如何让本地和虚拟机可以进行复制和粘贴操作?

ubuntu复制文件

如何在 python 中复制和移动另一个文件夹或目录? [复制]

如何把FTP中的文件复制到本地文件夹