File transfered via SFTP - linux

I have a Linux (openSUSE 10.X) box and have a SFTP service on it.
When someone puts a file I have to write a script to move the files to another dir. I do not want to write a cron job. Is there an event or something I can check to see if they have sent the file?

You can write a c application and hook into inotify events.

Check also Net::SFTP::Server, an SFTP server written in Perl that can be extended to do things like the one you need.
Some code:
#!/usr/bin/perl
use strict;
use warnings;
use File::Basename ();
my $server = Server->new(timeout => 15);
$server->run;
exit(0);
package Server;
use Net::SFTP::Server::Constants qw(SSH_FXF_WRITE);
use parent 'Net::SFTP::Server::FS';
sub handle_command_open_v3 {
my ($self, $id, $path, $flags, $attrs) = #_;
my $writable = $flags & SSH_FXF_WRITE;
my $pflags = $self->sftp_open_flags_to_sysopen($flags);
my $perms = $attrs->{mode};
my $old_umask;
if (defined $perms) {
$old_umask = umask $perms;
}
else {
$perms = 0666;
}
my $fh;
unless (sysopen $fh, $path, $pflags, $perms) {
$self->push_status_errno_response($id);
umask $old_umask if defined $old_umask;
return;
}
umask $old_umask if defined $old_umask;
if ($writable) {
Net::SFTP::Server::FS::_set_attrs($path, $attrs)
or $self->send_status_errno_response($id);
}
my $hid = $self->save_file_handler($fh, $flags, $perms, $path);
$self->push_handle_response($id, $hid);
}
sub handle_command_close_v3 {
my $self = shift;
my ($id, $hid) = #_;
my ($type, $fh, $flags, $perms, $path) = $self->get_handler($hid);
$self->SUPER::handle_command_close_v3(#_);
if ($type eq 'file' and $flags & SSH_FXF_WRITE) {
my $name = File::Basename::basename($path);
rename $path, "/tmp/$name";
}
}
Save the script to somewhere in your server, chmod 755 $it, and configure OpenSSH to use it as the SFTP server instead of the default one.

Related

Module cwd assistance

I created a Perl module that is to be used in many Perl scripts to use Net::SSH::Expect
to do a login.
package myRoutines;
#
use v5.22;
use strict;
use warnings;
use Net::SSH::Expect;
use Exporter qw(import);
our #EXPORT_OK = qw(my_login);
sub my_login {
my $user = 'xxxx';
my $port = '10000';
my $passwd = 'XYZ';
my $adminServer = 'myServer';
my $rootpassword = 'ABCDEF';
my ( $pName, $vName ) = #_;
our $ssh = Net::SSH::Expect->new(
host => "$adminServer",
ssh_option => "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null",
user => "$user",
password => "$passwd",
port => "$port",
raw_pty => 1,
restart_timeout_upon_receive => 1,
log_file => "/var/tmp/clilog_$pName$vName"
);
eval {
my $login_output = $ssh->login();
if ( $login_output !~ />/ ) {
die "Login has failed.
Login output was $login_output";
}
};
return $ssh;
}
1;
The scripts will do:
use myRoutines qw(my_login);
our ( $ssh, $pName, $vName );
$pName = 'abc';
$vName = '123';
$ssh = my_login( $pName, $vName );
$ssh->send( "some command\r" );
This all works if I'm in the directory that the script and module are in. If I'm in any other directory, the new call works but the call to $ssh->send does nothing.
I've tried adding to my script:
use lib '/some/dir';
(where the .pm file resides) to force it find the module, and that seems to work when I'm not in the directory where the pm file resides.
I've tried to:
use File::chdir;
$CWD = '/some/dir';
and again, the login seems to work but the next send does nothing. So I'm at a loss as to what might be happening and would like some advice.
Update 20170908:
Upon further playing and following the suggestions made, I've done the following and it now works:
removed the eval as it was unnecessary.
removed the our's and made it my's.
removed the ""'s
set the following in the script:
use File::Basename;
use Cwd qw( abs_path );
chdir "/some/dir";
use lib dirname(abs_path($0));
my $scriptName = basename($0);
use myRoutines qw(ovm_login);
my $pName = substr($scriptName,0,-3); (cutting off the .pl from the end of the script name to pass the scriptname as the pName)
using chdir to change directory to where my pl script and pm file is and then setting the lib is seemingly working as it should.
Borodin, I'm not sure I understand your meaning when you say to object orient the module and .... but would be interested in hearing more to better understand.
If you don't want to hardcode the directory, you can use
use FindBin qw( $RealBin );
use lib $RealBin;
($RealBin is the path to the script. Adjust as needed if myRoutines.pm is in a subdir.)
The simple and easy way would be placing your .pm file in:
/usr/lib64/perl5/
directory and you shouldn't have any problems.
But still not the perfect solution, you should be able to put the .pm file wherever you want.

Using SFTP to transfer images from HTML form to remote linux server using PERL/CGI.pm

This is a school project, and the instructor has no knowledge of how to write the code.
I am using CGI and I am attempting to transfer a file without using Net::FTP or Net::SFTP since the server I am attempting to transfer it to will not allow connections from these services. I have written the HTML form and I am able to grab the name of the file uploaded through CGI.
Is it possible to use the SFTP command within a Perl script that resides on a Linux server using bash to transfer a file uploaded through an HTML form?
If anyone knows a way to do it please post the code so I can modify it and insert into my script.
use CGI qw(:standard);
use File::Basename;
my ( $name, $path, $extension) = fileparse ( $productimage, '..*' );
$productimage = $name . $extension;
$productimage =~ tr/ /_/; $productimage =~ s/[^$safechars]//g;
if ( $productimage =~/^([$safechars]+)$/ ) {
$productimage = $1;
} else {
die "Filename contains invalid characters";
}
$fh = upload('image');
$uploaddir = "../../.hidden/images";
open ( UPLOADFILE, ">$uploaddir/$productimage" )
or die "$!"; binmode UPLOADFILE;
while (<$fh>) {
print UPLOADFILE;
}
close UPLOADFILE;
This is the code I used to upload the file into the server.

How to call a function in Perl script after performing SSH?

I am creating a perl script in which I have to ssh multiple servers from same script and perform same commands on all these remote servers.
Right now I am using "If loop" and call all other servers from this script and perform command on them.
I want to create a function with these set of commands, that I need to perform on these different servers.
if($random_number==1){
use Net::SSH::perl
use lib qw("user/share/perl5/");
my $hostname = "10.*.*.*";
my $username = "root";
my $password = "root\#123";
my $cmd1 = "ls /home/ashish/"
my $cmd2 = "netstat -na | grep *.*.*.*;
$ssh->login("$username" , "$password");
my ($stdout,$stderr,$exit) = $ssh->cmd("$smd1" && "$cmd2");
print $stdout;
}
the above commands after if syntax needs to be repeated for different servers.
want to use a function call.
Start with general programming toutorials, then do it like:
use Net::SSH::perl;
use strict;
use warnings;
my #servers = (
{
hostname => 'somehost1',
username => 'someuser1',
password => 'somepass1',
commands => ['somecmd11','somecmd12'],
},
{
hostname => 'somehost2',
username => 'someuser2',
password => 'somepass2',
commands => ['somecmd21','somecmd22'],
},
# ...
);
do_something_on_remote_servers_one_by_one( #servers );
exit(0);
sub do_something_on_remote_servers_one_by_one {
my (#servers) = #_;
foreach my $server (#servers) {
my $ssh = Net::SSH::perl->new($server->{hostname});
$ssh->login($server->{username}, $server->{password});
my $cmd_string = join(' & ', #{ $server->{commands} } );
my ($stdout,$stderr,$exit) = $ssh->cmd($cmd_string);
print $stdout;
}
}
After that, you can think about executing commands in paralell.

Using Net::Telnet to ssh into linux

I am trying to use below perl code to ssh into linux machine and pull output of ls -l but it doesnt seem to be working.
What am i doing wrong?
#!/usr/bin/perl
use warnings;
use strict;
use Net::Telnet;
use IO::Pty;
use POSIX 'setsid';
use Getopt::Long;
use constant PROMPT => '/[a-z#>]/';
my $host = "192.168.1.121";
my $user = "root";
my $ssh = do_cmd( 'ssh', "-l$user", $host );
my $shell = Net::Telnet->new( Fhopen => $ssh );
$shell->binmode(1);
$shell->cmd( String => 'test', Prompt => '/[a-z]/' );
$shell->waitfor(PROMPT);
my #lines = $shell->cmd( String => 'ls -l', Prompt => '/[a-z]/' );
print #lines;
print "\n";
sub do_cmd {
my ( $cmd, #args ) = #_;
my $pty = IO::Pty->new;
defined( my $child = fork );
return $pty if $child;
setsid();
my $tty = $pty->slave;
close $pty;
STDIN->fdopen( $tty, "<" );
STDOUT->fdopen( $tty, ">" );
STDERR->fdopen( $tty, ">" );
close $tty;
$| = 1;
exec $cmd, #args;
}
Telnet and SSH are two different programs. You can't use telnet client for ssh server.

How to avoid the hard coded username/password in perl script

How to avoid the hard coded username/password in perl script
I am new to perl I have tried lot of things nothing worked out for me, Please help to provide some method to read the username/password from config file. What things I need to change here,
Below is my perl script:
#!/usr/bin/perl -w
use strict;
use warnings;
use Net::SFTP::Foreign;
my $server="sftp.abcpvt.com";
my $remote="outgoing_folder";
my $user="auser";
my $LOCAL_PATH="/home/sara";
my $file_transfer="DATA.ZIP";
my $password="abc123"
my %args = (user => "$user", password => "$password");
chdir $LOCAL_PATH or die "cannot cd to ($!)\n";
my $sftp = Net::SFTP::Foreign->new(host=>$server,user=>$user,password=>$password) or die "unable to connect";
$sftp->error and die "SSH connection failed: " . $sftp->error;
$sftp->get("$remote/$file_transfer","$LOCAL_PATH/$file_transfer") or die "unable to retrieve file".$sftp->error;
undef $sftp;
exit;
MY config file contains below thing.
Username = “auser”;
Password = “abc123”;
Time_out=180;
Port = 22
I tried the below things,
my $user=get_credentials("/home/sar/config");
my $password=get_credentials("/home/sar/config");
sub get_credentials {
my ($file) = #_;
open my $fh, "<", $file or die $!;
my $line = <$fh>;
chomp($line);
my ($user, $pass) = split /:/, $line;
return ($user, password => $pass);
}
Here I am getting only the password, Username is not getting here…
Could you please share the sample coding for using the username/password in perl script.
I think you want something like this.
sub get_config {
my ($file) = #_;
open my $fh, "<", $file or die $!;
my %config;
while (<>) {
chomp;
next unless /\S/;
my ($key, $val) = split /\s*=\s*/;
$val =~ s/^"//;
$val =~ s/"$//;
%config{$key} = $val;
}
return \%config;
}
my $config = get_config('/home/a911091/config');
my $user = $config->{Username};
my $pass = $config->{Password};
But you'd be far better off looking for a config file module from CPAN.

Resources