19
0
Fork 0
wiki/TipsShell.md

614 lines
17 KiB
Markdown
Raw Normal View History

2017-04-07 12:01:14 +02:00
Quelques astuces SHell. Des bouts de commandes, ou simplement les arguments qui vont bien.
2016-12-21 19:32:52 +01:00
2017-04-07 12:01:14 +02:00
# Script
2016-12-21 19:32:52 +01:00
2017-03-28 10:42:28 +02:00
Style guide : <https://google.github.io/styleguide/shell.xml>
2017-01-03 09:15:29 +01:00
2017-04-07 12:01:14 +02:00
# Configuration
2017-01-20 10:33:36 +01:00
2017-04-07 12:01:14 +02:00
## Initialisation du shell
2017-01-20 10:33:36 +01:00
2017-03-28 10:42:28 +02:00
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>
2017-01-24 11:50:40 +01:00
2017-04-07 12:01:14 +02:00
## History Bash
2017-01-24 11:50:40 +01:00
`bashrc` :
~~~
2018-09-11 14:01:18 +02:00
export HISTCONTROL=$HISTCONTROL${HISTCONTROL+:}ignoreboth:erasedups
2017-01-24 11:50:40 +01:00
export HISTSIZE=65535
export HISTTIMEFORMAT="%c : "
~~~
> *Note* : si besoin on peut `chattr +a /root/.bash_history` pour empêcher sa suppression
2017-03-14 12:22:58 +01:00
2018-09-11 14:01:18 +02:00
Pour avoir un historique qui ne sauvegarde à chaque commande saisie et se synchronise entre plusieurs terminaux :
~~~
shopt -s histappend
PROMPT_COMMAND="history -a;history -n;${PROMPT_COMMAND}"
~~~
2017-04-07 12:01:14 +02:00
## Changer l'éditeur de texte par défaut pour une commande
2017-03-14 12:22:58 +01:00
2017-03-14 12:23:31 +01:00
Normalement le script (vipw, vigr, -ldapvi, ...) se réfère aux fichiers scripts (qui ne sont que des liens vers les binaires) :
2017-03-14 12:22:58 +01:00
~~~{.bash}
/etc/alternatives/
~~~
Sinon en ligne de commande :
~~~{.bash}
$ EDITOR=nano vipw
$ EDITOR=pico crontab -e
~~~
2017-04-07 12:01:14 +02:00
# Manipulations
2017-03-15 12:01:56 +01:00
2020-03-23 08:37:57 +01:00
## 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.
Déplacement :
2020-03-23 08:54:19 +01:00
2020-03-23 08:37:57 +01:00
* `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
Effacement :
2020-03-23 08:54:19 +01:00
2020-03-23 08:37:57 +01:00
* `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
> NB : Certaines lettres sont faciles à retenir : E = End, F = Forward, B = Backward.
C'est aussi valable dans tous les outils utilisant la bibliothèque "readline", c'est à dire un grand nombre de logiciels.
2022-07-25 10:55:01 +02:00
Il est possible déditer la ligne actuelle dans un éditeur de texte avec `Ctrl-X` puis `Ctrl-E`.
2022-07-25 10:54:47 +02:00
2017-04-07 12:01:14 +02:00
## Tâches de fond
2017-03-15 12:01:56 +01:00
~~~{.bash}
$ bg = "mettre en arrière plan"
$ fg = "mettre en premier plan"
$ jobs = "lister les tâches de fond"
%% = "dernier job utilisé (représenté par un +)"
%x = "job numéro x"
~~~
~~~{.bash}
$ vi foo
^Z
[1]+ Stopped vi foo
$ tail -f bar
...
^C
$ fg
^Z
[1]+ Stopped vi foo
$ kill -9 %%
[1]+ Killed vi foo
$ ( sleep 1m; echo "Premier !" ) &
[1] 13649
$ ( sleep 30; echo "Deuxième !" ) &
[2] 13651
$ jobs
2017-03-15 12:04:20 +01:00
[1]- Running sleep 1m && echo ...
[2]+ Running sleep 30 && echo ...
2017-03-15 12:01:56 +01:00
$ fg %2
^Z
2017-03-15 12:04:20 +01:00
[2]+ Stopped sleep 30 && echo ...
2017-03-15 12:01:56 +01:00
$ jobs
2017-03-15 12:04:20 +01:00
[1]- Running sleep 1m && echo ...
[2]+ Stopped sleep 30 && echo ...
2017-03-15 12:01:56 +01:00
$ sleep 30; bg
Premier !
2017-03-15 12:04:20 +01:00
[2]- Done sleep 30 && echo ...
2017-03-15 12:01:56 +01:00
Deuxième !
$ jobs
2017-03-15 12:04:20 +01:00
[1]- Done sleep 1m && echo ...
2017-03-15 12:07:25 +01:00
$ vi foo
^Z
[1]+ Stopped vi foo
$ exit
There are stopped jobs.
$ kill -9 %% #fg :x
$ exit
2017-03-15 12:39:56 +01:00
~~~
2017-04-10 12:07:44 +02:00
## Connaître le rang d'un élément dans une liste
Utilisation de **tac** pour inverser la liste, sans la trier :
~~~{.bash}
$ ./liste_serveur.sh | tac | grep -n NOUVEAU_SERVEUR
2:NOUVEAU_SERVEUR
~~~
2017-06-22 14:37:21 +02:00
-> 'grep -n' reviens au même que 'nl | grep'
2017-06-23 15:02:45 +02:00
## Ajout mot en début de chaque ligne d'un buffer
2017-07-18 16:02:11 +02:00
~~~{.bash}
2017-06-23 15:02:45 +02:00
$ sed 's/^/Coucou /g' <<<"$VAR"
~~~
2017-07-18 16:02:11 +02:00
## Avoir le 'fingerprint' SSH d'une liste de serveur
-> 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)
~~~
2017-04-07 12:01:14 +02:00
# Fichiers et FS
2017-03-28 10:42:28 +02:00
2017-04-07 12:01:14 +02:00
## Ordinaire
2017-04-07 11:20:35 +02:00
2017-09-18 10:42:00 +02:00
### Lister les répertoires monté sur le même FS
~~~{.bash}
2017-09-19 10:36:58 +02:00
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
2017-09-18 10:42:00 +02:00
~~~
2017-04-07 12:01:14 +02:00
### Savoir si lignes en doublon dans un fichier
2017-03-28 10:42:28 +02:00
~~~{.bash}
$ uniq -d <fichier>
~~~
ou autrement (appliquer un filtre différent) :
~~~{.bash}
$ diff <fichier> <(cat <fichier> | uniq)
~~~
2017-04-07 12:01:14 +02:00
### Comparer deux fichiers quant à l'existence de nouvelles lignes
2017-03-28 10:42:28 +02:00
~~~{.bash}
$ grep -F -x -v -f <fichier1> <fichier2>
~~~
2017-04-07 12:01:14 +02:00
### Supprimer des vieux fichiers
2017-03-15 12:39:56 +01:00
2017-04-07 11:20:35 +02:00
- Par exemple, si + vieux de 30 jours en modification :
2017-04-04 11:35:43 +02:00
2017-04-07 11:20:35 +02:00
~~~{.bash}
$ find DIR/ -type f -mtime +30 -delete
$ find DIR/ -type f -mtime +30 -exec rm '{}' \;
2017-04-04 11:35:43 +02:00
~~~
2017-04-07 12:01:14 +02:00
### Comparer deux fichiers à travers SSH
2017-04-07 11:43:55 +02:00
~~~{.bash}
$ diff <fichier> <(ssh REMOTE cat <fichier>)
~~~
2018-03-29 10:12:20 +02:00
### Changer le propriétaire des fichiers selon le user
~~~{.bash}
$ find /path/ -user www-user -exec chown user: '{}' \;
~~~
2018-01-17 10:16:20 +01:00
### Lister fichiers
Connaître la taille totale des derniers fichiers copiés :
~~~{.bash}
2018-03-29 10:12:20 +02:00
$ find /path/ -type f -mtime -1 -printf "'%p' " | xargs du -ch
2018-01-17 10:16:20 +01:00
~~~
2017-06-22 14:29:00 +02:00
## Droits
### 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
2017-04-07 12:01:14 +02:00
## Répertoire
2017-04-07 12:01:14 +02:00
### Surveiller les ouvertures/écriture des fichiers présent dans un répertoire
2017-03-15 17:41:23 +01:00
~~~{.bash}
$ iwatch <target>
~~~
2017-04-07 12:01:14 +02:00
### Savoir les différents users qui ont écris dans /tmp
~~~{.bash}
2017-03-15 16:17:03 +01:00
$ stat -c %U /tmp/* | sort | uniq -c | sort -n
2017-03-16 10:37:53 +01:00
~~~
2017-04-07 12:48:14 +02:00
Si «too arguments pour stat» (version bien plus lente) :
2017-04-07 15:54:39 +02:00
2017-04-07 12:48:14 +02:00
~~~
$ find /tmp -exec stat -c %U '{}' \; | sort | uniq -c | sort -n
~~~
2017-04-07 12:01:14 +02:00
### Comparer deux répertoires à travers SSH
2017-04-07 11:43:55 +02:00
Générique :
~~~{.bash}
$ DIR=$PWD
2017-04-07 11:46:43 +02:00
$ 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
2017-04-07 11:43:55 +02:00
~~~
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 \
2017-04-07 11:46:43 +02:00
echo /etc/$file :; diff /etc/$file <(ssh REMOTE cat /etc/$file); done
2017-04-07 11:43:55 +02:00
~~~
2017-04-07 12:01:14 +02:00
## Espace et Inode
2017-04-07 11:20:35 +02:00
2017-04-07 12:01:14 +02:00
### Analyse disque
2017-04-07 11:20:35 +02:00
Quand il s'agit de / - penser à exclure les autres partitions (si existante de toute évidence) :
~~~
2017-07-19 12:55:37 +02:00
# ncdu / --exclude /home --exclude /srv --exclude /var --exclude /tmp --exclude /boot --exclude /usr --exclude /proc
2017-04-07 11:20:35 +02:00
~~~
Pour certaines anciennes versions :
~~~
# ncdu --exclude "/home/*" /
~~~
2017-09-19 10:36:58 +02:00
ou plus simplement :
~~~
# du -chx / | sort -h | tail
~~~
2017-04-07 11:20:35 +02:00
Sinon voir du côté de [HowtoDUC](/HowtoDUC).
2017-04-07 12:01:14 +02:00
### Tester l'écriture disque
2017-03-16 10:37:53 +01:00
Simplement, en écriture (fichier de 5.1GB) :
~~~{.bash}
$ dd if=/dev/zero of=test count=10000000
2017-03-21 11:45:57 +01:00
~~~
2017-04-07 12:01:14 +02:00
### Lister les répertoires ayant le plus de fichiers <=> max inode
2017-03-28 10:42:28 +02:00
2018-03-21 15:26:41 +01:00
#### À partir de Stretch (Debian 9)
2018-03-21 15:25:27 +01:00
2018-03-21 15:26:41 +01:00
On peut utiliser la commande *ncdu*, et lors du listage, appuyer sur la touche c (*sort by items*).
#### À partir de Jessie (Debian 8)
2018-03-21 15:20:41 +01:00
~~~{.bash}
du --inodes -x /path | sort -n
~~~
2018-03-21 15:26:41 +01:00
#### Autres versions
2018-03-21 15:25:27 +01:00
Sinon étapes par étapes (sans la commande *du --inodes*) :
2018-03-21 15:20:41 +01:00
2017-03-28 10:42:28 +02:00
~~~{.bash}
2017-04-20 17:31:16 +02:00
PATH_TO_WATCH='/var'; RESULT_FILE='list_max_inode.txt'; TMP=$(mktemp)
2017-03-28 10:42:28 +02:00
#Regarder dans le premier niveau
2018-03-21 11:09:34 +01:00
#OLD : find $PATH_TO_WATCH -type d -printf '%p\n' | sed 's/"/\\"/g' | sed 's/^\(.*\)$/"\1"/' | while read i; do echo $(echo $i | xargs ls -a | wc -l) $i; done | sort -n > $TMP
2018-06-22 10:28:49 +02:00
#OLD : export IFS="
2018-06-22 10:29:32 +02:00
#"; for i in $(find $PATH_TO_WATCH -type d); do echo $(ls -a | wc -l) $i; done | sort -n > $TMP
2018-06-22 10:28:49 +02:00
for i in $(du -x $PATH_TO_WATCH | awk '{print $2}'); do echo $(ls -1 -a $i| wc -l) $i; done | sort -n > $TMP
2018-03-21 11:09:34 +01:00
2017-03-28 10:42:28 +02:00
#compter dans les sous niveaux
cat $TMP | (while read line; do num=$(echo $line | awk '{ print $1 }'); path=$(echo $line | awk '{ print $2 }'); echo ${path%/*}; done) | sort | uniq | (while read line; do echo $(grep "$line" $TMP | cut -f1 -d' ' | xargs echo -n | tr -s ' ' '+' | xargs echo | bc -l) $line; done) | sort -n | tee $RESULT_FILE
rm $TMP
~~~
2018-05-09 15:50:23 +02:00
### 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 :
~~~{}
# lsof /var/ | grep deleted
~~~
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.
2017-04-07 12:01:14 +02:00
# Utilisateurs UNIX
2017-04-05 14:42:17 +02:00
2018-02-01 11:46:19 +01:00
## 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) :
~~~{.bash}
# mkhomedir_helper user
~~~
2018-02-01 11:46:51 +01:00
Va appliquer les bon droits sur fichiers/répertoires + copier ce qu'il y a dans /etc/skel.
2018-02-01 11:46:19 +01:00
2017-04-07 12:01:14 +02:00
## Lister les utilisateurs + groupe
2017-04-05 14:42:17 +02:00
2017-04-07 12:01:14 +02:00
### UNIX
2017-04-05 14:48:22 +02:00
2017-04-05 14:42:17 +02:00
~~~{.bash}
$ for user in $(getent passwd | awk -F ':' '$3 > 10000 {printf $1 " "}'); do groups $user; done
~~~
2017-04-07 12:01:14 +02:00
### LDAP
2017-04-05 14:48:22 +02:00
2017-04-05 15:58:31 +02:00
~~~{.bash}
2017-04-05 15:58:47 +02:00
$ for user in $(getent passwd | awk -F ':' '$3 > 10000 {printf $1 " "}'); do \
2017-04-07 11:22:33 +02:00
ldapsearch -x -h localhost -LLL -b "dc=MACHINE,dc=DOMAIN,dc=COM" cn | tail -n2 | \
2017-04-05 15:58:31 +02:00
tr '\n' ' ' | cut -d':' -f2 | echo -n "$(cat <&0)"; echo = $(groups $user); done
~~~
2017-04-05 14:48:22 +02:00
## Lister les expirations des mot de passe utilisateurs par date
### 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.
~~~{.bash}
#!/bin/bash
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"
~~~
2017-04-07 12:01:14 +02:00
# Serveur web
2017-03-28 10:42:28 +02:00
2017-04-07 12:01:14 +02:00
## Avoir un rendu des requêtes par IP à partir d'un access.log
2017-03-21 11:45:57 +01:00
2017-05-02 10:51:45 +02:00
Selon le format, il faudra peut-être changer la valeur du field de cut (-f1 par -f2).
2017-04-07 12:04:21 +02:00
### Compte rendu pour un laps de temps
2017-03-21 12:07:28 +01:00
2017-04-13 11:30:57 +02:00
~~~{.bash}
$ date; (timeout 60 tail -f access.log | cut -d' ' -f1) | sort | uniq -c | sort -n
2017-03-21 12:07:28 +01:00
~~~
2017-04-07 12:04:21 +02:00
### En direct
2017-03-21 12:07:28 +01:00
2017-03-21 16:44:00 +01:00
- Version simple :
2017-04-13 11:30:57 +02:00
~~~{.bash}
$ tail -f access.log | stdbuf -oL cut -d ' ' -f1 | uniq -c
2017-03-21 16:44:00 +01:00
~~~
- Version couleur :
2017-04-13 11:30:57 +02:00
~~~{.bash}
$ SEUIL=5; tail -f access.log | stdbuf -oL cut -d ' ' -f1 | stdbuf -oL uniq -c | \
2017-03-21 16:44:00 +01:00
eval "awk '\$1 > $SEUIL {printf \"\\033[1;31m\" \$1 \" \" \$2 \"\\033[0m \\n\"; next;};{printf \$1 \" \" \$2 \"\\n\";}'"
2017-03-21 17:24:13 +01:00
~~~
2017-04-11 10:57:19 +02:00
## 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); \
2017-08-10 14:40:49 +02:00
((diff<SEUIL)) && ((i=i+1)) || { echo "$i $line"; i=1; }; lastline="$line"; done)
2017-04-11 10:57:19 +02:00
~~~
Si on veut les adresses IPs, ou simplement trier le access.log avant l'analyse, il faut modifier après le : cat acccess.log |
2017-04-13 11:27:18 +02:00
Et si l'on considère les mots comme une seule différence (et non par caractères), on peut descendre le seuil :
~~~{.bash}
2017-04-13 11:30:57 +02:00
SEUIL=3; i=1; lastline=; cat access.log | sed 's/.*\] \(.*\)\" [0-9]\{3\}.*$/\1\"/' | \
2017-04-13 11:27:18 +02:00
(while read line; do diff=$(cmp -bl <(echo "$lastline") <(echo "$line") 2>/dev/null | awk '{print $1}' | \
2017-04-13 11:35:09 +02:00
(compt=0; lastnumber=0; while read number; do ((lastnumber+1!=number)) && ((compt=compt+1)); lastnumber=$number; done; echo $compt)); \
2017-08-10 14:40:49 +02:00
((diff<SEUIL)) && ((i=i+1)) || { echo "$i $line"; i=1; }; lastline="$line"; done)
2017-04-13 11:27:18 +02:00
~~~
C'est à dire que entre 2 requêtes du type :
- /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».
2017-10-12 15:12:13 +02:00
## Analyser un apache-status
Compter le nombre de requêtes par IPs :
~~~{.bash}
cat FICHIER | 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
~~~
Le faire pour un créneau horaire :
~~~{.bash}
$ cd /var/www/apache-status
$ 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
~~~
2017-05-05 10:47:29 +02:00
# Processus / Process
2017-03-28 10:42:28 +02:00
2017-07-18 13:51:04 +02:00
## Surveiller les nouveaux processus créés
2017-04-06 12:35:32 +02:00
2017-04-07 12:04:21 +02:00
### Liste simple
2017-04-06 12:35:32 +02:00
~~~{.bash}
$ ps -e -o etimes=,pid,cmd | sort -rn | awk '{if ($1!=0 && $3!~/\[.*\]/) print $0 }'
~~~
2017-09-26 09:59:50 +02:00
### 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 }'
~~~
2017-04-07 12:04:21 +02:00
### Watch
2017-04-06 12:47:43 +02:00
2017-04-06 12:53:57 +02:00
Toutes les 5 secondes :
2017-04-06 12:47:43 +02:00
~~~{.bash}
2017-04-18 12:23:42 +02:00
$ watch -n 5 -d "ps -e -o etimes=,pid,user,cmd | sort -n | awk '{if (\$1==0 || \$2==$$ || \$3~/watch/ || \$3~/\[.*\]/) {} else print \$0 }'"
2017-04-18 16:43:26 +02:00
~~~
Se baser seulement par rapport aux utilisateurs ayant créés dernièrement ces processus (SEUIL <=> processus vieux de moins de $SEUIL secondes) :
~~~{.bash}
$ SEUIL=100; watch -n 5 -d "ps -e -o etimes=,user | sort -n | awk '{if (\$1<$SEUIL) print \$2 }' | sort | uniq -c | sort -n"
2017-05-02 18:02:26 +02:00
~~~
2018-04-19 14:43:12 +02:00
### Cron
Recevoir le output de la commande *top* en cron :
~~~{.bash}
top -b -d 1
~~~
2017-05-05 10:47:29 +02:00
## Lister avec le plus de fils (/fork)
2017-05-02 18:02:26 +02:00
~~~{.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
2017-05-04 16:41:59 +02:00
~~~
2017-05-05 10:47:29 +02:00
## Consommation Swap
2017-05-05 10:46:22 +02:00
~~~{.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
~~~
2017-06-19 11:27:09 +02:00
## Consommation RAM (VmSize)
2017-08-31 11:11:28 +02:00
~~~{.bash}
$ top -o RES
~~~
2018-05-23 11:16:02 +02:00
### Par process
~~~{.bash}
$ ps o user:20,pid,pcpu,pmem,vsz,rss,tty,stat,start,time,comm -p 3108
~~~
2017-06-19 11:27:09 +02:00
### Par utilisateur
~~~{.bash}
2017-07-26 13:06:34 +02:00
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
2017-08-31 11:10:06 +02:00
for var in $(getent passwd | cut -d':' -f1); 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
2017-06-19 11:27:09 +02:00
~~~
2017-07-18 13:51:04 +02:00
## Fichiers ouverts
2017-05-04 16:41:59 +02:00
2017-05-05 10:46:22 +02:00
### socket/port
- Connaître les sockets ouvertes et ports en écoutent par un processus :
~~~{.bash}
$ lsof -Pan -p PID -i
~~~
- Connaître le pid qui écoute sur un port (2ème colonne) :
~~~{.bash}
$ lsof -i :Port
~~~
2017-05-04 16:42:24 +02:00
### Selon l'utilisateur
2017-05-04 16:41:59 +02:00
~~~
# lsof -u UID
~~~
Si www-data a uid=33, lister fichiers ouvert par serveur-web :
~~~
# lsof -u 33 | awk '{ print $2 " = " $9 }' | grep "/home/.*$"
2017-05-26 10:41:16 +02:00
~~~
## Créer un fichier "dummy" de différentes tailles
Pour tester les performances d'un FTP ou autre on a besoin d'envoyer un fichier volumineux ou pas, voici comment créer un fichier vide (dummy) d'une certaine taille avec dd :
Pour un fichier de 10Mio :
~~~
dd if=/dev/zero of=10M.bin bs=1024 count=0 seek=$[1024*10]
2017-05-26 10:41:16 +02:00
~~~
Pour 100Mio :
~~~
dd if=/dev/zero of=100M.bin bs=1024 count=0 seek=$[1024*100]
2017-05-26 10:41:16 +02:00
~~~
Pour 1Gio :
~~~
dd if=/dev/zero of=1G.bin bs=1024 count=0 seek=$[1024*1024]
2017-07-18 13:51:04 +02:00
~~~
## stdout / stderr
Renvoyer stdout/stderr dans une même sortie (par exemple /dev/null) :
~~~
eject /dev/coin > /dev/null 2>&1
2017-08-20 04:33:33 +02:00
~~~
Détecter les tabulations
~~~
$ grep -P '\t'
2017-09-25 09:53:44 +02:00
~~~
# Serveur mail
## 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
2017-11-03 13:59:11 +01:00
~~~
2018-09-19 19:56:48 +02:00
# Parsing
## 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.
~~~
# apt install jq
$ curl --silent ipinfo.io | jq
~~~
On peut s'en servir pour extraire certaine partie du JSON :
* .[] : Addresser une entrée d'un tableau. Exemple ".[0]" pour la première entrée
* .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
~~~
# docker inspect docker_gwbridge | jq ".[0].Containers.f37ac628a4630da4aabbd23ba8eebf9c72dce5f3ba03675515a8b3619f8425d2.IPv4Address"
~~~
Tips : Pour faire des tests ou s'entrainer : https://jqplay.org/