1168 private links
grep -vE '^\s*#' /path/to/the/file | sed '/^\s*$/d'
La boucle doit être alimentée par un process au même niveau.
Par exemple, cette boucle ne peut modifier la variable globale unformatted
.
#!/bin/bash
unformatted=""
lsblk -dn -o NAME,TYPE,SIZE | while read name type size
do
if [ "$type" == "disk" ]
then
parts=$(lsblk -n /dev/$name | grep part)
if [ -z "$parts" ]
then
unformatted="$unformatted /dev/$name,$size"
fi
fi
done
Dans la boucle while
la variable unformatted
est locale et ne modifie donc pas la variable globale du même nom définie plus haut car la boucle ne s'exécute pas au même niveau que le shell principal, mais dans un subshell à cause du pipe |
.
Une solution pour l'exécuter au même niveau, utiliser <<<
. On remplace donc la boucle par celle-ci.
#!/bin/bash
unformatted=""
while read name type size
do
if [ "$type" == "disk" ]
then
parts=$(lsblk -n /dev/$name | grep part)
if [ -z "$parts" ]
then
unformatted="$unformatted /dev/$name,$size"
fi
fi
done <<< $(lsblk -dn -o NAME,TYPE,SIZE)
Subtle differences in proxy setting implementations led to surprising problems for a GitLab customer. Here's how we got to the root of it.
Pour effacer le disque /dev/da1
j'utilise la commande dd
combinée avec /dev/urandom
pour générer des nombres aléatoires.
Exemple
dd if=/dev/urandom of=/dev/da1 conv=sync status=progress
Par défaut, dd
positionne la taille du bloc/secteur à 512. Pour accélérer le process, on peut l'aligner à la taille du secteur physique du disque, qui est de 4096 (stripesize).
Cette information peut s'obtenir à l'aide de diskinfo
et camcontrol
.
Exemple avec diskinfo
$ diskinfo -v /dev/da1
/dev/da1
512 # sectorsize
500107862016 # mediasize in bytes (466G)
976773168 # mediasize in sectors
4096 # stripesize
0 # stripeoffset
60801 # Cylinders according to firmware.
255 # Heads according to firmware.
63 # Sectors according to firmware.
ST500LM0 12 HN-M500MBB # Disk descr.
0322031102F9 # Disk ident.
umass-sim1 # Attachment
No # TRIM/UNMAP support
Unknown # Rotation rate in RPM
Not_Zoned # Zone Mode
Petit calcul pour comprendre : si on reprend la taille du media en bytes (mediasize in bytes) et qu'on divise par la taille du secteur (sectorsize), on retrouve la taille du media en nombre de secteurs (mediasize in sectors).
$ echo $((500107862016 / 512))
976773168
On peut obtenir d'avantage d'infos sur le disque avec camcontrol identify /dev/da1
, mais je vais pas aborder ce sujet dans cette note, on a déjà l'info nécessaire avec diskinfo
.
Le paramètre bs
de la commande dd
permet de paramétrer la taille du bloc/secteur (block/sector size).
Avec cette nouvelle info cela donne
dd if=/dev/urandom of=/dev/da1 bs=4096 conv=sync status=progress
Top, c'est bien plus rapide !
Vu la taille de mon disque (500G), j'ai interrompu le process par manque de temps pour le laisser finir. 309G ont été effacés. Pour ne pas recommencer depuis le début, il me fallait calculer le nombre de secteurs à sauter pour donner un point de départ à dd
.
J'ai décidé de repartir à 300G, voici comment j'ai calculé.
Calculer la taille à sauter en bytes
$ echo $((300 * 1024 * 1024 * 1024))
322122547200
Calcul du nombre de secteurs d'une taille de 4096 à sauter
# echo $((322122547200 / 4096))
78643200
Pour reprendre la tâche après interruption, il est possible de définir un nombre de blocs à sauter en sortie avec l'argument oseek
.
# dd if=/dev/urandom of=/dev/da1 bs=4096 oseek=78643200 conv=sync status=progress
dd: /dev/da1: end of deviceB, 166 GiB) transferred 16298.003s, 11 MB/s
43453447+0 records in
43453446+0 records out
177985314816 bytes transferred in 16298.896788 secs (10920084 bytes/sec)
Résumons et vérifions le résultat ci-dessus. J'ai un disque de 500G dont j'ai déjà formaté 309G (disons 300).
Le mediasize in bytes est de 500107862016 (466G). Vérifions...
$ echo $((500107862016 / 1024 / 1024 / 1024))
465
Plus précisément 465.76, arrondi à 465 par le Shell et à 466 par diskinfo
.
Calcul de la taille restant à effacer
$ echo $((466 - 300))
166
La commande dd
nous dit que 166G ont été transférés.
Elle nous dit aussi que 177985314816 bytes ont été transférés, calculons cela encore une fois...
$ echo $((177985314816 / 1024 / 1024 / 1024))
165
Plus précisément 165.76, arrondi à 165 par le Shell et à 166 par dd
. On est tout bon !
En essayant de faire de la substitution dans un fichier avec la version BSD de sed
je me suis rendu compte qu'il fallait préciser un suffixe pour le backup après l'option -i
sous peine de se ramasser une sympathique erreur dont le titre fait l'objet.
La commande accepte un suffixe vide.
En somme pour substituer directement dans le fichier original sans backup :
sed -i '' 's/foo/bar/' file.txt
On en apprend tous les jours :-)
Une solution simple pour exécuter plusieurs commandes sur les résultats d'un find
et d'appeler un shell avec -exec
en passant en argument -c
les commandes.
Exemple, pour afficher et supprimer les fichiers dans /tmp
dont la date de dernière modification remonte à plus de 365 jours :
find /tmp -type f -mtime +365 -exec sh -c 'echo {}; rm {}' \;
Pour exclure un chemin de la recherche d'un find
on peut utiliser la fonction -wholename
en combinant avec la négation !
.
Exemple, je recherche les logs dont la date de dernière modification remonte à plus de 365 jours en excluant ceux dans /var/log/journal
:
find /var/log -type f -mtime +365 ! -wholename "/var/log/journal*"
#!/bin/bash
# Bash Script to identify disk, Vendor name, Serial & WWN for all kinds of Mounted Block devices
for i in `lsblk | grep disk | egrep -v 'Vx|ram|raw|loop|fd|md|dm-|sr|scd|st' | awk '{ print $1 }'`
do
lsblk /dev/$i | awk '{print "MOUNT="$NF}' | grep -i '/'
if [ $? = "0" ]; then
lsblk /dev/$i | grep disk | awk '{print "BLOCK_SIZE="$4}'
udevadm info --query=all --name /dev/$i | egrep 'DEVNAME=|ID_VENDOR=|ID_SERIAL_RAW=|ID_WWN=|ID_PATH=|ID_SCSI_SERIAL=' | awk '{ print $2 }'
echo "--------------"
fi
done
Alimenter un script depuis stdin :
#!/bin/bash
# Check to see if a pipe exists on stdin.
if [ -p /dev/stdin ]; then
echo "Data was piped to this script!"
# If we want to read the input line by line
while IFS= read line; do
echo "Line: ${line}"
done
# Or if we want to simply grab all the data, we can simply use cat instead
# cat
else
echo "No input was found on stdin, skipping!"
# Checking to ensure a filename was specified and that it exists
if [ -f "$1" ]; then
echo "Filename specified: ${1}"
echo "Doing things now.."
else
echo "No input given!"
fi
fi
Pourquoi faire simple quand on peut faire compliqué avec un outil comme more ?
J'ai souvenir qu'à l'époque on pouvait utiliser les touches Up/Down, Page Up/Page Down ou B/Space pour faire défiler les pages. Chose qui est toujours d'actualité sur FreeBSD.
Sur Ubuntu, Red Hat et d'autres distributions, il n'y a plus que la combinaison B/Space qui fonctionne. Il n'y a plus d'autre alternative.
Je me pose souvent la question : pourquoi d'abord proposer plusieurs combinaisons, puis en imposer qu'une seule ?
J'ai eu un cas d'école intéressant. A l'aide d'un script Shell, je cherchais à boucler sur une liste de serveurs contenue dans un fichier hosts.txt pour y exécuter des commandes via SSH.
while read host
do
ssh $host 'uname -a'
done < hosts.txt
Sauf que la boucle prenait fin après la première itération. J'ai mis un peu de temps à comprendre ce qui se passait, mais finalement l'explication est logique.
- La boucle while prend en entrée (< stdin) le contenu du fichier hosts.txt.
- Ensuite, SSH prend tout le reste de ce qui se trouve dans stdin.
- A la fin de la première itération, il n'y a donc plus rien dans stdin et la boucle prend fin.
La solution est dans le man de SSH
-n Redirects stdin from /dev/null (actually, prevents reading
from stdin). This must be used when ssh is run in the back‐
ground. A common trick is to use this to run X11 programs on
a remote machine. For example, ssh -n shadows.cs.hut.fi
emacs & will start an emacs on shadows.cs.hut.fi, and the X11
connection will be automatically forwarded over an encrypted
channel. The ssh program will be put in the background.
(This does not work if ssh needs to ask for a password or
passphrase; see also the -f option.)
Cela fonctionnera mieux ainsi
while read host
do
ssh -n $host 'uname -a'
done < hosts.txt
Une importante vulnérabilité de Bash a été découverte par Stéphane Chazelas. Elle concerne quasiment toutes les versions de Bash (1.14 à 4.3) des systèmes d'exploitation de type Unix (Unix, Linux et OS X ).
Cette faille réside dans la manière dont Bash interprète les variables d'environnement et peut être utilisée dans un large éventail de contextes : requêtes web, applications exécutant des scripts Bash, Telnet, etc.
Il faut savoir qu'à ce jour la majorité des grandes distributions a déjà contourné ce problème de sécurité en appliquant un correctif.
Vous pouvez faire le test suivant pour savoir si votre système est vulnérable :
env X="() { :;} ; echo Système vulnérable" /bin/sh -c "echo Test complété"
Si votre terminal renvoi "Système vulnérable" c'est pas bon signe. Mettez à jour votre distribution sans tarder.
Sources :