Non*_*yme 10 environment-variables persistence
我希望能够将我当前的环境保存在一个文件中(用于正在运行的交互式会话),以便我可以:
我只对导出的变量感兴趣。因为我希望能够恢复环境,所以它必须是一个 shell 函数,所以我正在使用 bash。理想情况下,它不依赖于外部程序,并且适用于从 v3.2.25 到当前的 bash 版本。
现在,为了保存我的环境,我使用以下函数:
env_save () {
export -p > "$STORAGE/$1.sh"
}
Run Code Online (Sandbox Code Playgroud)
我env_save <filename>
在运行会话中使用的。我有一些样板代码来保存备份,但让我们忽略它。
但是,我在重新加载环境时遇到了困难:
env_restore () {
source "$STORAGE/$1.sh"
}
Run Code Online (Sandbox Code Playgroud)
因为这不会删除我同时创建的虚假变量。也就是说,调用export -p
afterenv_restore <filename>
可能不会给出与cat $STORAGE/$1.sh
.
有没有一种干净的方法来处理这个问题?我可能需要将一些变量(例如 PWD、OLDPWD、SHELL、SHLVL、USER、SSH_*、STORAGE 等)列入黑名单……也就是说,这些变量不应保存且在恢复时不应更改,因为它们是特殊变量. 我不能使用白名单,因为我不知道那里会有哪些变量。
POSIXly,你可以这样做:
# save
export -p > saved-env
...
# restore
blacklisted () {
case $1 in
PWD|OLDPWD|SHELL|STORAGE|-*) return 0 ;;
*) return 1 ;;
esac
}
eval '
export() {
blacklisted "${1%%=*}" || unset -v "${1%%=*}"
}
'"$(export -p)"
export() {
blacklisted "${1%%=*}" || command export "$@"
}
. saved-env
unset -f export
Run Code Online (Sandbox Code Playgroud)
请注意,对于bash
not 调用 as sh
,您需要发出 aset -o posix
才能正常工作。同样bash
在 4.4 之前的版本中,输出的来源export -p
可能不安全:
$ env -i 'a;reboot;=1' /bin/bash -o posix -c 'export -p'
export OLDPWD
export PWD="/"
export SHLVL="1"
export a;reboot;
Run Code Online (Sandbox Code Playgroud)
ksh93 也有类似的问题。yash
没有那个特定的,但仍然有以 开头的变量名的问题-
:
$ env -i -- '-p=' yash -c 'export -p'
export '-p'=''
export OLDPWD
export PWD='/'
Run Code Online (Sandbox Code Playgroud)
如果您在保存和恢复变量时不在同一语言环境中,还要注意潜在的问题。
bash-4.3$ locale charmap
ISO-8859-15
bash-4.3$ export Stéphane=1
bash-4.3$ export -p > a
bash-4.3$ LC_ALL=en_GB.UTF-8 bash -c '. ./a'
./a: line 5: export: `Stéphane=1': not a valid identifier
Run Code Online (Sandbox Code Playgroud)