В бородатые 2000е была такая консольная игруля «Русская рулетка», состояла она из одной строчки:
[ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo "You live"
Для начала давай сделаем её более безопасной:
[ $[ $RANDOM % 6 ] == 0 ] && echo 'You died' || echo 'You live'
Суть такая: Если деление по модулю псевдослучайного числа переменной RANDOM вернёт - 0, значит тебе песда и пистолет выстрелил. Соответственно если > 0, то ты пока еще жив и тебе повезло.
А теперь давай посмотрим на условия, при которых «пистолет выстрелит» сразу.
Число отличное от 0, указанное в качестве переменной RANDOM используется как seed (семя) для генератора псевдослучайных чисел.
Если посеять число 2, то при первом обращении к переменной RANDOM получим значение, которое делится на 6 без остатка.
RANDOM=2
[ $[ $RANDOM % 6 ] == 0 ] && echo 'You died' || echo 'You live'
Этот посев даст нужное в разных версиях интерпретатора. Все дело в том, что в версии bash 5.1 были внесены изменения связанные с этим. Короче если у тебя версия баша > 5.0, то можно изменить поведение генератора с помощью переменной BASH_COMPAT.
Переменная BASH_COMPAT в оболочке Bash используется для указания совместимости с предыдущими версиями Bash. Если установить ее на определенное значение, это может изменить поведение Bash так, чтобы оно соответствовало определенной версии.
Например, если вы установите BASH_COMPAT=3.2, то это означает, что текущая оболочка Bash будет работать совместимо с версией 3.2. Это может быть полезно, если у вас есть скрипты, которые были написаны для старых версий Bash и вы хотите, чтобы они продолжали работать в новых версиях без изменений поведения.
Так, давай теперь это проверим:
( BASH_COMPAT=51 ; RANDOM=0 ; echo $RANDOM )
Получаем значение: 20814
( BASH_COMPAT=50 ; RANDOM=0 ; echo $RANDOM )
А тут уже другое: 20034
Если мы задаем 0 в переменную RANDOM, тогда семя (seed) инициализируется жестко заданным значением. При котором генерируется требуемое число, то есть делится на 6 без остатка.
RANDOM=0
[ $[ $RANDOM % 6 ] == 0 ] && echo 'You died' || echo 'You live'
Тут пистолет гарантированно выстрелит. Аналогично предыдущему примеру, если начало строки не число:
RANDOM='bashdays'
[ $[ $RANDOM % 6 ] == 0 ] && echo 'You died' || echo 'You live'
Снова получим 100% выстрел.
✔️ Как работает генератор:
- Начальное значение seed, оболочка получает совершая манипуляции над значениями pid, ppid, uid + текущие время (секунды, микросекунды).
- Далее полученное значение пропускается через алгоритм, а результат сохраняется. При следующих обращениях также пропускается через алгоритм.
- Потом полученное число усекается. В документации указано максимальное возможное значение 32367.
Как я писал выше, руки у нас развязаны и мы можем влиять на начальное значение генератора через переменную RANDOM.
Такие дела, исследуйте!
tags: #bash #linux
@ВАSНDАYS | BАSHDАYS.CОM