如何在PHP中操作Shell输出

3

我正在尝试编写一个PHP脚本,其中包含一些像报告之类的shell函数。因此,我从磁盘使用情况报告开始。

我希望以以下格式呈现:

drive path ------------total-size --------free-space

除此之外无他

我的脚本是

$output = shell_exec('df -h -T');
echo "<pre>$output</pre>";

并且它的输出如下所示。
Filesystem    Type    Size  Used Avail Use% Mounted on
/dev/sda6     ext3     92G  6.6G   81G   8% /
none      devtmpfs    3.9G  216K  3.9G   1% /dev
none         tmpfs    4.0G  176K  4.0G   1% /dev/shm
none         tmpfs    4.0G  1.1M  4.0G   1% /var/run
none         tmpfs    4.0G     0  4.0G   0% /var/lock
none         tmpfs    4.0G     0  4.0G   0% /lib/init/rw
/dev/sdb1     ext3    459G  232G  204G  54% /media/Server
/dev/sdb2  fuseblk    466G  254G  212G  55% /media/BACKUPS
/dev/sda5  fuseblk    738G  243G  495G  33% /media/virtual_machines

我该如何将输出转换为我的格式化输出?
3个回答

3
为什么不使用PHP的disk_total_space()disk_free_space()函数呢?否则,一种方法是使用preg_函数将$output解析为多维数组,将'g'、'k'、'm'字符转换为数字,并总计列。或者,如果列空间是单个制表符或一组空格,您可以将每行explode()成一个多维数组。

+1 可能不完全符合 OP 的要求,但在我看来,使用 PHP 的内置函数而不是自己编写定制解决方案(并使用 shell_exec() ;))是更好的解决方案。 - Sune Rievers

3

类似这样:

// Use awk to pull out the columns you actually want
$output = shell_exec('df -h -T | awk \'{print $1 " " $3 " " $5}\'');
// Split the result into an array by lines (removing the final linefeed)
$drives = split("[\r|\n]", trim($output));
// Chuck away the unused first line
array_shift($drives);

echo "<pre>drive path\ttotal-size\tfree-space\n";

foreach($drives as $drive) {
    // Explode the individual lines to get the values
    $values = explode(" ", $drive);
    echo $values[0], "\t", $values[1], "\t", $values[2], "\n";
}

echo "</pre>";

无论如何,这应该能让你开始了。


0
shell_exec()调用不需要包含-T,因为输出中不需要类型值。 -h选项很有用,它用于使大小值可读。
要将数据输出为可读的列,可以使用printf()进行左/右填充。我的脚本将硬编码列宽度为任意选择的宽度(将路径右填充到20个字符,将大小值左填充到10个字符)。要确定最合适的动态宽度,您需要遍历所有值,缓存最大字符串长度,然后在另一个循环中将计算出的空格数量应用于每个值。
在第一次迭代中,应用自定义列标题。
在所有后续迭代中,使用sscanf()解析行为所需的值。
foreach (explode(PHP_EOL, rtrim(shell_exec('df -h'))) as $i => $line) {
    vprintf(
        "%-20s %10s %10s\n",
        !$i
            ? ['drive path', 'total-size', 'free-space']
            : sscanf($line, '%s %s %*s %s')
    );
}

对于那些绝对需要一个AWK(最初由Alfred Aho,Peter J. Weinberger,Brian Kernighan开发)一行代码的人,可以使用BEGIN来循环,使用NR(记录数)来检查迭代计数器。
echo shell_exec('df -h | awk \'BEGIN {printf "%-20s %10s %10s\n", "drive path", "total-size", "free-space"} NR>1 {printf "%-20s %10s %10s\n", $1, $2, $4}\'');

无论上面的脚本哪一个,都会将您的数据集输出为:
drive path          total-size free-space
/dev/sda6                  92G       6.6G
none                      3.9G       216K
none                      4.0G       176K
none                      4.0G       1.1M
none                      4.0G          0
none                      4.0G          0
/dev/sdb1                 459G       232G
/dev/sdb2                 466G       254G
/dev/sda5                 738G       243G

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接