-
Notifications
You must be signed in to change notification settings - Fork 43
/
Copy pathwatch_url.pl
executable file
·165 lines (150 loc) · 6.11 KB
/
watch_url.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#!/usr/bin/perl -T
#
# Author: Hari Sekhon
# Date: 2011-05-24 10:38:54 +0100 (Tue, 24 May 2011)
#
# https://github.com/HariSekhon/DevOps-Perl-tools
#
# License: see accompanying Hari Sekhon LICENSE file
#
# If you're using my code you're welcome to connect with me on LinkedIn
# and optionally send me feedback to help improve or steer this or other code I publish
#
# https://www.linkedin.com/in/HariSekhon
#
$DESCRIPTION = "Watch a given URL, outputting status code, content, round trip time and percentages of return codes. Useful for testing web farms and load balancers";
$VERSION = "0.5.0";
use strict;
use warnings;
BEGIN {
use File::Basename;
use lib dirname(__FILE__) . "/lib";
}
use HariSekhonUtils;
use LWP::UserAgent;
use POSIX;
use Time::HiRes qw/sleep time/;
# This is the max content length if on one line before outputting it on a separate line
my $default_output_length = 40;
my $output_length = $default_output_length;
my $count = 0;
my $interval = 1;
my $output;
my $regex;
my $res;
my $request_timeout = 1;
my $returned = 0;
my $sleep_time;
my $ssl_ca_path;
my $ssl_noverify;
my $status;
my $status_line;
my $time;
my $time_taken;
my $total = 0;
my $tstamp1;
my $tstamp2;
my $url;
my %stats;
$usage_line = "usage: $progname --url http://host.domain.com/page [ --interval=1 --count=0 ]";
%options = (
"u|url=s" => [ \$url, "URL to GET. Will use first arg as URL if this switch is omitted. URL may optionally be prefixed with http:// or https:// for SSL" ],
"c|count=i" => [ \$count, "Number of times to request the given URL. Default: 0 (unlimited)" ],
"i|interval=f" => [ \$interval, "Interval in secs between URL requests. Default: 1" ],
"t|request-timeout=s" => [ \$request_timeout, "Per request timeout in secs. Default: 1" ],
"o|output" => [ \$output, "Show raw output at end of each line or on new line if output contains carriage returns or newlines or is longer than --output-length characters" ],
"r|regex=s" => [ \$regex, "Output regex match of against entire web page (useful for testing embedded host information of systems behind load balancers)" ],
"l|output-length=i" => [ \$output_length, "Max length of single line output before putting in on a separate line (defaults to $default_output_length chars)" ],
"ssl-CA-path=s" => [ \$ssl_ca_path, "Path to CA certificate directory to verify SSL certificate if specifying https://" ],
"ssl-noverify" => [ \$ssl_noverify, "Do not verify SSL certificate if specifying https://" ],
);
@usage_order=qw/url count interval request-timeout output regex output-length ssl-CA-path tls-noverify/;
remove_timeout();
get_options();
$url = $ARGV[0] if not defined($url) and defined($ARGV[0]);
#$url =~ /^(http:\/\/\w[\w\.-]+\w(?:\/[\w\.\;\=\&\%\/-]*)?)$/ or die "Invalid URL given\n";
$url = validate_url($url);
#isInt($count) or usage "Invalid count given, must be a positive integer";
#isFloat($interval) or usage "Invalid sleep interval given, must be a positive floating point number";
#$interval > 0 or usage "Interval must be greater than zero";
#vlog_option "Count", $count ? $count : "$count (unlimited)";
validate_int($count, "count", 0, 1000000);
validate_float($interval, "interval", 0.00001, 1000);
validate_float($request_timeout, "request timeout", 1, 100);
$regex = validate_regex($regex) if $regex;
validate_int($output_length, "output length", 0, 1000);
my $ua = LWP::UserAgent->new;
$ua->agent("Hari Sekhon Watch URL version $main::VERSION ");
$ua->show_progress(1) if $debug;
$ua->timeout($request_timeout);
if(defined($ssl_noverify)){
$ua->ssl_opts( verify_hostname => 0 );
}
if(defined($ssl_ca_path)){
$ssl_ca_path = validate_directory($ssl_ca_path, "SSL CA directory", undef, "no vlog");
$ua->ssl_opts( SSL_ca_path => $ssl_ca_path );
}
vlog_option "SSL CA Path", $ssl_ca_path if defined($ssl_ca_path);
vlog_option "SSL noverify", $ssl_noverify ? "true" : "false";
vlog2;
my $req = HTTP::Request->new(GET => $url);
print "="x133 . "\n";
#print "Time\t\t\tCount\t\tResult\t\tHTTP Status Code = Number (% of Total Requests, % of Returned Requests)\n";
print "Time\t\t\tCount\t\tResult\t\tRound Trip Time\t\tHTTP Status Code = % of Total Requests (number/total)\n";
print "="x133 . "\n";
#while(1){
for(my $i=1;$i<=$count or $count eq 0;$i++){
$time = strftime("%F %T", localtime);
vlog2 "* sending request";
$tstamp1 = time;
$res = $ua->request($req);
$tstamp2 = time;
vlog2 "* got response";
$status_line = $res->status_line;
$status = $res->code;
$total++;
if($status !~ /^\d+$/){
warn "$time\tCODE ERROR: status code '$status' is not a number (status line was: '$status_line')\n";
next;
}
$returned += 1;
$time_taken = sprintf("%.4f", $tstamp2 - $tstamp1);
chomp $status_line;
$msg = "$status_line\t\t$time_taken secs\t\t";
$stats{$status} += 1;
$returned = 0;
foreach(keys %stats){
$returned += $stats{$_};
}
foreach(sort keys %stats){
#$msg .= "$_ = $stats{$_} (" . int($stats{$_} / $returned * 100) . "% $stats{$_}/$returned) (" . int($stats{$_} / $total * 100) . "% $stats{$_}/$total)\t\t";
$msg .= "$_ = " . int($stats{$_} / $total * 100) . "% ($stats{$_}/$total), ";
}
$msg =~ s/,\s*$//;
print "$time\t$i\t\t$msg";
if($output or $regex or $verbose >= 3){
my $content = $res->content;
chomp $content;
if($regex){
$content =~ /($regex)/m;
$content = $1 if $1;
}
if(length($content) > $output_length or $content =~ /[\r\n]/){
print "\ncontent: $content\n";
} else {
print "content: $content";
}
}
print "\n";
if($status_line eq "500 Can't verify SSL peers without knowning which Certificate Authorities to trust"){
die "\n\n$status_line\n\nPlease specify either --ssl-CA-path or --ssl-noverify\n";
}
$sleep_time = ($interval - $time_taken) < 0 ? 0 : ($interval - $time_taken);
vlog2 "* sleeping for $sleep_time seconds\n";
sleep $sleep_time;
}
if($status =~ /^2/){
exit 0;
} else {
exit 2;
}