Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente | ||
linux:bash [23-12-2016 20:49] edmc73 [trap, wait, sleep] |
linux:bash [07-05-2023 20:38] (Version actuelle) edmc73 [Date de fichier] |
||
---|---|---|---|
Ligne 42: | Ligne 42: | ||
* '' | * '' | ||
* '' | * '' | ||
- | + | ||
+ | |||
+ | ===== Variable ===== | ||
+ | |||
+ | toto=lol | ||
+ | echo $toto | ||
+ | echo ${toto} | ||
+ | cpt=1 | ||
+ | echo $((cpt++)) | ||
+ | echo $((cpt+15)) | ||
+ | |||
+ | Tableau associatif ( http:// | ||
+ | < | ||
+ | $ declare -A MYMAP # Create an associative array | ||
+ | $ MYMAP[foo]=bar | ||
+ | $ echo ${MYMAP[foo]} | ||
+ | bar | ||
+ | $ echo MYMAP[foo] | ||
+ | MYMAP[foo] | ||
+ | $ echo $MYMAP[foo] | ||
+ | [foo] | ||
+ | |||
+ | $ K=baz | ||
+ | $ MYMAP[$K]=quux | ||
+ | $ echo ${MYMAP[$K]} | ||
+ | quux | ||
+ | $ echo ${MYMAP[baz]} | ||
+ | quux | ||
+ | |||
+ | $ declare -A MYMAP=( [foo a]=bar [baz b]=quux ) | ||
+ | $ echo " | ||
+ | foo a baz b | ||
+ | |||
+ | $ # Looping through keys and values in an associative array | ||
+ | $ for K in " | ||
+ | foo a --- bar | ||
+ | baz b --- quux | ||
+ | |||
+ | $ # Loop through all values in an associative array | ||
+ | $ for V in " | ||
+ | bar | ||
+ | quux | ||
+ | |||
+ | $ echo ${# | ||
+ | 2 | ||
+ | </ | ||
+ | |||
+ | Faire une liste simple | ||
+ | < | ||
+ | list=( | ||
+ | aaa | ||
+ | bbb | ||
+ | ccc | ||
+ | ddd | ||
+ | ) | ||
+ | |||
+ | $ echo $list | ||
+ | aaa | ||
+ | |||
+ | $ echo ${list[@]} | ||
+ | aaa bbb ccc ddd | ||
+ | |||
+ | $ echo ${list[1]} | ||
+ | bbb | ||
+ | |||
+ | $ for i in ${list[@]}; do echo $i; done | ||
+ | aaa | ||
+ | bbb | ||
+ | ccc | ||
+ | ddd | ||
+ | |||
+ | </ | ||
===== Manipuler du texte ===== | ===== Manipuler du texte ===== | ||
Ligne 272: | Ligne 343: | ||
</ | </ | ||
+ | Tester le contenu d'une chaine avec du regex | ||
+ | Tester une date yyyymmdd de facon très simple | ||
+ | |||
+ | <code bash> | ||
+ | [[ $date =~ ^[0-9]{8}$ ]] && echo " | ||
+ | </ | ||
+ | |||
+ | ou plus complet | ||
+ | |||
+ | <code bash> | ||
+ | [[ $date =~ ^[0-9]{4}(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])$ ]] && echo " | ||
+ | # | ||
+ | # | ||
+ | # | ||
+ | # | ||
+ | # | --year-- | ||
+ | # | ||
+ | # start of line or 10, | ||
+ | # or 30, 31 | ||
+ | </ | ||
+ | |||
+ | That is, you can define a regex in Bash matching the format you want. This way you can do: | ||
+ | |||
+ | <code bash> | ||
+ | [[ $date =~ ^regex$ ]] && echo " | ||
+ | </ | ||
+ | where commands after && are executed if the test is successful, and commands after || are executed if the test is unsuccessful. | ||
+ | |||
+ | Note this is based on the solution by Aleks-Daniel Jakimenko in User input date format verification in bash. | ||
+ | |||
+ | In other shells you can use grep. If your shell is POSIX compliant, do | ||
+ | |||
+ | <code bash> | ||
+ | (echo " | ||
+ | </ | ||
+ | In fish, which is not POSIX-compliant, | ||
+ | |||
+ | <code bash> | ||
+ | echo " | ||
+ | </ | ||
===== Boucle ===== | ===== Boucle ===== | ||
Ligne 306: | Ligne 417: | ||
for i in {1..5}; do COMMAND-HERE; | for i in {1..5}; do COMMAND-HERE; | ||
+ | for X in /dev/sd*; do echo $X; smartctl -a $X | grep overall; done | ||
+ | < | ||
+ | ~# for X in {a..z}; do smartctl -a /dev/sd$X | grep overall; done | ||
+ | SMART overall-health self-assessment test result: PASSED | ||
+ | SMART overall-health self-assessment test result: PASSED | ||
+ | SMART overall-health self-assessment test result: PASSED | ||
+ | SMART overall-health self-assessment test result: PASSED | ||
+ | ... | ||
+ | </ | ||
===== Suppression d'un grand nombre de fichiers ===== | ===== Suppression d'un grand nombre de fichiers ===== | ||
Ligne 330: | Ligne 450: | ||
Pour savoir combien de fichiers vont être effacés | Pour savoir combien de fichiers vont être effacés | ||
find . -name " | find . -name " | ||
+ | | ||
+ | |||
+ | Garder les 5 fichiers les plus récents et supprimer le reste | ||
+ | ls -c *.txt | tail -n +5 | xargs rm | ||
+ | |||
===== Taille de plusieurs répertoires ===== | ===== Taille de plusieurs répertoires ===== | ||
Permet d' | Permet d' | ||
Ligne 338: | Ligne 463: | ||
Affiche la taille des répertoires en ignorant les autres disques (sans compter les /mnt, /media..) et trie du plus petit au plus grand. | Affiche la taille des répertoires en ignorant les autres disques (sans compter les /mnt, /media..) et trie du plus petit au plus grand. | ||
- | du -x -h --max-depth=1 | sort -h | + | du -xhcs --max-depth=1 | sort -h |
Compter le nombre de fichier récursivement sans compter les répertoires | Compter le nombre de fichier récursivement sans compter les répertoires | ||
Ligne 345: | Ligne 470: | ||
Compter le nombre de répertoire | Compter le nombre de répertoire | ||
ls -dR repertoire/ | ls -dR repertoire/ | ||
+ | | ||
+ | |||
+ | Un petit programme nommé **ncdu** dispo dans les dépots permet d' | ||
===== Faire un prompt ===== | ===== Faire un prompt ===== | ||
Ligne 354: | Ligne 482: | ||
select CHOIX in " | select CHOIX in " | ||
case $REPLY in | case $REPLY in | ||
- | | + | |
echo ok | echo ok | ||
break | break | ||
;; | ;; | ||
- | | + | |
echo ko | echo ko | ||
break | break | ||
;; | ;; | ||
+ | *) echo " | ||
esac | esac | ||
done | done | ||
</ | </ | ||
+ | Demander de saisir un texte | ||
+ | <code bash> | ||
+ | echo Hello, who am I talking to? | ||
+ | read varname | ||
+ | echo It\'s nice to meet you $varname | ||
+ | </ | ||
===== echo ===== | ===== echo ===== | ||
Ligne 534: | Ligne 669: | ||
PID2=$! | PID2=$! | ||
- | # plusieurs commandes | + | # plusieurs commandes |
( | ( | ||
echo blabla | echo blabla | ||
Ligne 709: | Ligne 844: | ||
Modify: 2015-01-01 00: | Modify: 2015-01-01 00: | ||
Change: 2016-07-04 08: | Change: 2016-07-04 08: | ||
+ | |||
+ | On peut aussi utiliser la notation suivante | ||
+ | # touch -d "-1 day" toto.txt | ||
</ | </ | ||
Ligne 715: | Ligne 853: | ||
A creuser pour les accès restreint en ssh https:// | A creuser pour les accès restreint en ssh https:// | ||
+ | ===== vérifier si le script tourne encore ===== | ||
+ | |||
+ | Pour voir si le script **abc.sh** tourne encore, on peut utiliser le code suivant | ||
+ | |||
+ | <code bash> | ||
+ | if pidof -x " | ||
+ | echo " | ||
+ | fi | ||
+ | </ | ||
+ | |||
+ | Alternatively, | ||
+ | |||
+ | <code bash> | ||
+ | #!/bin/bash | ||
+ | # abc.sh | ||
+ | |||
+ | mypidfile=/ | ||
+ | |||
+ | # Could add check for existence of mypidfile here if interlock is | ||
+ | # needed in the shell script itself. | ||
+ | |||
+ | # Ensure PID file is removed on program exit. | ||
+ | trap "rm -f -- ' | ||
+ | |||
+ | # Create a file with current PID to indicate that process is running. | ||
+ | echo $$ > " | ||
+ | </ | ||
+ | |||
+ | ... | ||
+ | Update: The question has now changed to check from the script itself. In this case, we would expect to always see at least one abc.sh running. If there is more than one abc.sh, then we know that process is still running. I'd still suggest use of the pidof command which would return 2 PIDs if the process was already running. You could use grep to filter out the current PID, loop in the shell or even revert to just counting PIDs with wc to detect multiple processes. | ||
+ | |||
+ | Here's an example: | ||
+ | <code bash> | ||
+ | #!/bin/bash | ||
+ | |||
+ | for pid in $(pidof -x abc.sh); do | ||
+ | if [ $pid != $$ ]; then | ||
+ | echo " | ||
+ | exit 1 | ||
+ | fi | ||
+ | done | ||
+ | </ | ||
+ | |||
+ | Optimisation, | ||
+ | <code bash> | ||
+ | for pid in $(pidof -x $0); do | ||
+ | if [ $pid != $$ ]; then | ||
+ | echo " | ||
+ | exit 1 | ||
+ | fi | ||
+ | done | ||
+ | </ | ||
+ | |||
+ | Très utile quand on lance un script toutes les minutes pour éviter de se retrouver avec 500 process qui tournent en même dans le cas ou la réponse du script dépasserait la minute | ||
+ | |||
+ | ===== ls et le globbing (ou filtrage avancé) ===== | ||
+ | |||
+ | <code bash> | ||
+ | bash$ ls -l | ||
+ | total 2 | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | bash$ ls -l t?.sh | ||
+ | | ||
+ | |||
+ | bash$ ls -l [ab]* | ||
+ | | ||
+ | | ||
+ | |||
+ | bash$ ls -l [a-c]* | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | bash$ ls -l [^ab]* | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | bash$ ls -l {b*, | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | | ||
+ | |||
+ | |||
+ | ===== Problème d' | ||
+ | |||
+ | Avec certain prompt fantaisiste, | ||
+ | |||
+ | D'où l' | ||
+ | |||
+ | Si vous appelez une fonction dans la variable PS1, il faudra entourer le code couleur par \001 | ||
+ | |||
+ | (voir le code dans le chapitre suivant) | ||
+ | |||
+ | source: http:// | ||
+ | |||
+ | Mots clés pour recherche sur le web: Line wrapping issues in Bash | ||
+ | |||
+ | ===== Afficher le status de la dernière commande dans le prompt ===== | ||
+ | |||
+ | Ajoutez dans votre .bashrc ce petit bout de code | ||
+ | |||
+ | <code bash> | ||
+ | get_exit_status(){ | ||
+ | es=$? | ||
+ | if [ $es -eq 0 ] | ||
+ | then | ||
+ | echo -e ' | ||
+ | else | ||
+ | echo -e ' | ||
+ | fi | ||
+ | } | ||
+ | |||
+ | PS1=' | ||
+ | </ |