3

I am trying to write a PHP script which executes shell functions for reporting. I am starting with disk usage report.

I want in following format.

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

Nothing else.

My script is:

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

and its output is like below:

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

How can I convert that output into my formatted output?

3 Answers 3

3

Something like this:

// 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>";

Should get you going anyway

Sign up to request clarification or add additional context in comments.

Comments

3

Why not use PHP's disk_total_space() and disk_free_space() functions instead? Otherwise, one way is you could parse $output into a multidimensional array using preg_ functions, convert 'g', 'k', 'm' characters to numbers, and total the column. Alternatively, if the column space is a single tab character or a set number of spaces, you could just explode() each line into a multidimensional array.

1 Comment

+1 Might not be exactly what the OP wanted, but IMHO a better solution to use built-in functions of PHP instead of rolling your own tailor-made solution (and using shell_exec() ;))
0

The shell_exec() call doesn't need to include -T because the type values aren't desired in the output.

The -h option is helpful as it is used to make the size values human readable.

To output the data into readable columns, use left/right padding with printf(). My script will hardcode the columns to an arbitrarily selected width (right padding paths to 20 characters and left padding size values to 10 characters). To determine the most appropriate dynamic widths, you'll need to run through all values, cache the greatest string length, then apply the calculated amount of whitespace to each value in another loop.

On the first iteration, apply your custom column headers.

On all subsequent iterations, use sscanf() to parse the line into the desired values.

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')
    );
}

For anyone absolutely needing an AWK (initially developed by Alfred Aho, Peter J. Weinberger, Brian Kernighan) one-liner, use BEGIN to loop and NR (number of records) to check the iteration counter.

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}\'');

Either script above will output your dataset as:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.