456 lines
14 KiB
Bash
Executable file
456 lines
14 KiB
Bash
Executable file
#!/bin/sh
|
|
# Copyright (C) 2025 Michael Erdely All Rights Reserved.
|
|
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
# shellcheck disable=SC1091
|
|
. "$(dirname "$0")"/common.sh
|
|
|
|
assertHaveCommand column
|
|
|
|
# jscpd:ignore-start
|
|
if [ "$KERNEL" = "Linux" ] ; then
|
|
assertHaveCommand df
|
|
CMD='df -h --output=source,fstype,size,used,avail,pcent,itotal,iused,iavail,ipcent,target'
|
|
# shellcheck disable=SC2016
|
|
BEGIN='BEGIN { OFS = "\t" }'
|
|
# shellcheck disable=SC2016
|
|
FILTER_PRE='$2=="btrfs"&&btrfs[$1]==1{next}$2=="btrfs"{btrfs[$1]=1}'
|
|
# shellcheck disable=SC2016
|
|
FILTER_POST='/(devtmpfs|tmpfs|efivars)/ {next}'
|
|
# shellcheck disable=SC2016
|
|
PRINTF='
|
|
{
|
|
if($0 ~ /^Filesystem.*/){
|
|
sub("Mounted on","MountedOn",$0);
|
|
}
|
|
match($0,/^(.*[^ ]) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+%|-) +(.*)$/,a);
|
|
if (length(a) != 0)
|
|
{ printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],a[10],a[11];}
|
|
}'
|
|
|
|
elif [ "$KERNEL" = "SunOS" ] ; then
|
|
assertHaveCommandGivenPath /usr/bin/df
|
|
CMD_1='eval /usr/bin/df -n ; /usr/bin/df -g'
|
|
CMD_2='/usr/bin/df -h'
|
|
|
|
# shellcheck disable=SC2016
|
|
BEGIN='BEGIN { OFS = "\t" }'
|
|
#Filters out Inode info from df -g output -> inodes = Value just before "total files" & ifree = Value just before "free files"
|
|
# shellcheck disable=SC2016
|
|
INODE_FILTER='
|
|
/^\// {key=$1}
|
|
{
|
|
for(i=1;i<=NF;i++)
|
|
{
|
|
if($i == "total" && $(i+1) == "files")
|
|
{
|
|
inodes=$(i-1)
|
|
}
|
|
if($i == "free" && $(i+1) == "files")
|
|
{
|
|
ifree=$(i-1)
|
|
}
|
|
}
|
|
}
|
|
{if(NR%5==0) sub("\\(.*\\)?", "", key); print "INODE:" key, inodes, ifree}'
|
|
|
|
CMD="${CMD_1} | ${AWK} '${INODE_FILTER}'; ${CMD_2}"
|
|
FILTER_PRE='/libc_psr/ {next}'
|
|
|
|
#Maps fsType and inode info from the output of INODE_FILTER
|
|
# shellcheck disable=SC2016
|
|
MAP_FS_TO_TYPE='/INODE:/ {MoInodes[$1] = $2; MoIFree[$1] = $3;} /: / {
|
|
for(i=1;i<=NF;i++){
|
|
if($i ~ /^\/.*/)
|
|
keyCol=i;
|
|
else if($i ~ /[a-zA-Z0-9]/)
|
|
valueCol=i;
|
|
}
|
|
if($keyCol ~ /^\/.*:/)
|
|
fsTypes[substr($keyCol,1,length($keyCol)-1)] = $valueCol;
|
|
else
|
|
fsTypes[$keyCol]=$valueCol;
|
|
}'
|
|
|
|
#Append Type and Inode headers to the main header and print respective fields from values stored in MAP_FS_TO_TYPE variables
|
|
# shellcheck disable=SC2016
|
|
PRINTF='
|
|
{
|
|
if($0 ~ /^Filesystem.*/){
|
|
for(i=1;i<=NF;i++){
|
|
if($i=="Mounted" && $(i+1)=="on"){
|
|
mountedCol=i;
|
|
sub("Mounted on","MountedOn",$0);
|
|
}
|
|
}
|
|
$(NF+1)="Type";
|
|
$(NF+1)="INodes";
|
|
$(NF+1)="IUsed";
|
|
$(NF+1)="IFree";
|
|
$(NF+1)="IUsePct";
|
|
|
|
print $0;
|
|
}
|
|
}
|
|
{
|
|
for(i=1;i<=NF;i++)
|
|
{
|
|
if($i ~ /^\/\S*/ && i==mountedCol && !(fsTypes[$mountedCol]~/(devfs|ctfs|proc|mntfs|objfs|lofs|fd|tmpfs)/) && !($0 ~ /.*\/proc.*/)){
|
|
$(NF+1)=fsTypes[$mountedCol];
|
|
$(NF+1)=MoInodes["INODE:"$mountedCol];
|
|
$(NF+1)=MoInodes["INODE:"$mountedCol]-MoIFree["INODE:"$mountedCol];
|
|
$(NF+1)=MoIFree["INODE:"$mountedCol];
|
|
|
|
if(MoInodes["INODE:"$mountedCol]>0)
|
|
{
|
|
$(NF+1)=int(((MoInodes["INODE:"$mountedCol]-MoIFree["INODE:"$mountedCol])*100)/MoInodes["INODE:"$mountedCol])"%";
|
|
}
|
|
else
|
|
{
|
|
$(NF+1)="0";
|
|
}
|
|
|
|
print $0;
|
|
}
|
|
}
|
|
}'
|
|
|
|
elif [ "$KERNEL" = "AIX" ] ; then
|
|
assertHaveCommandGivenPath /usr/bin/df
|
|
CMD='eval /usr/sysv/bin/df -n ; /usr/bin/df -kP -F %u %f %z %l %n %p %m'
|
|
|
|
#Maps fsType
|
|
# shellcheck disable=SC2016
|
|
MAP_FS_TO_TYPE='/: / {
|
|
key = "";
|
|
value = "";
|
|
foundColon = 0;
|
|
|
|
for (i = 1; i <= NF; i++) {
|
|
if (!foundColon) {
|
|
if ($i ~ /:$/) {
|
|
clean = $i;
|
|
sub(/:$/, "", clean);
|
|
if (clean != "") {
|
|
key = (key ? key " " : "") clean;
|
|
}
|
|
foundColon = 1;
|
|
} else {
|
|
if ($i != "") {
|
|
key = (key ? key " " : "") $i;
|
|
}
|
|
}
|
|
} else if ($i ~ /[a-zA-Z0-9]/ && value == "") {
|
|
value = $i;
|
|
}
|
|
}
|
|
|
|
gsub(/ /, " ", key);
|
|
|
|
fsTypes[key] = value;
|
|
}'
|
|
|
|
|
|
# shellcheck disable=SC2016
|
|
BEGIN='BEGIN {
|
|
OFS = "\t";
|
|
printedHeader = 0;
|
|
}'
|
|
# Append Type and Inode headers to the main header and print respective fields from values stored in MAP_FS_TO_TYPE variables
|
|
# shellcheck disable=SC2016
|
|
PRINTF='
|
|
function fromKB(KB) {
|
|
MB = KB/1024;
|
|
if (MB<1024) return MB "M";
|
|
GB = MB/1024;
|
|
if (GB<1024) return GB "G";
|
|
TB = GB/1024; return TB "T"
|
|
}
|
|
{
|
|
if ($0 ~ /^Filesystem.*/) {
|
|
if (!printedHeader) {
|
|
sub("%iused", "IUsePct", $0);
|
|
header_field_count = NF;
|
|
|
|
for (i = 1; i <= NF; i++) {
|
|
if ($i == "iused") iusedCol = i;
|
|
if ($i == "ifree") ifreeCol = i;
|
|
if ($i == "Mounted" && $(i + 1) == "on") {
|
|
mountedCol = i;
|
|
sub("Mounted on", "MountedOn", $0);
|
|
}
|
|
}
|
|
|
|
$(NF + 1) = "Type";
|
|
$(NF + 1) = "INodes";
|
|
printf "%-50s %-8s %-8s %-8s %-10s %-8s %-8s %-7s %-25s %-10s %-8s\n",
|
|
"Filesystem", "Size", "Used", "Avail", "Capacity",
|
|
"iused", "ifree", "IUsePct","MountedOn", "Type", "INodes";
|
|
printedHeader = 1;
|
|
}
|
|
next;
|
|
}
|
|
|
|
if (NF >= 8 && $0 !~ /\(.*\)/ && $0 !~ /^.* on \/.* \(/) {
|
|
found = 0
|
|
for (i = 1; i <= NF - 6; i++) {
|
|
cond = ($(i) ~ /^[0-9.]+[KMGTPBi]*$/ || $(i) == "-") &&
|
|
($(i+1) ~ /^[0-9.]+[KMGTPBi]*$/ || $(i+1) == "-") &&
|
|
($(i+2) ~ /^[0-9.]+[KMGTPBi]*$/ || $(i+2) == "-") &&
|
|
($(i+3) ~ /^[0-9]+%$/ || $(i+3) == "-") &&
|
|
($(i+4) ~ /^[0-9]+(\.[0-9]+)?[kMGTPBi]?$/ || $(i+4) == "-") &&
|
|
($(i+5) ~ /^[0-9]+(\.[0-9]+)?[kMGTPBi]?$/ || $(i+5) == "-") &&
|
|
($(i+6) ~ /^[0-9]+%$/ || $(i+6) == "-")
|
|
if (cond) {
|
|
start = i
|
|
found = 1
|
|
break
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
next
|
|
}
|
|
|
|
fs = $1
|
|
for (j = 2; j < start; j++) {
|
|
print($j)
|
|
fs = fs " " $j
|
|
}
|
|
gsub("^/dev/", "", fs);
|
|
gsub("s[0-9]+$", "", fs);
|
|
|
|
size = fromKB($(start))
|
|
used = fromKB($(start + 1))
|
|
avail = fromKB($(start + 2))
|
|
capacity = $(start + 3)
|
|
iused = $(start + 4)
|
|
ifree = $(start + 5)
|
|
iusepct = $(start + 6)
|
|
|
|
mounted = $(start + 7)
|
|
for (k = start + 8; k <= NF; k++) {
|
|
mounted = mounted " " $k
|
|
}
|
|
|
|
fstype = (mounted in fsTypes) ? fsTypes[mounted] : "-";
|
|
inodes = iused + ifree;
|
|
|
|
printf "%-50s %-8s %-8s %-8s %-10s %-8s %-8s %-7s %-25s %-10s %-8s\n",
|
|
fs, size, used, avail, capacity,
|
|
iused, ifree, iusepct, mounted, fstype, inodes;
|
|
}
|
|
}'
|
|
|
|
elif [ "$KERNEL" = "HP-UX" ] ; then
|
|
assertHaveCommand df
|
|
assertHaveCommand fstyp
|
|
CMD='df -Pk'
|
|
# shellcheck disable=SC2016
|
|
MAP_FS_TO_TYPE='{c="fstyp " $1; c | getline ft; close(c);}'
|
|
# shellcheck disable=SC2016
|
|
HEADER='Filesystem\tType\tSize\tUsed\tAvail\tUsePct\tINodes\tIUsed\tIFree\tIUsePct\tMountedOn'
|
|
# shellcheck disable=SC2016
|
|
HEADERIZE='/^Filesystem/ {print header; next}'
|
|
# shellcheck disable=SC2016
|
|
FORMAT='{size=$2; used=$3; avail=$4; usePct=$5; mountedOn=$6; $2=ft; $3=size; $4=used; $5=avail; $6=usePct; $7=mountedOn}'
|
|
# shellcheck disable=SC2016
|
|
FILTER_POST='($2 ~ /^(tmpfs)$/) {next}'
|
|
# shellcheck disable=SC2016
|
|
PRINTF='{printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11}'
|
|
elif [ "$KERNEL" = "Darwin" ] ; then
|
|
assertHaveCommand mount
|
|
assertHaveCommand df
|
|
CMD='eval mount -t nocddafs,autofs,devfs,fdesc,nfs; df -h -T nocddafs,autofs,devfs,fdesc,nfs'
|
|
# shellcheck disable=SC2016
|
|
BEGIN='BEGIN {
|
|
OFS = "\t";
|
|
printedHeader = 0;
|
|
}'
|
|
#Maps fsType
|
|
# shellcheck disable=SC2016
|
|
MAP_FS_TO_TYPE='/ on / {
|
|
key = "";
|
|
value = "";
|
|
|
|
for (i = 1; i <= NF; i++) {
|
|
if ($i == "on") {
|
|
# Start capturing key from the next field
|
|
j = i + 1;
|
|
while (j <= NF && $(j) !~ /^\(/) {
|
|
key = (key == "") ? $(j) : key " " $(j);
|
|
j++;
|
|
}
|
|
}
|
|
|
|
if ($i ~ /^\(/) {
|
|
value = substr($i, 2); # Remove starting (
|
|
# Optionally remove trailing comma/parenthesis if needed
|
|
if (substr(value, length(value), 1) == "," || substr(value, length(value), 1) == ")") {
|
|
value = substr(value, 1, length(value)-1);
|
|
}
|
|
}
|
|
}
|
|
|
|
gsub(/ /, " ", key); # Replace spaces with
|
|
fsTypes[key] = value;
|
|
}'
|
|
# Append Type and Inode headers to the main header and print respective fields from values stored in MAP_FS_TO_TYPE variables
|
|
# shellcheck disable=SC2016
|
|
PRINTF='{
|
|
if ($0 ~ /^Filesystem.*/) {
|
|
if (!printedHeader) {
|
|
sub("%iused", "IUsePct", $0);
|
|
header_field_count = NF;
|
|
|
|
for (i = 1; i <= NF; i++) {
|
|
if ($i == "iused") iusedCol = i;
|
|
if ($i == "ifree") ifreeCol = i;
|
|
if ($i == "Mounted" && $(i + 1) == "on") {
|
|
mountedCol = i;
|
|
sub("Mounted on", "MountedOn", $0);
|
|
}
|
|
}
|
|
|
|
$(NF + 1) = "Type";
|
|
$(NF + 1) = "INodes";
|
|
printf "%-50s %-8s %-8s %-8s %-10s %-8s %-8s %-7s %-25s %-10s %-8s\n",
|
|
"Filesystem", "Size", "Used", "Avail", "Capacity",
|
|
"iused", "ifree", "IUsePct","MountedOn", "Type", "INodes";
|
|
printedHeader = 1;
|
|
}
|
|
next;
|
|
}
|
|
|
|
if (NF >= 8 && $0 !~ /\(.*\)/ && $0 !~ /^.* on \/.* \(/) {
|
|
found = 0
|
|
for (i = 1; i <= NF - 6; i++) {
|
|
cond = ($(i) ~ /^[0-9.]+[KMGTPBi]*$/ || $(i) == "-") &&
|
|
($(i+1) ~ /^[0-9.]+[KMGTPBi]*$/ || $(i+1) == "-") &&
|
|
($(i+2) ~ /^[0-9.]+[KMGTPBi]*$/ || $(i+2) == "-") &&
|
|
($(i+3) ~ /^[0-9]+%$/ || $(i+3) == "-") &&
|
|
($(i+4) ~ /^[0-9]+(\.[0-9]+)?[kMGTPBi]?$/ || $(i+4) == "-") &&
|
|
($(i+5) ~ /^[0-9]+(\.[0-9]+)?[kMGTPBi]?$/ || $(i+5) == "-") &&
|
|
($(i+6) ~ /^[0-9]+%$/ || $(i+6) == "-")
|
|
if (cond) {
|
|
start = i
|
|
found = 1
|
|
break
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
next
|
|
}
|
|
|
|
fs = $1
|
|
for (j = 2; j < start; j++) {
|
|
fs = fs " " $j
|
|
}
|
|
gsub("^/dev/", "", fs);
|
|
gsub("s[0-9]+$", "", fs);
|
|
|
|
size = $(start)
|
|
used = $(start + 1)
|
|
avail = $(start + 2)
|
|
capacity = $(start + 3)
|
|
iused = $(start + 4)
|
|
ifree = $(start + 5)
|
|
iusepct = $(start + 6)
|
|
|
|
mounted = $(start + 7)
|
|
for (k = start + 8; k <= NF; k++) {
|
|
mounted = mounted " " $k
|
|
}
|
|
|
|
fstype = (mounted in fsTypes) ? fsTypes[mounted] : "-";
|
|
inodes = iused + ifree;
|
|
|
|
printf "%-50s %-8s %-8s %-8s %-10s %-8s %-8s %-7s %-25s %-10s %-8s\n",
|
|
fs, size, used, avail, capacity,
|
|
iused, ifree, iusepct, mounted, fstype, inodes;
|
|
}
|
|
}'
|
|
|
|
|
|
elif [ "$KERNEL" = "OpenBSD" ] ; then
|
|
assertHaveCommand mount
|
|
assertHaveCommand df
|
|
CMD='eval mount -t nodevfs,nonfs,noswap,nocd9660; df -ih -t nodevfs,nonfs,noswap,nocd9660'
|
|
# shellcheck disable=SC2016
|
|
BEGIN='BEGIN { OFS = "\t" }'
|
|
#Maps fsType
|
|
# shellcheck disable=SC2016
|
|
MAP_FS_TO_TYPE='/ on / {
|
|
for (i = 1; i <= NF; i++){
|
|
if ($i == "on" && $(i + 1) ~ /^\/.*/)
|
|
key = $(i + 1);
|
|
}
|
|
fsTypes[key] = $5;
|
|
}'
|
|
# Append Type and Inode headers to the main header and print respective fields from values stored in MAP_FS_TO_TYPE variables
|
|
# shellcheck disable=SC2016
|
|
PRINTF='/^Filesystem/ {
|
|
print "Filesystem\tType\tSize\tUsed\tAvail\tUse%\tInodes\tIUsed\tIFree\tIUse%\tMountedOn";
|
|
}
|
|
$0 !~ /^Filesystem/ && $0 !~ / on / {
|
|
printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", $1, fsTypes[$NF], $2, $3, $4, $5, $6+$7, $6, $7, $8, $9;
|
|
}'
|
|
|
|
elif [ "$KERNEL" = "FreeBSD" ] ; then
|
|
assertHaveCommand mount
|
|
assertHaveCommand df
|
|
CMD='eval mount -t nodevfs,nonfs,noswap,nocd9660; df -ih -t nodevfs,nonfs,noswap,nocd9660'
|
|
# shellcheck disable=SC2016
|
|
BEGIN='BEGIN { OFS = "\t" }'
|
|
#Maps fsType
|
|
# shellcheck disable=SC2016
|
|
MAP_FS_TO_TYPE='/ on / {
|
|
for(i=1;i<=NF;i++){
|
|
if($i=="on" && $(i+1) ~ /^\/.*/)
|
|
{
|
|
key=$(i+1);
|
|
}
|
|
if($i ~ /^\(/)
|
|
value=substr($i,2,length($i)-2);
|
|
}
|
|
fsTypes[key]=value;
|
|
}'
|
|
# Append Type and Inode headers to the main header and print respective fields from values stored in MAP_FS_TO_TYPE variables
|
|
# shellcheck disable=SC2016
|
|
PRINTF='
|
|
{
|
|
if($0 ~ /^Filesystem.*/){
|
|
sub("%iused","IUsePct",$0);
|
|
|
|
for(i=1;i<=NF;i++){
|
|
if($i=="iused") iusedCol=i;
|
|
if($i=="ifree") ifreeCol=i;
|
|
|
|
if($i=="Mounted" && $(i+1)=="on"){
|
|
mountedCol=i;
|
|
sub("Mounted on","MountedOn",$0);
|
|
}
|
|
}
|
|
$(NF+1)="Type";
|
|
$(NF+1)="INodes";
|
|
print $0;
|
|
}
|
|
}
|
|
{
|
|
for(i=1;i<=NF;i++)
|
|
{
|
|
if($i ~ /^\/\S*/ && i==mountedCol){
|
|
$(NF+1)=fsTypes[$mountedCol];
|
|
$(NF+1)=$iusedCol+$ifreeCol;
|
|
print $0;
|
|
}
|
|
}
|
|
}'
|
|
|
|
fi
|
|
# jscpd:ignore-end
|
|
|
|
$CMD | tee "$TEE_DEST" | $AWK "$BEGIN $HEADERIZE $FILTER_PRE $MAP_FS_TO_TYPE $FORMAT $FILTER_POST $NORMALIZE $PRINTF" header="$HEADER" | column -t
|
|
echo "Cmd = [$CMD]; | $AWK '$BEGIN $HEADERIZE $FILTER_PRE $MAP_FS_TO_TYPE $FORMAT $FILTER_POST $NORMALIZE $PRINTF' header=\"$HEADER\"" >> "$TEE_DEST"
|