Vous êtes ici : Accueil / Développement / Shell Unix / Trucs et astuces shell

Trucs et astuces shell

Par Pierre-Yves Landuré Dernière modification 11/11/2017 09:52

Aide mémoire de commandes Bash.

Fond d'écran aide-mémoire

Ce fond d'écran regroupe les commandes Shell les plus courantes. Téléchargez le fond d'écran aide-mémoire shell.

Source: Merci à Olivier Prieur pour fond d’écran avec toutes les commandes unix : trop fort !.

Sudoifier la dernière commande tapée

Si vous avez oublié sudo pour une commande, rattrapez l'erreur:

sudo !!

Source: Oublié de taper sudo ? sudo !!

Gérer les arguments d'un script Bash

Pour gérer les options courtes (-h) ou longues (--help) d'un script Bash, reportez-vous à la fonction getoptex, documentée dans le paquet bash-doc:

sudo apt-get install bash-doc

Ouvrez le fichier /usr/share/doc/bash/examples/functions/getoptx.bash :

command gedit /usr/share/doc/bash/examples/functions/getoptx.bash

Le fonctionnement de cette fonction est similaire à celui de getopt:

man getopt

Obtenir le chemin réel d'un fichier dans Bash (équivalent de la fonction PHP realpath)

Pour obtenir l'équivalent de la fonction PHP realpath dans un script shell, utilisez:

REAL_PATH=$(command readlink -f "./chemin/../vers/mon/fichier.txt")

Source: Merci à Andy Skelton pour son article Bash equivalent for PHP realpath().

Obtenir l'adresse IP correspondant à un hôte:

Obtenez l'adresse IP de l'hôte DOMAIN:

DOMAIN='localhost'
HOST_IP="$(command getent ahostsv4 "${DOMAIN}" \
| command cut --delimiter=" " --fields=1 \
| command tail -n 1)"
echo "${HOST_IP}"

Obtenir l'adresse IP d'une interface réseau:

Obtenez l'adresse IP de l'interface eth0:

NET_DEV="eth0"
NET_IP="$(command ifconfig "${NET_DEV}" \
  | command grep 'inet ' \
| command sed -e 's/^.*inet [^:]*:\([^ ]*\) .*$/\1/')"
echo "${NET_IP}"

Obtenir l'adresse IP publique d'un ordinateur:

Obtenez l'adresse IP publique d'un ordinateur derrière un pare-feu NAT (ou autre):

PUBLIC_IP=$(command wget -qO- 'http://ipecho.net/plain')
echo "${PUBLIC_IP}"

Source : Merci au Labo Linux de Supinfo pour l'article Connaître son IP publique derrière un routeur.

Détecter si un port TCP est ouvert

La commande suivante liste les ports TCP ouverts:

command netstat -tnl \
| command cut --characters=21-44 \
| command sed -e 's/.*:\([^:]*\)[ ]*$/\1/' \
| command tail -n +3

La commande suivante incrémente la variable ${SERVER_PORT} jusqu'à ce qu'elle pointe vers un port ouvert. Renseignez le port de base à tester:

SERVER_PORT=8080

Recherchez le premier port ouvert à partir de ce port de base (par incrément de 1):

while [ -n "$(command netstat -tnl \
| command cut --characters=21-44 \
| command sed -e 's/.*:\([^:]*\)[ ]*$/\1/' \
| command tail -n +3 \
| command grep "${SERVER_PORT}")" ]; do
SERVER_PORT=$((${SERVER_PORT} + 1))
done

Vérifier qu'un hôte est joignable

Utilisez ping pour vérifier qu'il est possible d'accéder à un hôte par le réseau. Déclarez la fonction is_host_alive:

# Check if a host is alive.
#
# @param string $host A IP address or FQDN.
#
# @return integer 0 if host is alive, 1 if not.
function is_host_alive() {
command test ${#} -ne 1 && exit 1
PING_SUCCESS_COUNT="$(command ping -c 2 -q "${1}" 2>&1 \
| command grep "received" \
| command cut -d ',' -f2 \
| command cut -d ' ' -f2)"
if [ "${PING_SUCCESS_COUNT}" != "0" -a "${PING_SUCCESS_COUNT}" != "" ]; then
# host replied
return 0
  fi
# No reply from host.
return 1
} # is_host_alive()

Renseignez le nom de domaine, ou l'adresse IP, de l'hôte:

CHECKED_HOST="www.google.fr"

Vérifiez que l'hôte répond au ping:

if is_host_alive "${CHECKED_HOST}"; then
echo "${CHECKED_HOST} is alive."
else
echo "${CHECKED_HOST} is dead."
fi

Merci à Linux Poison pour Bash Script: Check Servers Availability using ping command.

Trouver quel processus écoute sur un port

Si vous souhaitez découvrir quel processus écoute sur un port, utilisez (ici pour le port TCP 443):

command lsof -i TCP:443

Convertir une chaîne en hexadécimal

Convertissez une chaîne de caractères en hexadécimal:

CHAINE="exemple"
echo -n "${CHAINE}" \
| command od -An -tx1 -w250

L'option -w250 de od spécifie qu'il doit y avoir 250 caractères par lignes dans la réponse.

Convertir un nombre hexadécimal en décimal

Utilisez (ou FF est le nombre hexadécimal):

command printf "%d\n" 0xFF

Écrire un nombre décimal dans un fichier binaire

Pour convertir un décimal en sa version binaire sur 32bits:

command printf "%.8x" ${NUMBER} | command xxd -r -p -g0 >> 'output.bin'

Source: Merci aux participants à Bash: write integer to binary file

Appliquer une commande à plusieurs fichiers

Hormis le célèbre caractère joker "*", il est possible de sélectionner de manière précise des fichiers lors que l'on utilise un shell Bash. Il est ainsi possible de placer des textes entre { et }, séparés par des virgules, pour faire une sorte de boucle sélectionnant les fichiers correspondants. Par exemple, pour sélectionner les fichiers exemple avec l'extension "odt" et "txt":

cat exemple.{odt,txt}

Trouver les liens symboliques cassés dans un dossier

Listez tous les liens symboliques cassés dans le dossier courant:

command find ./ -type l -follow

Supprimez tous les liens symboliques cassés dans le dossier courant:

command find ./ -type l -follow -print0 | command xargs -0 rm

Obtenir la taille totale d'un dossier sur le disque

Obtenez la taille totale d'un dossier sur le disque:

command du --human-readable --summarize  /mon/dossier

Pour obtenir la taille totale de chaque élément contenu dans un dossier, rajoutez une étoile:

command du --human-readable --summarize  /mon/dossier/*

Trouvez les fichiers modifiés il y a plus de N jours.

Listez les fichiers modifiés il y a plus de N jours (ici N=365):

command find ./ -mtime +365 -daystart

Source : Merci à MindSpill pour l'article Find files modified before or after a given date.

Empêcher l'exécution concurrente d'un script Bash avec un fichier verrou

Voici une méthode empêchant l'exécution d'un script Bash s'il est déjà en cours d'exécution.

#!/bin/bash
LOCKFILE=/tmp/extract.lock
if [ -f $LOCKFILE ]; then
echo "Lockfile Exists"
#check if process is running
MYPID=`head -n 1 "${LOCKFILE}"`
TEST_RUNNING=`ps -p ${MYPID} | grep ${MYPID}`
if [ -z "${TEST_RUNNING}" ]; then
echo "The process is not running, resuming normal operation!"
rm $LOCKFILE
else
echo "`basename $0` is already running [${MYPID}]"
exit 1
fi
fi
echo $$ > "${LOCKFILE}"
##Do your stuff here


rm $LOCKFILE
exit 0

Source: Merci à Sysadmin Notebook pour Bash script lock file.

Connaître les programmes utilisant un fichier ou un point de montage

Listez les programmes bloquant le démontage d'un point de montage à l'aide des commande "fuser" et "lsof".

Affichez les logiciels utilisant des fichiers sur le point de montage /point/montage:

command lsof /point/montage

La commande lsof n'affiche pas les points de montages présents dans/point/montage et qui bloquent aussi son démontage.

Calculer la somme MD5 de tous les fichiers présent dans un dossier et ses sous-dossiers

Obtenez les sommes MD5 de tous les fichiers présent dans le dossier en cours et ses sous-dossiers:

command find ./ -type f -print0 | command xargs -0 md5sum

Supprimer la dernière accolade fermante et le contenu qui la suit dans un fichier

Supprimez la dernière accolade fermante d'un fichier:

command sed -i -ne '/}/{x;s/^\n//;p;s/.*//;x};H;${g;s/\n\(.*\)}.*/\1/;p}' fichier.php

Source: Merci à ramok sur irc.freenode.net#sed pour son aide précieuse.

Horodater la commande tail

Pour faciliter l'analyse de fichiers journaux sans horodatage, appliquez un horodatage à la volée:

command tail -F mon-fichier.log | command awk '{ print strftime("%c") " " $0}'

Ajoutez un filtre (grep) si besoin est:

command tail -F mon-fichier.log | command egrep 'ma recherche' | command awk '{ print strftime("%c") " " $0}'

Source : Merci à Jugulu pour sa réponse à Show date/time with tail|grep command.

Modifier le contenu d'un fichier

Remplacer la première occurrence d'une recherche

Remplacez la première occurence d'une recherche:

command sed -i -e '0,/recherche/s//remplacement/' fichier.txt

Remplacer la première occurrence d'une recherche après une autre recherche

Remplacez la première occurrence d'une recherche après une autre recherche:

command sed -i -e '/première recherche/,/élément à remplacer/{s/élément à remplacer/remplacement/}' fichier.txt

Source : merci à gnubien sur irc.freenode.net/#sed

Insérer du contenu dans un fichier

Insérez du contenu au milieu d'un fichier:

/bin/sed -i -e "/correspondance sur la ligne après laquelle insérer le contenu/a\
contenu à insérer\\
seconde ligne de contenu à insérer
" fichier

Notez les \\ à la fin de chaque ligne de contenu inséré. Ils servent à préserver le retour à la ligne.

Par exemple, pour ajouter la ligne:

blessent mon cœur d'une langueur monotone.

Après la ligne:

Les sanglots longs des violons de l'automne

Dans le fichier BBC.txt, contenant:

Et maintenant, quelques messages personnels :
Les sanglots longs des violons de l'automne
Je répète :
...

Exécutez la commande:

command sed -i -e "/.*sanglots longs.*/a\
blessent mon cœur d'une langueur monotone." BBC.txt

Vous obtenez ainsi le résultat suivant :

Et maintenant, quelques messages personnels :
Les sanglots longs des violons de l'automne
blessent mon cœur d'une langueur monotone.
Je répète :
...

La syntaxe '//a\' permet d'insérer du contenu après la correspondance. La syntaxe '//i\' permet d'en insérer avant (a pour append, i pour insert).

Insérer du contenu uniquement après la première occurence d'une recherche

Dans certains cas, la chaîne après laquelle insérer des lignes est présente plusieurs fois dans le fichier modifié. Dans ce cas, il est nécessaire de séparer la recherche de l'insertion :

command sed -i -e '0,/^eggs[ ]*=/{//a\
Products.Ploneboard
;}' /opt/Plone-3.1/zeocluster/buildout.cfg

Cet exemple insère "Products.Ploneboards" après la première occurrence de "eggs =". Notez le "0," en début d'expression régulière, il restreint la recherche à la première occurence.

Pour insérer du contenu après la première ligne apparaissant après une ligne donnée, utilisez:

command sed -i -e '/contenu de la première ligne/,/contenu de la seconde ligne/{/contenu de la seconde ligne/a\
contenu inséré.
;}' /etc/squid/squid.conf

Références

Remerciements