При запуске rackup в качестве демона File.expand_path возвращает / вместо папки проекта

Я не уверен, что я что-то не так сделал в некоторых файлах конфигурации. Когда я бегу rackup -D, делая это:

File.expand_path(__FILE__)

на самом деле возвращается /file.rb, И добавление File.dirname как-то возвращается /, Так что теперь весь мой код загрузки файлов не работал, поскольку он пытается посмотреть в / каталог, а не каталог проекта.

Это не произойдет, если я удаляю -D вариант. Возвращает полный путь /home/blablabla/stuff/file.rb

Образец кода:

test.rb:

require 'rubygems' if RUBY_VERSION <= '1.8.7'
require 'sinatra'

get '/expdir' do
  File.expand_path(File.dirname(__FILE__))
end

get '/exp' do
  File.expand_path(__FILE__)
end

get '/file' do
  __FILE__
end

get '/dirname' do
  File.dirname(__FILE__)
end

get '/dir' do
  Dir.entries(File.expand_path(File.dirname(__FILE__))).to_s
end

config.ru:

require 'test.rb'

run Sinatra::Application

Выполнил это с rackup -p 4567 и смотрел, как он возвращает правильные значения. Выполнил это с rackup -p 4567 -D и смотрел, как он возвращает неправильные значения.

1 ответ

Решение

Rack действительно меняет рабочий каталог на / когда запускается как демон.

В Ruby 1.8.7, __FILE__ в обязательном файле относится к пути, используемому для загрузки файла, который может быть относительным путем из текущего рабочего каталога процесса. Однако это значение не обновляется, если рабочий каталог изменяется позже, например, с помощью вызова Dir.chdir,

File.expand_path расширяет относительные пути к файлам относительно рабочего каталога. Так что в этом случае File.expand_path(__FILE__) приводит к путям относительно корня, но значение __FILE__ относительно исходного рабочего каталога, что дает неверный результат.

В Ruby 1.9.2 и 1.9.3, __FILE__ в обязательном файле указывается абсолютный путь к файлу, поэтому такой проблемы не возникает.

Один из способов исправить это в Ruby 1.8.7 - использовать абсолютный путь, когда требуется файл приложения. Изменить линию require 'test.rb' в вашем config.ru чтобы:

require File.expand_path('../test', __FILE__)

Теперь ссылки на __FILE__ будет абсолютным, поэтому не повлияет на изменение рабочего каталога при демонизации.

Если ваше приложение более сложное, с большим количеством файлов, лучше настроить путь загрузки. Например, вы могли бы поставить все свои .rb файлы в lib/ каталог, то в вашем config.ru добавлять:

$LOAD_PATH.unshift(File.expand_path '../lib', __FILE__)

Затем вы можете просто требовать свои файлы, не беспокоясь об относительных путях.

Другие вопросы по тегам