正在运行的 shell 是否有重新创建其调用的机制?
我有时会对变量或我的配置文件进行更改,并且必须手动source
启动文件才能再次运行,例如,PATH
.
我想这主要适用于交互式 shell。
我在 OS X 中使用 bash 4,但问题并不限于这些。
答案1
我愿意exec bash
。它清理变量和函数。它不应该清理新打开的文件描述符(使用exec $someNumber<>somefile
)或导出的变量,但我很少使用打开新文件,exec
并且我的启动文件(当你这样做时会加载exec bash
)将我关心的环境变量(例如PATH
)恢复到我的状态想要他们进来。
(做一个普通的bash
有一个缺点,它会将另一个外壳粘到你当前的外壳上,所以你将不得不exit
再做一次。)
如果我不关心清理额外的变量和函数,我只需重新加载点文件。
~/.bashrc
我经常编辑和重新加载它,所以我有一个组合的键盘快捷键:
bashrcEdit() { $EDITOR "$HOME/.bashrc"; }
bind -x '"\C-e": bashrcEdit && bashrcReload'
对于简单的重新加载:
bind -x '"\C-o": bashrcReload;'
(我的重新加载功能是:
bashrcReload() { unset bashrcSourced; unset PROFILE_SOURCED; source "$HOME/.bashrc"; }
而不仅仅是:
source "$HOME/.bashrc";
它具有unset
s 是因为这些变量(第一个未导出的 - for .bashrc
,第二个导出的 - for .profile
)在我的设置中充当双重包含防护 - 没有这些unset
s,source
ing.bashrc
在我的设置中将是无操作。 )
正确行事
如果你想彻底的话,你可以
- 在 .bashrc 末尾对环境进行快照(然后重新加载它——你可以完美地做到这一点)
- 快照哪些文件描述符已打开(然后关闭所有其他文件描述符——这不是也永远不可能是一个完美的解决方案)
将其添加到您的末尾.bashrc
:
#Take a snapshot of the env and fds
envSnap() {
export FDS="$(/bin/ls /proc/$$/fd/)"
export ENV="$(export -p)"
}
#Restore env, close extra fds, and re-exec bash
envRestore(){
exec env - ENV="$ENV" bash --noprofile -c '
eval "$ENV"
for fd in `{ /bin/ls /proc/$$/fd; echo "$FDS"; } | sort | uniq -u`; do
eval "exec $fd>&-"
done
exec bash
'
}
#Take the snapshot now
envSnap
现在您可以envRestore
几乎完美地恢复环境。
例如,如果你这样做:
export FOO=bar
touch file
exec 5<file
然后,在 之后exec bash
,您仍然会看到:
/bin/ls /proc/self/fd
include 5 和echo $FOO
print bar
。
但是,如果您这样做envRestore
而不是exec bash
,则/bin/ls/ /proc/self/fd
不应包含 5 (除非您的 bash 通常以 fd 5 打开)并且echo $FOO
应打印空行。
(文件描述符是一个弱点,因为关闭额外的文件描述符并不能保证原始文件描述符不会被重定向,或者它们指向的虚表条目不会以某种方式改变,从而改变读取或在该文件描述符上写入将起作用。)