Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Looping File transfer using SFTP in TK

by deadpickle (Pilgrim)
on Apr 10, 2007 at 17:18 UTC ( #609216=perlquestion: print w/replies, xml ) Need Help??

deadpickle has asked for the wisdom of the Perl Monks concerning the following question:

This program is used to transfer a file to a server and is written in perl/Tk. The idea of the file is to enter all the information and then hit the connect button. The button then says Stop which is suppost to end the sftp subroutine. The program then creates a thread and connects to the server and transfers the file repeatedly until the stop button is clicked. What I am having trouble in doing is once you click "Connect" the file should keep transfering until the user clicks the 'Stop" button. As of now the file only transfers once. If anyone has ideas on how to do this I would be eternally greatful.
#!/usr/bin/perl -w use strict; use warnings; use Tk; use Net::SFTP::Foreign; use threads; use threads::shared; my $user = 'jlahowet'; my $server = 'mistral.unl.edu'; my $lcl = '/home/deadpickle/Desktop/Virtual Cockpit/'; my $rmt = '/home/jlahowet/UAV/COORDS/'; my$uav = 'uavposition'; my $mw = MainWindow->new(); my $go = 0; my $monitor: shared; $mw->configure(-title => 'VIRTUAL COCKPIT:SFTP', -background => 'blue' +); $mw->geometry('+400+300'); #User entry my $usr = $mw->Frame(-relief => 'groove', -borderwidth => 3, -backgrou +nd => 'blue')->pack(-side => 'top', -fill => 'x'); my $usrlbl = $usr->Label(-text => 'Username', -background => 'blue', - +foreground => 'white')->pack(-side => 'left'); my $usreny = $usr->Entry(-width=> 10, -textvariable => \$user)->pack(- +side => 'left', -pady => 3); #Server entry #my $svr = $mw->Frame(-relief => 'groove', -borderwidth => 3, -backgro +und => 'blue')->pack(-side => 'top', -fill => 'x'); my $svrlbl = $usr->Label(-text => 'Server', -background => 'blue', -fo +reground => 'white')->pack(-side => 'left'); my $svreny = $usr->Entry(-width=> 15, -textvariable => \$server)->pack +(-side => 'left', -pady => 3); #File locations my $loc = $mw->Frame(-relief => 'groove', -borderwidth => 3, -backgrou +nd => 'blue')->pack(-side => 'top', -fill => 'x'); my $uavlbl = $loc->Label(-text => 'UAV: ', -background => 'blue', -fo +reground => 'white')->pack(-side => 'left'); my $filelbl = $loc->Label(-text => 'File', -background => 'blue', -for +eground => 'white')->pack(-side => 'left'); my $fileeny = $loc->Entry(-width=> 8, -textvariable => \$uav)->pack(-s +ide => 'left', -pady => 3); my $lcllbl = $loc->Label(-text => 'Local', -background => 'blue', -for +eground => 'white')->pack(-side => 'left'); my $lcleny = $loc->Entry(-width=> 25, -textvariable => \$lcl)->pack(-s +ide => 'left', -pady => 3); my $rmtlbl = $loc->Label(-text => 'Remote', -background => 'blue', -fo +reground => 'white')->pack(-side => 'left'); my $rmteny = $loc->Entry(-width=> 25, -textvariable => \$rmt)->pack(-s +ide => 'left', -pady => 3); #Connect button my @setup = ($user, $server, $lcl, $rmt, $uav); my $btn = $mw->Button(-text => 'Connect', -background => 'gray', -comm +and => \&sub1)->pack(-side => 'bottom', -padx => 3, -pady => 3, -anch +or => 'e'); MainLoop; sub sub1 { if($btn->cget(-text) eq 'Connect'){ $go = 1; $btn->configure(-text=> 'Stop'); my $thr = threads->new(\&sftp, @setup); $monitor = 0; } else{ $go = 0; $btn->configure(-text=> 'Connect'); $monitor = 1; } print "$go\n"; } sub sftp { my $host = $_[1]; my $usrname = $_[0]; my $port = 22; my $seconds = 20; my %args = (user=>$usrname, port=>$port, timeout=>$seconds); my $local = $_[2]; my $remote = $_[3]; my $uavfile = $_[4]; my $sftp = Net::SFTP::Foreign->new($host, %args); print $monitor; eval { $sftp->put("$local$uavfile", "$remote$uavfile", callback => sub { die "aborted" if $monitor; # $monitor +has to be set from the other thread }) }; if ($@ and $@ =~ /^aborted/) { undef $sftp; print "Stopped"; $monitor = 0; } sleep (2); exit(1); }

Replies are listed 'Best First'.
Re: Looping File transfer using SFTP in TK
by zentara (Archbishop) on Apr 10, 2007 at 18:21 UTC
    You probably havn't seen it yet, but I answered you in comp.lang.perl.tk

    I made a fake sftp client for testing, but you can uncomment the real lines. Also, since you want to repeatedly send the same file, you didn't need the callback(unless you want to track large file progress).

    #!/usr/bin/perl use strict; use warnings; use Tk; use Net::SFTP::Foreign; use threads; use threads::shared; my $user = 'jlahowet'; my $server = 'mistral.unl.edu'; my $lcl = '/home/deadpickle/Desktop/Virtual Cockpit/uavposition'; my $rmt = '/home/jlahowet/UAV/COORDS/uavposition'; my $go:shared = 0; #my $monitor:shared = 0; my $die:shared = 0; my $progress:shared = 0; my @setup = ($user, $server, $lcl, $rmt); #start thread before any Tk code my $thr = threads->new(\&sftp, @setup); #now setup Tk my $mw = MainWindow->new(); $mw->protocol('WM_DELETE_WINDOW' => sub { &clean_exit }); $mw->configure(-title => 'VIRTUAL COCKPIT:SFTP', -background =>'blue') +; $mw->geometry('+400+300'); #User entry my $usr = $mw->Frame(-relief => 'groove', -borderwidth => 3, -backgrou +nd => 'blue')->pack(-side => 'top', -fill => 'x'); my $usrlbl = $usr->Label(-text => 'Username', -background => 'blue', - +foreground => 'white')->pack(-side => 'left'); my $usreny = $usr->Entry(-width=> 10, -textvariable => \$user)->pack(- +side => 'left', -pady => 3); #Server entry my $svr = $mw->Frame(-relief => 'groove', -borderwidth => 3, -backgrou +nd => 'blue')->pack(-side => 'top', -fill => 'x'); my $svrlbl = $svr->Label(-text => 'Server', -background => 'blue', -fo +reground => 'white')->pack(-side => 'left'); my $svreny = $svr->Entry(-width=> 15, -textvariable => \$server)->pack +(-side => 'left', -pady => 3); #File locations my $loc = $mw->Frame(-relief => 'groove', -borderwidth => 3, -backgrou +nd => 'blue')->pack(-side => 'top', -fill => 'x'); my $lcllbl = $loc->Label(-text => 'Local', -background => 'blue', -for +eground => 'white')->pack(-side => 'left'); my $lcleny = $loc->Entry(-width=> 25, -textvariable => \$lcl)->pack(-s +ide => 'left', -pady => 3); my $rmtlbl = $loc->Label(-text => 'Remote', -background => 'blue', -fo +reground => 'white')->pack(-side => 'left'); my $rmteny = $loc->Entry(-width=> 25, -textvariable => \$rmt)->pack(-s +ide => 'left', -pady => 3); #Connect button my $btn = $mw->Button(-text => 'Connect', -background => 'gray', -command => \&sub1) ->pack(-side => 'bottom', -padx => 3, -pady => 3, -anchor => ' +e'); # to monitor file count, needs a timer to update # from thread my $val = 0; my $label = $mw->Label( -width => 50, -textvariable => \$val )->pack(-side => 'bottom', -padx => 3, + -pady => 3, -anchor => 'w'); my $timer = $mw->repeat(10,sub{ $val = $progress; }); MainLoop; sub sub1 { if($btn->cget(-text) eq 'Connect'){ $go = 1; $btn->configure(-text=> 'Stop'); #$monitor = 0; } else{ $go = 0; $btn->configure(-text=> 'Connect'); #$monitor = 1; } print "go = $go\n"; } sub sftp{ $|++; # setup your sftp connection my $host = $_[1]; my $usrname = $_[0]; my $port = 22; my $seconds = 20; my %args = (user=>$usrname, port=>$port, timeout=>$seconds); my $local = $_[2]; my $remote = $_[3]; # commented out to skip actual sftp use # my $sftp = Net::SFTP::Foreign->new($host, %args); my $sftp; print "sftp connected\n"; #now go into a waiting loop, where you wait for #$go to be 1 #when $go = 1, the sftp will keep sending the file #the only way to break out is to set $die=1 while(1){ if($die == 1){ goto END }; # the go loop if ( $go == 1 ){ for(;;){ # $sftp->put("$local", "$remote"); print "fake file being sent\n"; $progress++; sleep 2; if($go == 0){last} if($die == 1){ goto END }; } $go = 0; #turn off self before returning }else { sleep 1 } # sleep if $go == 0 # end of go loop } #end of while loop END: undef $sftp; print "sftp stopped thread ending\n"; } sub clean_exit{ $timer->cancel; my @running_threads = threads->list; if (scalar(@running_threads) < 1){print "\nFinished\n";exit} else{ $die = 1; $thr->join; exit; } }

    I'm not really a human, but I play one on earth. Cogito ergo sum a bum
      Thanks for the responses, they are very helpful. What I want is for the sftp to disconnect when the Stop button is pushed. that way the script allows the user to change the variables and run the transfer again. Right now I am trying to understand how zentara's code works since it incorporates syntax I have never seen (and it seems to make it easier). One problem is that the program connects right away not allowing the user to change the variables before it is connected to the server. I moved the SFTP connection to work only when $go = 1, that way it only connects of you push connect. But you cant change the variables like username from jlahowet to something else. It wont pass the new value to the thread for some reason, any help?
        Well to save you the head-scratching( I'm familiar with it due to hours of my own head-scratching :-) ), here is how to do it so each sftp run can be different.

        I'm not really a human, but I play one on earth. Cogito ergo sum a bum
        Yeah, to make a new connection each run, move the connect to inside the go loop. To use new connection info for each connection, make them shared varaibles. Like:
        my $user:shared = 'jlahowet'; + my $server:shared = 'mistral.unl.edu'; + my $lcl:shared = '/home/deadpickle/Desktop/Virtual Cockpit/uavposition +'; my $rmt:shared = '/home/jlahowet/UAV/COORDS/uavposition'; #my $thr = threads->new(\&sftp, @setup); my $thr = threads->new(\&sftp); #then in your thread-code use the shared vars instead of #using the passed in @setup array
        You already have your entry widgets to setup to automatically change the vars with -textvariable. There is one thing to watch out for: sometimes the threads will not automatically pick up changes in textvariables, you might have to manually read them, but try it first, you may get lucky.

        I'm not really a human, but I play one on earth. Cogito ergo sum a bum
Re: Looping File transfer using SFTP in TK
by dana (Monk) on Apr 10, 2007 at 17:43 UTC

    I may be missing it but your program seems to only refer to sub1 one time, within the main body of the program

    my $btn = $mw->Button(-text => 'Connect', -background => 'gray', -comm +and => \&sub1)->pack(-side => 'bottom', -padx => 3, -pady => 3, -anch +or => 'e');

    I think you want a call to sub1 in sftp (I may be missing it). The sftp needs a way to check if 'stop' has been pushed and if not repeat the sftp subroutine.

Re: Looping File transfer using SFTP in TK
by MonkE (Hermit) on Apr 10, 2007 at 17:35 UTC
    You did say that you want to transfer the file "repeatedly", but I don't see any looping in your sftp sub ... or am I missing something? As soon as it completes one full transmission of the file, it will quit. The bit with the callback checking $monitor will halt the transmission in "mid put", but it will not send the file more than once.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://609216]
Approved by MonkE
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (4)
As of 2023-10-03 11:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?