Un site qu’il est bien pratique http://www.shellunix.com/commandes.html
Un autre bien détaillé sur le bash http://aral.iut-rodez.fr/fr/sanchis/enseignement/bash/index.html
La bible en anglais du GNU Bash ⇒ http://wiki.bash-hackers.org/start
Le guide du débutant, ici l’introduction au if ⇒ http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html
Se replacer dans le répertoire du script automatiquement
#!/bin/bash cd `dirname $0`
$1
est le 1er argument passé au script, $2
le 2ème etc.. A partir de 10, on note ${10}
$0
Contient le nom du script tel qu’il a été invoqué$*
L’ensembles des paramètres sous la forme d’un seul argument$@
L’ensemble des arguments, un argument par paramètre$#
Le nombre de paramètres passés au script$?
Le code retour de la dernière commande$$
Le PID su shell qui exécute le script$!
Le PID du dernier processus lancé en arrière-plan$RANDOM
Une valeur numeric au hasard$SECONDS
Valeur numéric s’incrémentant toutes les secondes, utile pour chronométrer un script
Re-run all or part of a previous command.
Event Designators. An event designator is a reference to a command line entry in the history list. Unless the reference is absolute, events are relative to the current position in the history list.
!!
Run the last command again!n
Refer to command line n.!-n
Refer to the current command minus n.!foo
Run the most recent command that starts with ‘foo’ (e.g. !ls)!foo:p
Print out the command that !foo would run also add it to the command history!$
Run the last word of the previous command (same as Alt + .)!$:p
Print out the word that !$ would substitute!*
Run the previous command except for the last word!*:p
Print out the previous command except for the last word^foo^bar
Run the previous command replacing foo with bar!#
The entire command line typed so far.toto=lol echo $toto echo ${toto} cpt=1 echo $((cpt++)) echo $((cpt+15))
Tableau associatif ( http://www.artificialworlds.net/blog/2012/10/17/bash-associative-array-examples/ )
$ declare -A MYMAP # Create an associative array $ MYMAP[foo]=bar # Put a value into an associative array $ echo ${MYMAP[foo]} # Get a value out of an associative array bar $ echo MYMAP[foo] # WRONG MYMAP[foo] $ echo $MYMAP[foo] # WRONG [foo] $ K=baz $ MYMAP[$K]=quux # Use a variable as key to put a value into an associative array $ echo ${MYMAP[$K]} # Use a variable as key to extract a value from an associative array quux $ echo ${MYMAP[baz]} # Obviously the value is accessible via the literal key quux $ declare -A MYMAP=( [foo a]=bar [baz b]=quux ) $ echo "${!MYMAP[@]}" # Print all keys - quoted, but quotes removed by echo foo a baz b $ # Looping through keys and values in an associative array $ for K in "${!MYMAP[@]}"; do echo $K --- ${MYMAP[$K]}; done foo a --- bar baz b --- quux $ # Loop through all values in an associative array $ for V in "${MYMAP[@]}"; do echo $V; done bar quux $ echo ${#MYMAP[@]} # Number of keys in an associative array 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
stringZ=abcABC123ABCabc echo ${#stringZ} # 15 echo `expr length $stringZ` # 15 echo `expr "$stringZ" : '.*'` # 15
stringZ=abcABC123ABCabc # 123456 ... echo `expr index "$stringZ" C12` # 6 # C position. echo `expr index "$stringZ" 1c` # 3 # 'c' (in #3 position) matches before '1'.
stringZ=abcABC123ABCabc # 0123456789..... # 0-based indexing. echo ${stringZ:0} # abcABC123ABCabc echo ${stringZ:1} # bcABC123ABCabc echo ${stringZ:7} # 23ABCabc echo ${stringZ:7:3} # 23A # Three characters of substring. # Is it possible to index from the right end of the string? echo ${stringZ:-4} # abcABC123ABCabc # Defaults to full string, as in ${parameter:-default}. # However . . . echo ${stringZ:(-4)} # Cabc echo ${stringZ: -4} # Cabc # Now, it works. # Parentheses or added space "escape" the position parameter. # Thank you, Dan Jacobson, for pointing this out.
stringZ=abcABC123ABCabc echo ${stringZ/abc/xyz} # xyzABC123ABCabc # Replaces first match of 'abc' with 'xyz'. echo ${stringZ//abc/xyz} # xyzABC123ABCxyz # Replaces all matches of 'abc' with # 'xyz'. echo --------------- echo "$stringZ" # abcABC123ABCabc echo --------------- # The string itself is not altered! # Can the match and replacement strings be parameterized? match=abc repl=000 echo ${stringZ/$match/$repl} # 000ABC123ABCabc # ^ ^ ^^^ echo ${stringZ//$match/$repl} # 000ABC123ABC000 # Yes! ^ ^ ^^^ ^^^ echo # What happens if no $replacement string is supplied? echo ${stringZ/abc} # ABC123ABCabc echo ${stringZ//abc} # ABC123ABC # A simple deletion takes place. echo ${stringZ/#abc/XYZ} # XYZABC123ABCabc # Replaces front-end match of 'abc' with 'XYZ'. echo ${stringZ/%abc/XYZ} # abcABC123ABCXYZ # Replaces back-end match of 'abc' with 'XYZ'.
#!/bin/bash # Usage: $0 < FILENAME while read line # Boucle sur chaque ligne du fichier do echo "$line" # Affiche la ligne en cours len=${#line} # taille de la ligne done
ou
#!/bin/bash while read line # Boucle sur chaque ligne du fichier do echo "$line" # Affiche la ligne en cours done < /home/user/mon_fichier
Traiter un fichier csv
#!/bin/bash while IFS=';' read champ1 champ2 champ3 # déclarez autant de champ séparé par un ; do echo "$champ1 $champ2 $champ3" # Affiche les champs done < /home/user/mon_fichier.csv
La 1ère façon la plus simple est d’utiliser &&
et ||
command && echo "tout est ok" || echo "la commande a échoué"
Dans des cas plus complexe, vous pouvez créer une fonction dans un fichier mesfonctions que vous pouvez inclure facilement dans d’autres scripts avec la commande
. /cheminde/mesfonctions
ou
source /chemeinde/mesfonctions
run() { # Vous pouvez lancer ici une pre-command # on exécute la commande passée en paramètre $@ if [ $? -ne 0 ] then #si le code retour est différent de zéro, cela signifie que la commande a échoué echo "Big problème !!!" return 1 else #sinon tout est ok echo "Good !" return 0 fi }
Voila un petit bout de bash pour tester l’existence d’un repertoire ou d’un fichier
#!/bin/bash dir="/home/hio/test" if [ -d "$dir" ]; then echo "$dir existe !" fi
et en rajoutant un else ^^
#!/bin/bash dir="/home/hio/test" if [ -d "$dir" ]; then echo "$dir existe !" else echo "$dir n'existe pas!" fi
et en inversant le test on rajoute juste un « ! » devant le « -d »
#!/bin/bash dir="/home/hio/test" if [ ! -d "$dir" ]; then echo "$dir n'existe pas!" else echo "$dir existe !" fi
Voila, c’est pas tres compliqué ^^ et pour tester l’existence d’un fichier, on remplace juste le « -d » par un « -f »
On peut aussi écrire
if test -f $1 then file $1 else echo " le fichier n'existe pas " fi
La commande test permet pas mal de possibilité ( voir man test )
Le fait de mettre -e à la place de -d ou -f est plus pratique car ca test tout sans distinction.
if [ -e index.html ]; then echo OK; fi
Autre facon encore plus courte de faire la même chose
[[e_index.html]] && echo OK
Pour tester le contenu d’une string
VAR="hello" if [ -n "$VAR" ]; then echo "VAR is not empty" fi
VAR="" if [ -z "$VAR" ]; then echo "VAR is empty" fi
Tester le contenu d’une chaine avec du regex
Tester une date yyyymmdd de facon très simple
[[ $date =~ ^[0-9]{8}$ ]] && echo "yes"
ou plus complet
[[ $date =~ ^[0-9]{4}(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])$ ]] && echo "yes" # |^^^^^^^^ ^^^^^^ ^^^^^^ ^^^^^^ ^^^^^^^^^^ ^^^^^^ | # | | ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^ | # | | | | | # | | \ | | # | --year-- --month-- --day-- | # | either 01...09 either 01..09 end of line # start of line or 10,11,12 or 10..29 # or 30, 31
That is, you can define a regex in Bash matching the format you want. This way you can do:
[[ $date =~ ^regex$ ]] && echo "matched" || echo "did not match"
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
(echo "$date" | grep -Eq ^regex$) && echo "matched" || echo "did not match"
In fish, which is not POSIX-compliant, you can do
echo "$date" | grep -Eq "^regex\$"; and echo "matched"; or echo "did not match"
for VARIABLE in 1 2 3 4 5 .. N do command1 command2 commandN done
Séquence
for i in {1..5} do echo "Welcome $i times" done
Affiche les nombres impaires
for i in {1..11..2} do echo "Welcome $i times" done
plus d’exemple ⇒ http://www.cyberciti.biz/faq/bash-for-loop/
Ecriture sur une ligne de commande
for i in {1..5}; do COMMAND-HERE; done
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 ...
Lorsqu’il y a un grand nombre de fichiers à supprimer, la commande rm ne suffit plus.
Voici 3 facons différentes d’effectuer cette suppression.
On liste les fichiers que l’on veut supprimer avec ls et avec xargs on les envoie en argument un par un à rm
ls * | xargs rm
NOTE : le ls * ne fonctionne pas quand on a trop de fichier…, essayer plutot ceci si vous voulez par exemple effacer tous les fichiers qui contient le mot toto
ls | grep toto | xargs rm -f
Si vous souhaitez effacer tous les fichiers du répertoire courant, ceci fonctionnera
ls | xargs rm -f
A la place de ls on peut aussi utiliser find
find . -type f -name \* | xargs rm
Ou utiliser find sans xargs
find . -name "*" -exec rm {} \;
Pour savoir combien de fichiers vont être effacés
find . -name "*" | wc -l
Garder les 5 fichiers les plus récents et supprimer le reste
ls -c *.txt | tail -n +5 | xargs rm
Permet d’afficher la taille des répertoires du répertoire courant.
du -h --max-depth=1
Affiche la taille des répertoires
du -hcs *
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 -xhcs --max-depth=1 | sort -h
Compter le nombre de fichier récursivement sans compter les répertoires
ls -Rp repertoire | grep -v -e ^$ -e / | wc -l
Compter le nombre de répertoire
ls -dR repertoire/* | wc -l
Un petit programme nommé ncdu dispo dans les dépots permet d’afficher sous forme graphique la taille des répertoires et de naviguer à l’intérieur
Ce script pose une question à l’utilisateur et la repose tant qu’une réponse valide n’a pas été donnée.
PS3='> ' # le prompt LISTE=("[y] yes" "[n] no") # liste de choix disponibles select CHOIX in "${LISTE[@]}" ; do case $REPLY in yes|y) echo ok break ;; no|n) echo ko break ;; *) echo "invalid option $REPLY";; esac done
Demander de saisir un texte
echo Hello, who am I talking to? read varname echo It\'s nice to meet you $varname
Ne pas revenir à la ligne
[user@pc]# echo -n blabla blabla[user@pc]#
Autoriser les sequences avec des backslash
echo -e blabla\\nbla blabla bla
\\ backslash \a alert (BEL) \b backspace \c produce no further output \e escape \f form feed \n new line \r carriage return \t horizontal tab \v vertical tab \0NNN byte with octal value NNN (1 to 3 digits) \xHH byte with hexadecimal value HH (1 to 2 digits)
Dans le cas d’une variable avec retour chariot, echo converti les retours chariots par un espace. Il est possible de faire autrement. Voici un exemple
[root@pc:~]# free total used free shared buffers cached Mem: 236736 185120 51616 0 80084 16968 -/+ buffers/cache: 88068 148668 Swap: 102396 96 102300 [root@pc:~]# toto=`free` [root@pc:~]# echo $toto total used free shared buffers cached Mem: 236736 185240 51496 0 80092 16968 -/+ buffers/cache: 88180 148556 Swap: 102396 96 102300 [root@pc:~]# echo "$toto" total used free shared buffers cached Mem: 236736 185240 51496 0 80092 16968 -/+ buffers/cache: 88180 148556 Swap: 102396 96 102300
!/bin/sh VERT="\\033[1;32m" NORMAL="\\033[0;39m" ROUGE="\\033[1;31m" ROSE="\\033[1;35m" BLEU="\\033[1;34m" BLANC="\\033[0;02m" BLANCLAIR="\\033[1;08m" JAUNE="\\033[1;33m" CYAN="\\033[1;36m" echo "" echo -e "$VERT" " ------------------ ""$ROUGE""Y o u W i l l B e C o l o r e d ""$VERT"" ------------ " "$NORMAL" echo " | Color bash script | " echo -e " | written by""$VERT" "selim,b." "$CYAN""(s.bouras@free.fr) " "$NORMAL" " | " echo -e " | This script is""$BLEU"" free Licence""$NORMAL"" | " echo -e "$VERT" " -------------------------------------------------------------------- " "$NORMAL" echo -e " $BLEU" " Ok!!..Dear ... Your bash is colored .. Have Fun!!.."
En php exécuté en mode console, vous pouvez aussi écrire en couleur avec un
echo "\033[47m \033[1;34m texte en bleu sur fond gris clair \033[0m \n";
Contrairement au bash, il faut mettre un seul backslash et utiliser des guillemets.
Code couleur du texte
black = \033[0;30m dark_gray = \033[1;30m blue = \033[0;34m light_blue = \033[1;34m green = \033[0;32m light_green = \033[1;32m cyan = \033[0;36m light_cyan = \033[1;36m red = \033[0;31m light_red = \033[1;31m purple = \033[0;35m light_purple = \033[1;35m brown = \033[0;33m yellow = \033[1;33m light_gray = \033[0;37m white = \033[1;37m
Code couleur du fond
black = \033[40m red = \033[41m green = \033[42m yellow = \033[43m blue = \033[44m magenta = \033[45m cyan = \033[46m light_gray = \033[47m
Toujours réinitialiser la fin de la phrase par
\033[0m
Il peut être utile d’utiliser sed pour modifier une valeur dans un fichier de configuration en tapant juste une ligne de commande.
Dans mon cas, je voulais modifier une variable dans tous mes fichiers *awstats et donc au lieu d’ouvrir un à un mes fichiers de conf, j’ai juste eu à lancer la commande sed ;)
Exemple pour modifier la variable Categories dans un fichier
sed -i 's/^Categories=.*/Categories=toto/' FILENAME
option -i de sed : écrire dans le fichier commande ‘s/A/B/' : remplacer A par B avec pour A : ^Categories=.* : n’importe quelle ligne commençant (le ^) par Categories= et suivi par un nombre quelconque (*) de n’importe quel caractère (.)
Une variante qui fait la même chose que sed mais en utilisant grep et echo
grep '^Categories=' FILENAME || { echo; echo 'Categories=toto'; } >>FILENAME
grep ‘^Categories=' FILENAME : cherche une ligne commençant par Categories= dans FILENAME si la commande échoue elle retourne un code d’erreur 1 et ce qui est après || est exécuté : { echo; echo ‘Categories=toto’; } »FILENAME : saute une ligne et ajoute (») ‘Categories=toto’ à FILENAME, ce qui aurait pu aussi être écrit :
echo -e "\nCategories=toto" >>FILENAME
l’option -e autorise les caractères spéciaux tels que \n (newline)
edit: et juste pour le fun (et le chipotage) il ne sert à rien de lancer la substitution si le motif Categories= est absent (dans le cas où on fait le grep) donc :
if grep -q '^Categories=' FILENAME; then sed -i 's/^Categories=.*/Categories=toto/' FILENAME else echo -e "\nCategories=toto" >>FILENAME fi
grep -q pour ne pas avoir de sortie, juste le code de retour 0 (trouvé) ou 1 (absent)
trap
sert à exécuter une commande lorsqu’un signal est envoyé au script en cours
wait
sert à attendre la fin d’une commande qui aura été lancé en tache de fond
sleep
sert à faire une pause suivant un nombre de seconde définit
Le petit script suivant est une démonstration de wait, trap et sleep.
Le but est de lancer 3 commandes en parallèle et de vérifier l’état d’avancement en parallèle puis de récupérer le code de retour à la fin.
wget
en tache de fond dont le 3ème est volontairement erronéjobs
qui ne renvoi rien quand il n’y a plus rien qui tourne en tache de fond. Donc, tant que les commandes précédentes lancées en tache de fond ne sont pas fini, on continu d’exécuter tout ce qui se trouve dans la boucle whilewait
et on affiche le résultat.#!/bin/bash wget -q http://proof.ovh.net/files/10Mio.dat -O 10Mio.dat & PID1=$! wget -q http://proof.ovh.net/files/1Mio.dat -O 1Mio.dat & PID2=$! # plusieurs commandes passées en tache de fond ( echo blabla wget -q http://proof.ovh.net/files/1Mio.dat -O 1Mio.dat ) & PID3=$! trap 'kill $PID1 $PID2; exit 0' 1 2 3 15 while [ -n "`jobs`" ] do jobs if [ -d /proc/$PID1 ] then sleep 1 echo Process $PID1 du 10Mio.dat | cut -f1 fi if [ -d /proc/$PID2 ] then sleep 1 echo Process $PID2 du 1Mio.dat | cut -f1 fi done wait $PID1 exit1=$? wait $PID2 exit2=$? wait $PID3 exit3=$? echo "Process $PID1 : Code de retour $exit1" echo "Process $PID2 : Code de retour $exit2" echo "Process $PID3 : Code de retour $exit3"
A quoi sert le trap ?
Lorsque je lance mon script et que je ne veux pas attendre la fin du téléchargement, je quitte en faisant un Ctrl+C. Le problème est que le wget continu de tourner en tache de fond et si je lance 10 fois mon script et que je fais 10 fois Ctrl+C je me retrouve avec 10 wget qui tournent en tache de fond.
trap va me permettre de lancer une commande lorsque je fais un Ctrl+C ou un kill (mais pas un kill -9). Ici j’ai mis la commande kill $!
. Souvenez-vous que $!
correspond au pid de la commande lancé précédemment. Il ne faut pas oublier exit 0
sinon vous ne sortirez jamais du script avec votre Ctrl+C, vous serez obliger d’utiliser kill -9
Dans le cas d’un backup avec rsnapshot ou on a des dossiers de type daily.0, daily.1, daily.2 etc.. je voulais des noms de répertoire plus parlant comme par exemple la date de création du répertoire.
for f in /media/hdd/backup/daily.* ; do ln -s $f `ls -ld --time-style=+%Y-%m-%d $f | awk '{print $6}'`; done
On obtient :
lrwxrwxrwx 1 root root 29 janv. 29 00:15 2014-01-16 -> /media/hdd/backup/daily.12 lrwxrwxrwx 1 root root 29 janv. 29 00:15 2014-01-17 -> /media/hdd/backup/daily.11 lrwxrwxrwx 1 root root 29 janv. 29 00:15 2014-01-18 -> /media/hdd/backup/daily.10 lrwxrwxrwx 1 root root 28 janv. 29 00:15 2014-01-19 -> /media/hdd/backup/daily.9 lrwxrwxrwx 1 root root 28 janv. 29 00:15 2014-01-20 -> /media/hdd/backup/daily.8 lrwxrwxrwx 1 root root 28 janv. 29 00:15 2014-01-21 -> /media/hdd/backup/daily.7 lrwxrwxrwx 1 root root 28 janv. 29 00:15 2014-01-22 -> /media/hdd/backup/daily.6 lrwxrwxrwx 1 root root 28 janv. 29 00:15 2014-01-23 -> /media/hdd/backup/daily.5 lrwxrwxrwx 1 root root 28 janv. 29 00:15 2014-01-24 -> /media/hdd/backup/daily.4 lrwxrwxrwx 1 root root 28 janv. 29 00:15 2014-01-25 -> /media/hdd/backup/daily.3 lrwxrwxrwx 1 root root 28 janv. 29 00:15 2014-01-26 -> /media/hdd/backup/daily.2 lrwxrwxrwx 1 root root 28 janv. 29 00:15 2014-01-27 -> /media/hdd/backup/daily.1 lrwxrwxrwx 1 root root 28 janv. 29 00:15 2014-01-28 -> /media/hdd/backup/daily.0
Il n’y a plus qu’a faire pointer votre partage samba sur ce répertoire de lien symbolique ;)
Pour changer l’extension de tous les fichiers .css en .less
rename 's/\.css$/\.less/' *.css
# split --help Utilisation : split [OPTION]... [INPUT [PREFIX]] Affiche sur la sortie des morceaux de INPUT de taille fixe selon PREFIXaa, PREFIXab, ... ; par défaut la taille est de 1000 lignes et le préfixe par défaut est « x ». Sans INPUT ou quand INPUT est -, la lecture se fait sur l'entrée standard. Les arguments obligatoires pour les options longues le sont aussi pour les options courtes. -a, --suffix-length=N utilise les suffixes de longueur N (par défaut 2) -b, --bytes=BYTES écrit BYTES octets par fichier de sortie -C, --line-bytes=SIZE écrit au plus SIZE octets par ligne par fichier de sortie -d, --numeric-suffixes utilise des suffixes numériques et non alphabétiques -l, --lines=NUMBER écrit NUMBER lignes par fichier de sortie --verbose affiche un diagnostic juste avant chaque ouverture de fichier de sortie --help affiche l'aide et quitte --version affiche des informations de version et quitte SIZE peut être (ou un entier optionnellement suivi par) l'une des valeurs suivantes : kB 1000, K 1024, MB 1000*1000, M 1024*1024 et ainsi de suite pour G, T, P, E, Z et Y.
Pour découper un gros messages.log en plusieurs petits fichier nommé messages.split.00, messages.split.01…
split -d -b 500MB messages.log messages.split.
On a un répertoire plein d’image HD et on voudrait un répertoire miniature avec les images redimensionnées. Et bien sur, on ne veut pas recréer les miniatures qui existe déjà sauf si c’est voulu.
En 1er lieu, installez le paquet imagemagick qui contient tout un tas d’outils de création, conversion d’images ( http://www.imagemagick.org/script/command-line-tools.php )
Si vous voulez tout convertir en une fois
mogrify -resize 200 -quality 75 -interlace Plane -strip -path /home/user/photo/miniature /home/user/photo/*.jpg
Sinon voici le script
#!/bin/bash path_src='/home/user/photo' path_dest='/home/user/photo/miniature' cd $path_src for file in *.jpg; do if [ ! -f $path_dest/$file -o "$1" == "overwrite" ]; then convert -resize 200 -quality 75 -interlace Plane -strip $file $path_dest/$file fi done
Ici on fait une boucle sur les fichiers avec un filtre sur les extensions jpg. Ensuite on teste si le fichier n’existe pas dans la destination OU si l’argument passé au script est “overwrite” alors on exécute la commande “convert”
-resize 200
permet de réduire l’image sur une largeur de 200px en gardant la proportionnalité de l’image-quality 75
joue sur la compression de l’image et donc sa qualité. 0 renvoie une petite taille mais une image pourri, 100 renvoie une belle image mais d’une taille conséquente-interlace Plane
est le mode progressif du format jpeg qui permet sur les sites web d’afficher une 1er image en mode dégradé avant d’avoir fini son chargement complet-strip
permet de supprimer les informations inutiles de l’imagesource : http://monkeypatch.me/blog/move-a-running-process-to-a-new-screen-shell.html
Récupérer un process lancé sur un autre terminal avec la commande reptyr
En bref
La commande touch permet de changer la date de modification d’un fichier
# touch toto.txt # stat toto.txt File: « toto.txt » Size: 0 Blocks: 0 IO Block: 4096 fichier vide Device: fd00h/64768d Inode: 130793 Links: 1 Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2016-07-04 08:47:38.715578195 +0000 Modify: 2016-07-04 08:47:38.715578195 +0000 Change: 2016-07-04 08:47:38.715578195 +0000 # touch -d "2015-01-01 00:00" toto.txt # stat toto.txt File: « toto.txt » Size: 0 Blocks: 0 IO Block: 4096 fichier vide Device: fd00h/64768d Inode: 130793 Links: 1 Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2015-01-01 00:00:00.000000000 +0000 Modify: 2015-01-01 00:00:00.000000000 +0000 Change: 2016-07-04 08:48:40.464863103 +0000 On peut aussi utiliser la notation suivante # touch -d "-1 day" toto.txt
A creuser pour les accès restreint en ssh https://en.wikipedia.org/wiki/Restricted_shell
Pour voir si le script abc.sh tourne encore, on peut utiliser le code suivant
if pidof -x "abc.sh" >/dev/null; then echo "Process already running" fi
Alternatively, have your script create a PID file when it executes. It’s then a simple exercise of checking for the presence of the PID file to determine if the process is already running.
#!/bin/bash # abc.sh mypidfile=/var/run/abc.sh.pid # 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 -- '$mypidfile'" EXIT # Create a file with current PID to indicate that process is running. echo $$ > "$mypidfile"
… 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:
#!/bin/bash for pid in $(pidof -x abc.sh); do if [ $pid != $$ ]; then echo "[$(date)] : abc.sh : Process is already running with PID $pid" exit 1 fi done
Optimisation, comme on sait que le nom du script est le notre, on peut écrire
for pid in $(pidof -x $0); do if [ $pid != $$ ]; then echo "[$(date)] : $0 : Process is already running with PID $pid" 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
bash$ ls -l total 2 -rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 a.1 -rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 b.1 -rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 c.1 -rw-rw-r-- 1 bozo bozo 466 Aug 6 17:48 t2.sh -rw-rw-r-- 1 bozo bozo 758 Jul 30 09:02 test1.txt bash$ ls -l t?.sh -rw-rw-r-- 1 bozo bozo 466 Aug 6 17:48 t2.sh bash$ ls -l [ab]* -rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 a.1 -rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 b.1 bash$ ls -l [a-c]* -rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 a.1 -rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 b.1 -rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 c.1 bash$ ls -l [^ab]* -rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 c.1 -rw-rw-r-- 1 bozo bozo 466 Aug 6 17:48 t2.sh -rw-rw-r-- 1 bozo bozo 758 Jul 30 09:02 test1.txt bash$ ls -l {b*,c*,*est*} -rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 b.1 -rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 c.1 -rw-rw-r-- 1 bozo bozo 758 Jul 30 09:02 test1.txt
Avec certain prompt fantaisiste, il peut y avoir des problème d’affichage notamment quand on remonte dans l’historique des commandes, ça peut vite devenir illisible.
D’où l’importance d’entourer vos codes couleurs dans la variable PS1 par \[ et \]
Si vous appelez une fonction dans la variable PS1, il faudra entourer le code couleur par \001 et \002
(voir le code dans le chapitre suivant)
source: http://mywiki.wooledge.org/BashFAQ/053
Mots clés pour recherche sur le web: Line wrapping issues in Bash
Ajoutez dans votre .bashrc ce petit bout de code
get_exit_status(){ es=$? if [ $es -eq 0 ] then echo -e '\001\033[0;32m\002✔\001\033[0;0m\002' else echo -e '\001\033[0;31m\002✘ '$es'\001\033[0;0m\002' fi } PS1='$(get_exit_status) \[\033[1;34m\]\u:\[\033[0;36m\]\W\[\033[0;0m\] $ '