Intereting Posts
Как настроить ipv6 на centos? Как Linux вычисляет общее количество блоков при запуске / bin / ls -l? Почему мой cronjob не выполняет мой shell-скрипт? Почему я не могу восстановить (почти) все свободное место с помощью resize2fs? Как запустить keychain из gdm? `/ proc / $ PID / cwd`: есть ли эквивалент POSIX? Не удается восстановить со спящего tmux во время сеанса SSH Политика SELinux для авторизации некоторых пользователей для запуска / остановки определенных сервисов Сортировка на основе последнего появления символа Я хочу установить Kali Linux бок о бок на моей машине, которая в настоящее время работает на Ubuntu 12.10 Формат запроса zsh в соответствии со значением переменной среды Домен Google переадресовывается на Linux-сервер Digital Ocean с подпапкой Apache2 и отображает домен как root UUID в / etc / mtab CSV – сохранить только определенные записи Почему «ps ax» не находит работающий скрипт bash без заголовка «#!»?

Почему $ RANDOM не включен в вывод ‘env’?

Я знаю, что env – это команда оболочки, ее можно использовать для печати списка текущих переменных среды. И, насколько я понимаю, RANDOM также является переменной среды.

Так почему же, когда я запускаю env в Linux, вывод не включает RANDOM ?

RANDOM не является переменной среды. Это переменная оболочки, поддерживаемая некоторыми shellми. Обычно он не экспортируется по умолчанию. Вот почему он не отображается в выводе env .

Как только он будет использован хотя бы один раз, он будет отображаться в выходных данных set , который сам по себе перечисляет переменные оболочки (и функции) и их значения в текущем сеансе оболочки. Это поведение зависит от оболочки и при использовании pdksh в OpenBSD, RANDOM будет указан в списке set даже если он ранее не использовался.


Остальная часть этого ответа касается того, что могло бы произойти, если бы RANDOM был экспортирован (т.е. превращен в переменную окружения).

Экспорт его с помощью export RANDOM сделает его переменной среды, но его использование будет строго ограничено, поскольку его значение в дочернем процессе будет «случайным, но статическим» (то есть это будет неизменное случайное число). Точное поведение отличается между shellми.

Я использую pdksh в OpenBSD в приведенном ниже примере и получаю новое случайное значение при каждом запуске awk (но одно и то же значение каждый раз в одном и том же экземпляре awk ). Используя bash , я получал бы одно и то же случайное значение во всех вызовах awk .

 $ awk 'BEGIN { print ENVIRON["RANDOM"], ENVIRON["RANDOM"] }' 25444 25444 $ awk 'BEGIN { print ENVIRON["RANDOM"], ENVIRON["RANDOM"] }' 30906 30906 

В bash экспортированное значение RANDOM будет оставаться статическим независимо от использования RANDOM в оболочке (где каждое использование $RANDOM все равно будет давать новое значение).

Это связано с тем, что каждая ссылка на переменную оболочки RANDOM в bash заставляет оболочку обращаться к своей внутренней функции get_random() чтобы присвоить переменной новое случайное значение, но shell не обновляет переменную среды RANDOM . По поведению это похоже на другие динамические переменные bash , такие как LINENO , SECONDS , BASHPID и т. Д.

Чтобы обновить переменную среды RANDOM в bash , вам нужно будет присвоить ей значение переменной оболочки RANDOM и повторно экспортировать его:

 export RANDOM="$RANDOM" 

Мне неясно, будет ли это иметь дополнительный побочный эффект повторного заполнения генератора случайных чисел в bash или нет (но обоснованное предположение будет, что это не так).

Не все переменные, которые установлены в вашем сеансе оболочки, являются переменными среды. «Переменные среды» относятся только к тем переменным, которые были экспортированы в среду с помощью встроенной функции export . Команда env печатает только такие переменные окружения . Например:

 $ foo="bar" $ env | grep foo ## returns nothing $ export foo $ env | grep foo ## now, env will print it foo=bar 

Если вы хотите увидеть все переменные, установленные в вашем сеансе, независимо от того, были ли они экспортированы, вы можете использовать set :

 $ set | grep foo= foo=bar 

Встроенная функция set также возвращает функции, поэтому для просмотра только переменных вы можете использовать:

 set | grep '^[^[:space:]]*=' 

Наконец, переменная RANDOM отличается тем, что ей присваивается значение только при обращении к ней. Это упоминается в bash (1) :

RANDOM

    Каждый раз, когда на этот параметр ссылаются, генерируется случайное целое число от 0 до 32767. Последовательность случайных чисел может быть инициализирована путем присвоения значения RANDOM . Если RANDOM не установлен, он теряет свои специальные свойства, даже если впоследствии он сбрасывается.

Таким образом, даже если бы это была переменная окружения, как вы и думали, она не была бы показана в env так как не была бы установлена ​​до первого вызова. Это также, почему это не показано в set :

 $ set | grep RAN ## returns nothing, RANDOM is unset $ echo "$RANDOM" ## this will assign a value to RANDOM 1234 $ set | grep RAN ## so now it will also appear in the output of set RANDOM=1234 

У большинства оболочек есть ряд других переменных, установленных или используемых оболочкой, которые по умолчанию не экспортируются в дочерние процессы.

В Bash есть некоторые, очевидно, специфичные для Bash:

 $ echo "${!BASH*}" BASH BASHOPTS BASHPID BASH_ALIASES BASH_ARGC BASH_ARGV BASH_CMDS BASH_COMMAND BASH_LINENO BASH_SOURCE BASH_SUBSHELL BASH_VERSINFO BASH_VERSION $ echo $BASH_VERSION 4.4.12(1)-release $ env|grep -c BASH 0 

Тогда есть более стандартные, такие как OPTIND и OPTERR (используемые getopts ), и PS2 , PS3 (вторичные запросы) и даже другая «волшебная» переменная: SECONDS (показывает время в секундах с момента запуска оболочки)

В Bash вы можете увидеть все переменные и их статус экспорта с помощью declare -p . Отмеченные с -x экспортируются, без x – нет. (У некоторых будут другие флаги, такие как i для целого числа или r для чтения.)

В Zsh или ksh93 вы можете использовать typeset -p , хотя Zsh помечает экспортируемые переменные, изменяя typeset для export в вывод, вместо использования флагов. Сам по себе export также покажет все экспортированные переменные, но это примерно тот же результат, который вы получите, запустив env .

Если вы гуглите по этому поводу, документы сообщат следующее:

$RANDOM – это внутренняя функция Bash (не константа), которая возвращает псевдослучайное целое число [1] в диапазоне от 0 до 32767. Она не должна использоваться для генерации ключа шифрования.

Если вы используете strace вы можете видеть, что переменная $RANDOM передается непосредственно командам, как если бы это была обычная переменная оболочки или переменная окружения, но это просто внутренняя функция, встроенная в оболочку, Bash, которая выполняет расширение.

 $ strace -t echo "random value: $RANDOM" 04:37:58 execve("/bin/echo", ["echo", "random value: 30795"], [/* 27 vars */]) = 0 04:37:58 brk(NULL) = 0x19c1000 04:37:58 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9841351000 ... 

против этой регулярной переменной:

 $ strace -t echo "random value: $SOMEVAR" 04:40:19 execve("/bin/echo", ["echo", "random value: helloworld"], [/* 27 vars */]) = 0 04:40:19 brk(NULL) = 0x154b000 04:40:19 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f659d2eb000 ... 

Переменная не передается в качестве ссылки.

Рекомендации

  • $ RANDOM: генерировать случайное целое число