Как узнать переменные окружения, установленные после входа в сеанс оболочки
Как я могу узнать переменные среды, установленные после входа в сеанс оболочки?
Мои два фиктивных решения были следующими:
_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 ответа
Одним из подходов является переопределение 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
Где мы должны поместить эти функции, псевдонимы и т. Д.?
Я бы порекомендовал вам добавить функции, псевдонимы и служебную команду в конец ~/.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> и нажмите Ввести функцию 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, если встроенная оболочка не является встроенной командой оболочки.
Команда по ведению домашнего хозяйства перечисляет и фильтрует активный ~/.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
Если вас интересуют только переменные среды, вы должны использовать 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.)
Если вы хотите узнать, какие переменные среды были установлены, просто введите следующую команду:
printenv