无法从 shell 脚本成功获取 .bashrc

sha*_*anu 65 bash scripts bashrc

通常我们可以~/.bashrc使用这个命令来获取文件

source ~/.bashrc
Run Code Online (Sandbox Code Playgroud)

但是如果我在 shell 脚本中编写并执行它,则什么也不会发生。为什么?
有没有办法做到这一点?

我的脚本:

#!/bin/bash
chmod a+x ~/.bashrc
source ~/.bashrc
Run Code Online (Sandbox Code Playgroud)

也试过.(dot) 而不是source. 结果一样。

Flo*_*sch 29

shell 脚本在它自己的 shell 实例中运行。所有变量设置、函数定义等只影响这个实例(可能还有它的子实例)而不影响调用 shell,所以它们在脚本完成后消失了。

相比之下,该source命令不会启动新的 shell 实例,而是使用当前的 shell,因此更改仍然存在。

如果您想要读取 .bashrc 的快捷方式,请使用 shell 函数或别名而不是 shell 脚本,例如

alias brc='source ~/.bashrc'
Run Code Online (Sandbox Code Playgroud)

  • 那么,我是否应该将别名命令放在脚本的前面,然后当我想要获取 .bashrc 的来源或者需要将该别名命令放在某个文件中时调用 brc? (3认同)

ste*_*ric 22

我想补充ravi 的回答

此行为特定于 Ubuntu(并且可能是大多数衍生发行版),因为您的默认~/.bashrc文件以短路 Ubuntu 18.04 开头,例如:

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac
Run Code Online (Sandbox Code Playgroud)

如果文件在非交互式 shell 中运行,这将停止对文件的评估,这是您的脚本的情况,因为所有脚本都在非交互式 shell 中运行,随后您source将继承此属性的每个文件。

eval 黑客

我发现了一个丑陋的黑客来专门解决 Ubuntu,使用eval代替source

eval "$(cat ~/.bashrc | tail -n +10)"
Run Code Online (Sandbox Code Playgroud)

它只是跳过前几行并评估其余的行,因此评估其余~/.bashrc部分并修改当前执行。

请注意,这是一个神奇的数字,可能不适用于 Ubuntu 版本;但如果您正在为或多或少已知的系统制作脚本,这可能是一个很好的解决方案。

更好的解决方案可能涉及使用正则表达式来定位停止评估的特定位。

舍邦替代品

在某些情况下可能更好的另一种选择是通过在shebang 中添加一个标志来强制脚本在交互式 shell 中运行:

#!/bin/bash -i
Run Code Online (Sandbox Code Playgroud)

请注意以下几点:


小智 16

.bashrc通常开始:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return
Run Code Online (Sandbox Code Playgroud)

由于您的脚本没有设置 PS1(因为它不是交互式的),因此它不会重置路径,因为它提前退出。为了演示,请修改您的脚本:

    #!/bin/bash
    chmod a+x ~/.bashrc
    PS1='$ '
    source ~/.bashrc
Run Code Online (Sandbox Code Playgroud)

这将允许您的脚本使用新的.bashrc. 注意:一旦您的脚本退出,环境将设置为启动脚本之前的状态。下次启动终端时将反映这些更改。


Ali*_*rei 11

尝试:

exec bash
Run Code Online (Sandbox Code Playgroud)

这应该重新加载~/.bashrc~/.bash_aliases等等。

  • 这将用新的 bash 进程替换当前的 bash 进程。它并不比使用 `source` 更短或更容易,但会破坏任何变量,并且用户已手动设置 - 这可能是您想要的,也可能不是。 (9认同)