像我在 Googleverse 中看到的许多其他人一样,我成为了陷阱的受害者File.exists?
,它当然会检查您的本地文件系统,而不是您要部署到的服务器。
我发现了一个使用 shell hack 的结果,例如:
if [[ -d #{shared_path}/images ]]; then ...
但这并不适合我,除非它被很好地包装在 Ruby 方法中。
有人优雅地解决了这个问题吗?
像我在 Googleverse 中看到的许多其他人一样,我成为了陷阱的受害者File.exists?
,它当然会检查您的本地文件系统,而不是您要部署到的服务器。
我发现了一个使用 shell hack 的结果,例如:
if [[ -d #{shared_path}/images ]]; then ...
但这并不适合我,除非它被很好地包装在 Ruby 方法中。
有人优雅地解决了这个问题吗?
在 capistrano 3 中,您可以执行以下操作:
on roles(:all) do
if test("[ -f /path/to/my/file ]")
# the file exists
else
# the file does not exist
end
end
这很好,因为它将远程测试的结果返回给您的本地 ruby 程序,您可以使用更简单的 shell 命令工作。
@knocte 是正确的,这capture
是有问题的,因为通常每个人都将部署定位到多个主机(并且捕获仅从第一个主机获取输出)。为了检查所有主机,您需要改为使用invoke_command
(这是capture
内部使用的)。这是一个示例,我检查以确保文件存在于所有匹配的服务器中:
def remote_file_exists?(path)
results = []
invoke_command("if [ -e '#{path}' ]; then echo -n 'true'; fi") do |ch, stream, out|
results << (out == 'true')
end
results.all?
end
请注意,默认情况下invoke_command
使用run
- 查看您可以传递的选项以获得更多控制权。
受@bhups 响应的启发,通过测试:
def remote_file_exists?(full_path)
'true' == capture("if [ -e #{full_path} ]; then echo 'true'; fi").strip
end
namespace :remote do
namespace :file do
desc "test existence of missing file"
task :missing do
if remote_file_exists?('/dev/mull')
raise "It's there!?"
end
end
desc "test existence of present file"
task :exists do
unless remote_file_exists?('/dev/null')
raise "It's missing!?"
end
end
end
end
可能你想做的是:
isFileExist = 'if [ -d #{dir_path} ]; then echo "yes"; else echo "no"; fi'.strip
puts "File exist" if isFileExist == "yes"
在 capistrano 中使用 run 命令(在远程服务器上执行 shell 命令)之前,我已经这样做了
例如,这里有一个 capistrano 任务,它将检查 database.yml 是否存在于 shared/configs 目录中,如果存在则链接它。
desc "link shared database.yml"
task :link_shared_database_config do
run "test -f #{shared_path}/configs/database.yml && ln -sf
#{shared_path}/configs/database.yml #{current_path}/config/database.yml ||
echo 'no database.yml in shared/configs'"
end