douneiben2240
2013-12-09 13:52
浏览 62
已采纳

将IPTables输出拆分为数据库的多维数组

I'm trying to get the current IPTables rules in my Debian server neatly listed up in a database.

To do this, I've written a few steps.

  1. First, we get the IPTables output with line number. (Input chain for example)

    iptables -L INPUT -nvx --line

I get a neat output, that I want to get in my database the exact same way. For example;

Number, Chain, Protocol, Port, in, out

etcetera.

To get this output to be compatible with importing to the database, I need to get it into a multidimensional array. This is where I'm stuck. It's needs to be like this;

[0] (entry of rule)
[number],[chain],[protocol]...

[1]
[number],[chain],[protocol]

How exactly can I do this the most efficient way?

-- UPDATED CODE --

function getIPTables() {
$processHandle = popen('/usr/bin/sudo /sbin/iptables -L INPUT -nvx --line-numbers | tail -n +3', 'r');
$content = '';
    while (!feof($processHandle)) {
        $content .= fread($processHandle, 4096);
    }
pclose($processHandle);



// break out all new lines into an array
$lines = explode("
", $content);


foreach ($lines as $line) {
    $commands = array();

    $segments = explode(" ", $line); 

    $newEntry = array(
        'Number'    =>  $segments[0],
        'Chain'     =>  $segments[1],
        'Protocol'  =>  $segments[2],
        'Port'      =>  $segments[3],
        'in'        =>  $segments[4],
        'out'       =>  $segments[5]
    );
    array_push($commands, $newEntry);
    print_r($commands);
}



}

-- OUTPUT --

root@debian:/home/michael/Documents/PHPCLIFILES# php getAllRules
Local DB rules from users loaded in array 
 PHP Notice:  Undefined offset: 1 in /home/michael/Documents/PHPCLIFILES/getAllRules on line 47
PHP Notice:  Undefined offset: 2 in /home/michael/Documents/PHPCLIFILES/getAllRules on line 48
PHP Notice:  Undefined offset: 3 in /home/michael/Documents/PHPCLIFILES/getAllRules on line 49
PHP Notice:  Undefined offset: 4 in /home/michael/Documents/PHPCLIFILES/getAllRules on line 50
PHP Notice:  Undefined offset: 5 in /home/michael/Documents/PHPCLIFILES/getAllRules on line 51
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • douzai3399 2013-12-09 14:01
    已采纳

    I'm going to assume that your regex's are correct. You're actually appending everything to the same string using $commands .= <some text>. Rather than appending it to the same string, you should make $commands an array. Then you want to instantiate a new array for every line you go into ($line). push the things you want to keep onto your $line array, and at the end of every line you array_push($commands, $line)

    Array_push(): http://php.net/manual/en/function.array-push.php

    this could be an approach for your foreach()

    foreach ($lines as $line) {
        $commands = new array;
        if (empty($line)) {
            continue; //empty lines are silly
        }
        // ... do all the checks to validate if you currently have a valid LINE
        //We know that whatever we have now is a valid line 
        $segments = explode(line bla bla); //explode this line on tabs or spaces .. dunno what the output of your console is.
        //At this point you know exactly where every part you need is, considering the console always gives the same output.
        //Either you do some validations here, or you go for the lazy approach and go:
        $newEntry = array(
            'Number'    =>  $segments[0],
            'Chain'     =>  $segments[1],
            'Protocol'  =>  $segments[2],
            'Port'      =>  $segments[3],
            'in'        =>  $segments[4],
            'out'       =>  $segments[5]
        );
        array_push($commands, $newentry);
    }
    

    code is not tested, but you should get an idea where i'm going to.

    Your code:

    //instantiate a new empty named variable.
    $commands = '';
    //for every line in your console-dump file
    foreach ($lines as $line) {
        //Is the line empty
        if (empty($line)) {
            //skip line and go to next line
            continue;
        }
        //Does the line start with #
        if (preg_match('/^#/', $line) === 1) {
            //skip line and go to next line
            continue;
        }
        //Does the line start with *
        if (preg_match('/^\*/', $line) === 1) {
            //skip line and go to next line
            continue;
        }
        //Does the line start with 'COMMIT'
        if (preg_match('/^COMMIT/', $line) === 1) {
            //skip line and go to next line
            continue;
        }
        //we have a valid line now, so let's do stuff
        $match = array();
        //Does the line contain:
        if (preg_match('/^:([A-Z ]*).*/', $line, $match) === 1) {
            //skip line and go to next line
            continue;
        }
        //Only if the line is a 'valid' line, and does not have your last match,
        //Then you will append "iptables {$line}
    " to $commands
        $commands .= "iptables {$line}
    ";
        //This way it was a bit useless for you to cut up the line using the preg_match
        //and store it into $match, cause you don't do anything with $match
    }
    

    Your initial approach is good. And depending how your console returns predictable values, you either follow your approach with the regex (but then actually use the result) or you just go the lazy approach and use the one i suggested.

    Do note that CONTINUE actually breaks your current loop, and goes into the next iteration.

    $array = array(1, 2, 3, 4, 5);
    foreach($array as $number){
        if($number < 3){
            continue;
        }
        print($number .'
    ');
    }
    

    The outcome will be:

    3
    
    4
    
    5
    
    

    as continue actually completely stops this attempt in your foreach()

    点赞 打赏 评论

相关推荐 更多相似问题