Accueil > Technique > Informatique > Mac OS X > Commande bash free like pour Mac OSX - bash free like command for Mac (...)
Robert Sebille
Commande bash free like pour Mac OSX - bash free like command for Mac OSX.
dimanche 12 mai 2013, par
Testé sous Mac OSX Snow Leopard 10.6.8. OK.
Testé sous Mac OSX Mountain Lion 10.8.3. OK.



Mac OSX freeBSD n’a pas d’équivalent de la commande "free" sous Linux. On peut, via le shell en recréer une. Ici, il s’agit du shell bash.
En fait, deux objectifs contradictoires m’ont amené à créer deux commandes :
Plus de précision, d’affichage "friendly" et configurable, mais aussi plus de calculs et de consommation de ressources, avec free-like.sh, orienté "end user"
XOR
Moins de calculs et de consommation de ressources, mais aussi moins de précision, de d’affichage "friendly" et configurable, avec free-like-raw.sh, orienté développeur, sysadmin, etc.
Les commandes affichent leurs résultats pour la mémoire physique et/ou virtuelle. Les calculs pour la mémoire physique font appel à vm_stat. Ceux pour la mémoire virtuelle font appel à "top" et la réponse à cet appel est plus lente. D’où, par défaut, seule la mémoire physique est affichée, mais on peut choisir par options d’afficher la mémoire physique et/ou virtuelle. On peut afficher en byte (defaut), en kilo, en mega ou en giga, avec x décimales dans le cas de free-like.sh.
Elles utilisent "awk" pour leurs calculs. "awk" est plus précis que "bc", car il respecte les arrondis (pour bc, avec 3 décimales (scale=3), 10/6 = 1.666, ce qui est incorrect, et pour awk 10/6 = 1.667, ce qui est correct). Aux tests, "awk" se révèle également plus rapide que "bc".
Marges d’erreur
Il y a des marges d’erreur. En effet, vm_stat retourne des résultats en taille « block » et top en mega ou giga suivant « son humeur ».
Une donnée brute de 2.5k transformée en byte, c-à-d 2.5*1O24, ne permet pas de savoir ce qu’il en est des 511 bytes au dessus de 2.5k, ni ce qu’il en est des 512 en dessous. Avec le byte des 2.5k, cela nous fait une erreur maximum possible de 511+512=1023 bytes.
Idem pour les données brutes renvoyées en nombre de « blocks », leur conversion en byte résultant du calcul « nb_blocs*taille_bloc », l’erreur maximum peut donc être de « taille_bloc »
Certaines additions ou multiplication augmentent les marges d’erreur. Ces marges sont calculées et affichées par free-like.sh, pas par free-like-raw.sh.
Affichage
free-like.sh
:~ $ ./free-like.sh -v -m -d3
PHYSICAL MEMORY ABS. SIZE % SIZE MAX. ERROR <
=============== ========= ====== ============
Unit: Megabyte % Megabyte
Active: 1402,164 36,52% 0,004
Inactive: 358,941 9,35% 0,004
Wired: 478,605 12,47% 0,004
Total used: 2239,710 58,34% 0,012
Free: 1599,262 41,66% 0,008
Total memory: 3838,972 100,00% 0,020
VIRTUAL MEMORY ABS. SIZE MAX. ERROR <
============== ========= ============
Unit: Megabyte Megabyte
PagesIN: 5894,180 0,004
PagesOUT: 53,000 0,004
Swap used: 12,000 1,000
Swap free: 244,000 1,000
3 swapfile*
in /var/vm/: 256,000 1,000
______________ __________
Block size: 4096 bytes
free-like-raw.sh
:~ $ ./free-like-raw.sh -v -m
PHYSICAL MEMORY:
Active: 1461 M
Inactive: 365 M
Wired: 477 M
Total used: 2303 M
Free: 1535 M
Total memory: 3838 M
VIRTUAL MEMORY:
PagesIN: 5640 M
PagesOUT: 53 M
Swap used: 12 M
Swap free: 244 M
swapfile* file(s): 3
swapfile* size: 256 M
Block size: 4096 B
L’aide
free-like.sh
:~ $ ./free-like.sh -h
Usage: ./free-like.sh [-sv] [-k|-mg[ -d[0-9]] [-q]
./free-like.sh [-h|--help]
./free-like.sh [-V|--version]
Display information about physical and virtual memory on MAC OSX.
In bytes by default.
The calculation for the physical memory is extracted from the results of
the command vm_stat (which returns the results in blocksize). The
imprecision resulting from the transformation in bytes (number_of_blocks *
block_size, the default value of the calculations) will be between 0 and
the size of the block.
The calculation for virtual memory is taken from the "top" command.
The imprecision here is linked to the unit of reference of the "top"
command: kilo, mega, giga.
Calculations are made using "awk" that respects rounded (as opposed
to "bc"). "awk" is also quicker than "bc".
This command, with its with friendly and highly configurable display
is suitable for use oriented end user. For a command with raw display,
oriented developper, system administrator, etc., with less computation,
but also less precise, see free-like-raw.sh.
http://myblog.robert.sebille.name/article29.html
-s --swap Display only the swap. By default, the script displays only
the physical memory. (The call to "top" command to evaluate
virtual memory is more time intensive than the call to
"vm_stat".)
-v --verbose Display results for virtual AND physical memory.
-k --kilo Display in kilobytes. Integer. (Here, the decimals have no
sense given the transformation calculation in bytes and
imprecision that results.)
-m --mega Display in megabytes. Decimals have little meaning given
the imprecision, but they are possible. -d3 will show 3
decimal places, etc.
-g --giga Display in gigabyte. Here, the maximum imprecision is
reduced relative to the selected unit. The decimals make
sense and are necessary for a meaningful display. -d7 will
show 7 décimal places, etc.
-d[0-9] Display from 0 to 9 decimal places. Only possible with-m or-g.
-q --quiet Prevents display on stdout.
-h --help This help and exit.
-V --version Print version and exit.
More information about MAC OSX memory managment:
EN: http://apple.stackexchange.com/questions/104/whats-the-difference-between
-real-virtual-shared-and-private-memory (please restick the link)
FR: http://www.osxfacile.com/memoire.html
FreeBSD licence
free-like-raw.sh
:~ $ ./free-like-raw.sh -h
Usage: ./free-like-raw.sh [-sv] [-kmg] [-q]
./free-like-raw.sh [-h|--help]
./free-like-raw.sh [-V|--version]
Display raw information about physical and virtual memory on MAC OSX.
In bytes by default.
The calculation for the physical memory is extracted from the results of
the command vm_stat (which returns the results in blocksize). The
imprecision resulting from the transformation in bytes (number_of_blocks *
block_size, the default value of the calculations) will be between 0 and
the size of the block.
The calculation for virtual memory is taken from the "top" command.
The imprecision here is linked to the unit of reference of the "top"
command: kilo, mega, giga.
Calculations are made using "awk" that respects rounded (as opposed
to "bc"). "awk" is also quicker than "bc".
This command is suitable for use oriented developper, system administrator,
etc. For a command with friendly and highly configurable display, more
precise, but with more calculations, see:
free-like.sh. http://myblog.robert.sebille.name/article29.html
-s --swap Display only the swap. By default, the script displays only
the physical memory. (The call to "top" command to evaluate
virtual memory is more time intensive than the call to
"vm_stat".)
-v --verbose Display results for virtual AND physical memory.
-k --kilo Display in kilobytes. Integer.
-m --mega Display in megabytes. Integer.
-g --giga Display in gigabyte. Integer.
-q --quiet Prevents display on stdout.
-h --help This help and exit.
-V --version Print version and exit.
More information about MAC OSX memory managment:
EN: http://apple.stackexchange.com/questions/104/whats-the-difference-between
-real-virtual-shared-and-private-memory (please restick the link)
FR: http://www.osxfacile.com/memoire.html
FreeBSD licence
Récupérer un résultat de free-like-raw.sh dans un script
Exemple :
:~ $ freeraw=$(echo $(./free-like-raw.sh -m))
:~ $ echo $freeraw
PHYSICAL MEMORY: Active: 1376 M Inactive: 503 M Wired: 474 M Total used: 2353 M Free: 1484 M Total memory: 3837 M Block size: 4096 B
:~ $ Active=$(echo "$freeraw" | awk '{ print $4;print $5 }' )
:~ $ echo $Active
1376 M
Installation
Dans un répertoire quelconque
Télécharger free-like.sh.zip (voir au bas de l’article)
Puis, dans un terminal BASH :
unzip free-like.sh.zip
chmod 755 free-like.sh
./free-like.sh [options]
Dans le système
Pour ceux qui voudrait en faire une commande système, voici. J’ai choisi de l’installer dans /usr/local/
. Certains penseront sans doute que /opt/local/
est plus adéquat, à vous de choisir. quoiqu’il en soit, assurez-vous, avec dans un terminal echo $PATH
que /usr/local/bin
ou /opt/local/bin
est dans le chemin d’exécution.
Dans un terminal, toujours, après installation dans un répertoire (voir ci-dessus) :
sudo cp free-like.sh /usr/local/libexec/
cd /usr/local/bin
sudo ln -s ../libexec/free-like.sh free-like
cd ~
free-like [options]
Les procédures d’installation sont bien sur pareilles pour free-like-raw.sh.
Les scripts à télécharger
Le code
free-like.sh
#!/bin/bash
##########################################################################################
# Free-like command for MAC OSX #
##########################################################################################
# Copyright 1992-2013 The FreeBSD Project. All rights reserved. #
# #
# Redistribution and use in source and binary forms, with or without modification #
# are permitted provided that the following conditions are met: #
# #
# 1) Redistributions of source code must retain the above copyright notice, #
# this list of conditions and the following disclaimer. #
# 2) Redistributions in binary form must reproduce the above copyright notice, #
# this list of conditions and the following disclaimer in the documentation #
# and/or other materials provided with the distribution. #
# #
# THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY EXPRESS OR #
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT #
# SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, #
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT #
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR #
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, #
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY #
# OF SUCH DAMAGE. #
# #
# The views and conclusions contained in the software and documentation are those of the #
# authors and should not be interpreted as representing official policies, either #
# expressed or implied, of the FreeBSD Project. #
# #
# Authors: Robert Sebille, may 2013 #
##########################################################################################
### Aide ###
help() {
echo -e "\tUsage:\t./free-like.sh [-sv] [-k|-mg[ -d[0-9]] [-q]"
echo -e "\t\t./free-like.sh [-h|--help]"
echo -e "\t\t./free-like.sh [-V|--version]\n"
echo -e "\tDisplay information about physical and virtual memory on MAC OSX."
echo -e "\tIn bytes by default.\n"
echo -e "\tThe calculation for the physical memory is extracted from the results of"
echo -e "\tthe command vm_stat (which returns the results in blocksize). The"
echo -e "\timprecision resulting from the transformation in bytes (number_of_blocks *"
echo -e "\tblock_size, the default value of the calculations) will be between 0 and"
echo -e "\tthe size of the block."
echo -e "\tThe calculation for virtual memory is taken from the \"top\" command."
echo -e "\tThe imprecision here is linked to the unit of reference of the \"top\""
echo -e "\tcommand: kilo, mega, giga."
echo -e "\tCalculations are made using \"awk\" that respects rounded (as opposed"
echo -e "\tto \"bc\"). \"awk\" is also quicker than \"bc\".\n"
echo -e "\tThis command, with its with friendly and highly configurable display"
echo -e "\tis suitable for use oriented end user. For a command with raw display,"
echo -e "\toriented developper, system administrator, etc., with less computation,"
echo -e "\tbut also less precise, see free-like-raw.sh."
echo -e "\thttp://myblog.robert.sebille.name/article29.html\n"
echo -e "\t-s --swap\tDisplay only the swap. By default, the script displays only"
echo -e "\t\t\tthe physical memory. (The call to \"top\" command to evaluate"
echo -e "\t\t\tvirtual memory is more time intensive than the call to"
echo -e "\t\t\t\"vm_stat\".)"
echo -e "\t-v --verbose\tDisplay results for virtual AND physical memory."
echo -e "\t-k --kilo\tDisplay in kilobytes. Integer. (Here, the decimals have no"
echo -e "\t\t\tsense given the transformation calculation in bytes and"
echo -e "\t\t\timprecision that results.)"
echo -e "\t-m --mega\tDisplay in megabytes. Decimals have little meaning given"
echo -e "\t\t\tthe imprecision, but they are possible. -d3 will show 3"
echo -e "\t\t\tdecimal places, etc."
echo -e "\t-g --giga\tDisplay in gigabyte. Here, the maximum imprecision is"
echo -e "\t\t\treduced relative to the selected unit. The decimals make"
echo -e "\t\t\tsense and are necessary for a meaningful display. -d7 will"
echo -e "\t\t\tshow 7 décimal places, etc."
echo -e "\t-d[0-9]\t\tDisplay from 0 to 9 decimal places. Only possible with-m or-g."
echo -e "\t-q --quiet\tPrevents display on stdout.\n"
echo -e "\t-h --help\tThis help and exit."
echo -e "\t-V --version\tPrint version and exit.\n"
echo -e "\tMore information about MAC OSX memory managment:"
echo -e "\tEN: http://apple.stackexchange.com/questions/104/whats-the-difference-between"
echo -e "\t-real-virtual-shared-and-private-memory (please restick the link)"
echo -e "\tFR: http://www.osxfacile.com/memoire.html\n"
echo -e "\tFreeBSD licence"
exit
}
### Conversion d'une chaine type 255M ou 2G, etc. en byte ###
# Exemple: Le paramètre 2048K passé à la fonction retournera
# CHAINE_BYTE=2097152 # (2048*1024)
# CHAINE_UNIT=K
# CHAINE_BYTE_MAX_ERROR=1024
conversion_chaine_byte () {
CHAINE_A_CONVERTIR=$1
CHAINE_UNIT=$(echo "$CHAINE_A_CONVERTIR" | sed -E 's/^[0-9]+//')
CHAINE_SANS_UNIT=$(echo "$CHAINE_A_CONVERTIR" | sed -E 's/[kKmMgG]//')
case "$CHAINE_UNIT" in
"k" | "K" )
CHAINE_BYTE=$(($CHAINE_SANS_UNIT*1024))
CHAINE_BYTE_MAX_ERROR=$((1024))
;;
"m" | "M" )
CHAINE_BYTE=$(($CHAINE_SANS_UNIT*1024*1024))
CHAINE_BYTE_MAX_ERROR=$((1024*1024))
;;
"g" | "G" )
CHAINE_BYTE=$(($CHAINE_SANS_UNIT*1024*1024*1024))
CHAINE_BYTE_MAX_ERROR=$((1024*1024)*1024)
;;
* )
CHAINE_BYTE=$(($CHAINE_SANS_UNIT))
CHAINE_BYTE_MAX_ERROR=$((0))
;;
esac
}
### Echelle pour awk printf ###
echelle_awk(){
SCALE_AWK="%.${SCALE}f"
}
### Valeurs par defaut ###
# version
VERSION="1.0.3"
VM_DIR="/var/vm/"
SWAP_FILE="swapfile*"
SLEEPIMAGE_FILE="sleepimage*"
# Vue brute ou vue humaine
SIZE_VIEW=1
KILO=$((1024))
MEGA=$((1024*$KILO))
GIGA=$((1024*$MEGA))
SCALE=$((0))
echelle_awk $SCALE
# Unité par défaut
UNIT="Byte"
# Pas de calcul avec des réels par défaut
DECIMAL="false"
# Mémoire physique par défaut et pour calcul page size
VMSTAT=$(vm_stat)
# Taille block (page size)
BLOCK_SIZE=$(echo "$VMSTAT" | awk '/page size of / {print $8}')
# Drapeaux d'affichage et de calculs
AFFICHAGE="true"
PHYSICAL_CALC="true"
VIRTUAL_CALC="false"
#### Boucle sur les paramètres passés au script ###
until [ -z "$1" ] # Jusqu'à ne plus avoir de paramètres...
do
CURRENT_ARG="$1"
# help
if [ "$CURRENT_ARG" = "-h" -o "$CURRENT_ARG" = "--help" ]
then
help
exit 0
fi
# version
if [ "$CURRENT_ARG" = "-V" -o "$CURRENT_ARG" = "--version" ]
then
echo -e "Free-like command for MAC OSX. Version: $VERSION"
exit 0
fi
# Vue humaine en kilo
if [ "$CURRENT_ARG" = "-k" -o "$CURRENT_ARG" = "--kilobyte" ]
then
SIZE_VIEW=$KILO
UNIT="Kilobyte"
fi
# Vue humaine en mega (avec décimales possibles)
if [ "$CURRENT_ARG" = "-m" -o "$CURRENT_ARG" = "--megabyte" ]
then
SIZE_VIEW=$MEGA
UNIT="Megabyte"
DECIMAL="true"
fi
# Vue humaine en giga (avec décimales possibles)
if [ "$CURRENT_ARG" = "-g" -o "$CURRENT_ARG" = "--gigabyte" ]
then
SIZE_VIEW=$GIGA
UNIT="Gigabyte"
DECIMAL="true"
fi
# Décimales (seulement avec mega ou giga)
if echo "$CURRENT_ARG" | grep -q -E '^-d[0-9]?$'
then
if [ "$DECIMAL" = "true" ]
then
SCALE=${CURRENT_ARG:2:1}
if [ x$SCALE = "x" ]; then SCALE=$((0)); fi;
echelle_awk $SCALE
fi
fi
# Supprime l'affichage (quiet)
if [ "$CURRENT_ARG" = "-q" -o "$CURRENT_ARG" = "--quiet" ]
then
AFFICHAGE="false"
fi
# Calcul et affichage éventuels de la mémoire virtuelle seulement (swap)
# (par défaut, affichage de la mémoire physique seulement)
if [ "$CURRENT_ARG" = "-s" -o "$CURRENT_ARG" = "--swap" ]
then
VIRTUAL_CALC="true"
PHYSICAL_CALC="false"
fi
# Calcul et affichage éventuels des mémoires physiques ET virtuelle (verbose)
# (par défaut, affichage de la mémoire physique seulement)
if [ "$CURRENT_ARG" = "-v" -o "$CURRENT_ARG" = "--verbose" ]
then
VIRTUAL_CALC="true"
PHYSICAL_CALC="true" # Pour garder une cohérence si on a entré -s avant -v (but why ? ;-)
fi
shift
done
### Calculs ###
# Mémoire physique
if [ "$PHYSICAL_CALC" = "true" ]
then
FREE_BLOCKS=$(echo "$VMSTAT" | awk '/^Pages free:/ {sub("\\\.", "", $3); print $3}')
INACTIVE_BLOCKS=$(echo "$VMSTAT" | awk '/^Pages inactive:/ {sub("\\\.", "", $3); print $3}')
SPECULATIVE_BLOCKS=$(echo "$VMSTAT" | awk '/^Pages speculative:/ {sub("\\\.", "", $3); print $3}')
ACTIVE_BLOCKS=$(echo "$VMSTAT" | awk '/^Pages active:/ {sub("\\\.", "", $3); print $3}')
WIRED_BLOCKS=$(echo "$VMSTAT" | awk '/^Pages wired down:/ {sub("\\\.", "", $4); print $4}')
# Calcule les differentes memoires physiques et les totaux.
# Conversion en byte (ou kb, ou mb, ou gb suivant les arguments passés)
ACTIVE=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${ACTIVE_BLOCKS}'"*"'${BLOCK_SIZE}'"/"'${SIZE_VIEW}'") }')
ACTIVE_MAX_ERROR=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${BLOCK_SIZE}'"/"'${SIZE_VIEW}'") }')
INACTIVE=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${INACTIVE_BLOCKS}'"*"'${BLOCK_SIZE}'"/"'${SIZE_VIEW}'") }')
INACTIVE_MAX_ERROR=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${BLOCK_SIZE}'"/"'${SIZE_VIEW}'") }')
WIRED=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${WIRED_BLOCKS}'"*"'${BLOCK_SIZE}'"/"'${SIZE_VIEW}'") }')
WIRED_MAX_ERROR=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${BLOCK_SIZE}'"/"'${SIZE_VIEW}'") }')
TOTAL_USED=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${ACTIVE}'"+"'${WIRED}'"+"'${INACTIVE}'") }')
TOTAL_USED_MAX_ERROR=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${BLOCK_SIZE}'"*3/"'${SIZE_VIEW}'") }')
FREE=$(awk 'BEGIN { printf("'${SCALE_AWK}'", ("'${FREE_BLOCKS}'"+"'${SPECULATIVE_BLOCKS}'")*"'${BLOCK_SIZE}'"/"'${SIZE_VIEW}'") }')
FREE_MAX_ERROR=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${BLOCK_SIZE}'"*2/"'${SIZE_VIEW}'") }')
TOTAL=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${TOTAL_USED}'"+"'${FREE}'") }')
TOTAL_MAX_ERROR=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${BLOCK_SIZE}'"*5/"'${SIZE_VIEW}'") }')
# Calcul en % de la mémoire totale
ACTIVE_PROCENT=$(awk 'BEGIN { printf("%.2f", "'${ACTIVE}'"*100/"'${TOTAL}'") }')
INACTIVE_PROCENT=$(awk 'BEGIN { printf("%.2f", "'${INACTIVE}'"*100/"'${TOTAL}'") }')
WIRED_PROCENT=$(awk 'BEGIN { printf("%.2f", "'${WIRED}'"*100/"'${TOTAL}'") }')
TOTAL_USED_PROCENT=$(awk 'BEGIN { printf("%.2f", "'${TOTAL_USED}'"*100/"'${TOTAL}'") }')
FREE_PROCENT=$(awk 'BEGIN { printf("%.2f", "'${FREE}'"*100/"'${TOTAL}'") }')
TOTAL_PROCENT=$(awk 'BEGIN { printf("%.2f", "'${TOTAL_USED_PROCENT}'"+"'${FREE_PROCENT}'") }')
fi
# Mémoire virtuelle (swap)
if [ "$VIRTUAL_CALC" = "true" ]
then
# Chercher les informations sur la mémoire virtuelle dans la commande top
TOP=$(top -S -l 1 -n 0 -R)
# Pages d'entrée et de sorties
PAGESIN_BLOCKS=$( echo "$TOP" | awk '/^VM:.*\.$/ { print $7 }' | sed 's/(0)//')
PAGESOUT_BLOCKS=$( echo "$TOP" | awk '/^VM:.*\.$/ { print $9 }' | sed 's/(0)//')
PAGESIN=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${PAGESIN_BLOCKS}'"*"'${BLOCK_SIZE}'"/"'${SIZE_VIEW}'") }')
PAGESIN_MAX_ERROR=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${BLOCK_SIZE}'"/"'${SIZE_VIEW}'") }')
PAGESOUT=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${PAGESOUT_BLOCKS}'"*"'${BLOCK_SIZE}'"/"'${SIZE_VIEW}'") }')
PAGESOUT_MAX_ERROR=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${BLOCK_SIZE}'"/"'${SIZE_VIEW}'") }')
# swap
SWAP_USED_RAW=$(echo "$TOP" | awk '/^Swap:/ { print $2 }')
SWAP_FREE_RAW=$(echo "$TOP" | awk '/^Swap:/ { print $4 }')
# conversion swap en byte et calcul suivant le SIZE_VIEW (b, k, m ou g)
conversion_chaine_byte $SWAP_USED_RAW
SWAP_USED=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${CHAINE_BYTE}'"/"'${SIZE_VIEW}'") }')
MAX_SWAP_USED_ERROR=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${CHAINE_BYTE_MAX_ERROR}'"/"'${SIZE_VIEW}'") }')
conversion_chaine_byte $SWAP_FREE_RAW
SWAP_FREE=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${CHAINE_BYTE}'"/"'${SIZE_VIEW}'") }')
MAX_SWAP_FREE_ERROR=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${CHAINE_BYTE_MAX_ERROR}'"/"'${SIZE_VIEW}'") }')
# Nombre de swapfile et poid
SWAPFILE_NUMBER=$(ls -l $VM_DIR$SWAP_FILE | wc -l)
SWAPFILE_NUMBER=$(echo $SWAPFILE_NUMBER | sed 's/ //')
SWAPFILE_SIZE_RAW=$(du -sh -I $SLEEPIMAGE_FILE $VM_DIR)
conversion_chaine_byte $SWAPFILE_SIZE_RAW
SWAPFILE_SIZE=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${CHAINE_BYTE}'"/"'${SIZE_VIEW}'") }')
MAX_SWAPFILE_SIZE_ERROR=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${CHAINE_BYTE_MAX_ERROR}'"/"'${SIZE_VIEW}'") }')
fi
### Affichage ###
prf1="%15s";prf2="%15s";prf3="%8s";prf4="%15s"
prf12="$prf1 $prf2";prf124="$prf1 $prf2 $prf4";prf1234="$prf1 $prf2 $prf3 $prf4";
# Mémoire physique
if [ $AFFICHAGE = "true" -a $PHYSICAL_CALC = "true" ]
then
printf "$prf1234 \n" "PHYSICAL MEMORY" "ABS. SIZE" "% SIZE" "MAX. ERROR <"
printf "$prf1234 \n" "===============" "=========" "======" "============"
printf "$prf1234 \n\n" "Unit:" "$UNIT" "%" "$UNIT"
printf "$prf1234 \n" "Active:" "$ACTIVE" "$ACTIVE_PROCENT%" "$ACTIVE_MAX_ERROR"
printf "$prf1234 \n" "Inactive:" "$INACTIVE" "$INACTIVE_PROCENT%" "$INACTIVE_MAX_ERROR"
printf "$prf1234 \n" "Wired:" "$WIRED" "$WIRED_PROCENT%" "$WIRED_MAX_ERROR"
printf "$prf1234 \n\n" "Total used:" "$TOTAL_USED" "$TOTAL_USED_PROCENT%" "$TOTAL_USED_MAX_ERROR"
printf "$prf1234 \n\n" "Free:" "$FREE" "$FREE_PROCENT%" "$FREE_MAX_ERROR"
printf "$prf1234 \n\n" "Total memory:" "$TOTAL" "$TOTAL_PROCENT%" "$TOTAL_MAX_ERROR"
fi
if [ $AFFICHAGE = "true" -a $VIRTUAL_CALC = "true" ]
then
printf "$prf1234 \n" "VIRTUAL MEMORY" "ABS. SIZE" "" "MAX. ERROR <"
printf "$prf1234 \n" "==============" "=========" "" "============"
printf "$prf1234 \n\n" "Unit:" "$UNIT" "" "$UNIT"
printf "$prf1234 \n" "PagesIN:" "$PAGESIN" "" "$PAGESIN_MAX_ERROR"
printf "$prf1234 \n" "PagesOUT:" "$PAGESOUT" "" "$PAGESOUT_MAX_ERROR"
printf "$prf1234 \n" "Swap used:" "$SWAP_USED" "" "$MAX_SWAP_USED_ERROR"
printf "$prf1234 \n" "Swap free:" "$SWAP_FREE" "" "$MAX_SWAP_FREE_ERROR"
printf "$prf1 \n" "$SWAPFILE_NUMBER $SWAP_FILE"
printf "$prf1234 \n" "in $VM_DIR:" "$SWAPFILE_SIZE" "" "$MAX_SWAPFILE_SIZE_ERROR"
fi
# Généralités
if [ $AFFICHAGE = "true" ]
then
printf "$prf12 \n" "______________" "__________"
printf "$prf12 \n" "Block size:" "$BLOCK_SIZE bytes"
fi
exit 0
free-like-raw.sh
#!/bin/bash
##########################################################################################
# Free-like-raw command for MAC OSX #
##########################################################################################
# Copyright 1992-2013 The FreeBSD Project. All rights reserved. #
# #
# Redistribution and use in source and binary forms, with or without modification #
# are permitted provided that the following conditions are met: #
# #
# 1) Redistributions of source code must retain the above copyright notice, #
# this list of conditions and the following disclaimer. #
# 2) Redistributions in binary form must reproduce the above copyright notice, #
# this list of conditions and the following disclaimer in the documentation #
# and/or other materials provided with the distribution. #
# #
# THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY EXPRESS OR #
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT #
# SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, #
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT #
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR #
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, #
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY #
# OF SUCH DAMAGE. #
# #
# The views and conclusions contained in the software and documentation are those of the #
# authors and should not be interpreted as representing official policies, either #
# expressed or implied, of the FreeBSD Project. #
# #
# Authors: Robert Sebille, may 2013 #
##########################################################################################
### Aide ###
help() {
echo -e "\tUsage:\t./free-like-raw.sh [-sv] [-kmg] [-q]"
echo -e "\t\t./free-like-raw.sh [-h|--help]"
echo -e "\t\t./free-like-raw.sh [-V|--version]\n"
echo -e "\tDisplay raw information about physical and virtual memory on MAC OSX."
echo -e "\tIn bytes by default.\n"
echo -e "\tThe calculation for the physical memory is extracted from the results of"
echo -e "\tthe command vm_stat (which returns the results in blocksize). The"
echo -e "\timprecision resulting from the transformation in bytes (number_of_blocks *"
echo -e "\tblock_size, the default value of the calculations) will be between 0 and"
echo -e "\tthe size of the block."
echo -e "\tThe calculation for virtual memory is taken from the \"top\" command."
echo -e "\tThe imprecision here is linked to the unit of reference of the \"top\""
echo -e "\tcommand: kilo, mega, giga."
echo -e "\tCalculations are made using \"awk\" that respects rounded (as opposed"
echo -e "\tto \"bc\"). \"awk\" is also quicker than \"bc\".\n"
echo -e "\tThis command is suitable for use oriented developper, system administrator,"
echo -e "\tetc. For a command with friendly and highly configurable display, more"
echo -e "\tprecise, but with more calculations, see:"
echo -e "\tfree-like.sh. http://myblog.robert.sebille.name/article29.html\n"
echo -e "\t-s --swap\tDisplay only the swap. By default, the script displays only"
echo -e "\t\t\tthe physical memory. (The call to \"top\" command to evaluate"
echo -e "\t\t\tvirtual memory is more time intensive than the call to"
echo -e "\t\t\t\"vm_stat\".)"
echo -e "\t-v --verbose\tDisplay results for virtual AND physical memory."
echo -e "\t-k --kilo\tDisplay in kilobytes. Integer."
echo -e "\t-m --mega\tDisplay in megabytes. Integer."
echo -e "\t-g --giga\tDisplay in gigabyte. Integer."
echo -e "\t-q --quiet\tPrevents display on stdout.\n"
echo -e "\t-h --help\tThis help and exit."
echo -e "\t-V --version\tPrint version and exit.\n"
echo -e "\tMore information about MAC OSX memory managment:"
echo -e "\tEN: http://apple.stackexchange.com/questions/104/whats-the-difference-between"
echo -e "\t-real-virtual-shared-and-private-memory (please restick the link)"
echo -e "\tFR: http://www.osxfacile.com/memoire.html\n"
echo -e "\tFreeBSD licence"
exit
}
### Conversion d'une chaine type 255M ou 2G, etc. en byte ###
# Exemple: Le paramètre 2048K passé à la fonction retournera
# CHAINE_BYTE=2097152 # (2048*1024)
# CHAINE_UNIT=K
conversion_chaine_byte () {
CHAINE_A_CONVERTIR=$1
CHAINE_UNIT=$(echo "$CHAINE_A_CONVERTIR" | sed -E 's/^[0-9]+//')
CHAINE_SANS_UNIT=$(echo "$CHAINE_A_CONVERTIR" | sed -E 's/[kKmMgG]//')
case "$CHAINE_UNIT" in
"k" | "K" )
CHAINE_BYTE=$(($CHAINE_SANS_UNIT*1024))
;;
"m" | "M" )
CHAINE_BYTE=$(($CHAINE_SANS_UNIT*1024*1024))
;;
"g" | "G" )
CHAINE_BYTE=$(($CHAINE_SANS_UNIT*1024*1024*1024))
;;
* )
CHAINE_BYTE=$(($CHAINE_SANS_UNIT))
;;
esac
}
### Valeurs par defaut ###
# version
VERSION="1.1.1"
VM_DIR="/var/vm/"
SWAP_FILE="swapfile*"
SLEEPIMAGE_FILE="sleepimage*"
UNIT="B"
SIZE_VIEW=$((1))
SCALE_AWK="%.0f"
# Mémoire physique par défaut et pour calcul page size
VMSTAT=$(vm_stat)
# Taille block (page size)
BLOCK_SIZE=$(echo "$VMSTAT" | awk '/page size of / {print $8}')
# Drapeaux d'affichage et de calculs
AFFICHAGE="true"
PHYSICAL_CALC="true"
VIRTUAL_CALC="false"
#### Boucle sur les paramètres passés au script ###
until [ -z "$1" ] # Jusqu'à ne plus avoir de paramètres...
do
CURRENT_ARG="$1"
# help
if [ "$CURRENT_ARG" = "-h" -o "$CURRENT_ARG" = "--help" ]
then
help
exit 0
fi
# version
if [ "$CURRENT_ARG" = "-V" -o "$CURRENT_ARG" = "--version" ]
then
echo -e "Free-like-raw command for MAC OSX. Version: $VERSION"
exit 0
fi
# Vue brute en kilo
if [ "$CURRENT_ARG" = "-k" -o "$CURRENT_ARG" = "--kilobyte" ]
then
SIZE_VIEW=$((1024))
UNIT="K"
fi
# Vue brute en mega
if [ "$CURRENT_ARG" = "-m" -o "$CURRENT_ARG" = "--megabyte" ]
then
SIZE_VIEW=$((1024*1024))
UNIT="M"
fi
# Vue brute en giga
if [ "$CURRENT_ARG" = "-g" -o "$CURRENT_ARG" = "--gigabyte" ]
then
SIZE_VIEW=$((1024*1024*1024))
UNIT="G"
fi
# Supprime l'affichage (quiet)
if [ "$CURRENT_ARG" = "-q" -o "$CURRENT_ARG" = "--quiet" ]
then
AFFICHAGE="false"
fi
# Calcul et affichage éventuels de la mémoire virtuelle seulement (swap)
# (par défaut, affichage de la mémoire physique seulement)
if [ "$CURRENT_ARG" = "-s" -o "$CURRENT_ARG" = "--swap" ]
then
VIRTUAL_CALC="true"
PHYSICAL_CALC="false"
fi
# Calcul et affichage éventuels des mémoires physiques ET virtuelle (verbose)
# (par défaut, affichage de la mémoire physique seulement)
if [ "$CURRENT_ARG" = "-v" -o "$CURRENT_ARG" = "--verbose" ]
then
VIRTUAL_CALC="true"
PHYSICAL_CALC="true" # Pour garder une cohérence si on a entré -s avant -v (but why ? ;-)
fi
shift
done
### Calculs ###
# Mémoire physique
if [ "$PHYSICAL_CALC" = "true" ]
then
# Calcule les blocks via vm_stat
FREE_BLOCKS=$(echo "$VMSTAT" | awk '/^Pages free:/ {sub("\\\.", "", $3); print $3}')
INACTIVE_BLOCKS=$(echo "$VMSTAT" | awk '/^Pages inactive:/ {sub("\\\.", "", $3); print $3}')
SPECULATIVE_BLOCKS=$(echo "$VMSTAT" | awk '/^Pages speculative:/ {sub("\\\.", "", $3); print $3}')
ACTIVE_BLOCKS=$(echo "$VMSTAT" | awk '/^Pages active:/ {sub("\\\.", "", $3); print $3}')
WIRED_BLOCKS=$(echo "$VMSTAT" | awk '/^Pages wired down:/ {sub("\\\.", "", $4); print $4}')
# Calcule les différentes mémoires RAM et les totaux. Conversion en byte
ACTIVE=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${ACTIVE_BLOCKS}'"*"'${BLOCK_SIZE}'"/"'${SIZE_VIEW}'") }')
INACTIVE=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${INACTIVE_BLOCKS}'"*"'${BLOCK_SIZE}'"/"'${SIZE_VIEW}'") }')
WIRED=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${WIRED_BLOCKS}'"*"'${BLOCK_SIZE}'"/"'${SIZE_VIEW}'") }')
TOTAL_USED=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${ACTIVE}'"+"'${WIRED}'"+"'${INACTIVE}'") }')
FREE=$(awk 'BEGIN { printf("'${SCALE_AWK}'", ("'${FREE_BLOCKS}'"+"'${SPECULATIVE_BLOCKS}'")*"'${BLOCK_SIZE}'"/"'${SIZE_VIEW}'") }')
TOTAL=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${TOTAL_USED}'"+"'${FREE}'") }')
fi
# Mémoire virtuelle (swap)
if [ "$VIRTUAL_CALC" = "true" ]
then
# Chercher les informations sur la mémoire virtuelle dans la commande top
TOP=$(top -S -l 1 -n 0 -R)
# Pages d'entrée et de sorties
PAGESIN_BLOCKS=$( echo "$TOP" | awk '/^VM:.*\.$/ { print $7 }' | sed 's/(0)//')
PAGESOUT_BLOCKS=$( echo "$TOP" | awk '/^VM:.*\.$/ { print $9 }' | sed 's/(0)//')
PAGESIN=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${PAGESIN_BLOCKS}'"*"'${BLOCK_SIZE}'"/"'${SIZE_VIEW}'") }')
PAGESOUT=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${PAGESOUT_BLOCKS}'"*"'${BLOCK_SIZE}'"/"'${SIZE_VIEW}'") }')
# swap
SWAP_USED_RAW=$(echo "$TOP" | awk '/^Swap:/ { print $2 }')
SWAP_FREE_RAW=$(echo "$TOP" | awk '/^Swap:/ { print $4 }')
# conversion swap en byte
conversion_chaine_byte $SWAP_USED_RAW
SWAP_USED=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${CHAINE_BYTE}'"/"'${SIZE_VIEW}'") }')
conversion_chaine_byte $SWAP_FREE_RAW
SWAP_FREE=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${CHAINE_BYTE}'"/"'${SIZE_VIEW}'") }')
# Nombre de swapfile et poid
SWAPFILE_NUMBER=$(ls -l $VM_DIR$SWAP_FILE | wc -l)
SWAPFILE_NUMBER=$(echo $SWAPFILE_NUMBER | sed 's/ //')
SWAPFILE_SIZE_RAW=$(du -sh -I $SLEEPIMAGE_FILE $VM_DIR)
conversion_chaine_byte $SWAPFILE_SIZE_RAW
SWAPFILE_SIZE=$(awk 'BEGIN { printf("'${SCALE_AWK}'", "'${CHAINE_BYTE}'"/"'${SIZE_VIEW}'") }')
fi
### Affichage ###
# Mémoire physique
if [ $AFFICHAGE = "true" -a $PHYSICAL_CALC = "true" ]
then
echo -e "PHYSICAL MEMORY:"
echo -e "Active: $ACTIVE $UNIT"
echo -e "Inactive: $INACTIVE $UNIT"
echo -e "Wired: $WIRED $UNIT"
echo -e "Total used: $TOTAL_USED $UNIT"
echo -e "Free: $FREE $UNIT"
echo -e "Total memory: $TOTAL $UNIT"
fi
if [ $AFFICHAGE = "true" -a $VIRTUAL_CALC = "true" ]
then
echo -e "VIRTUAL MEMORY:"
echo -e "PagesIN: $PAGESIN $UNIT"
echo -e "PagesOUT: $PAGESOUT $UNIT"
echo -e "Swap used: $SWAP_USED $UNIT"
echo -e "Swap free: $SWAP_FREE $UNIT"
echo -e "$SWAP_FILE file(s): $SWAPFILE_NUMBER"
echo -e "$SWAP_FILE size: $SWAPFILE_SIZE $UNIT"
fi
# Généralités
if [ $AFFICHAGE = "true" ]
then
echo -e "Block size: $BLOCK_SIZE B"
fi
exit 0
Test awk versus bc
Script de test
#!/bin/bash
SCALE_AWK="%.6f"
SCALE_BC=$((6))
FREE_BLOCKS=$((64147))
SPECULATIVE_BLOCKS=$((4211))
BLOCK_SIZE=$((4096))
SIZE_VIEW=$((1024*1024))
echo -e "Résultats bc:"
time FREE=$(echo "scale=$SCALE_BC; ((($FREE_BLOCKS+$SPECULATIVE_BLOCKS)*$BLOCK_SIZE)/$SIZE_VIEW)" | bc)
echo -e "Calcul de FREE (bc) = $FREE"
echo -e "\n----\nRésultats awk:"
time FREE=$(awk 'BEGIN { printf("'${SCALE_AWK}'", ("'${FREE_BLOCKS}'"+"'${SPECULATIVE_BLOCKS}'")*"'${BLOCK_SIZE}'"/"'${SIZE_VIEW}'") }')
echo -e "Calcul de FREE (awk) = $FREE"
Exemple de résultat
:~ $ ./awk-bc.sh
Résultats bc:
real 0m0.006s
user 0m0.001s
sys 0m0.003s
Calcul de FREE (bc) = 267.023437
----
Résultats awk:
real 0m0.003s
user 0m0.001s
sys 0m0.002s
Calcul de FREE (awk) = 267,023438
A chaque lancement du test, awk s’est révélé le plus rapide. (Avec une erreur d’arrondi pour bc).
Télécharger le script de test
Merci à Antoine pour ses remarques sur le code qui me furent bien utiles.