Supposons que j'ai écrit un script bash avec le nom delay.sh
. Que pensez-vous qu'il fait?#!/bin/bash
sleep 30
echo "Time's up!"
Il semble qu'il attend 30 secondes, puis affiche un message à l'écran. Il n'y a pas de trucs ici - il fait exactement cela. Il y a une commande dangereuse au milieu, mais elle est commentée et n'est pas exécutée.Imaginez que j'exécute à nouveau ce script, mais maintenant je ne veux pas attendre 30 secondes - c'est trop long. J'ouvre la deuxième console, passe sleep 30
à sleep 3
, puis enregistre le fichier. Que pensez-vous qu'il va se passer maintenant?Eh bien, après 30 secondes, le script supprimera tous mes fichiers.En effet, bash lit le contenu du script en fragments au fur et à mesure de sa progression, en suivant l'offset en octets. Lorsque je supprime un caractère de la chaîne sleep
, le décalage pour le début des prochains points de commande pour r
au #rm
lieu #
. Du point de vue de l'interpréteur, il #
est déplacé sur la ligne précédente, il exécute donc la commande à partir de rm
.Cela peut être confirmé en observant les appels système bash sous Linux. Voici le numéro strace bash delay.sh
, avec commentaires et abréviation.
openat(AT_FDCWD, "delay.sh", O_RDONLY) = 3
read(3, "#!/bin/bash\nsleep 30\n#echo \"Don'"..., 80) = 64
lseek(3, 0, SEEK_SET) = 0
dup2(3, 255) = 255
read(255, "#!/bin/bash\nsleep 30\n#echo \"Don'"..., 64) = 64
lseek(255, -43, SEEK_CUR) = 21
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 2072
read(255, "echo \"Don't execute me\"\necho \"Ti"..., 64) = 42
write(1, "Don't execute me\n", 17) = 17
write(1, "Time's up!\n", 11) = 11
read(255, "", 64) = 0
Par conséquent, soyez prudent lorsque vous commencez à modifier le script bash en cours d'exécution. Il peut exécuter la mauvaise commande ou faire quelque chose de très inattendu.