 |
Account Login
|
 |
 |
Latest Articles
|
 |
 |
IRC Channel
|
 |
 |
Associates
|
 |
 |
Associates
|
 |
|
 |
 |
|
 |
03-21-2009, 02:31 AM
|
#1 (permalink)
|
|
The Gregarious
Join Date: Feb 2009
Location: New York
Posts: 645
Thanks: 64
|
Help search through file....
Hey guys, I need to read through my apache error_log file and filter out only what I'm looking for. (specific IP addresses)
Below is the normal format in the file:
192.168.2.1 - - [20/Mar/2009:21:03:38 -0400] "GET /index.php HTTP/1.1" 200 58
192.168.2.3 - - [20/Mar/2009:21:03:38 -0400] "GET /index.php HTTP/1.1" 200 58
192.168.2.3 - - [20/Mar/2009:21:03:38 -0400] "GET /index.php HTTP/1.1" 200 58
192.168.2.5 - - [20/Mar/2009:21:03:38 -0400] "GET /index.php HTTP/1.1" 200 58
192.168.2.5 - - [20/Mar/2009:21:03:38 -0400] "GET /index.php HTTP/1.1" 200 58
192.168.2.1 - - [20/Mar/2009:21:03:38 -0400] "GET /index.php HTTP/1.1" 200 58
Here's my code but it doesn't seem to work right?
What I'm trying to do is, as I read through the file, output anything that matches in the array....
Code:
<?php
$bad_ip_address = array('192.168.2.1','192.168.2.3');
$fh = fopen("error_log",'r');
while (!feof($fh)) {
$buffer = fgets($fh, 4096);
if(in_array("$bad_ip_address", $buffer)) {
echo $buffer;
}
}
fclose($fh);
?>
So based on the array, my output should be:
192.168.2.1 - - [20/Mar/2009:21:03:38 -0400] "GET /index.php HTTP/1.1" 200 58
192.168.2.3 - - [20/Mar/2009:21:03:38 -0400] "GET /index.php HTTP/1.1" 200 58
192.168.2.3 - - [20/Mar/2009:21:03:38 -0400] "GET /index.php HTTP/1.1" 200 58
192.168.2.1 - - [20/Mar/2009:21:03:38 -0400] "GET /index.php HTTP/1.1" 200 58
|
|
|
|
03-21-2009, 07:13 AM
|
#2 (permalink)
|
|
The Frequenter
Join Date: Dec 2007
Location: Bucharest, Romania
Posts: 438
Thanks: 3
|
Try this way:
PHP Code:
if(preg_match('/^(?:' . str_replace('.', '\.', implode('|', $bad_ip_address)) . ')/', $buffer) > 0) echo $buffer;
$bad_ip_address is an array, so in your statement, it wouldn't work, because the word "Array" would be checked against the $buffer variable (which, btw, is a string, not an array, so the search would not work).
__________________
I have optimistic thoughts, even though sometimes (if not always) life's a bitch.
|
|
|
|
|
The Following User Says Thank You to xenon For This Useful Post:
|
|
03-21-2009, 11:39 AM
|
#3 (permalink)
|
|
Moderateur
Join Date: Apr 2007
Posts: 1,393
Thanks: 5
|
If you want simple, perhaps something along the lines of the following would suffice.
PHP Code:
$bad_ips = array('12.34.56.78', '127.0.0.1'); $fp = fopen('apache.log', 'r'); while ( ! feof($fp)) { $line = fgets($fp, 4096); $ip = substr($line, 0, strpos($line, ' ')); if (in_array($ip, $bad_ips)) { echo $line; } } fclose($fp);
Or you could go the OOP route with a little SPL goodness.
PHP Code:
class ApacheFilter extends FilterIterator { protected $filter; public function __construct(Iterator $it, $filter) { parent::__construct($it); $this->filter = (array) $filter; } public function accept() { $line = $this->getInnerIterator()->current(); $ip = substr($line, 0, strpos($line, ' ')); return (bool) in_array($ip, $this->filter); } }
$file = new SplFileObject('apache.log'); $filter = new ApacheFilter($file, array('12.34.56.78', '127.0.0.1')); foreach ($filter as $line) { echo $line; }
Last edited by Salathe : 03-21-2009 at 03:59 PM.
|
|
|
|
|
The Following User Says Thank You to Salathe For This Useful Post:
|
|
03-21-2009, 03:24 PM
|
#4 (permalink)
|
|
The Gregarious
Join Date: Feb 2009
Location: New York
Posts: 645
Thanks: 64
|
Thanks to both you guys!
I am going to attempt Sal's OOP way since I'm trying to learn OOP, might as well start with this...
I'll give it a shot and see how it turns out!
|
|
|
|
03-21-2009, 03:51 PM
|
#5 (permalink)
|
|
The Gregarious
Join Date: Feb 2009
Location: New York
Posts: 645
Thanks: 64
|
It's amazing how much shorter the procedural way is.
But I know what the power of OOP can bring to me if I keep at it.....
|
|
|
|
03-21-2009, 04:09 PM
|
#6 (permalink)
|
|
The Gregarious
Join Date: Feb 2009
Location: New York
Posts: 645
Thanks: 64
|
Hey Salathe,
I am getting this error when I run it.
Quote:
Fatal error: Uncaught exception 'RuntimeException' with message 'SplFileObject::__construct(error.log): failed to open stream: No such file or directory' in /usr/storage/testphp/read_error_log.php:21
Stack trace:
#0 /usr/storage/testphp/read_error_log.php(21): SplFileObject->__construct('error.log')
#1 {main}
thrown in /usr/storage/testphp/read_error_log.php on line 21
|
|
|
|
|
03-21-2009, 05:08 PM
|
#7 (permalink)
|
|
Moderateur
Join Date: Apr 2007
Posts: 1,393
Thanks: 5
|
The error says that there is no such file or directory called "error.log". Is the error.log file in the same directory as the script?
|
|
|
|
|
The Following User Says Thank You to Salathe For This Useful Post:
|
|
03-21-2009, 06:25 PM
|
#8 (permalink)
|
|
The Gregarious
Join Date: Feb 2009
Location: New York
Posts: 645
Thanks: 64
|
Quote:
Originally Posted by Salathe
The error says that there is no such file or directory called "error.log". Is the error.log file in the same directory as the script?
|
Ohhh I am such a fool!! The name of my file is called: error_log
And I called the file: error.log hahaha..
That's what happens when you roll out of bed and the coffee doesn't kick in yet and you try to program...
It works now perfectly!!!
If you don't mind, I am going to try attempt to comment on your code and if you can be so kind to point out where I may be wrong?
I want to make sure I understand this OOP stuff....
|
|
|
|
03-21-2009, 07:06 PM
|
#9 (permalink)
|
|
The Gregarious
Join Date: Feb 2009
Location: New York
Posts: 645
Thanks: 64
|
Ok Salathe:
Here is my attempt at commenting your code. Please let me know where I am wrong. Also, the method accept(), if you can explain that further because I don't see that called anywhere??
Thanks!!
Code:
<?php
/* Create custom class called ApacheFilter that extends from existing
class FilterIterator from PHP's built-in SPL */
class ApacheFilter extends FilterIterator
{
/* This is a protected property only available to the ApacheFilter class methods */
protected $filter;
/* This is the class's main construct. It accepts 2 attributes. Type casting the "$it" with Iterator? */
public function __construct(Iterator $it, $filter)
{
/* You are passing the "$it" attribute to the static parent??? */
parent::__construct($it);
/* You are passing this attribute to the class pointer "filter". Type casted as array? */
$this->filter = (array) $filter;
}
/* Create a method accessible outside of the class */
public function accept()
{
/* NEED HELP UNDERSTANDING THIS */
$line = $this->getInnerIterator()->current();
/* substr function. Take the first part of the line that is before the space ''
Start at the beginning of the line and up to the space ''
*/
$ip = substr($line, 0, strpos($line, ' '));
/* If TRUE, return the line that has the IP address found in the array */
return (bool) in_array($ip, $this->filter);
}
}
/* This is the object we create to access the file we want to read */
$file = new SplFileObject('error_log');
/* This is the object we create to access the ApacheFilter class and its methods.
We pass the newly created file object and array data */
$filter = new ApacheFilter($file, array('206.107.147.230', '75.149.134.235'));
/* This is just a simple array loop to echo out our data */
foreach ($filter as $line)
{
echo $line;
}
|
|
|
|
03-21-2009, 10:11 PM
|
#10 (permalink)
|
|
Moderateur
Join Date: Apr 2007
Posts: 1,393
Thanks: 5
|
- Create custom class called ApacheFilter that extends from existing class FilterIterator from PHP's built-in SPL
Absolutely correct. 
- This is a protected property only available to the ApacheFilter class methods
Whilst this is true, it's also important to note that any classes extending from ApacheFilter will be able to define and modify this property. Compare that to declaring it as 'private'.
- This is the class's main construct. It accepts 2 attributes. Type casting the "$it" with Iterator?
It does not cast the $it argument at all. The term to use is 'type hinting' and declares that this argument should implement the Iterator interface. Failing to pass an iterator as the argument will generate a "Catchable fatal error" stating that "Argument 1 passed to ApacheFilter::__construct() must implement interface Iterator".
- You are passing the "$it" attribute to the static parent???
This is calling the parent class's constructor. In the case that we define our own behaviour with a custom __construct method, we need to manually call the parent's constructor if we want to use it. Essentially it's calling FilterIterator's __construct method. More info.
- You are passing this attribute to the class pointer "filter". Type casted as array?
Yes, the value is type casted to an array (for example, if only a string is provided it will be converted to an array containing that string). The array is assigned to the filter property of the class for use later.
- Create a method accessible outside of the class
Yes.
- NEED HELP UNDERSTANDING THIS
This is some of the OOP magic inherited from the FilterIterator and beyond. Remember the iterator that we passed along when creating the instance of our class? Well, the getInnerIterator method retrieves that iterator (our SplFileObject) for us. We then call the current method on that iterator (our SplFileObject) to retrieve the current line of the file. The terminology used for stringing multiple method calls together is 'method chaining' which is an incredibly useful (and easy to misuse!) feature introduced for us in PHP5 (not sure if you've seen or used chaining before).
- substr function. Take the first part of the line that is before the space '' Start at the beginning of the line and up to the space ''
Yes. In these Apache logs, the IP address is always at the start of the line and followed by a space character.
- If TRUE, return the line that has the IP address found in the array
This line returns TRUE if the IP address matches one in the filter array, FALSE otherwise: this is the purpose of the accept method (see below). The type casting to bool is only there so that I (or you, or anyone else reading it) can quickly see that the function returns a boolean TRUE/FALSE (which in_array does by default) and isn't strictly necessary.
- This is the object we create to access the file we want to read
Yep. SplFileObject is a utility class which can read and write files, and access useful information about them, in a variety of ways. More info.
- This is the object we create to access the ApacheFilter class and its methods. We pass the newly created file object and array data
Yes.
- This is just a simple array loop to echo out our data
Yes. Note that since we're iterating over the filter, only our filtered lines get echoed. This is where the accept method comes in to play. The accept method is automatically called as the foreach loop goes through each line. It defines which lines should be accepted or not (by returning TRUE/FALSE respectively) and is therefore where we place our filtering code.
|
|
|
|
|
The Following User Says Thank You to Salathe For This Useful Post:
|
|
03-22-2009, 02:15 AM
|
#11 (permalink)
|
|
The Gregarious
Join Date: Feb 2009
Location: New York
Posts: 645
Thanks: 64
|
Quote:
Originally Posted by Salathe
- Create custom class called ApacheFilter that extends from existing class FilterIterator from PHP's built-in SPL
Absolutely correct. 
- This is a protected property only available to the ApacheFilter class methods
Whilst this is true, it's also important to note that any classes extending from ApacheFilter will be able to define and modify this property. Compare that to declaring it as 'private'.
- This is the class's main construct. It accepts 2 attributes. Type casting the "$it" with Iterator?
It does not cast the $it argument at all. The term to use is 'type hinting' and declares that this argument should implement the Iterator interface. Failing to pass an iterator as the argument will generate a "Catchable fatal error" stating that "Argument 1 passed to ApacheFilter::__construct() must implement interface Iterator".
- You are passing the "$it" attribute to the static parent???
This is calling the parent class's constructor. In the case that we define our own behaviour with a custom __construct method, we need to manually call the parent's constructor if we want to use it. Essentially it's calling FilterIterator's __construct method. More info.
- You are passing this attribute to the class pointer "filter". Type casted as array?
Yes, the value is type casted to an array (for example, if only a string is provided it will be converted to an array containing that string). The array is assigned to the filter property of the class for use later.
- Create a method accessible outside of the class
Yes.
- NEED HELP UNDERSTANDING THIS
This is some of the OOP magic inherited from the FilterIterator and beyond. Remember the iterator that we passed along when creating the instance of our class? Well, the getInnerIterator method retrieves that iterator (our SplFileObject) for us. We then call the current method on that iterator (our SplFileObject) to retrieve the current line of the file. The terminology used for stringing multiple method calls together is 'method chaining' which is an incredibly useful (and easy to misuse!) feature introduced for us in PHP5 (not sure if you've seen or used chaining before).
- substr function. Take the first part of the line that is before the space '' Start at the beginning of the line and up to the space ''
Yes. In these Apache logs, the IP address is always at the start of the line and followed by a space character.
- If TRUE, return the line that has the IP address found in the array
This line returns TRUE if the IP address matches one in the filter array, FALSE otherwise: this is the purpose of the accept method (see below). The type casting to bool is only there so that I (or you, or anyone else reading it) can quickly see that the function returns a boolean TRUE/FALSE (which in_array does by default) and isn't strictly necessary.
- This is the object we create to access the file we want to read
Yep. SplFileObject is a utility class which can read and write files, and access useful information about them, in a variety of ways. More info.
- This is the object we create to access the ApacheFilter class and its methods. We pass the newly created file object and array data
Yes.
- This is just a simple array loop to echo out our data
Yes. Note that since we're iterating over the filter, only our filtered lines get echoed. This is where the accept method comes in to play. The accept method is automatically called as the foreach loop goes through each line. It defines which lines should be accepted or not (by returning TRUE/FALSE respectively) and is therefore where we place our filtering code.
|
Wow I cannot thank you enough. The Thank You button only let's me click on it once...
I've read about 3-4 books on OOP the last 2 months. My favorite is this one: The Object-Oriented Thought Process by Matt Wiesfeld.
Maybe you've read it or heard of it, but I like that it's not PHP related but just the overall thought process of OO design.
Anyways, this OO stuff is taking a long time for it to sink in for me. Especially things like method overloading, and the many types of design patterns.
Thanks again and I am still going to look at your code so I fully understand it.
In all the books I've read, I don't recall reading up on Method chaining so I'll have to do some digging on that, sounds pretty important!!! (unless there's another term out there for method chaining?)
|
|
|
|
|
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
|
|
|
| Thread Tools |
Search this Thread |
|
|
|
| Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|