Это единственная вещь, которая работает для того, что мне нужно было сделать (создать виртуальную среду, затем активировать ее, а затем установить требования из сценария bash):
создать подоболочку/дочернюю оболочку из скрипта, как в:
глупый _файл.sh
(
set -o errexit
#bunch of commands
#one line fails
)
запустите дурацкий файл _с помощью:
source stupid_file.sh <file arguments here> || true
КОНЕЦ.
**поклон**
(кредит принадлежит Джеффу и Тердону)
GNU Parallel включает env_parallel
. В части env_parallel
перечислены все переменные для поддерживаемых оболочек.
Для bash
это код :
_names_of_VARIABLES() {
compgen -A variable
}
_bodies_of_VARIABLES() {
typeset -p "$@"
}
Таким образом, учитывая все переменные, нам нужно выяснить, какие из них установлены пользователем. Мы можем сделать это, жестко запрограммировав все переменные, установленные данной версией bash
, но это не будет очень надежным доказательством будущего, потому что bash
может установить больше переменных в будущих версиях (Является ли $BASH_MYVAR
установлен пользователем или будущей версией bash
? ).
Вместо этого env_parallel
просит вас определить чистую среду и запустить env_parallel --session
в ней. Это установит $PARALLEL_IGNORED_NAMES
путем перечисления имен, определенных до (с использованием кода выше ).
При последующем запуске в среде, в которой пользователь задал переменные, легко определить разницу между чистой средой и текущей средой.
env_parallel --session
позволяет определить чистую среду для каждого сеанса, но если вы предпочитаете иметь эталонную среду, которую можно использовать между сеансами, просто сохраните список переменных в файле.Так:
# In clean envronment
compgen -A variable > ~/.clean-env-vars
# In environment with user defined vars
compgen -A variable | grep -Fxvf ~/.clean-env-vars
Например:
#!/bin/bash
# In clean envronment
compgen -A variable > ~/.clean-env-vars
myvar=4
yourvar=3
# In environment with user defined vars
compgen -A variable | grep -Fxvf ~/.clean-env-vars
# This prints:
# myvar
# yourvar
# PIPESTATUS (which is set when running a pipe)
Kludgy, bash -единственное решение:
(setn(){
set | sed '/^{/,/^}/d;/=/!d;/^BASH[A-Z_]*=\|^PPID=\|^SHLVL=\|^PIPESTATUS=\|^HISTSIZE=\|^HISTFILESIZE=\|^_[a-z_]*=/d' | sort
}
export -f setn
comm -23 <(setn) <("$BASH" -ic setn))
Возможно, вам придется также отфильтровать другие переменные с помощьюsed
(или сделать шаблон BASH..
более строгим ). Предполагается, что /_[a-z_]*=/
исключает переменные, определяемые программируемым завершением, например _backup_glob
или _xspecs
; это тоже можно было бы сделать более строгим.
bash
выведет значения переменных, содержащих забавные символы, в формате $'...'
, так что вам придется обработать это:
foo='
bar
baz
'
...
foo=$'\nbar\nbaz\n'
bash
не будет создавать переменные оболочки из envvar, чьи имена содержат символы новой строки, поэтому такой трюк не может сломать этот хак.
В зависимости от ваших потребностей,одно простое решение может быть:
set > tmp
или set > /tmp/current
diff -u <(cat tmp) <(set)
или diff -u <(cat tmp) <(set) | tail -n +3 | grep -v PIPESTATUS | grep -v "_=" | grep -E "^\+"
Где:
tail -n +3
:удалить первую ненужную строку команды diff
grep -v PIPESTATUS | grep -v "_="
:удалить ненужные переменные
grep -E "^\+"
:отображать только требуемые/необходимые изменения
Альтернатива:
diff -u <(set -o posix; set) <(bash -lc 'set -o posix; set') | grep -E "^\+"
Примечание:
В вашем скрипте обратите внимание, что exec
полностью замените процесс, из которого он запущен, это может помешать тому, чего вы пытаетесь достичь
I'd like to echo all self-declared variables (all non-environment variables)
Это задача для comm
, как по мне:
comm -23 <( set | cut -d= -f1 | sort ) <( env | cut -d= -f1 | sort )
-23
означает, что comm
не должен печатать столбцы 2 и 3.
3-й — это такие записи, которые находятся в обоих списках, а 2-й — это записи, которые есть только в обработанном выводе env
поста -.
Или, IOW, показывают только уникальные записи, которые были в 1-м списке .
P. S. Так как некоторые записи могут быть найдены в обоих списках сразу (проверьте их с помощью comm -12 …
), вы можете также включить их в результирующий набор. Это означает, что вы не должны использовать -3
в этом случае, и строки из 3-го столбца будут отображаться со смещением при печати.
Добавьте это в свой~/.bashrc
pre () {
set -o posix;set > /tmp/tmp-original-envs
}
post () {
set -o posix;set > /tmp/tmp-new-envs
diff /tmp/tmp-original-envs /tmp/tmp-new-envs | grep -v BASH_LINENO | grep -v FUNCNAME | grep '>'
}
Затем запустите pre
перед вашими изменениями и post
после
Пример:
[localhost]$ pre
[localhost]$ test=new
[localhost]$ post
> test=new
[localhost]$