Отказано в разрешении на удаление SFTP

Я использую клиент SFTP для загрузки файлов с SFTP-сервера. Я могу успешно прочитать файл и сохранить его, но не могу удалить его с SFTP-сервера после того, как закончу его сохранение.

КОД

require 'net/sftp'

class Sftp
  def self.save
    Net::SFTP.start(somehost, ****, password: ****) do |sftp|
      sftp.dir.foreach("/files") do |entry|
        next unless entry.file?

        file_name = entry.name
        source_file = "/files/#{file_name}"
        destination_file = "tmp/#{file_name}"

        sftp.download!(source_file, destination_file)

        df = File.open(destination_file, "r")
        file_data = df.read

        # Some logic to utilise read file info. in variable "file_data"

        File.delete(df) # deleted from tmp
        sftp.remove!(source_file) # deleted from sftp server
      end
    end
  end
end

Когда строка sftp.remove!(source_file) выполняется, я получаю сообщение об ошибке, например:

"Net::SFTP::StatusException (3, \"отказано в доступе\")"

Разрешение для каталога files

drwxr-xr-x  2 root    root    4096 Dec 22 10:54 files

Разрешение для файлов в каталоге files:

drwxr-xr-x 2 root root   4096 Dec 22 10:54 .
drwxr-xr-x 4 root root   4096 Dec 18 15:29 ..
-rwxrwxrwx 1 root root 749199 Dec 18 14:39 a.pdf
-rwxrwxrwx 1 root root   7945 Dec 18 15:41 b.pdf
-rwxrwxrwx 1 root root   7945 Dec 22 10:54 c.pdf

ИЗМЕНИТЬ

Я заменил следующую строку кода

sftp.remove!(source_file)

с

sftp.send(:exec, "sudo rm /var/sftp/#{source_file}")

Теперь удаление работает, но только для первого файла. Затем цикл завершается без ошибок.

В чем может быть причина?


person Abhi    schedule 26.12.2017    source источник


Ответы (1)


Я предполагаю, что вы входите на удаленный хост как пользователь, отличный от root. Это верно?

Ваша проблема в том, что root является владельцем этих файлов на удаленном хосте, и как пользователь, отличный от root, вы не имеете права удалять их.

Если вы управляете удаленными файлами, вы можете захотеть сохранить их пользователем, отличным от root — тем, под чьим именем вы можете войти, чтобы удалить их, но тем, под которым другие не могут, при условии, что вы не хотите, чтобы другие могли для удаления файлов.

Если вы войдете на этот сервер как root, вы сможете удалить файлы.

Относительно этого кода:

df = File.open(destination_file, "r")
file_data = df.read
File.delete(df) # deleted from tmp

Это слишком сложный способ удаления файла. Вы читаете данные файла в file_data, но ничего с ним не делаете. Кроме того, нет необходимости открывать файл, чтобы удалить его — вы можете вызвать File.delete для спецификации файла, а не для объекта File.

person Keith Bennett    schedule 26.12.2017
comment
Да, вы правы, я захожу под другим пользователем. Во-вторых, я использую file_data, но я не публиковал этот код, так как он не имел отношения к контексту, я сосредоточен на удалении файла с SFTP-сервера. - person Abhi; 27.12.2017
comment
Мое главное намерение - удалить файл с SFTP-сервера, чтобы я больше его не читал. - person Abhi; 27.12.2017
comment
Кстати, Ruby предоставляет методы File.read и File.readlines, которые избавляют от необходимости явно открывать файл. - person Keith Bennett; 27.12.2017
comment
@Abhi Вы не ответили на мои предложения. У вас есть какие-либо вопросы о них? - person Keith Bennett; 27.12.2017
comment
Я попытался установить права доступа к файлам для локального пользователя вместо root, но это не сработало. Кроме того, я нашел этот пост немного полезным stackoverflow.com/a/1619146/2968762. Но мне пришлось использовать sftp.send(:exec, "rm full_path_to_#{source_file}"), потому что exec закрытый метод. И по неизвестной причине после удаления первого файла, из-за вышеприведенного кода, цикл обрывается без ошибки. Я не знаю. - person Abhi; 28.12.2017
comment
На этом этапе было бы полезно, если бы вы разместили свой код там, где мы могли бы его увидеть. Для этого отлично подходит гист (отдельный фрагмент кода или текста, часто содержащий содержимое файла) на Github; он кодирует ваш код цветом и сохраняет историю. Если у вас нет идентификатора Github, я рекомендую зарегистрироваться, а затем перейти на gist.github.com и добавить суть. - person Keith Bennett; 28.12.2017
comment
Если вы собираетесь выполнять код на этом сервере, я рекомендую использовать ssh, так как это одно из его предназначений (в отличие от sftp). Обычно ssh и sftp помещают вас в домашний каталог пользователя, под которым вы вошли в систему. Вам даже не нужна библиотека, если в вашей ОС есть команды ssh и sftp; вы можете создать и выполнить внешнюю команду, такую ​​как `ssh user@host rm #{filespec_to_delete}`; хотя в целом использование библиотеки Ruby лучше, когда это возможно. - person Keith Bennett; 28.12.2017
comment
Что касается моего комментария о сути, размещение кода здесь, в Stack Overflow, лучше, когда это возможно. Я упомянул суть, если это много кода. - person Keith Bennett; 28.12.2017