I worked in enough HTML to display progress onscreen for testing... it is failing at the "put" command.
NOTE: the script runs on a Linux/Apache server with Perl and makes an FTP connection to an NT server, logs in, get directory info, changes directory, etc.. and works fine --- as soon as I run put it stops dead.
The file "test.txt" is in the same directory as the script... I have tried various path(s) -- and having the test file in other directories -- any clues? Guesses? Witty remarks about my stupidity? Thanks!
#!/usr/local/bin/perl
#
#
$ftp_user = 'someuser';
$ftp_pass = 'pass2345';
$ftp_remote_addr = 'ftp.example.com';
$ftp_cwd_path = '/someuser/myroot/etc';
$ftp_put_filename = 'test.txt';
#
#
use Net::FTP;
#
print "Content-type: text/html\n\n";
#
print "Connecting to: $ftp_remote_addr<br>\n<br>\n";
#
$ftp = Net::FTP->new("$ftp_remote_addr") ¦¦ die "Could not connect to $ftp_remote_addr : $!";
print "Connected......<br>\n<br>\n";
#
$ftp -> login("$ftp_user","$ftp_pass") ¦¦ die "Could not login : $!";
print "User, $ftp_user, logged in to $ftp_remote_name<br>\n<br>\n";
#
$curr_dir = $ftp -> pwd() ¦¦ die "Could not get PWD : $!";
print "<i>(current directory: $curr_dir)</i><br>\n<br>\n";
#
$ftp -> cwd("$ftp_cwd_path") ¦¦ die "Could not CWD : $!";
print "Changed Directory to $ftp_cwd_path<br>\n<br>\n";
#
$curr_dir = $ftp -> pwd() ¦¦ die "Could not get PWD : $!";
print "<i>(current directory: $curr_dir)</i><br>\n<br>\n";
#
$ftp -> ascii() ¦¦ die "Could not set ASCII mode : $!";
print "<i>(set ASCII transfer mode)</i><br>\n<br>\n";
#
$ftp -> put("$ftp_put_filename") ¦¦ die "Could not PUT $ftp_put_filename : $!";
#
$remote_size = $ftp -> size("$ftp_put_filename");
#
print "Remote File Size: $remote_size bytes<br>\n<br>\n";
#
$ftp -> quit;
print "Done.<br>\n<br>\n";
#
exit;
#
I got it to go a bit further and now the PUT fails with:
Could not PUT test.html : Bad file descriptor
I've tested to get the environment variables for the path, the "use Cwd;" method, etc..
I've tried all kinds of combinations of paths and syntax on the put()..
- with full path from root
- file outside cgi-bin
- file in 777 directory
- file name with no extension, ("test" in case the period was a problem)...
Questions:
in the construct:
$ftp -> put( $file1, $file2 ) ¦¦ die "Could not PUT $file1 as $file2 : $!<br><br>";
What should the value of "$file1" and "$file2" be?
just a file name?
a full path with file name?
special encoding, (e.g. slashes, etc?)...?
Ideas?
put(filename.ext)
put("filename.ext")
put('filename.ext')
put(local.txt, remote.txt)
put("$file1", "$file2")
put(/path/here/local.txt, remote.txt)
put(/path/here/local.txt, /path/there/remote.txt)
etc..
in combinations with:
ascii()
binary()
pasv()
... still dies on the put() line.
I also tried stor() which does not not error out, but file is not there.
put() always fails with "No such file or directory" or "Bad File Descriptor" if I get the local or remote names/paths wrong -- but get them right and I get "Died at Line ##".
If I use put() it fails.
This uses stor()
With stor() it does create the remote file -- but the file is empty, (size = 0 bytes).
#!/usr/local/bin/perl
#
$ftp_user = 'thisuser';
$ftp_pass = 'pass234';
$ftp_remote_addr = 'ftp.exaple.com';
$ftp_cwd_path = '/thisuser/wwwroot/test';
$ftp_put_filename = 'test.html';
#
use Net::FTP;
#
print "Content-type: text/html\n\n";
#
$ftp = Net::FTP->new("$ftp_remote_addr") ¦¦ die $ftp->message;
print "1. FTP ready<br>\n";
$ftp -> login("$ftp_user","$ftp_pass") ¦¦ die $ftp->message;
print "2. LOGIN $ftp_user<br>\n";
$ftp -> cwd("$ftp_cwd_path") ¦¦ die $ftp->message;
print "3. CWD $ftp_cwd_path<br>\n";
$ftp -> ascii() ¦¦ die $ftp->message;
print "4. ASCII mode<br>\n";
$ftp -> pasv () ¦¦ die $ftp->message;
print "5. PASV mode<br>\n";
$ftp -> stor("$ftp_put_filename") ¦¦ die $ftp->message;
print "6. STOR $ftp_put_filename<br>\n";
$ftp -> quit;
print "7. QUIT<br>\n";
exit;
... and the file is ok too?
Have you tried a different file; perhaps one created with vi?-DrDoc
The file is ok... I have tried with low ASCII text only (as a .txt file), an .HTML file, (both in ASCII mode), and with .GIF files in BINARY mode... all show up in the right directory on the remote server -- but any/all have 0 byte size.
In reading the Net::FTP docs, I start thinking it may be how the remote server assigns and communicates on FTP ports.
When I use WS_FTP to transfer the file, the log is showing me port addresses like:
connecting to ###.###.###.###:48979
Connected to ###.###.###.### port 48979
Transfer a file and see:
connecting to ###.###.###.###:48986
Connected to ###.###.###.### port 48986
Here's a snip of the WS_FTP log:
connecting to ###.###.###.###:48019
Connected to ###.###.###.### port 48019
LIST
125 Data connection already open; Transfer starting.
Received 53 bytes in 0.1 secs, (5300.00 bps), transfer succeeded
226 Transfer complete.
sending myfile.jpg as myfile.jpg (1 of 1)
TYPE I
200 Type set to I.
PASV
227 Entering Passive Mode (###,###,###,###,191,83).
connecting to ###.###.###.###:48979
As I mentioned; the server I am trying to PUT (or STOR) the file to is an NT server. The machine where the script runs is *Nix.
I got it working!
Here's what I did;
First, I changed the line that initializes the FTP session to:
$ftp = Net::FTP->new("$ftp_remote_addr", Debug => 3 ) ¦¦ die $ftp->message;
The verbose Debug option gave me much more detailed info about what was happening. Debug writes out what is happening with arrows, (>>>> or <<<<) at each line to tell you which way the commands and data are flowing.
It was still failing, (writing a ZERO byte file), but with the Debug in place I could see what was happening.
Since the connect was not using PORT 21 (the default), the Net::FTP docs indicated a PASSIVE connection was needed.
I was setting it using:
$ftp -> pasv();
just before the STOR command thinking that would setup the transfer as passive. I don't think it works that way, I think the entire session needs to be in passive mode, so I removed the line with the pasv() command and added "Passive=> 1" into the initialization;
$ftp = Net::FTP->new("$ftp_remote_addr", Passive => 1 ) ¦¦ die $ftp->message;
I then changed the stor() command back to put()
$ftp -> put("$ftp_put_filename") ¦¦ die $ftp->message;
Short story, now it works fine!
Here's the final script:
#!/usr/local/bin/perl
#
$ftp_user = 'thisuser';
$ftp_pass = 'pass2345';
$ftp_remote_addr = 'ftp.example.com';
$ftp_cwd_path = '/thisuser/wwwroot/test';
$ftp_put_filename = 'test.gif';
#
use Net::FTP;
#
print "Content-type: text/html\n\n";
#
$ftp = Net::FTP->new("$ftp_remote_addr", Passive => 1 ) ¦¦ die $ftp->message;
print "1. FTP ready<br>\n";
$ftp -> login("$ftp_user","$ftp_pass") ¦¦ die $ftp->message;
print "2. LOGIN $ftp_user<br>\n";
$ftp -> cwd("$ftp_cwd_path") ¦¦ die $ftp->message;
print "3. CWD $ftp_cwd_path<br>\n";
$ftp -> binary() ¦¦ die $ftp->message;
print "4. BINARY mode<br>\n";
$ftp -> put("$ftp_put_filename") ¦¦ die $ftp->message;
print "5. PUT $ftp_put_filename<br>\n";
$ftp -> quit;
print "6. QUIT<br>\n";
exit;
Now all I need to do is code a recursive loop and logic to set ASCII or BINARY mode on each file and I can update the NT box with content from the Linux machine.