relecture en vrac et ajout de qq infos
This commit is contained in:
parent
ad5b778ce0
commit
4499c26a9a
362
TipsShell.md
362
TipsShell.md
|
@ -1,18 +1,24 @@
|
|||
---
|
||||
categories: tips shell
|
||||
title: Tips SHell
|
||||
...
|
||||
|
||||
* Style guide : <https://google.github.io/styleguide/shell.xml>
|
||||
* Bash Reference Manual : <https://www.gnu.org/software/bash/manual/bash.html>
|
||||
* man dash : <https://linux.die.net/man/1/dash>
|
||||
|
||||
Quelques astuces SHell. Des bouts de commandes, ou simplement les arguments qui vont bien.
|
||||
|
||||
# Script
|
||||
## Configuration
|
||||
|
||||
Style guide : <https://google.github.io/styleguide/shell.xml>
|
||||
### Initialisation du shell
|
||||
|
||||
# Configuration
|
||||
Entre les 3 modes ("login", "interactive non-login" et "non-interactive non-login") il y a de quoi se perdre à propos des fichiers chargés.
|
||||
Voici un rappel assez complet : <https://github.com/rbenv/rbenv/wiki/Unix-shell-initialization>
|
||||
|
||||
## Initialisation du shell
|
||||
### Bash history
|
||||
|
||||
Entre les 3 modes ("login", "interactive non-login" et "non-interactive non-login") il y a de quoi se perdre à propos des fichiers chargés. Voici un rappel assez complet : <https://github.com/rbenv/rbenv/wiki/Unix-shell-initialization>
|
||||
|
||||
## History Bash
|
||||
|
||||
`bashrc` :
|
||||
Pour avoir un « joli » [history](https://www.gnu.org/software/bash/manual/html_node/Bash-History-Builtins.html) sous Bash :
|
||||
|
||||
~~~
|
||||
export HISTCONTROL=$HISTCONTROL${HISTCONTROL+:}ignoreboth:erasedups
|
||||
|
@ -20,59 +26,54 @@ export HISTSIZE=65535
|
|||
export HISTTIMEFORMAT="%c : "
|
||||
~~~
|
||||
|
||||
> *Note* : si besoin on peut `chattr +a /root/.bash_history` pour empêcher sa suppression
|
||||
> *Note* : si besoin on peut `chattr +a /root/.bash_history` pour compliquer sa modification/suppression
|
||||
|
||||
Pour avoir un historique qui ne sauvegarde à chaque commande saisie et se synchronise entre plusieurs terminaux :
|
||||
Pour avoir un historique sauvegarde à chaque commande saisie et se synchronise entre plusieurs terminaux :
|
||||
|
||||
~~~
|
||||
shopt -s histappend
|
||||
PROMPT_COMMAND="history -a;history -n;${PROMPT_COMMAND}"
|
||||
~~~
|
||||
|
||||
## Changer l'éditeur de texte par défaut pour une commande
|
||||
### Changer l'éditeur de texte par défaut pour une commande
|
||||
|
||||
Normalement le script (vipw, vigr, -ldapvi, ...) se réfère aux fichiers scripts (qui ne sont que des liens vers les binaires) :
|
||||
|
||||
~~~{.bash}
|
||||
/etc/alternatives/
|
||||
~~~
|
||||
|
||||
Sinon en ligne de commande :
|
||||
Normalement les commandes utilisant un éditeur (`vipw`, `vigr`, `ldapvi`…) utilisent `/etc/alternatives/editor` qui est un lien symbolique vers l'éditeur par défaut du système. Sinon en ligne de commande on peut forcer la variable `EDITOR` :
|
||||
|
||||
~~~{.bash}
|
||||
$ EDITOR=nano vipw
|
||||
$ EDITOR=pico crontab -e
|
||||
~~~
|
||||
|
||||
# Manipulations
|
||||
## Manipulations
|
||||
|
||||
## Déplacements et effacements
|
||||
### Déplacements et effacements
|
||||
|
||||
La plupart des terminaux/consoles utilisent les commandes [readline](https://fr.wikipedia.org/wiki/GNU_Readline). Il est donc possible d'utiliser ses commandes pour faciliter le déplacement du curseur ou la suppression de caractères dans une ligne.
|
||||
La plupart des terminaux/consoles utilisent les commandes [readline](https://fr.wikipedia.org/wiki/GNU_Readline).
|
||||
Il est donc possible d'utiliser ses commandes pour faciliter le déplacement du curseur ou la suppression de caractères dans une ligne.
|
||||
|
||||
Déplacement :
|
||||
|
||||
* `Ctrl-E` : avancer à la fin de la ligne
|
||||
* `Alt-F` : avancer à la fin du mot
|
||||
* `Ctrl-F` : avancer d'un caractère
|
||||
* `Ctrl-A` : revenir au début de la ligne
|
||||
* `Alt-B` : revenir au début du mot
|
||||
* `Ctrl-B` : revenir d'un caractère
|
||||
* `Ctrl-e` : avancer à la fin de la ligne
|
||||
* `Ctrl-f` : avancer d'un caractère
|
||||
* `Ctrl-a` : revenir au début de la ligne
|
||||
* `Ctrl-b` : revenir d'un caractère
|
||||
* `Meta-b` : revenir au début du mot
|
||||
* `Meta-f` : avancer à la fin du mot
|
||||
|
||||
Effacement :
|
||||
|
||||
* `Ctrl-K` : effacer jusqu'à la fin de la ligne
|
||||
* `Alt-D` : effacer jusqu'à la fin du mot
|
||||
* `Ctrl-U` : effacer jusqu'au début de la ligne
|
||||
* `Ctrl-W` : effacer jusqu'au début du mot
|
||||
* `Ctrl-k` : effacer jusqu'à la fin de la ligne
|
||||
* `Ctrl-u` : effacer jusqu'au début de la ligne
|
||||
* `Ctrl-w` : effacer jusqu'au début du mot
|
||||
* `Meta-d` : effacer jusqu'à la fin du mot
|
||||
|
||||
> NB : Certaines lettres sont faciles à retenir : E = End, F = Forward, B = Backward.
|
||||
> *Note* : Certaines lettres sont faciles à retenir : `e` pour End, `f` pour Forward, `b` pour Backward.
|
||||
|
||||
C'est aussi valable dans tous les outils utilisant la bibliothèque "readline", c'est à dire un grand nombre de logiciels.
|
||||
|
||||
Il est possible d’éditer la ligne actuelle dans un éditeur de texte avec `Ctrl-X` puis `Ctrl-E`.
|
||||
### Tâches de fond
|
||||
|
||||
## Tâches de fond
|
||||
Jouons sur le fond :
|
||||
|
||||
~~~{.bash}
|
||||
$ bg = "mettre en arrière plan"
|
||||
|
@ -123,7 +124,7 @@ $ kill -9 %% #fg :x
|
|||
$ exit
|
||||
~~~
|
||||
|
||||
## Connaître le rang d'un élément dans une liste
|
||||
### Connaître le rang d'un élément dans une liste
|
||||
|
||||
Avec `grep` :
|
||||
|
||||
|
@ -146,21 +147,23 @@ $ ./liste_serveur.sh | awk '/NOUVEAU_SERVEUR/ { printf "%u\t%s\n", NR, $0 }'
|
|||
2 NOUVEAU_SERVEUR
|
||||
~~~
|
||||
|
||||
## Ajout mot en début de chaque ligne d'un buffer
|
||||
### Ajout mot en début de chaque ligne d'un buffer
|
||||
|
||||
~~~{.bash}
|
||||
$ sed 's/^/Coucou /' <<<"$VAR"
|
||||
~~~
|
||||
|
||||
## Avoir l’empreinte SSH d'une liste de serveurs
|
||||
### Avoir l’empreinte SSH d'une liste de serveurs
|
||||
|
||||
-> pour s'assurer que le host soit connu (~/.ssh/known_hosts) et ainsi automatiser des tâches sur des serveurs même si toujours aucune connexion effectuée et acceptée :
|
||||
Pour s'assurer que le host soit connu (`~/.ssh/known_hosts`) et ainsi automatiser des tâches sur des serveurs même si toujours aucune connexion effectuée et acceptée :
|
||||
|
||||
~~~{.bash}
|
||||
$ (for host in machine1 machine2 ...; do echo $host; timeout -k 2 2 ssh -o 'StrictHostKeyChecking no' $host cat /etc/ssh/ssh_host_dsa_key.pub >> ~/.ssh/known_hosts; done)
|
||||
~~~
|
||||
|
||||
## Manipuler l’historique
|
||||
### Manipuler l’historique
|
||||
|
||||
<http://www.faqs.org/docs/bashman/bashref_109.html#SEC116>
|
||||
|
||||
Les éléments suivants permettent de rappeler des bouts des commandes précédentes. Voir la section [_History Expansion_(https://www.gnu.org/software/bash/manual/bash.html#History-Interaction) dans le manuel de Bash.
|
||||
|
||||
|
@ -199,17 +202,17 @@ $ ^list^extract^
|
|||
tar --extract --file mon-archive.tar
|
||||
~~~
|
||||
|
||||
# Fichiers et FS
|
||||
## Fichiers et filesystems
|
||||
|
||||
## Ordinaire
|
||||
### Ordinaire
|
||||
|
||||
### Lister les répertoires monté sur le même FS
|
||||
#### Lister les répertoires montés sur le même FS
|
||||
|
||||
~~~{.bash}
|
||||
ROOT=/; get_fs(){ df $1 | tail -n1 | awk '{print $1}'; }; fs_root="$(get_fs $ROOT)"; for file in $(ls -1 $ROOT); do [ "$(get_fs $ROOT$file)" = "$fs_root" ] && echo "$ROOT$file"; done
|
||||
$ ROOT=/; get_fs(){ df $1 | tail -n1 | awk '{print $1}'; }; fs_root="$(get_fs $ROOT)"; for file in $(ls -1 $ROOT); do [ "$(get_fs $ROOT$file)" = "$fs_root" ] && echo "$ROOT$file"; done
|
||||
~~~
|
||||
|
||||
### Savoir si lignes en doublon dans un fichier
|
||||
#### Savoir si lignes en doublon dans un fichier
|
||||
|
||||
~~~{.bash}
|
||||
$ uniq -d <fichier>
|
||||
|
@ -221,40 +224,34 @@ ou autrement (appliquer un filtre différent) :
|
|||
$ diff <fichier> <(cat <fichier> | uniq)
|
||||
~~~
|
||||
|
||||
### Comparer deux fichiers quant à l'existence de nouvelles lignes
|
||||
#### Comparer deux fichiers quant à l'existence de nouvelles lignes
|
||||
|
||||
~~~{.bash}
|
||||
$ grep -F -x -v -f <fichier1> <fichier2>
|
||||
~~~
|
||||
|
||||
### Supprimer des vieux fichiers
|
||||
#### Supprimer des vieux fichiers
|
||||
|
||||
- Si + vieux de 30 jours en modification :
|
||||
Si + vieux de 30 jours en modification :
|
||||
|
||||
~~~{.bash}
|
||||
$ find DIR/ -type f -mtime +30 -delete
|
||||
$ find DIR/ -type f -mtime +30 -exec rm '{}' \;
|
||||
~~~
|
||||
|
||||
- Si + vieux depuis le 24 aout 2022 à 11h :
|
||||
Si + vieux depuis le 24 aout 2022 à 11h :
|
||||
|
||||
~~~{.bash}
|
||||
$ find DIR/ -type f ! -newermt "2022-08-24 11:00:00.00" -delete
|
||||
~~~
|
||||
|
||||
### Comparer deux fichiers à travers SSH
|
||||
#### Comparer deux fichiers à travers SSH
|
||||
|
||||
~~~{.bash}
|
||||
$ diff <fichier> <(ssh REMOTE cat <fichier>)
|
||||
~~~
|
||||
|
||||
### Changer le propriétaire des fichiers selon le user
|
||||
|
||||
~~~{.bash}
|
||||
$ find /path/ -user www-user -exec chown user: '{}' \;
|
||||
~~~
|
||||
|
||||
### Lister fichiers
|
||||
#### Lister fichiers
|
||||
|
||||
Lister les fichiers dont le nom contient autre chose que des
|
||||
lettres sans accent, des chiffres, des points ou des tirets :
|
||||
|
@ -271,9 +268,9 @@ Connaître la taille totale des derniers fichiers copiés :
|
|||
$ find /path/ -type f -mtime -1 -printf "'%p' " | xargs du -ch
|
||||
~~~
|
||||
|
||||
### Archiver
|
||||
#### Archiver
|
||||
|
||||
~~~ { .bash }
|
||||
~~~{.bash}
|
||||
tar --create --file archive.tar --verbose -- directory
|
||||
tar --create --file archive.tar --exclude='directory/subdir' --verbose -- directory
|
||||
tar --create --file archive.tar --exclude='directory/subdir/*.mp3' --verbose -- directory
|
||||
|
@ -281,38 +278,42 @@ tar --create --file archive.tar --exclude='directory/subdir/*.mp3' --verbose --
|
|||
|
||||
> Lorsqu'on exclut un répertoire, il ne faut pas mettre de `/` à la fin du chemin.
|
||||
|
||||
## Droits
|
||||
### Droits
|
||||
|
||||
### Changer propriétaires owner et group selon actuels
|
||||
#### Changer le propriétaire des fichiers selon le user
|
||||
|
||||
~~~{.bash}
|
||||
$ find /path/ -user www-user -exec chown user: '{}' \;
|
||||
~~~
|
||||
|
||||
#### Changer propriétaires owner et group selon actuels
|
||||
|
||||
~~~{.bash}
|
||||
$ chown -c -R --from user:user userbis:userbis .
|
||||
$ chown -c -R --from www-user:user www-userbis:userbis .
|
||||
~~~
|
||||
|
||||
### Copier seulement les droits de deux hiérarchies de fichiers
|
||||
### Répertoire
|
||||
|
||||
## Répertoire
|
||||
|
||||
### Surveiller les ouvertures/écriture des fichiers présent dans un répertoire
|
||||
#### Surveiller les ouvertures/écritures des fichiers présents dans un répertoire
|
||||
|
||||
~~~{.bash}
|
||||
$ iwatch <target>
|
||||
~~~
|
||||
|
||||
### Savoir les différents users qui ont écris dans /tmp
|
||||
#### Savoir les différents users qui ont écrit dans /tmp
|
||||
|
||||
~~~{.bash}
|
||||
$ stat -c %U /tmp/* | sort | uniq -c | sort -n
|
||||
~~~
|
||||
|
||||
Si «too arguments pour stat» (version bien plus lente) :
|
||||
Si « too arguments pour stat » (version plus lente) :
|
||||
|
||||
~~~
|
||||
$ find /tmp -exec stat -c %U '{}' \; | sort | uniq -c | sort -n
|
||||
~~~
|
||||
|
||||
### Comparer deux répertoires à travers SSH
|
||||
#### Comparer deux répertoires à travers SSH
|
||||
|
||||
Générique :
|
||||
|
||||
|
@ -321,21 +322,21 @@ $ DIR=$PWD
|
|||
$ for file in $(rsync -rvn $DIR REMOTE:$DIR | grep -v "^skipping non-regular file" | head -n -2); do echo $DIR/$file :; diff $DIR/$file <(ssh REMOTE cat $DIR/$file); done
|
||||
~~~
|
||||
|
||||
Pour /etc/ :
|
||||
Pour `/etc/` :
|
||||
|
||||
~~~
|
||||
# for file in $(rsync -rvn /etc/ --exclude=*.log --exclude=ssh --exclude=ssl --exclude=.git --exclude=shadow* --exclude=gshadow* REMOTE:/etc/ | \
|
||||
grep -v "^skipping non-regular file" | head -n -2); do \
|
||||
echo /etc/$file :; diff /etc/$file <(ssh REMOTE cat /etc/$file); done
|
||||
grep -v "^skipping non-regular file" | head -n -2); do \
|
||||
echo /etc/$file :; diff /etc/$file <(ssh REMOTE cat /etc/$file); done
|
||||
~~~
|
||||
|
||||
## Espace et Inode
|
||||
### Espace disque
|
||||
|
||||
Attention, `tune2fs -l` [ne rapporte pas les bonnes valeurs d'inodes libres](https://bbs.archlinux.org/viewtopic.php?id=117301) lorsque le système de fichiers est monté.
|
||||
|
||||
### Analyse disque
|
||||
#### Analyse disque
|
||||
|
||||
Quand il s'agit de / - penser à exclure les autres partitions (si existante de toute évidence) :
|
||||
Quand il s'agit de `/` penser à exclure les autres partitions (si existante de toute évidence) :
|
||||
|
||||
~~~
|
||||
# ncdu / --exclude /home --exclude /srv --exclude /var --exclude /tmp --exclude /boot --exclude /usr --exclude /proc
|
||||
|
@ -361,7 +362,7 @@ Lister les dix plus gros fichiers réguliers sous `/home` :
|
|||
|
||||
Sinon voir du côté de [HowtoDUC](/HowtoDUC).
|
||||
|
||||
### Tester l'écriture disque
|
||||
#### Tester l'écriture disque
|
||||
|
||||
Simplement, en écriture (fichier de 5.1GB) :
|
||||
|
||||
|
@ -369,19 +370,19 @@ Simplement, en écriture (fichier de 5.1GB) :
|
|||
$ dd if=/dev/zero of=test count=10000000
|
||||
~~~
|
||||
|
||||
### Lister les répertoires ayant le plus de fichiers <=> max inode
|
||||
#### Lister les répertoires ayant le plus de fichiers <=> max inode
|
||||
|
||||
#### À partir de Stretch (Debian 9)
|
||||
##### À partir de Stretch (Debian 9)
|
||||
|
||||
On peut utiliser la commande *ncdu*, et lors du listage, appuyer sur la touche c (*sort by items*).
|
||||
|
||||
#### À partir de Jessie (Debian 8)
|
||||
##### À partir de Jessie (Debian 8)
|
||||
|
||||
~~~{.bash}
|
||||
du --inodes -x /path | sort -n
|
||||
$ du --inodes -x /path | sort -n
|
||||
~~~
|
||||
|
||||
#### Autres versions
|
||||
##### Autres versions
|
||||
|
||||
Sinon étapes par étapes (sans la commande *du --inodes*) :
|
||||
|
||||
|
@ -398,26 +399,27 @@ cat $TMP | (while read line; do num=$(echo $line | awk '{ print $1 }'); path=$(e
|
|||
rm $TMP
|
||||
~~~
|
||||
|
||||
### Comprendre pourquoi résultat d'un `df` ne correspond pas un `du`
|
||||
#### Comprendre pourquoi résultat d'un `df` ne correspond pas un `du`
|
||||
|
||||
Si le résultat d'un `df` indique une occupation disque plus importante que lorsque on fait un `du -cx /to/path`, cela veut dire que sans doute un fichier a été supprimé mais est encore en lecture par un process.
|
||||
|
||||
On peut le rechercher en faisant :
|
||||
|
||||
~~~{}
|
||||
~~~{.bash}
|
||||
# lsof /var/ | grep deleted
|
||||
~~~
|
||||
|
||||
Ce qui équivaut à
|
||||
Ce qui équivaut à :
|
||||
|
||||
~~~{}
|
||||
# lsof -Fn | grep ^n/var/ | sed 's/^n//' | xargs -n1 -I file stat file | grep 'No such file or directory'
|
||||
~~~
|
||||
|
||||
En tuant le process, la mémoire sur le disque devrait se «libérer» et être de nouveau disponible.
|
||||
En tuant le process, la place sur le disque devrait se « libérer » et être de nouveau disponible.
|
||||
|
||||
# Utilisateurs UNIX
|
||||
## Utilisateurs UNIX
|
||||
|
||||
## Créer HOME
|
||||
### Créer HOME
|
||||
|
||||
Si l'utilisateur existe, et qu'il est nécessaire de créer un répertoire $HOME pour ce dernier (car non existant) :
|
||||
|
||||
|
@ -427,25 +429,25 @@ Si l'utilisateur existe, et qu'il est nécessaire de créer un répertoire $HOME
|
|||
|
||||
Va appliquer les bon droits sur fichiers/répertoires + copier ce qu'il y a dans /etc/skel.
|
||||
|
||||
## Lister les utilisateurs + groupe
|
||||
### Lister les utilisateurs + groupe
|
||||
|
||||
### UNIX
|
||||
#### UNIX
|
||||
|
||||
~~~{.bash}
|
||||
$ for user in $(getent passwd | awk -F ':' '$3 > 10000 {printf $1 " "}'); do groups $user; done
|
||||
~~~
|
||||
|
||||
### LDAP
|
||||
#### LDAP
|
||||
|
||||
~~~{.bash}
|
||||
$ for user in $(getent passwd | awk -F ':' '$3 > 10000 {printf $1 " "}'); do \
|
||||
ldapsearch -x -h localhost -LLL -b "dc=MACHINE,dc=DOMAIN,dc=COM" cn | tail -n2 | \
|
||||
tr '\n' ' ' | cut -d':' -f2 | echo -n "$(cat <&0)"; echo = $(groups $user); done
|
||||
ldapsearch -x -h localhost -LLL -b "ou=people,dc=example,dc=com" cn | tail -n2 | \
|
||||
tr '\n' ' ' | cut -d':' -f2 | echo -n "$(cat <&0)"; echo = $(groups $user); done
|
||||
~~~
|
||||
|
||||
## Lister les expirations des mot de passe utilisateurs par date
|
||||
### Lister les expirations des mots de passe utilisateurs par date
|
||||
|
||||
### LDAP
|
||||
#### LDAP
|
||||
|
||||
On se sert pour ça du champ `sambaPwdLastSet` indiquant la date du dernier changement et on y ajoute 200 jours (17280000 secondes) correspondant au champ `shadowMax` indiquant la durée de validité d'un mot de passe. On n'affiche pas les utilisateurs ayant leur mot de passe déjà expirés depuis plus d'un mois.
|
||||
|
||||
|
@ -457,19 +459,19 @@ delete_before=$(date "+%Y %b" -d -1month)
|
|||
/usr/bin/ldapsearch -x -b 'ou=people,dc=XXXXXXX,dc=com' | /bin/sed '/sambaPwdLastSet\|uid:/!d' | /usr/bin/awk 'NR%2{printf "%s ",$0;next;}1' | /bin/sed -e 's/uid: //' -e 's/sambaPwdLastSet: //' | /usr/bin/xargs -L1 bash -c 'echo $(($1+17280000)); echo $0' | /usr/bin/awk 'NR%2{printf "%s ",$0;next;}1' | /usr/bin/xargs -L1 bash -c 'date -d @$0; echo $1' | /usr/bin/awk 'NR%2{printf "%s ",$0;next;}1' | /bin/sed -e "s/^\(.*\)\ \(20..\)\ \(.*\)$/- \2 \1 \3/" | /bin/sed -r -e 's/(\s+)?\S+//3' -e 's/(\s+)?\S+//6' | /usr/bin/sort -n -k 2 -k 3M -k 4 | /usr/bin/awk "/$delete_before/{p=1}p"
|
||||
~~~
|
||||
|
||||
# Serveur web
|
||||
## Serveur web
|
||||
|
||||
## Avoir un rendu des requêtes par IP à partir d'un access.log
|
||||
### Avoir un rendu des requêtes par IP à partir d'un access.log
|
||||
|
||||
Selon le format, il faudra peut-être changer la valeur du field de cut (-f1 par -f2).
|
||||
|
||||
### Compte rendu pour un laps de temps
|
||||
#### Compte rendu pour un laps de temps
|
||||
|
||||
~~~{.bash}
|
||||
$ date; (timeout 60 tail -f access.log | cut -d' ' -f1) | sort | uniq -c | sort -n
|
||||
~~~
|
||||
|
||||
### En direct
|
||||
#### En direct
|
||||
|
||||
- Version simple :
|
||||
|
||||
|
@ -484,35 +486,35 @@ $ SEUIL=5; tail -f access.log | stdbuf -oL cut -d ' ' -f1 | stdbuf -oL uniq -c |
|
|||
eval "awk '\$1 > $SEUIL {printf \"\\033[1;31m\" \$1 \" \" \$2 \"\\033[0m \\n\"; next;};{printf \$1 \" \" \$2 \"\\n\";}'"
|
||||
~~~
|
||||
|
||||
## Comparer les requêtes effectués dans access.log
|
||||
### Comparer les requêtes effectués dans access.log
|
||||
|
||||
Les différentes requêtes sont comparés aux nombres de caractères différent. La variable SEUIL est la limite de caractères différents pour 2 requêtes.
|
||||
|
||||
~~~{.bash}
|
||||
SEUIL=20; i=1; lastline=; cat access.log | sed 's/.*\] \(.*\)\" [0-9]\{3\}.*$/\1\"/' | \
|
||||
(while read line; do diff=$(cmp -bl <(echo "$lastline") <(echo "$line") 2>/dev/null | wc -l); \
|
||||
((diff<SEUIL)) && ((i=i+1)) || { echo "$i $line"; i=1; }; lastline="$line"; done)
|
||||
$ SEUIL=20; i=1; lastline=; cat access.log | sed 's/.*\] \(.*\)\" [0-9]\{3\}.*$/\1\"/' | \
|
||||
(while read line; do diff=$(cmp -bl <(echo "$lastline") <(echo "$line") 2>/dev/null | wc -l); \
|
||||
((diff<SEUIL)) && ((i=i+1)) || { echo "$i $line"; i=1; }; lastline="$line"; done)
|
||||
~~~
|
||||
|
||||
Si on veut les adresses IPs, ou simplement trier le access.log avant l'analyse, il faut modifier après le : cat acccess.log |
|
||||
Si on veut les adresses IP, ou simplement trier le access.log avant l'analyse, il faut modifier après le : cat acccess.log |
|
||||
|
||||
Et si l'on considère les mots comme une seule différence (et non par caractères), on peut descendre le seuil :
|
||||
|
||||
~~~{.bash}
|
||||
SEUIL=3; i=1; lastline=; cat access.log | sed 's/.*\] \(.*\)\" [0-9]\{3\}.*$/\1\"/' | \
|
||||
(while read line; do diff=$(cmp -bl <(echo "$lastline") <(echo "$line") 2>/dev/null | awk '{print $1}' | \
|
||||
(compt=0; lastnumber=0; while read number; do ((lastnumber+1!=number)) && ((compt=compt+1)); lastnumber=$number; done; echo $compt)); \
|
||||
((diff<SEUIL)) && ((i=i+1)) || { echo "$i $line"; i=1; }; lastline="$line"; done)
|
||||
$ SEUIL=3; i=1; lastline=; cat access.log | sed 's/.*\] \(.*\)\" [0-9]\{3\}.*$/\1\"/' | \
|
||||
(while read line; do diff=$(cmp -bl <(echo "$lastline") <(echo "$line") 2>/dev/null | awk '{print $1}' | \
|
||||
(compt=0; lastnumber=0; while read number; do ((lastnumber+1!=number)) && ((compt=compt+1)); lastnumber=$number; done; echo $compt)); \
|
||||
((diff<SEUIL)) && ((i=i+1)) || { echo "$i $line"; i=1; }; lastline="$line"; done)
|
||||
~~~
|
||||
|
||||
C'est à dire que entre 2 requêtes du type :
|
||||
C'est à dire qu'entre 2 requêtes du type :
|
||||
|
||||
- /page.do?pseudo=Example&pass=0322
|
||||
- /page.do?pseudo=Mail&pass=3892
|
||||
- `/page.do?pseudo=Example&pass=0322`
|
||||
- `/page.do?pseudo=Mail&pass=3892`
|
||||
|
||||
il n'y a que 2 différences : le «pseudo», et le «pass».
|
||||
il n'y a que 2 différences : le « pseudo », et le « pass ».
|
||||
|
||||
## Analyser un apache-status
|
||||
### Analyser un apache-status
|
||||
|
||||
Compter le nombre de requêtes par IPs :
|
||||
|
||||
|
@ -528,23 +530,23 @@ $ DATE=2017-10-12-14-
|
|||
$ cat ${DATE}*.html | grep --color '<td>[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+</td>' | sed 's/.*<td>\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\)<\/td>.*/\1/g' | sort -n | uniq -c | sort -n
|
||||
~~~
|
||||
|
||||
# Processus / Process
|
||||
## Processus / Process
|
||||
|
||||
## Surveiller les nouveaux processus créés
|
||||
### Surveiller les nouveaux processus créés
|
||||
|
||||
### Liste simple
|
||||
#### Liste simple
|
||||
|
||||
~~~{.bash}
|
||||
$ ps -e -o etimes=,pid,cmd | sort -rn | awk '{if ($1!=0 && $3!~/\[.*\]/) print $0 }'
|
||||
~~~
|
||||
|
||||
### il y a moins de X minutes
|
||||
#### il y a moins de X minutes
|
||||
|
||||
~~~{.bash}
|
||||
$ MIN=5; ps -e -o etimes=,pid,cmd | sort -rn | awk '{if ($1<'$(( MIN * 60 ))' && $1>0 && $3!~/\[.*\]/) print $0 }'
|
||||
~~~
|
||||
|
||||
### Watch
|
||||
#### Watch
|
||||
|
||||
Toutes les 5 secondes :
|
||||
|
||||
|
@ -558,7 +560,7 @@ Se baser seulement par rapport aux utilisateurs ayant créés dernièrement ces
|
|||
$ SEUIL=100; watch -n 5 -d "ps -e -o etimes=,user | sort -n | awk '{if (\$1<$SEUIL) print \$2 }' | sort | uniq -c | sort -n"
|
||||
~~~
|
||||
|
||||
### Cron
|
||||
#### Cron
|
||||
|
||||
Recevoir le output de la commande *top* en cron :
|
||||
|
||||
|
@ -566,31 +568,31 @@ Recevoir le output de la commande *top* en cron :
|
|||
top -b -d 1
|
||||
~~~
|
||||
|
||||
## Lister avec le plus de fils (/fork)
|
||||
#### Lister avec le plus de fils (/fork)
|
||||
|
||||
~~~{.bash}
|
||||
(total_procs=0; for foo in $(ps -e -o ppid | sed '1d' | sort -n | uniq -c | sort -n | awk '{ print $1 ":" $2 }'); do val=$(echo $foo | cut -d: -f1); total_procs=$((total_procs+val)); pid=$(echo $foo | cut -d: -f2); (( pid != 0 )) && { echo -n $val ') '; ps -p $pid -o pid,cmd | tail -n1; }; done; echo Total = $total_procs) | tail
|
||||
~~~
|
||||
|
||||
## Consommation Swap
|
||||
#### Consommation Swap
|
||||
|
||||
~~~{.bash}
|
||||
(for file in /proc/*; do [ -e $file/status ] || continue; PID=$(basename $file); RES=$(grep VmSwap: $file/status | sed 's/VmSwap\:[[:space:]]*\(.*\)/\1/'); [ -n "$RES" ] && echo $RES ' = ' $PID ' ' $(ps -p $PID -o cmd --no-headers); done) | sort -n
|
||||
~~~
|
||||
|
||||
## Consommation RAM (VmSize)
|
||||
#### Consommation RAM (VmSize)
|
||||
|
||||
~~~{.bash}
|
||||
$ top -o RES
|
||||
~~~
|
||||
|
||||
### Par process
|
||||
#### Par process
|
||||
|
||||
~~~{.bash}
|
||||
$ ps o user:20,pid,pcpu,pmem,vsz,rss,tty,stat,start,time,comm -p 3108
|
||||
~~~
|
||||
|
||||
### Par utilisateur
|
||||
#### Par utilisateur
|
||||
|
||||
~~~{.bash}
|
||||
for var in users1 users2; do echo '#' $var ':'; ps -u $var -o pid= | while read pid; do echo -n $pid ') threads: ' "$(ps -p $pid -T | wc -l)" "; $(grep VmSize /proc/$pid/status)"; echo; vmsize=$(grep VmSize /proc/$pid/status | sed 's/^VmSize:\s*\([0-9]*\) kB/\1/'); done; done
|
||||
|
@ -615,13 +617,13 @@ $ lsof -i :Port
|
|||
|
||||
### Selon l'utilisateur
|
||||
|
||||
~~~
|
||||
~~~{.bash}
|
||||
# lsof -u UID
|
||||
~~~
|
||||
|
||||
Si www-data a uid=33, lister fichiers ouvert par serveur-web :
|
||||
|
||||
~~~
|
||||
~~~{.bash}
|
||||
# lsof -u 33 | awk '{ print $2 " = " $9 }' | grep "/home/.*$"
|
||||
~~~
|
||||
|
||||
|
@ -631,43 +633,43 @@ Pour tester les performances d'un FTP ou autre on a besoin d'envoyer un fichier
|
|||
|
||||
Pour un fichier de 10Mio :
|
||||
|
||||
~~~
|
||||
dd if=/dev/zero of=10M.bin bs=1024 count=0 seek=$[1024*10]
|
||||
~~~{.bash}
|
||||
$ dd if=/dev/zero of=10M.bin bs=1024 count=0 seek=$[1024*10]
|
||||
~~~
|
||||
|
||||
Pour 100Mio :
|
||||
|
||||
~~~
|
||||
dd if=/dev/zero of=100M.bin bs=1024 count=0 seek=$[1024*100]
|
||||
~~~{.bash}
|
||||
$ dd if=/dev/zero of=100M.bin bs=1024 count=0 seek=$[1024*100]
|
||||
~~~
|
||||
|
||||
Pour 1Gio :
|
||||
|
||||
~~~
|
||||
dd if=/dev/zero of=1G.bin bs=1024 count=0 seek=$[1024*1024]
|
||||
~~~{.bash}
|
||||
$ dd if=/dev/zero of=1G.bin bs=1024 count=0 seek=$[1024*1024]
|
||||
~~~
|
||||
|
||||
## stdout / stderr
|
||||
### stdout / stderr
|
||||
|
||||
Renvoyer stdout/stderr dans une même sortie (par exemple /dev/null) :
|
||||
|
||||
~~~
|
||||
eject /dev/coin > /dev/null 2>&1
|
||||
~~~{.bash}
|
||||
$ eject /dev/coin > /dev/null 2>&1
|
||||
~~~
|
||||
|
||||
Détecter les tabulations
|
||||
|
||||
~~~
|
||||
~~~{.bash}
|
||||
$ grep -P '\t'
|
||||
~~~
|
||||
|
||||
## Conflit sur `stdin`
|
||||
### Conflit sur `stdin`
|
||||
|
||||
Rediriger `stdin` peut être nécéssaire, par exemple, lorsqu’on combine une boucle `while read`, un _here-document_ et des commandes interactives.
|
||||
|
||||
Dans la boucle suivante, lorsqu’on rentre dans la boucle, la variable `hostname` contient bien « server1 ».
|
||||
|
||||
~~~ { .bash }
|
||||
~~~{.bash}
|
||||
while read hostname
|
||||
do
|
||||
ssh "${hostname}"
|
||||
|
@ -679,7 +681,7 @@ eof
|
|||
|
||||
On peut s’attendre à ce qu’au prochain tour de boucle, `hostname` contienne « server2 », mais lorsque la commande `ssh` sera exécutée durant le premier passage de la boucle, c’est bien `ssh` qui va consommer la ligne « server2 » ! Pour empêcher ça, on peut faire lire un autre descripteur de fichier, comme `3`, à `read` et envoyer le _here-document_ dessus :
|
||||
|
||||
~~~ { .bash }
|
||||
~~~{.bash}
|
||||
while read hostname 0<&3
|
||||
do
|
||||
ssh "${hostname}"
|
||||
|
@ -691,7 +693,7 @@ eof
|
|||
|
||||
On peut aussi faire lire au autre descripteur de fichier à `ssh` à la place :
|
||||
|
||||
~~~ { .bash }
|
||||
~~~{.bash}
|
||||
while read hostname
|
||||
do
|
||||
ssh "${hostname}" 0<&3
|
||||
|
@ -701,17 +703,17 @@ server2
|
|||
eof
|
||||
~~~
|
||||
|
||||
# Serveur mail
|
||||
## Serveur mail
|
||||
|
||||
## Avoir vision des différentes erreurs mailq (MAILER-DAEMON)
|
||||
### Avoir vision des différentes erreurs mailq (MAILER-DAEMON)
|
||||
|
||||
~~~{.bash}
|
||||
(for id in $(mailq | grep MAILER\-DAEMON | cut -d' ' -f1); do postcat -q $id| grep Diagnostic\-Code\:; done) | sort | uniq -c | sort -n
|
||||
~~~
|
||||
|
||||
# Parsing
|
||||
## Parsing
|
||||
|
||||
## JSON avec jq
|
||||
### JSON avec jq
|
||||
|
||||
jq est un puissant outil de manipulation de JSON en cli. Il va aussi mettre en forme et colorer en fonction du terminal.
|
||||
|
||||
|
@ -727,51 +729,91 @@ On peut s'en servir pour extraire certaine partie du JSON :
|
|||
* .foo : Récupérer la valeur de la clée foo
|
||||
|
||||
|
||||
Exemple: Récupérer l'ip d'un container (f37ac628a4630da4aabbd23ba8eebf9c72dce5f3ba03675515a8b3619f8425d2) sur l'interface docker_gwbridge
|
||||
Exemple : récupérer l'IP d'un container sur l'interface `docker_gwbridge` :
|
||||
|
||||
~~~
|
||||
# docker inspect docker_gwbridge | jq ".[0].Containers.f37ac628a4630da4aabbd23ba8eebf9c72dce5f3ba03675515a8b3619f8425d2.IPv4Address"
|
||||
~~~
|
||||
|
||||
> *Note* : Pour faire des tests ou s'entrainer : <https://jqplay.org/>
|
||||
|
||||
Tips : Pour faire des tests ou s'entrainer : https://jqplay.org/
|
||||
## Mot de passe
|
||||
|
||||
# Mot de passe
|
||||
~~~{.bash}
|
||||
apg -c /dev/urandom -a0 -n1 -m20 -MSNCL -E oOlL10\&\\\/\"\'
|
||||
~~~
|
||||
|
||||
Si on a pas la commande `apg` :
|
||||
Sans la commande `apg` :
|
||||
|
||||
$ tr -cd [:alnum:] < /dev/urandom | head -c22; echo
|
||||
~~~{.bash}
|
||||
$ tr -cd [:alnum:] < /dev/urandom | head -c22; echo
|
||||
~~~
|
||||
|
||||
> La commande `echo` à la fin permet d’avoir un saut de ligne. Sinon, le _prompt_ sera collé au mot de passe qui a été généré.
|
||||
|
||||
## Générer un mot de passe hexadecimal
|
||||
### En hexadecimal
|
||||
|
||||
Pour générer un mot de passe hexadecimal de 6 octets :
|
||||
```
|
||||
openssl rand -hex 6
|
||||
```
|
||||
Pour générer 6 octets en hexadecimal :
|
||||
|
||||
# Autres
|
||||
~~~{.bash}
|
||||
$ openssl rand -hex 6
|
||||
~~~
|
||||
|
||||
## Hexadécimal - décimal
|
||||
## Variables
|
||||
|
||||
```
|
||||
Les variables d'environnement actuelles :
|
||||
|
||||
~~~{.bash}
|
||||
$ printenv
|
||||
~~~
|
||||
|
||||
Ajouter une variable :
|
||||
|
||||
~~~{.bash}
|
||||
$ FOO=bar
|
||||
~~~
|
||||
|
||||
Ajouter une variable d'environnement :
|
||||
|
||||
~~~{.bash}
|
||||
$ export FOO=bar
|
||||
~~~
|
||||
|
||||
Supprimer une variable :
|
||||
|
||||
~~~{.bash}
|
||||
$ unset FOO
|
||||
~~~
|
||||
|
||||
Attention, quand on utilise une variable temporaire dans une ligne de commande, elle n'est utilisée
|
||||
que pour l'environnement et ne peut être utiliser comme une variable. Ainsi :
|
||||
|
||||
~~~{.bash}
|
||||
$ BAR=bar echo -n foo $BAR ; BAZ=baz env | grep baz
|
||||
fooBAZ=baz
|
||||
~~~
|
||||
|
||||
## Divers
|
||||
|
||||
### Hexadécimal - décimal
|
||||
|
||||
~~~{.bash}
|
||||
$ printf '%x\n' 27
|
||||
1b
|
||||
$ printf '%d\n' 0x1b
|
||||
27
|
||||
```
|
||||
~~~
|
||||
|
||||
```
|
||||
~~~{.bash}
|
||||
$ bc
|
||||
> obase=16
|
||||
> 27
|
||||
1B
|
||||
```
|
||||
~~~
|
||||
|
||||
```
|
||||
~~~{.bash}
|
||||
$ bc
|
||||
> ibase=16
|
||||
> 1B
|
||||
27
|
||||
```
|
||||
~~~
|
||||
|
|
Loading…
Reference in a new issue