1

Как узнать переменные среды, установленные после входа в сеанс оболочки?

Мои два фиктивных решения были следующими:

_VariableName1="VarValue1";export _VariableName1;
_VariableName2="VarValue2";export _VariableName2;

...

set | grep '_' 

… Который почти показывает переменные, установленные после входа в систему (отличающиеся от переменных, установленных .bash_profile и .bashrc). Этот подход заставляет меня постоянно забывать о подчеркивании в vars - и старые гуру на работе смеются надо мной, когда видят это;)

Второй подход заключается в использовании "читабельных переменных", но для запуска после входа в систему или sudo:

 su - username the 
 set > /tmp/vars.before 

установить переменную

 VariableName1="VarValue1";export VariableName1;
 VariableName2="VarValue2";export VariableName2;

set > /tmp/vars.after

… А затем выполните следующую команду:

 comm -13 /tmp/vars.before /tmp/vars.after

или же

 comm --nocheck-order -3 /tmp/vars.before /tmp/vars.after

в зависимости от двоичного comm и т.д.

Так какой же самый чистый или самый умный способ выяснить это?

3 ответа3

3

Один из подходов - переопределить export и unset с помощью функций, которые отслеживают ваши переменные.

Обратите внимание: чтобы это работало, вы должны экспортировать переменные следующим образом: export <variable>=<value> .

Эти две функции должны называться export и unset и поддерживать список ваших переменных в файле, который я назову ~/.track$$ ($$ - это PID вашей текущей оболочки):

export ()
{
    if echo $@ | egrep -q '[^=]+=[^=]+' && builtin export "$@" && echo $- | grep -q i; then          # [1]
        touch ~/.track$$                                                                             # [2]
        cp -fa ~/{.track$$,.track$$.bak} 2> /dev/null;                                               # [3]  
        grep -v "^$(echo $@ | sed 's/\([^=]=\).\+/\1/')" < ~/.track$$.bak > ~/.track$$ 2> /dev/null; # [4]
        echo $@ >> ~/.track$$;                                                                       # [5]
    fi
}

unset ()
{
    if builtin unset $@ && echo $- | grep -q i; then                # [1]
        touch ~/.track$$                                            # [2]
        cp -fa ~/{.track$$,.track$$.bak} 2> /dev/null;              # [3]
        egrep -v "^$@=" < ~/.track$$.bak > ~/.track$$ 2> /dev/null; # [4]
    fi
}

Кроме того, вам необходимо выяснить, какие переменные среды вы установили. Такой псевдоним сделает это:

alias iset="cat ~/.track$$ 2>/dev/null"

Псевдоним как это:

alias ireset="rm ~/.track$$ >/dev/null 2>&1"

может быть использован для сброса списка.

Чтобы свести к минимуму количество файлов ~/.track$$ мы можем использовать эту служебную команду:

rm $(ls -d ~/.* | egrep 'track[0-9]+$|track[0-9]+\.bak$' | egrep -v $(ps -ef | grep bash | grep -v grep | awk '{print $2}' | tr '\n' '|' | sed 's/|$//')) > /dev/null 2>&1

Где мы должны поместить эти функции, псевдонимы и т.д.?

Я бы порекомендовал добавить функции, псевдонимы и команду housekeeping в конец ~/.bashrc , чтобы подоболочки тоже получали функции. В зависимости от вашего дистрибутива и того, как /etc/profile , /etc/bash.bashrc и друзья выполняются, вы можете определить их слишком рано (в некоторых дистрибутивах ~/.profile ~/.bashrc или наоборот), так что вы можете иметь отрегулировать это.

Затем выйдите и войдите снова.

Теперь, если вы запустите export <variable>=<value> в вашем сеансе bash, функция export:

  • [1] проверяет, правильно ли задан параметр (это позволяет избежать ложных записей при вводе export MYVAR , поскольку его возвращаемое значение равно 0 и создаст запись в ~/.track$$)

  • [1] затем он выполняет builtin export <variable>=<value> (это устанавливает переменную независимо от того, что произойдет впоследствии)

  • [1] затем greps $- чтобы увидеть, является ли это интерактивной оболочкой (см. Этот ответ. Когда я запускаю ssh на машине с Ubuntu, какую оболочку я использую [бесстыдный плагин]). По умолчанию подоболочки не наследуют функции, поэтому сценарии не будут создавать файлы ~/.track$$ . Если скрипт использует #!/bin/bash -i , однако, это будет. Это предотвратит это.

  • [2] затем он касается ~/.track$$ чтобы убедиться, что он существует и

  • [3] делает резервную копию

  • [4] затем он проверяет, существует ли переменная, если это так, она удаляется из ~/.track$$

  • [5] наконец, он добавляет строку в ~/.track$$

Точно так же, если вы unset <variable> и нажмете Enter, функция unset:

  • [1] выполняет builtin unset <variable> (это отменяет переменную, независимо от того, что происходит потом)

  • [1], если unset был успешным, он проверяет, как в функции export выше. является ли это интерактивной оболочкой (см. этот ответ Когда я захожу в машину с Ubuntu, какую оболочку я использую [бесстыдный плагин]). По умолчанию подоболочки не наследуют функции, поэтому сценарии не будут создавать файлы ~/.track$$ . Если скрипт использует #!/bin/bash -i , однако, это будет. Это предотвратит это.

  • [2] затем он касается ~/.track$$ чтобы убедиться, что он существует и

  • [3] затем делает резервную копию ~/.track$$

  • [4] удаляет запись переменной из ~/.track$$

Какое builtin ключевое слово я использовал в обеих функциях? Поскольку export или unset являются оболочки (встроенные функции, что есть, команды , которые приходят с оболочкой) , мне нужно использовать builtin который сам по себе является встроенной командой (от man bash

встроенная оболочка-встроенная [аргументы]

Выполните указанную встроенную оболочку, передав ей аргументы, и верните ее состояние выхода. Это полезно при определении функции, имя которой совпадает со встроенной оболочкой, сохраняя функциональность встроенной функции. Встроенный CD обычно переопределяется таким образом. Возвращаемый статус - false, если shell-buildin не является встроенной командой shell.

Команда housekeeping перечисляет и фильтрует активные файлы ~/.track$$ и удаляет остальные.

Что вы получаете с этой настройкой:

  • Нет необходимости использовать подчеркивания больше. Просто используйте знакомую команду export (которая была переопределена функцией), и она будет работать.

  • Каждый сеанс bash имеет свой собственный файл ~/.track$$ . Никаких столкновений между снарядами.

  • Как побочный эффект от вышеупомянутого, подоболочки не наследуют родительский файл ~/.track$$ , хотя они наследуют все переменные окружения.

  • Переменные среды, заданные в исходных файлах (. file или source file), добавляются в ~/.track$$ .

  • Переменные среды, заданные в подоболочке (), также (неправильно) отслеживаются, поскольку $$ расширяется до идентификатора процесса текущей оболочки, а не подоболочки (см. man bash).

  • Переменные перечислены от первого до последнего экспортируемого.

  • Переменные, заданные .profile и другими переназначенными вами сценариями (даже с тем же значением), будут перечислены в iset . Например, HOME обычно устанавливается .profile . Если вы выполните export HOME=/usr/local/bin:$HOME и запустите iset вы увидите список HOME .

А теперь несколько примеров:

  • Экспортируемые переменные отображаются с помощью iset:

    $ export MYVAR1=0987654321; iset
    MYVAR1=0987654321
    
  • Переопределенные переменные обрабатываются правильно:

    $ export MYVAR2="this is a string"; iset
    MYVAR1=0987654321
    MYVAR2=this is a string
    $ export MYVAR2="this is a different string for the same variable"; iset
    MYVAR1=0987654321
    MYVAR2=this is a different string for the same variable
    
  • Среда в соответствии с env соответствует iset:

    $ env|grep MYVAR
    MYVAR2=this is a different string for the same variable
    MYVAR1=0987654321
    
  • Переменные только для чтения не добавляются в ~/.track$$:

    $ export EUID=0; iset
    -bash: EUID: readonly variable
    MYVAR1=0987654321
    
  • Старые, более не используемые файлы дорожек удаляются при выполнении ~/.bashrc (например, при создании подоболочки):

    $ ls -1 ~/.track*
    .track11002
    .track11002.bak
    .track21774
    .track21774.bak
    .track2923
    .track2923.bak
    .track7382
    .track7382.bak
    .track8374
    .track8374.bak
    $ echo $$
    2923
    $ bash
    <subshell>$ ls -1 ~/.track*
    .track2923
    .track2923.bak
    
1

Если вас интересуют только переменные окружения , вы должны использовать env вместо set . Я не совсем уверен, правильно ли я понимаю, чего вы пытаетесь достичь, но кажется, что

env | sort > /tmp/vars.before

после входа в систему, а затем

env | sort > /tmp/vars.after
comm -13 /tmp/vars.before /tmp/vars.after

в какой-то более поздний момент поступает правильно, по крайней мере, если ни одна из переменных среды не содержит строку, содержащую символ новой строки. (Если это так, я бы либо использовал env -0 | sort -z чтобы получить переменные окружения, разделенные NULL, а затем использовал perl для сравнения, либо запрограммировал все это на perl.)

0

Если вы хотите узнать, какие переменные среды были установлены, просто введите следующую команду:

printenv

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .