Blog de Robert Sebille


Vers mon curriculum vitae - Conception

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 Robert

- Testé sous Mac OSX Snow Leopard 10.6.8. OK.
- Testé sous Mac OSX Mountain Lion 10.8.3. OK.

For english eyes :
- Go to the display of the display, it’s in english
- Go to the display of the integrated help, it’s in english
- Go to the display of the code, it’s in english (except for comments)

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".

Test awk versus 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

Commande bash free-like.sh pour MAC OSX
Version 1.0.3
Commande bash free-like-raw.sh pour MAC OSX
Version 1.1.1

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

Test awk versus bc
Script bash

Revenir d’où je viens


Merci à Antoine pour ses remarques sur le code qui me furent bien utiles.

Un message, un commentaire ?

modération a priori

Ce forum est modéré a priori : votre contribution n’apparaîtra qu’après avoir été validée par un administrateur du site.

Qui êtes-vous ?
Votre message

Pour créer des paragraphes, laissez simplement des lignes vides.