Frequently installing apps via any FTP

Your app is in a tarball and clients only have FTP access to install your app on their host. Furthermore, you need to customize the config file (or do other process) for each install. What you need is Net::xFTP and Archive::Tar. Net::xFTP's put allows you to pass in an open filehandle typeglob as the local file. So you can open a filehandle on a string reference and use that as the LOCAL FILE. This is a simplified version.

my $xftp = Net::xFTP->new('Foreign', 'hostname', user => $user, password => $password,);

my $next = Archive::Tar->iter('mytarball.tar.gz');
while (my $file = $next->() )  {
   
  if ($file->type == 5) {    # 5 is the filetype number for directories in this case
$xftp->mkdir($file->full_path); next; } open FH, '<', $file->get_content_by_ref; $xftp->put(*FH, $file->full_path) or die $xftp->message; }

If for some reason the files you need are expanded on the filesystem, you can use File::Find to get a list of the files you want, then use Archive::Tar to create the archive in memory and loop through that.

find(sub{push @files,$File::Find::name}, "./");

my $archive;
open (my $in, '>', \$archive);
Archive::Tar->create_archive($in,0,@files);

open (my $out, '<', \$archive);
my $tar = Archive::Tar->new($out);

foreach my $file ($tar->get_files) {
  if ($file->type == 5) {
    $xftp->mkdir($file->full_path);
    next;
  }

  open (FH, "<", \$file->get_content);
  $xftp->put(*FH, $file->full_path) or die $xftp->message;
}

A couple of things to note. The filehandle typeglob does not work with the regular SFTP protocol module (but does work for FTP and FTPS and Foreign). Use Foreign as the protocol if you want SFTP; this will use Net::SFTP::Foreign and not Net::SFTP. Also, if using an in memory created archive $file->get_content_by_ref does not work, use \$file->get_content.

Leave a comment

About Jesse Shy

user-pic Perl pays for my travel addiction.