четверг, 9 июня 2016 г.

Изменение shell-скриптов во воремя выполнения

Возьмите простенький шелл-скриптик типа вот такого под названием 1.sh
echo 'echo 1' > 1.sh
echo 2
и запустите. Первой командой этот скриптик перезатирает своё содержимое и... выполняет вторую команду, хотя в нём её уже нет. Всё логично пока, да? Смотрим дальше. 2.sh:
echo 'echo 2' > 2.sh
for i in `seq 1 50`
do
    echo 'echo '$i >> 2.sh
done
Результат работы поразительный, числа от 20 до 50. То есть как это, кажись бы, происходит: скрипт удалил своё содержимое первой командой, но продолжил выполнять вторую команду, цикл. После чего он обнаружил, что после 75-го байта (размер первоначального скрипта) появилось ещё что-то, и выполнил всё остальное. Магия? Ничуть. Мы вчера на работе с администратором экспериментировали с изменением bash-скриптов во время их выполнения. Скрипты перезаписывали сами себя, меняли своё содержимое, и, в общем, одни и те же скрипты, написанные на одном и том же баше (мы в начале специально указывали #!/bin/bash, я в примерах просто не писал) вели себя по-разному на разных серверах. В общих чертах, мы разобрались, как это работает.

Результаты неутешительные. Если интерпретатор успевает считать содержимое файла (следующую команду или несколько команд) с того места, где он сейчас остановился, ДО того, как произойдёт запись на жёсткий диск, вызванная предыдущей командой того же скрипта, он будет выполнять старый код. Если он протупит (sleep 0.1 например) и считает данные ПОСЛЕ того, как произойдёт запись, то выполнит новый. Либо он заранее считывает как минимум одну следующую команду или один следующий блок команд перед выполнением текущего, это неизвестно (по результатам экспериментов на Ubuntu и Gentoo это не подтверждается, скорее, всё-таки зависит от скорость чтения и записи на диск). В любом случае, изменение шелл-скриптов во время их выполнения - это очень опасно, потому что имеет непредсказуемые последствия. Магия.

Комментариев нет:

Отправить комментарий

Ублюдочный Гугл поломал форму комментариев. Извините.