Один из подходов - переопределить 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