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

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

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

source ~/.bashrc

但是如果我在 shell 脚本中编写并执行它,什么也不会发生。为什么?
有什么办法吗?

我的脚本:

#!/bin/bash
chmod a+x ~/.bashrc
source ~/.bashrc

还尝试用.(dot) 代替source。结果相同。

答案1

我想补充ravi 的回答

此行为特定于 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 -iset +i在需要时打开和关闭该功能,但是这不行

答案2

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

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

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

alias brc='source ~/.bashrc'

答案3

.bashrc通常开始:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

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

    #!/bin/bash
    chmod a+x ~/.bashrc
    PS1='$ '
    source ~/.bashrc

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

答案4

其他方法都不适合我[ source /path/to/filevs . ./path/to/file,别名等...],直到,感谢本教程我发现使用:

#!/usr/bin/env bash舍邦

而不是更简单的#!/usr/bin/env方法让参数传递给解释器,我认为这是关键——参见这个文件了解更多信息。

无论如何,如果任何形式的源命令对您不起作用,请尝试检查您的shebang,这可能是问题所在:)

相关内容