这是我在厨师食谱中的Ruby:
# if datadir doesn't exist, move over the default one
if !File.exist?("/vol/postgres/data")
execute "mv /var/lib/postgresql/9.1/main /vol/postgres/data"
end
结果是:
Executing mv /var/lib/postgresql/9.1/main /vol/postgres/data
mv: inter-device move failed: `/var/lib/postgresql/9.1/main' to `/vol/postgres/data/main'; unable to remove target: Is a directory
我知道/vol/postgres/data
存在并且是一个目录,但它仍然尝试执行mv
。为什么呢?
可以肯定的是,在同一台机器上运行以下独立的Ruby脚本会输出“nomv”:
if !File.exist?("/vol/postgres/data")
print "mv"
else
print "nomv"
end
答案 0 :(得分:9)
我之前并不那么专注,我以为你正在检查not_if
或only_if
块中是否存在文件。您的问题类似于此问题中的问题:Chef LWRP - defs/resources execution order。请参阅那里的详细解释。
你的问题是!File.exist?("/vol/postgres/data")
代码会立即被执行 - (因为它是纯粹的红宝石),在执行任何资源之前,因此在安装postgress之前。
解决方案应该是将检查移至not_if
阻止。
execute "mv /var/lib/postgresql/9.1/main /vol/postgres/data" do
not_if { File.exist?("/vol/postgres/data") }
end
答案 1 :(得分:5)
使用此代码块:
execute "name" do
command "mv /var/lib/postgresql/9.1/main /vol/postgres/data"
not_if { ::File.exists?("/vol/postgres/data")}
end
或
您也可以使用
execute "name" do
command "mv /var/lib/postgresql/9.1/main /vol/postgres/data"
creates "/vol/postgres/data"
end
仅当文件系统中不存在/vol/postgres/data
时,两者都将运行该命令。
如果你想运行命令块,那么使用类似的东西,
bash 'name' do
not_if { ::File.exists?("/vol/postgres/data") }
cwd "/"
code <<-EOH
mv /var/lib/postgresql/9.1/main /vol/postgres/data
#any other bash commands
#any other bash commands
EOH
end
答案 2 :(得分:1)
我用
!::File.directory?(::File.join('path/to/directory', 'directory_name'))
答案 3 :(得分:1)
要测试目录是否存在,您可以使用File.exists
的等效Dir.exist?("/vol/postgres/data")
:
not_if
正如其他人指出的那样,你应该使用only_if
或execute "mv /var/lib/postgresql/9.1/main /vol/postgres/data" do
not_if { Dir.exist?("/vol/postgres/data") }
end
而不是使用普通的Ruby条件,所以我不打算再解释一下。详情请查看Draco的答案。
{{1}}
答案 4 :(得分:0)
我会用, !File.directory?("/vol/postgres/data")
答案 5 :(得分:0)
您是在rails应用程序中调用它还是独立的ruby文件。
如果您正在使用rails应用程序。
然后,
<强> File.exist?( “#{Rails.root} / UR-文件路径”)强>
Ex:File.exist?(“#{Rails.root} / public / ur-filename”)
您需要从root指定特定的文件路径。
答案 6 :(得分:0)
快速谷歌搜索引发了很多关于“设备间移动失败”的答案。 Ruby只是传递操作系统返回的错误;这与测试文件无关,正如其他答案所示。
只要我们理解这个概念,这有点简单。 mv或move实际上并不将文件/文件夹移动到同一设备中的另一个位置,它只是替换设备第一个扇区中的指针。将移动指针(在inode表中),但实际上没有任何内容被复制。只要您保持在同一媒体/设备中,这将有效。
现在,当您尝试将文件从一个设备移动到另一个设备(/ dev / sda1到/ dev / sdb1)时,您将遇到“设备间移动失败,无法移除目标:是目录”错误。当mv必须实际将数据移动到另一个设备时,会发生这种情况,但是无法删除inode /指针,因为如果它确实没有数据可以回退,如果没有,那么mv操作并不是真的完整因为我们最终会得到源数据。如果你这样做该死的,如果你不这样做该死的话,所以明智的做法就不要这么做!
在这种情况下,cp是最好的。复制数据,然后手动删除源。
更好的解决方案可能是使用ruby工具而不是执行shell命令,因为它说If file and dest exist on the different disk partition, the file is copied then the original file is removed.
FileUtils.mv '/var/lib/postgresql/9.1/main', '/vol/postgres/data'