Answers:
Shell脚本在其自己的Shell实例中运行。所有变量设置,函数定义等仅影响此实例(可能还包括其子级),而不影响调用外壳程序,因此在脚本完成后它们将消失。
相比之下,该source
命令不会启动新的Shell实例,而是使用当前的Shell,因此更改仍然保留。
如果您想使用快捷方式读取.bashrc,请使用Shell函数或别名而不是Shell脚本,例如
alias brc='source ~/.bashrc'
source ~/.bashrc
在要更改其环境的Shell中运行。您不能从其他进程更改它。也许(全局)添加此别名可能是GUI安装过程的一部分。
您的.bashrc
通常开始时间:
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
由于您的脚本未设置PS1(因为它不是交互式的),因此不会重置路径,因为它会提前退出。为了演示,请修改您的脚本:
#!/bin/bash
chmod a+x ~/.bashrc
PS1='$ '
source ~/.bashrc
现在,这将使您的脚本可以与新的一起使用.bashrc
。注意:脚本退出后,环境将设置为启动脚本之前的状态。更改将在下次启动终端时反映出来。
.bashrc
使用更可靠的方法来检查shell是否是交互式的。/etc/bash.bashrc
仍然有PS1测试。
尝试:
exec bash
这应该重新加载〜/ .bashrc,〜/ .bash_aliases等。
source
但是会破坏任何变量,从而使用户手动设置了-这可能是您想要的,也可能不是。
exec bash
,按照我的理解,以后的命令仍将与以前相同的bash设置?
我想补充一下拉维的答案:
此行为特定于Ubuntu(并且可能是大多数派生的发行版),因为默认~/.bashrc
文件以短路(例如Ubuntu 18.04)开头,例如:
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
如果该文件在非交互式shell中运行,则将停止对该文件的评估(您的脚本就是这种情况),因为所有脚本均在非交互式shell中运行,并且随后每个文件都source
将继承此属性。
eval
骇客我发现一个丑陋的黑客可以专门解决Ubuntu问题,eval
而不是使用source
:
eval "$(cat ~/.bashrc | tail -n +10)"
它只是跳过了前几行并评估了其余的行,~/.bashrc
因此其余的行将被评估并修改当前执行。
请注意,这是一个神奇的数字,可能不适用于Ubuntu版本。但是如果您正在为或多或少的已知系统编写脚本,则可能是一个很好的解决方案。
更好的解决方案可能涉及使用正则表达式来定位停止评估的特定位。
在某些情况下可能更好用的另一种替代方法是通过在shebang中添加一个标志来强制脚本在交互式shell中运行:
#!/bin/bash -i
请注意以下几点:
#!/usr/bin/env bash
但是这样就不能用参数来启动shell。-i
具有自己的后果集,其中,程序将提示用户交互,并且通常不打算用于脚本,例如,安装deb
软件包可能会在dpkg configure
提示时停止脚本。set -i
和set +i
打开和关闭该功能,但这是行不通的。