Ostrożnie z edycją skryptów bash
Napisał: Patryk Krawaczyński
09/05/2020 w Hacks & Scripts Brak komentarzy. (artykuł nr 735, ilość słów: 459)
P
isząc i uruchamiając skrypty bash lepiej poczekać z ich edycją do czasu aż zakończą swoje działanie. Dlaczego? W naszym ulubionym edytorze stwórzmy prosty skrypt:
#!/bin/bash sleep 30 #echo "All your base are belong to us!" echo "Done!"
Jeśli uruchomimy go teraz w jednym oknie terminala to po 30 sekundach powinniśmy otrzymać tylko i wyłącznie komunikat o treści: Done!. Dobrze, a teraz po uruchomieniu go w pierwszym oknie terminala – z poziomu innego okna edytujmy jego zawartość, gdy ten jeszcze nie przekroczył czasu 30 sekund i usuńmy zero (0) z trzydziestki zostawiając samą trójkę (3), czyli finalnie nasz skrypt powinien mieć postać:
#!/bin/bash sleep 3 #echo "All your base are belong to us!" echo "Done!"
Co wypisał teraz skrypt w pierwszym oknie? Jak to możliwe skoro przy pierwszym komunikacje echo jest znak komentarza, który wyklucza wykonanie tego polecenia? Dzieje się tak, ponieważ bash podczas wykonywania skryptu odczytuje jego zawartość w kawałkach, a śledzi swoje aktualne położenie za pomocą przesunięć bajtów:
root@darkstar:~# strace bash ./delay.sh
# Otwórz skrypt
openat(AT_FDCWD, "delay.sh", O_RDONLY) = 3
# Przeanalizuj pierwszą linię (aż do 80 znaków)
read(3, "#!/bin/bash\nsleep 30\n#echo \"All "..., 80) = 79
# Wróć do początku
lseek(3, 0, SEEK_SET) = 0
# Przesuń to na deskryptor pliku 255
dup2(3, 255) = 255
# Przeczytaj fragment 79 bajtów, aby uzyskać polecenie
read(255, "#!/bin/bash\nsleep 30\n#echo \"All "..., 79) = 79
# Ustaw kursor z powrotem na końcu polecenia, które mamy wykonać
# Przesunięcie na 21 to znak "#"
lseek(255, -58, SEEK_CUR) = 21
# Wykonaj instrukcję sleep
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 13741
# Zanim wait4 się zakończyło nastąpiła edycja "30" na "3"
# i tym samym znak "#" na pozycji 21 zamienił się na "e"cho
# Przeczytaj fragment 79 bajtów, aby uzyskać kolejne polecenie
read(255, "echo \"All your base are belong t"..., 79) = 57
# bash postanowił wykonać oba echa jednocześnie
# tworząć niuans podczas wykonania skryptu
write(1, "All your base are belong to us!\n", 32All your base are belong to us!) = 32
write(1, "Done\n", 5Done) = 5
# Przeczytaj kolejny fragment i odkryj, że jesteśmy na końcu pliku (EOF)
read(255, "", 73) = 0
Więc zachowajmy ostrożność podczas edycji już uruchomionego skryptu bash, ponieważ możemy doprowadzić do wykonania nieprawidłowego polecenia lub zrobić coś bardzo zaskakującego.
Więcej informacji: Take care editing bash scripts

