Check cuda version in bash scripts - linux

Basically, I want to achieve a version control on CUDA, similar to this:
if python3 -c 'import sys; assert sys.version_info == (3,8)' > /dev/null
then
exit;
fi
In my case, the CUDA version shown by ncvv -V must be >=11.3
according to this answer we could get cuda version via:
CUDA_VERSION=$(nvcc --version | sed -n 's/^.*release \([0-9]\+\.[0-9]\+\).*$/\1/p')
from the output of nvcc -V, in which the version is given after the key word "release":
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2021 NVIDIA Corporation
Built on Sun_Mar_21_19:15:46_PDT_2021
Cuda compilation tools, release 11.3, V11.3.58
Build cuda_11.3.r11.3/compiler.29745058_0
But I am having trouble on further comparing the version with 11.3

I figured out a solution via python:
import os,re
b = os.popen('nvcc -V').readlines()
>>> b
['nvcc: NVIDIA (R) Cuda compiler driver\n', 'Copyright (c) 2005-2021 NVIDIA Corporation\n', 'Built on Sun_Mar_21_19:15:46_PDT_2021\n', 'Cuda compilation tools, release 11.3, V11.3.58\n', 'Build cuda_11.3.r11.3/compiler.29745058_0\n']
b = str(b)
c = re.findall(r"[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}",b)
>>> c[0]
'11.3.58'
cc = c[0].split(".")
>>> cc
['11', '3', '58']
>>> [int(x) for x in cc] >[11,3,0]
True
>>> [int(x) for x in cc] >[11,4,0]
False
>>> [int(x) for x in cc] >[8,4,0]
True
>>> [int(x) for x in cc] >[8,314,0]
True
to sum up:
#!/usr/bin/env bash
if python3 -c 'import os,re; assert [int(x) for x in re.findall(r"[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}", str(os.popen("nvcc -V").readlines()))[0].split(".")] >[11,3,0]'> /dev/null
then
echo '11'
else
echo '22'
fi

Awk will allow you to deal with the decimal places:
nvcc --version | awk '/V([0-9]+.){2}.[0-9]+$/ { sub("V","",$NF);if ($NF>11.3) { exit 0 } else { exit 1 } }'
Run the output of the nvcc command into awk and then process lines with V followed by any number of digits, a full stop (2 times) and then any number of digits followed by an end of line (this regular expression may need amending for your use case)
Processing the resulting line, we take the last field and remove the "V" using awk's sub function. We then compare the new field to see whether it is greater than 11.3. If it is exit with 0, otherwise exit with 1.
Finally, within your script, you can utilise the command result with:
if $(nvcc --version | awk '/V([0-9]+.){2}.[0-9]+$/ { sub("V","",$NF);if ($NF>11.3) { exit 0 } else { exit 1 } }')
then
exit
fi

nvcc --version | mawk 'NF*=/ release /' OFS='\f' FS='^.+[Vv]|[.]'
11
3
58
and this solution is very adaptable to other version number scenarios too - say i wanna extract out the xnu version (i.e. very-core-macos) out :
# this is one single line, re-formatted for readability
Darwin 21.6.0 Darwin Kernel Version 21.6.0: Sat Jun 18 17:07:22 PDT 2022;
root:xnu-8020.140.41~1/RELEASE_ARM64_T6000 arm64 arm
uname -mprsv |
mawk 'NF*=/[:]xnu[-]/' OFS='\f' FS='^.+[:]xnu[-]|[.~]|[/].+$'
8020
140
41
1

Related

fortran: Error: Type mismatch between actual argument at (1) and actual argument at (2) (INTEGER(8)/INTEGER(2))

I am a beginner of Fortran and running a model written by Fortran. When I tried to compile it, I got an error message like:
libtool: link: (cd ".libs" && rm -f "libgrib_api_f77.so" && ln -s "libgrib_api_f77.so.1.0.0" "libgrib_api_f77.so")
libtool: link: ar cru .libs/libgrib_api_f77.a grib_fortran.o grib_f77.o
libtool: link: ranlib .libs/libgrib_api_f77.a
libtool: link: ( cd ".libs" && rm -f "libgrib_api_f77.la" && ln -s "../libgrib_api_f77.la" "libgrib_api_f77.la" )
gfortran -c -o same_int_long.o same_int_long.f90
same_int_long.f90:23:18:
17 | call check_long(x2(1),x2(2),ret)
| 2
......
23 | call check_long(x4(1),x4(2),ret)
| 1
Error: Type mismatch between actual argument at (1) and actual argument at (2) (INTEGER(4)/INTEGER(2)).
same_int_long.f90:29:18:
17 | call check_long(x2(1),x2(2),ret)
| 2
......
29 | call check_long(x8(1),x8(2),ret)
| 1
Error: Type mismatch between actual argument at (1) and actual argument at (2) (INTEGER(8)/INTEGER(2)).
same_int_long.f90:51:17:
45 | call check_int(x2(1),x2(2),ret)
| 2
......
51 | call check_int(x4(1),x4(2),ret)
| 1
Error: Type mismatch between actual argument at (1) and actual argument at (2) (INTEGER(4)/INTEGER(2)).
same_int_long.f90:57:17:
45 | call check_int(x2(1),x2(2),ret)
| 2
......
57 | call check_int(x8(1),x8(2),ret)
| 1
Error: Type mismatch between actual argument at (1) and actual argument at (2) (INTEGER(8)/INTEGER(2)).
make[2]: *** [Makefile:546: same_int_long.o] Error 1
make[2]: Leaving directory '/gpfs/home3/eccei339/snellius_surfex/open_SURFEX_V8_1/src/LIB/grib_api-1.17.0-Source/fortran'
make[1]: *** [Makefile:604: all-recursive] Error 1
make[1]: Leaving directory '/gpfs/home3/eccei339/snellius_surfex/open_SURFEX_V8_1/src/LIB/grib_api-1.17.0-Source'
make: *** [Makefile:398: /home/eccei339/snellius_surfex/open_SURFEX_V8_1/src/LIB/grib_api-1.17.0-Source-LXgfortran/include/grib_api.mod] Error 2
What I did is basically following the installation of the model:
Step1
(base) [eccei339#int3 ~]$ mkdir snellius_surfex
(base) [eccei339#int3 ~]$ cp open_surfex_v8_1_20200107.tar-2.gz snellius_surfex/
(base) [eccei339#int3 ~]$ cd snellius_surfex/
(base) [eccei339#int3 snellius_surfex]$ tar zxvf open_surfex_v8_1_20200107.tar-2.gz
…(omit the tar zxvf logging information)
Step 2: some essential env variable
(base) [eccei339#int3 snellius_surfex]$ export VER_MPI="NOMPI"
(base) [eccei339#int3 snellius_surfex]$ export OMP_NUM_THREADS=1
(base) [eccei339#int3 snellius_surfex]$ module load 2021
(base) [eccei339#int3 snellius_surfex]$ module load GCC/10.3.0
(base) [eccei339#int3 snellius_surfex]$ ls
open_SURFEX_V8_1 open_surfex_v8_1_20200107.tar-2.gz
(here I exported some necessary envi var following the instructions of installation of the software)
Step 3: configure
(base) [eccei339#int3 snellius_surfex]$ cd open_SURFEX_V8_1/src/
(base) [eccei339#int3 src]$ ls
ASSIM Makefile Rules.bullXI15.mk Rules.MCgfortran.mk SURFEX
configure Makefile.SURFEX.mk Rules.bullXI16.mk Rules.SX8.mk
FORC OFFLIN Rules.LXgfortran.mk Rules.zgfortran.mk
include Rules.AIX64.mk Rules.LXifort.mk Rules.zifort.mk
LIB Rules.bgfortran.mk Rules.LXpgi.mk scripts
(base) [eccei339#int3 src]$ ./configure
(omit the long logging info of the “configure” command)
(base) [eccei339#int3 src]$ . ../conf/profile_surfex-LXgfortran-SFX-V8-1-1-NOMPI-OMP-O2-X0
(an essential step following the instructions of installation of the software)
Step 4: make the master
(base) [eccei339#int3 src]$ make
find: ‘/home/eccei339/snellius_surfex/open_SURFEX_V8_1/src/dir_obj-LXgfortran-SFX-V8-1-1-NOMPI-OMP-O2-X0/MASTER’: No such file or directory
cd /home/eccei339/snellius_surfex/open_SURFEX_V8_1/src/LIB/grib_api-1.17.0-Source && LDFLAGS= FCFLAGS= CPPFLAGS="" \
./configure --disable-jpeg --prefix=/home/eccei339/snellius_surfex/open_SURFEX_V8_1/src/LIB/grib_api-1.17.0-Source-LXgfortran FC="gfortran" && \
make -j 1 clean && \
make -j 1 && \
make -j 1 install && \
make -j 1 clean
checking build system type... x86_64-unknown-linux-gnu
checking host system type... x86_64-unknown-linux-gnu
checking how to print strings... printf
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
(omit the long logging information, and the final lines are the error message shown in the beginning of this question description.)
I searched the Internet that this could be due to the GCC 10 is more strict than older GCC (I compiled this model last year with older GCC and made it, but failed this time because our server is transferred to a new system, thus the GCC is upgraded from older version to a new version). Some information from Google said that I could add something like this:
export FCFLAGS="-w -fallow-argument-mismatch -O2"
export FFLAGS="-w -fallow-argument-mismatch -O2"
But I tried it in the step 2 where I export some essential environmental variables, it still does not work. So I am wondering is there anybody who can help me? Thanks a lot!
Updates: the source code of grib_api-1.17.0-Source/fortran/same_int_long.f90 from http://distfiles.macports.org/grib_api/ is as following:
! Copyright 2005-2016 ECMWF.
!
! This software is licensed under the terms of the Apache Licence Version 2.0
! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
!
! In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
! virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
integer function kind_of_long()
integer(2), dimension(2) :: x2 = (/1, 2/)
integer(4), dimension(2) :: x4 = (/1, 2/)
integer(8), dimension(2) :: x8 = (/1, 2/)
character(len=1) :: ret
kind_of_long=-1
call check_long(x2(1),x2(2),ret)
if (ret == 't') then
kind_of_long=2
return
endif
call check_long(x4(1),x4(2),ret)
if (ret == 't') then
kind_of_long=4
return
endif
call check_long(x8(1),x8(2),ret)
if (ret == 't') then
kind_of_long=8
return
endif
end function kind_of_long
integer function kind_of_int()
integer(2), dimension(2) :: x2 = (/1, 2/)
integer(4), dimension(2) :: x4 = (/1, 2/)
integer(8), dimension(2) :: x8 = (/1, 2/)
character(len=1) :: ret
kind_of_int=-1
call check_int(x2(1),x2(2),ret)
if (ret == 't') then
kind_of_int=2
return
endif
call check_int(x4(1),x4(2),ret)
if (ret == 't') then
kind_of_int=4
return
endif
call check_int(x8(1),x8(2),ret)
if (ret == 't') then
kind_of_int=8
return
endif
end function kind_of_int
program same_int_long
integer ki,kl
ki=kind_of_int()
kl=kind_of_long()
if (ki /= kl) then
write (*,'(i1)') 0
else
write (*,'(i1)') 1
endif
end program same_int_long
Here is the full log information of make: https://drive.google.com/file/d/14rkj2ay39Rv84QBL6UDiSdlIAfhuEt_z/view?usp=sharing
This appened to me with a MPI fortran code. The cause is a decision from gcc developpers on what should be «good interfaces» see here.
Two solutions in my case :
Tells gfortran to ignore this concerns with option -fallow-argument-mismatch.
Use modern fortran interface (use mpi instead of include mpif.h)
I chose the latter.
What you are instantiating as an INTEGER is getting its value assigned by another (variable or declaration) integer of a different "byte" memory storage size.
e.g. in other languages int is 4 bytes and long is 8 bytes. (note) Fortran also has pointers alike C/C++
https://docs.oracle.com/cd/E19957-01/805-4939/6j4m0vna5/index.html
nb: You did not show the code that has the problem , somewhere around line 29 char 18 in source file same_int_long.f90 ??

What does geeko#buildhost signify in linux version?

On a linux server when checking the Linux version I see the following "geeko#buildhost"
Version: Linux version 4.12.14-95.54-default (geeko#buildhost) (gcc version 4.8.5 (SUSE Linux) ) #1 SMP Thu Jun 4 12:49:28 UTC 2020 (892ef1f)
What does this signify? does it have something to do with who built the os packages?
It is simply an identifier showing the user and host names where the kernel is compiled. The former is the result of executing whoami and the latter is the result of running uname -n. You can see how it is put together in init/version.c:
const char linux_banner[] =
"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "#"
LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
The variables are set by scripts/mkcompile_h:
if test -z "$KBUILD_BUILD_USER"; then
LINUX_COMPILE_BY=$(whoami | sed 's/\\/\\\\/')
else
LINUX_COMPILE_BY=$KBUILD_BUILD_USER
fi
if test -z "$KBUILD_BUILD_HOST"; then
LINUX_COMPILE_HOST=`uname -n`
else
LINUX_COMPILE_HOST=$KBUILD_BUILD_HOST
fi

Nodejs node binary core dumped(Ilegal Insatruction)

I am working on bit-bake environment. I am using nodejs ver 10.15.3
dest cpu == ppc64 linux
My problem is node binary core dumps and I am not able to identify the root cause. I am trying to compile nodejs for dest cpu(ppc64).
I am not sure but I guess there are runtime requirements which are not satisfied on the target machine.
below is my recipe:-
DESCRIPTION = "nodeJS Evented I/O for V8 JavaScript"
HOMEPAGE = "http://nodejs.org"
LICENSE = "MIT & BSD & Artistic-2.0"
LIC_FILES_CHKSUM = "file://LICENSE;md5=9ceeba79eb2ea1067b7b3ed16fff8bab"
DEPENDS = "openssl zlib icu"
DEPENDS_append_class-target = " nodejs-native"
inherit pkgconfig
COMPATIBLE_MACHINE_armv4 = "(!.*armv4).*"
COMPATIBLE_MACHINE_armv5 = "(!.*armv5).*"
COMPATIBLE_MACHINE_mips64 = "(!.*mips64).*"
SRC_URI = "http://nodejs.org/dist/v${PV}/node-v${PV}.tar.xz \
file://0001-Disable-running-gyp-files-for-bundled-deps.patch \
file://0003-Crypto-reduce-memory-usage-of-SignFinal.patch \
file://0004-Make-compatibility-with-gcc-4.8.patch \
file://0005-Link-atomic-library.patch \
file://0006-Use-target-ldflags.patch \
"
SRC_URI_append_class-target = " \
file://0002-Using-native-torque.patch \
"
SRC_URI[md5sum] = "d76210a6ae1ea73d10254947684836fb"
SRC_URI[sha256sum] = "4e22d926f054150002055474e452ed6cbb85860aa7dc5422213a2002ed9791d5"
S = "${WORKDIR}/node-v${PV}"
# v8 errors out if you have set CCACHE
CCACHE = ""
def map_nodejs_arch(a, d):
import re
if re.match('i.86$', a): return 'ia32'
elif re.match('x86_64$', a): return 'x64'
elif re.match('aarch64$', a): return 'arm64'
elif re.match('(powerpc64|ppc64le)$', a): return 'ppc64'
elif re.match('powerpc$', a): return 'ppc'
return a
ARCHFLAGS_arm = "${#bb.utils.contains('TUNE_FEATURES', 'callconvention-hard', '--with-arm-float-abi=hard', '--with-arm-float-abi=softfp', d)} \
${#bb.utils.contains('TUNE_FEATURES', 'neon', '--with-arm-fpu=neon', \
bb.utils.contains('TUNE_FEATURES', 'vfpv3d16', '--with-arm-fpu=vfpv3-d16', \
bb.utils.contains('TUNE_FEATURES', 'vfpv3', '--with-arm-fpu=vfpv3', \
'--with-arm-fpu=vfp', d), d), d)}"
GYP_DEFINES_append_mipsel = " mips_arch_variant='r1' "
ARCHFLAGS ?= ""
# Node is way too cool to use proper autotools, so we install two wrappers to forcefully inject proper arch cflags to workaround gypi
do_configure () {
rm -rf ${S}/deps/openssl
export LD="${CXX}"
GYP_DEFINES="${GYP_DEFINES}" export GYP_DEFINES
# $TARGET_ARCH settings don't match --dest-cpu settings
./configure --prefix=${prefix} --with-intl=system-icu --without-snapshot --shared-openssl --shared-zlib \
--dest-cpu="${#map_nodejs_arch(d.getVar('TARGET_ARCH'), d)}" \
--dest-os=linux \
${ARCHFLAGS}
}
do_compile () {
export LD="${CXX}"
oe_runmake BUILDTYPE=Release
}
do_install () {
oe_runmake install DESTDIR=${D}
}
do_install_append_class-native() {
# use node from PATH instead of absolute path to sysroot
# node-v0.10.25/tools/install.py is using:
# shebang = os.path.join(node_prefix, 'bin/node')
# update_shebang(link_path, shebang)
# and node_prefix can be very long path to bindir in native sysroot and
# when it exceeds 128 character shebang limit it's stripped to incorrect path
# and npm fails to execute like in this case with 133 characters show in log.do_install:
# updating shebang of /home/jenkins/workspace/build-webos-nightly/device/qemux86/label/open-webos-builder/BUILD-qemux86/work/x86_64-linux/nodejs-native/0.10.15-r0/image/home/jenkins/workspace/build-webos-nightly/device/qemux86/label/open-webos-builder/BUILD-qemux86/sysroots/x86_64-linux/usr/bin/npm to /home/jenkins/workspace/build-webos-nightly/device/qemux86/label/open-webos-builder/BUILD-qemux86/sysroots/x86_64-linux/usr/bin/node
# /usr/bin/npm is symlink to /usr/lib/node_modules/npm/bin/npm-cli.js
# use sed on npm-cli.js because otherwise symlink is replaced with normal file and
# npm-cli.js continues to use old shebang
sed "1s^.*^#\!/usr/bin/env node^g" -i ${D}${exec_prefix}/lib/node_modules/npm/bin/npm-cli.js
# Install the native torque to provide it within sysroot for the target compilation
install -d ${D}${bindir}
install -m 0755 ${S}/out/Release/torque ${D}${bindir}/torque
}
do_install_append_class-target() {
sed "1s^.*^#\!${bindir}/env node^g" -i ${D}${exec_prefix}/lib/node_modules/npm/bin/npm-cli.js
}
PACKAGES =+ "${PN}-npm"
FILES_${PN}-npm = "${exec_prefix}/lib/node_modules ${bindir}/npm ${bindir}/npx"
RDEPENDS_${PN}-npm = "bash python-shell python-datetime python-subprocess python-textutils \
python-compiler python-misc python-multiprocessing"
PACKAGES =+ "${PN}-systemtap"
FILES_${PN}-systemtap = "${datadir}/systemtap"
BBCLASSEXTEND = "native"
I am able to apply gdb to node binary below is the snapshot. It core dumps at this point.
Thread 1 "node" hit Breakpoint 10, v8::internal::Runtime_PromiseHookInit (args_length=2, args_object=0x3fffffffd188, isolate=0x11284ab0)
at /usr/src/debug/nodejs/8.17.0-r0/node-v8.17.0/deps/v8/src/runtime/runtime-promise.cc:132
132 /usr/src/debug/nodejs/8.17.0-r0/node-v8.17.0/deps/v8/src/runtime/runtime-promise.cc: No such file or directory.
(gdb) bt
#0 v8::internal::Runtime_PromiseHookInit (args_length=2, args_object=0x3fffffffd188, isolate=0x11284ab0) at /usr/src/debug/nodejs/8.17.0-r0/node-v8.17.0/deps/v8/src/runtime/runtime-promise.cc:132
#1 0x000003c7b3f04134 in ?? ()
(gdb) c
Continuing.
Nodejs is not supported on PPC64 LE architecture. There is only support for the Big Endian platform on PPC architecture till 7.9 Version.

SNMP sysObjectID not translated when using Python3 easysnmp module

When I query SNMP sysObjectID using easysnmp module, then returned value is in numerical notation:
$ python3
Python 3.5.3 (default, Jan 19 2017, 14:11:04)
[GCC 6.3.0 20170118] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from easysnmp import Session
>>> session = Session(hostname="r1", community='public', version=2)
>>> session.get('sysObjectID.0')
<SNMPVariable value='.1.3.6.1.4.1.2636.1.1.1.2.21' (oid='sysObjectID', oid_index='0', snmp_type='OBJECTID')>
>>>
However, this does not seem to be because easysnmp is not able to find the correct MIB file. When I put the commands above into a file and execute it with strace, then correct MIB is accessed:
$ strace 2>&1 -f -e open python3 snmp_test.py | grep mib-jnx-chas-defines.txt
open("/usr/share/snmp/mibs/JuniperMibs_from_Juniper/mib-jnx-chas-defines.txt", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOTDIR (Not a directory)
open("/usr/share/snmp/mibs/JuniperMibs_from_Juniper/mib-jnx-chas-defines.txt", O_RDONLY) = 4
open("/usr/share/snmp/mibs/JuniperMibs_from_Juniper/mib-jnx-chas-defines.txt", O_RDONLY) = 3
$
I can double-check this using snmpget:
$ snmpget -v 2c -c public r1 sysObjectID.0
SNMPv2-MIB::sysObjectID.0 = OID: JUNIPER-CHASSIS-DEFINES-MIB::jnxProductNameMX960
$ strace 2>&1 -f -e open snmpget -v 2c -c public r1 sysObjectID.0 | grep mib-jnx-chas-defines.txt
open("/usr/share/snmp/mibs/JuniperMibs_from_Juniper/mib-jnx-chas-defines.txt", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOTDIR (Not a directory)
open("/usr/share/snmp/mibs/JuniperMibs_from_Juniper/mib-jnx-chas-defines.txt", O_RDONLY) = 4
open("/usr/share/snmp/mibs/JuniperMibs_from_Juniper/mib-jnx-chas-defines.txt", O_RDONLY) = 3
$
Still, just to be sure, I set the os.environ['MIBDIRS'], os.environ['MIBS'] and os.environ['PREFIX'] to same values as I see when I execute the snmpget -Dinit_mib -m ALL -v 2c -c public r1 sysObjectID.0 command, but this does not help either.
What might cause this?
This is because the value at the OID sysObjectID.0 is just being treated as a value. It looks like the use_sprint_value option enables the extra formatting on the return value:
>>> session = Session(hostname="abc", community='public', version=2, use_long_names=True, use_sprint_value=True)
>>> session.get('sysObjectID.0')
<SNMPVariable value='.iso.org.dod.internet.private.enterprises.2435.2.3.9.1' (oid='.iso.org.dod.internet.mgmt.mib-2.system.sysObjectID', oid_index='0', snmp_type='OBJECTID')>
Clearly the use_long_names option is also helpful to show the expanded name, though I don't have all the MIBs required to decode this example.

RHEL Release 5.5 (Tikanga), df --total option

I have a RHEL (Redhat Enterprise Linux) v6.5 (Santiago) server. On this server if i do a df -help there are list of options available. I am interested in the option --total
However there is an older version of RHEL (v5.5). In which there is no --total option.
My question is, I have a command like this:
df -h --total | grep total | awk 'NR==1{print$2}+NR==1{print$3}+NR==1{print$4}+NR==1{print$5}'
which gives the output as
62G
39G
21G
66%
Where
62G is Total size of the Disk
39G is Used
21G is remaining
61% Total usage %
The above command is working fine in RHEL v6.5. But fails in RHEL v5.5 since it does not have a --total option for df command.
When i run the same command on RHEL v5.5 i get the below error:
df: unrecognized option `--total'
Try `df --help' for more information.
So is there a command that can give me the output in the following way:
Total Disk Space
Used Space
Remaining Disk space
Usage %
Ex:
62G
39G
21G
66%
You'll have to do the calculation work yourself.
Something like this awk script should work.
$ cat dftotal.awk
BEGIN {
map[0] = "K"
map[1] = "M"
map[2] = "G"
map[3] = "T"
}
function fmt(val, c) {
c=0
while (val > 1024) {
c++
val = val / 1024
}
return val map[c]
}
{
for (i=2;i<5;i++) {
sum[i]+=$i
}
}
END {
print fmt(sum[2]) ORS fmt(sum[3]) ORS fmt(sum[4])
print ((sum[3] / sum[2]) * 100) "%"
}
$ df -P | awk -f dftotal.awk

Resources