Reputation: 44114
This is my piece of Ruby in a Chef recipe:
# 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
The result is:
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
I know that /vol/postgres/data
exists and is a directory, yet it still attempts to execute the mv
. Why?
Just to be sure, running the following standalone Ruby script on the same machine outputs "nomv":
if !File.exist?("/vol/postgres/data")
print "mv"
else
print "nomv"
end
Upvotes: 5
Views: 21184
Reputation: 25451
To test if a directory exists you can use an equvivalent of File.exists
which is Dir.exist
:
Dir.exist?("/vol/postgres/data")
As others pointed out, you should use not_if
or only_if
instead of using plain Ruby condition, so I'm not going to explain it again. Check Draco's answer for details.
execute "mv /var/lib/postgresql/9.1/main /vol/postgres/data" do
not_if { Dir.exist?("/vol/postgres/data") }
end
Upvotes: 1
Reputation: 2822
Use this block of code :
execute "name" do
command "mv /var/lib/postgresql/9.1/main /vol/postgres/data"
not_if { ::File.exists?("/vol/postgres/data")}
end
OR
you can also use
execute "name" do
command "mv /var/lib/postgresql/9.1/main /vol/postgres/data"
creates "/vol/postgres/data"
end
Both will run the command only if /vol/postgres/data
is not present in the file system.
If you want to run block of commands then use something like this,
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
Upvotes: 5
Reputation: 10953
I use
!::File.directory?(::File.join('path/to/directory', 'directory_name'))
Upvotes: 1
Reputation: 21226
I was not so attentive earlier, I thought you are checking for file existence in not_if
or only_if
block. Your problem is similar to the one in this question: Chef LWRP - defs/resources execution order. See the detailed explanation there.
Your problem is that !File.exist?("/vol/postgres/data")
code gets executed straight away - (because it's pure ruby), before any resource is executed and thus before the postgress is installed.
The solution should be to move the check to not_if
block.
execute "mv /var/lib/postgresql/9.1/main /vol/postgres/data" do
not_if { File.exist?("/vol/postgres/data") }
end
Upvotes: 9
Reputation: 26979
A quick google search turns up a lot of answers regarding "inter-device move failed". Ruby is just passing along the error returned by the operating system; this has nothing to do with testing the file as the other answers indicate.
This is somewhat simple as long as we understand the concept. mv or move does not actually move the file/folder to another location within the same device, it merely replaces the pointer in the first sector of your device. The pointer (in inode table) will be moved, but nothing is actually being copied. This will work as long as you stay within the same media/device.
Now, when you try to move files from one device to another (/dev/sda1 to /dev/sdb1) you will run into “inter-device move failed, unable to remove target: Is a directory” error. This happens when mv has to actually move your data to another device, but cannot remove the inode/pointer, because if it did then there will be no data to fall back to, and if it didn’t then mv operation is not really complete because we will end up with data in source. Damned if you do and damned if you don’t, so it’s wise not to do it to begin with!
In such situation cp is best. Copy your data over and then remove your source manually.
A better solution might be to just use ruby tools instead of executing a shell command, since it says 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'
Upvotes: 0
Reputation: 224
Are you calling it within your rails application or it is a standalone ruby file.
If you are doing in your rails app.
Then,
File.exist?("#{Rails.root}/ur-file-path")
Ex: File.exist?("#{Rails.root}/public/ur-filename")
You need to specify the particular file path from root.
Upvotes: 0