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

I wrote a script to count the number of hits but I do not want a cheesy hit counter like alot of sites have. What I want to do is take the hit count and simply wqrite at the bottom of my html page something like "100 people have visited since 10 Jan 2004" or something like that.

Any ideas on how I could do this? I have the script written and have already thought about embedding it into an image tag and then somehow have it print that way whenever someone accessed the site but am a little unclear on how to do that.

Here is the script:

#!/usr/bin/perl $file = "/home/master/temp/perlskripts_ip.log"; $visited = "/home/master/temp/count.log"; $time = `date`; if ($ENV{'REMOTE_ADDR'} !~ /192.168.0.(\d+)/) { if (!-e $file) { `touch $file`; } open(lg, ">>$file") || die "Can't open $file!\n"; print lg "User from ".$ENV{'REMOTE_ADDR'}." logged on ".$time; close(lg); if (!-e $visited) { `touch $visited`; } open (vis, "<$visited") || die "Cannot open $visited for reading!\n +"; $count = <vis>; close (vis); print "count is ".$count,"\n"; open (vis, ">$visited") || die "Cannot open $visited for writing!\n +"; if ($count ne "") { $count++; }else{ $count = 1; } print vis $count; close (vis); }
Any ideas?

Replies are listed 'Best First'.
Re: Need a way to print script output to web page?
by Zaxo (Archbishop) on Feb 12, 2004 at 06:12 UTC

    Your counter file has no flocking and is subject to race conditions. It will be subject to clearing itself or missing counts. Super Search for hit counters to see recommendations from merlyn (I think he has a column on it ;-) and others.

    You output perl data to a web page by printing it to STDOUT. It doesn't matter whether the data is text or numbers, just print it where you want it, with the tags you want, or from a template.

    After Compline,
    Zaxo

Re: Need a way to print script output to web page?
by jeffa (Bishop) on Feb 12, 2004 at 14:59 UTC

    "I wrote a script to count the number of hits but I do not want a cheesy hit counter like alot of sites have."

    Are you using Apache? Yes? Then how about "data mining" the access logfile? This one-liner:

    perl -lane'$h{$F[0]}++}{print scalar keys %h' /path/to/apache/logs/acc +ess_log
    will parse through the entire space delimited log file, store the first field ($F[0] ... don't worry if that is confusing right now, keep reading) of each line into a hash and finally, when the log file has been exhausted, it prints the total number of unique IP addresses read.

    Now then, in case that one-liner just made your ears bleed, here is the same thing in a more drawn out manner, this time as a CGI script that can be accessed via web browser. While we are at it, let's do a little reporting as well. We will show those unique IP address and their total number of hits as well, sorted by hits descending:

    use strict; use warnings; use CGI qw(:standard); use CGI::Carp qw(fatalsToBrowser); print header,start_html; open LOG, '/path/to/apache/logs/access_log' or die $!; my %hist; while (<LOG>) { my @F = split / /, $_; $hist{$F[0]}++; } print "there are ", scalar(keys %hist), " total hits"; # just run the code and worry how it works later ;) print table( Tr(th[qw(IP Hits)]), map Tr(td[ $_, $hist{$_} ]), sort {$hist{$b} <=> $hist{$a}} keys %hist, );

    But ... there are problems with this script. Big problems. For one, the access log files are rotated ... that is, we are not seeing a lot of hits from the past. What if we wanted to see hits for a certain date range, what if we wanted to see which pages had the most hits. We can do this with the code above because the data is there for the picking ... but we still haven't discussed the worst problem:

    IT IS SLOW! Not only that, but you are also using up a lot of RAM as well. Everytime a visitor hits the page that calls this script, they will have to wait about 5-30 seconds for the page to load.

    So ... how do fix this? Easy ... you could run a cron job every hour or so that parses the access log file, and writes the total hits to a file. We would have to ensure that no visitor tried to access that file while it was being written to of course ... that can be a pain. There are all kinds of wheels that we can re-invent to report IP hits ...

    But i think the best solution of all is to head ye over to The Home of The Webalizer and RTFM how to use it. That is not only a non-cheesy solution, it is a free, professional solution. Best of luck to you. :)

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    

      (See update below...)

      I had some semi-serious issues with Webalizer. I'm using OS X, and it came with a nifty Perl install script. But it hosed my httpd.conf (it did, at least, make a backup). Check out the offending section (note that $t is input from a diamond operator):

      if ($t =~ /^y/) { `cp /etc/httpd/httpd.conf /etc/httpd/httpd.conf.save`; $orig = 'CustomLog "\/private\/var\/log\/httpd\/access_log" common +'; $new = 'CustomLog "\/private\/var\/log\/httpd\/access_log" combine +d'; print "Modifying apache configuration..."; `/usr/bin/sed -e 's/$orig/\#$orig/' -e 's/\#$new/$new/' /etc/httpd +/httpd.conf > /etc/httpd/httpd.conf`; print " done. \n\nOriginal saved to /etc/httpd/httpd.conf.save\n\ +n"; print "Apache needs to be restarted for this to take effect, would + you like to do this now? (y/n) "; $a = <>; if ($a =~ /^y/) { print "Restarting apache..."; print " done\n\n"; } }
      Note a few things. This script needs to be run as root (I did, via sudo). Backticks in void context, then a sed call (sed? From within Perl?!). I believe the sed call is what zeroed out my httpd.conf. Then, the part that I'm just fuming about. "Would you like to restart Apache?" I say yes. Script does nothing. "OK!"

      It took me a little over a half hour to debug this. I didn't see any problems because I didn't have to reboot my machine until tonight (I originally installed Webalizer yesterday morning). And I only had to reboot tonight because I installed some other random program -- so I thought that the other program was the culprit (but it has nothing to do with Apache, which is why I was stumped).

      All in all I really like the reports from Webalizer. But be warned if you install it with the OS X script. I'll be contacting the author with this information after this...

      Update: I don't recall exactly which version of Webalizer had this malfunctioning script, but the latest seems to have addressed the problem. The script still has backticks in void context (so no error checking to see if the command failed) but at least it does actually perform the 'apachectl restart' when you tell it to. Just in case you were curious.

Re: Need a way to print script output to web page?
by Abigail-II (Bishop) on Feb 12, 2004 at 09:42 UTC
    Oh, a retro-site! Webcounters are so mid 1990's!

    I got to ask you, why do you think people are interested in seeing an up-to-date count of, uhm, yeah, what actually? Certainly not the count of visitors, as such counters don't count hits served from proxies. Or let me phrase that another way. What goes through your mind if you visit a web page, and it says you are visitor 123456 since some point in the past? Do you get thrilled? Do you keep a diary where you write down your score? Do you even read it?

    Anyway, your program is riddles with problems. It might work well if you get just a handful of requests, distributed over the day. But you a have a problem each and every time you have two hits almost simultaneously.

    If you really must include a counter, does it have to be up-to-date to the second? Why don't you just generate the entire page, including a new count, every night? You can get the count from your log files.

    Abigail
    -- 
    You are visitor 1,578,920,023 since the third month of the 15th year of the reign of Ramses II.

      Remember the fanatics who saw that their webpages were only getting 5 hits a day, so they manually editted the number every few hours to make it look like their sites were popular? Then of course the late 1990's came and cron jobs were thrown together to manipulate the hit counts automatically! Then came 2000 and suddenly a document is given a 50 thousand hit count before the page is even posted in the public's view. Of course, the cool people just generated a (pseudo)random number to show as the hit count on each hit. And then there were those who just put a static number in their plain HTML documents to make it appear as though they had a counter when they never did. See, history can be fun.

    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Need a way to print script output to web page?
by castaway (Parson) on Feb 12, 2004 at 06:32 UTC
    Assuming you want to embed the result into already existing, normal HTML pages, thats kinda difficult. HTML is text, and is just passed directly to a browser, so it cant execute a script on the server anyhow. If you are generating your HTML on the server already using CGI, then you need to get the generating programm to call the script, and output the result.

    C.

      Somebody has forgotten all about SSIs. Extremely easy if you take that route. Though come to think of it, I have not used a server side include in several years. Amazing :)

Re: Need a way to print script output to web page?
by CountZero (Bishop) on Feb 12, 2004 at 06:46 UTC
    If you want to incorporate your script into an image tag, then you must take care that your script returns an image or else the web-page wil not render correctly.

    CountZero

    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law