我正在尝试将我的 Debian 服务器中的当前 IPTables 规则整齐地列在数据库中。
为此,我编写了几个步骤。
首先,我们获得带有行号的 IPTables 输出。 (以输入链为例)
iptables -L INPUT -nvx --line
我得到了一个简洁的输出,我想以完全相同的方式进入我的数据库。 例如;
Number, Chain, Protocol, Port, in, out
等等。
为了使此输出与导入数据库兼容,我需要将其放入多维数组中。这就是我被困的地方。它需要像这样;
[0] (entry of rule)
[number],[chain],[protocol]...
[1]
[number],[chain],[protocol]
我怎样才能最有效地做到这一点?
-- 更新的代码 --
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("\n", $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);
}
}
-- 输出--
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
请您参考如下方法:
我假设您的正则表达式是正确的。您实际上是使用 $commands .= <some text> 将所有内容附加到同一字符串. 而不是将它附加到同一个字符串,你应该制作 $commands数组。然后你想为你进入的每一行实例化一个新数组($line)。 push你想保留在你的 $line 上的东西数组,在每一行的末尾你 array_push($commands, $line)
Array_push() : http://php.net/manual/en/function.array-push.php
这可能是您的 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);
}
代码未经测试,但您应该知道我要去哪里。
您的代码:
//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}\n" to $commands
$commands .= "iptables {$line}\n";
//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
}
您的初始方法很好。并取决于您的控制台如何返回可预测的 值,你要么按照你的方法使用正则表达式(但随后实际使用结果),要么你只是采用惰性方法并使用我建议的方法。
请注意 CONTINUE实际上会打破当前循环,并进入下一次迭代。
$array = array(1, 2, 3, 4, 5);
foreach($array as $number){
if($number < 3){
continue;
}
print($number .'\n');
}
结果将是:
3\n
4\n
5\n
as continue 实际上完全停止了在您的 foreach() 中的这种尝试
