我正在使用 Arch 和 bash 以及 Openbox 窗口管理器。
一切都是最新的。
Openbox 配置了一个名为rc.xml
在内部,rc.xml
我通常调用bash -c 'command1; command2; etc'
将必要的有用命令序列连接到热键。
我有一个热键定义rc.xml
如下
<keybind key="1"><action name="Execute"><command>bash -c '
command1;
command2;
etc;
yad --timeout=1 --text="$pos_x x $pos_y";
'</command></action></keybind>
这一切都按预期工作并且功能齐全,除了全局定义的变量$pos_x
并且$pos_y
不显示之外。
其中.bashrc
定义为
export pos_x=1000
export pos_y=500
当我打开一个新的 bash shell 终端窗口并键入时,
echo "$pos_x x $pos_y"
我看到了预期的
1000 x 500
。
但是,当我在这个新的终端窗口中键入时,
bash -c 'echo "$pos_x x $pos_y"'
我什么也看不到,因为显然子进程不会继承全局变量。
如果我输入,
bash -c 'source ~/.bashrc; echo "$pos_x x $pos_y"'
我什么也看不到,所以在子进程中获取 .bashrc 没有帮助。
如何将定义的全局变量传递.bashrc
给子进程?
我环顾四周,却找不到任何答案。
答案1
Arch 上的默认设置~/.bashrc
在文件顶部包含以下行:
# If not running interactively, don't do anything
[[ $- != *i* ]] && return
这使得任何非交互式 shell 停止读取该行的文件。由于bash -c
启动非交互式 shell,因此~/.bashrc
不会完整读取该文件,这就是未定义变量的原因。
所以,你可以尝试:
将变量放入
~/.profile
而不是~/.bashrc
.无论如何,这是全局变量的自然位置。只要您的登录管理器读取/.profile
,这应该有效。使用不同的文件。无需将变量定义放入其中
~/.bashrc
,只需将它们放入~/foo
然后发出命令即可bash -c '. ~/foo; echo "$pos_x x $pos_y"
。将变量定义放在我在开头显示的停止读取的行上方
~/.bashrc
。
答案2
当 Bash 作为交互式登录 shell 被调用时,或者作为带有 --login 选项的非交互式 shell,它首先从文件中读取并执行命令
/etc/profile
(如果该文件存在)。读取该文件后,它会按顺序查找~/.bash_profile
、~/.bash_login
、 和~/.profile
,并读取并执行命令 第一个存在并且可读。 ...当 Bash 以非交互方式启动时,例如,要运行 shell 脚本,它会在环境中查找变量 BASH_ENV,如果它出现在其中,则扩展其值,并使用扩展后的值作为要读取和执行的文件的名称。
因此,要正确设置环境,无论 Bash 是以交互方式还是非交互方式启动,仅拥有 是不够的~/.bash_env
,您还必须设置变量BASH_ENV
并指向它,并在交互模式下显式获取它。
我会将特定于 Bash 的内容放在特定于 Bash 的文件中,并保留~/.profile
在其他 shell 中仍然有效的常规设置(如果您有一天决定更改登录 shell)。
首先,创建一个~/.bash_profile
包含以下内容的文件:
[ -f "$HOME/.profile" ] && source "$HOME/.profile"
if [ -z "$POSIXLY_CORRECT" ]; then
[ -z "$BASH_ENV" ] && export BASH_ENV="$HOME/.bash_env"
source "$BASH_ENV"
fi
"$HOME/.bash_env"
然后创建一个包含所有 Bash 特定变量和函数的文件。
顺序很重要:将 source 行放在~/.profile
顶部~/.bash_profile
使您能够在运行 Bash 时覆盖其中定义的变量。
我还没有检查变量引用的文件是否BASH_ENV
是由远程 shell 守护程序(通常rshd
)或安全 shell 守护程序调用时获取的sshd
。再次引用 Bash 手册,
如果 Bash 确定它正在以这种方式非交互地运行,那么它会从 读取并执行命令
~/.bashrc
(如果该文件存在并且可读)。
创建包含~/.bashrc
以下内容的 可能是个好主意:
if [ -z "$POSIXLY_CORRECT" ]; then
[ -z "$BASH_ENV" ] && export BASH_ENV="$HOME/.bash_env"
source "$BASH_ENV"
fi
在这种情况下,您可以简化~/.bash_profile
:
[ -f "$HOME/.profile" ] && source "$HOME/.profile"
[ -f "$HOME/.bashrc" ] && source "$HOME/.bashrc"
最后,您希望有一些保护措施,防止您的 中出现多重包含~/.bash_env
:
[ -n "$BASH_ENV_VERSION" ] && return 0
BASH_ENV_VERSION=.....
...
export
注意:对变量(或整个文件中的任何变量)进行 ing是没有意义的,因为~/.bash_env
需要获取脚本才能使函数定义在当前 shell 中可访问。出于同样的原因,我们创建的所有文件都不需要 shebang 行。
我们处理了交互式登录 shell 和非交互式 shell。细心的读者可能会反对,认为缺少的部分是交互式非登录 shell。幸运的是,上述步骤涵盖了这些内容:
当启动非登录 shell 的交互式 shell 时,Bash 会从 ~/.bashrc 读取并执行命令(如果该文件存在)。