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


Hello everyone... I am having a hell of a time trying to extract (using the cat unix function)
a file into an array. The snippet below returns an empty array. The input_log shows the actions are performing accordingly. The program was timeing out at the cat line, I rectified this by forcing the Errmode to return. Anyones insight is greatly appreciated.

$telnetobj = new Net::Telnet->new(Timeout => 120, Prompt=> '/X>/', Binmode => 1, Errmode => "return", Output_record_separator => "\n", Input_log => $file_log); $telnetobj->open($HOH{$JOB}{Node}); $telnetobj->prompt('/login: /'); $telnetobj->print(''); #add one <CR> to display login my $loginpmpt = '/login: /'; $telnetobj->waitfor($loginpmpt); $telnetobj->print($HOH{$JOB}{'Login'}); $telnetobj->waitfor('/Password:/'); $telnetobj->print($HOH{$JOB}{"Password"}); $telnetobj->prompt; $telnetobj->waitfor(/X>/); $telnetobj->prompt(); $telnetobj->print("who"); $telnetobj->put(); my @stuff = $telnetobj->cmd("cat $filename"); $telnetobj->waitfor(/X>/); $telnetobj->close; ## close telnet session");

holli fixed formatting

jdporter fixed formatting even more

Replies are listed 'Best First'.
Re: unix cat
by davidrw (Prior) on Feb 09, 2006 at 14:01 UTC
    Your closing </code> tag is missing the slash...

    Is this the exact code you're running? The 'cat' line is missing a " ...

    Do you have to use Telnet for this? http, ftp, scp (bunches of modules for each) would be much easier and more robust (if $filename has a 'X>' in it you're going to lose data).
      That was a typo... The cat line does include the closing ".
Re: unix cat
by Roy Johnson (Monsignor) on Feb 09, 2006 at 15:10 UTC
    Are you sure $filename is set, contains no spaces, and that a file by that name exists? The waitfor call should be unnecessary after a cmd according to Net::Telnet docs.

    Caution: Contents may have been coded under pressure.
Re: unix cat
by jcc (Sexton) on Feb 09, 2006 at 16:30 UTC
    Since you're not changing directories, I assume that your file is in the user's home directory - or $filename contains an explicit path to the file with valid seperators etc.

    I also echo the sentiment that telnet is the wrong tool for this job... just grab the file with Net::FTP and operate on it locally.

      Thank you for everyones remarks. Further investigation found that the Telnet module needs to read in blocks when trying to populate a local variable...Should have researched this a little further before posting. Thanks again.
      ## Make sure prompt won't match anything in send data. $prompt = "_funkyPrompt_"; $host->prompt("/$prompt\$/"); $host->cmd("set prompt = '$prompt'"); ## Get size of file. ($line) = $host->cmd("/bin/ls -l $filename"); ($size_bsd, $size_sysv) = (split ' ', $line)[3,4]; if ($size_sysv =~ /^\d+$/) { $size = $size_sysv; } elsif ($size_bsd =~ /^\d+$/) { $size = $size_bsd; } else { die "$filename: no such file on $hostname"; } ## Start sending the file. binmode STDOUT; $host->binmode(1); $host->print("/bin/sh -c 'stty raw; cat $filename'"); $host->getline; # discard echoed back line ## Read file a block at a time. $num_read = 0; $prevblock = ""; $start_time = time; while (($block = $host->get) and $block !~ /$prompt$/o)) { if (length $block >= length $prompt) { print $prevblock; $num_read += length $prevblock; $prevblock = $block; } else { $prevblock .= $block; } } $host->close; ## Print last block without trailing prompt. $prevblock .= $block; $prevblock =~ s/$prompt$//; print $prevblock; $num_read += length $prevblock; die "error: expected size $size, received size $num_read\n" unless $num_read == $size; ## Print totals. $total_time = (time - $start_time) || 1; $k_per_sec = ($size / 1024) / $total_time; $k_per_sec = sprintf "%3.1f", $k_per_sec; warn("$num_read bytes received in $total_time seconds ", "($k_per_sec Kbytes/s)\n");

      Edited by planetscape - added code tags