1

I'm using SFTP client for fetching files froma SFTP server. I'm able to successfully read the file and store it, but I'm unsable to delete it from SFTP server after I'm done saving it.

CODE

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

When the line sftp.remove!(source_file) is executed, I get error like:

"Net::SFTP::StatusException (3, \"permission denied\")"

Permission for files directory

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

Permission for files inside the files directory:

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

EDIT

I replaced the following line of code

sftp.remove!(source_file)

with

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

Now, the removal works, but only for the first file. Then the loop exits without any error.

What may be the reason?

Abhi
  • 4,123
  • 6
  • 45
  • 77

1 Answers1

1

I'll assume you are logging in to the remote host as a user other than root. Is this correct?

Your problem is that root is the owner of those files on the remote host, and as a user other than root you are not authorized to delete them.

If you are in control of the remote files, you might want to save them by a user other than root -- one whom you can log in as to delete them but one whom others cannot, assuming you don't want others to be able to delete files.

If you log in to that server as root, you should be able to delete the files.

Regarding this code:

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

This is an overly complicated way to accomplish deleting the file. You are reading the file's data into file_data but not doing anything with it. Also, there is no need to open a file to delete it -- you can call File.delete on a filespec rather than a File object.

Keith Bennett
  • 4,722
  • 1
  • 25
  • 35
  • Yes, you are right, I'm logging in with different user. Secondly, I do use `file_data`, but I didn't post that code as it was not relevant to the context, my focus is to delete file from SFTP server. – Abhi Dec 27 '17 at 06:44
  • My main intention is to delete the file from SFTP server so that I don't read it again. – Abhi Dec 27 '17 at 06:46
  • 1
    By the way, Ruby provides `File.read` and `File.readlines` methods that eliminate the need to explicitly open the file. – Keith Bennett Dec 27 '17 at 12:27
  • @Abhi You did not address my suggestions. Do you have any questions about them? – Keith Bennett Dec 27 '17 at 12:28
  • I tried to set the permission of the files with the local user instead of **root**, but it didn't work. Also, I found this post bit helpful https://stackoverflow.com/a/1619146/2968762. But, I had to use `sftp.send(:exec, "rm full_path_to_#{source_file}")`, because **exec** a private method. And for some unknown reason after removing the first file, due to the above code, the loop breaks out without error. I'm clueless. – Abhi Dec 28 '17 at 11:58
  • It would be helpful at this point for you to put your code up where we could see it. Using a gist (a single fragment of code or text, often containing the contents of a file) on Github is great for this; it color codes your code, and keeps history. If you don't have a Github id, I recommend registering for one, and then go to gist.github.com and adding a gist. – Keith Bennett Dec 28 '17 at 13:07
  • If you are going to execute code on that server, I recommend using `ssh`, as that's one of its intended purposes (unlike sftp). Normally, `ssh` and `sftp` will normally put you in the home directory of the user with which you've logged in. You don't really even need a library if your OS has `ssh` and `sftp` commands; you can build and execute an external command such as ` ``ssh user@host rm #{filespec_to_delete}`` `; though in general using a Ruby library is better when possible. – Keith Bennett Dec 28 '17 at 13:15
  • Regarding my comment about a gist, posting the code here on Stack Overflow is better when possible. I mention a gist in case it's a _lot_ of code. – Keith Bennett Dec 28 '17 at 13:15