![无法从 shell 脚本成功获取 .bashrc](https://linux22.com/image/958593/%E6%97%A0%E6%B3%95%E4%BB%8E%20shell%20%E8%84%9A%E6%9C%AC%E6%88%90%E5%8A%9F%E8%8E%B7%E5%8F%96%20.bashrc.png)
通常我们可以~/.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 -i
并set +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
。注意:一旦您的脚本退出,环境将被设置为启动脚本之前的状态。更改将在下次启动终端时反映出来。