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)
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)
请注意以下几点:
#!/usr/bin/env bash但这样你就不能用 arguments 启动 shell。-i有它自己的一系列后果,其中,程序会提示用户交互,这通常不适用于脚本,例如,安装deb包可能会在dpkg configure提示时停止脚本。set -i和set +i打开和关闭该功能,但这不起作用。小智 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等等。