我已经打开了几个终端窗口;我刚刚对 进行了更改~/.bashrc
,并且我想source ~/.bashrc
在每个打开的终端中运行。
在我看来,如果我只是
source ~/.bashrc | tee /dev/pts/{0..12}
,然后~/.bashrc
应该在每个终端中运行。看起来确实如此,因为我clear
在 的末尾添加了 a ~/.bashrc
。
然而,我具体测试的是是否
PROMPT_COMMAND="history -a; history -c; history -r; ${PROMPT_COMMAND:+$PROMPT_COMMAND$'\n'}"
实际上为我的所有终端创建了单一事实来源,并在每个打开的终端中进行了修改。
现在我不确定这是否与写入有关/dev/pts/{0..12}
或与功能方式有关history
。如果我查看正在运行的打开终端之一git log
,并且echo $PROMPT_COMMAND
,我会这样做不是看到我期望的修改已经~/.bashrc
被获取。由于缺少命令,我在运行 的单独终端中看history
不到输出,我希望看到在 后是否确实进行了修改。git log
tail -f ~/.bash_history
PROMPT_COMMAND
source ~/.bashrc
但是,如果我询问每个终端echo $PROMPT_COMMAND | tee /dev/pts/{0..12}
的值PROMPT_COMMAND
是什么,我会得到:
history -a; history -c; history -r; pre_prompt_command; echo -ne "\033]0;${USER}@${HOSTNAME%%.*}:${PWD/#$HOME/\~}\007"
其中包括history -a; history -c; history -r;
我添加的更改~/.bashrc
。
现在我很困惑。我究竟做错了什么?或者我理解不正确?是PROMPT_COMMAND
修改了还是没修改?或者这是 bash/linux 工作方式的结果?我很确定这是用户错误,而不是错误。
答案1
source ~/.bashrc
制作当前的 shell 源~/.bashrc
。将输出重定向到tee
(在您的情况下将其发送到多个/dev/pts/…
文件)是重定向输出来自 中的命令.bashrc
,而不是 的内容.bashrc
。
但即使你这样做了cat ~/.bashrc | tee /dev/pts/{0..12}
,你也不会发送内容到其他 shell;并且echo 'source ~/.bashrc' | tee /dev/pts/{0..12}
您不会注入source ~/.bashrc
其他 shell 的命令行。看通过将字符串放入 tty 来构造命令, 尤其这个答案:
终端兼作两个东西:输入设备(例如键盘)和显示设备(例如监视器)。当您从终端读取时,您会得到来自输入设备的内容。当您写入终端时,数据会显示到显示设备上。
通过发送字节,/dev/pts/…
您只能从显示设备获得反应,而不能从使用它的(或任何)shell 获得反应。显示设备通常会通过显示/打印您发送的内容来做出反应。但有些字节序列是特殊的。
它恰好是clear
由输出某种特殊的字节序列,因此当您重定向并分叉输出时,其他终端会通过清除屏幕来做出反应。一般来说,另一个终端可能会也可能不会对“外部”作出反应,clear
因为序列clear
取决于$TERM
(clear
例子),因此它是根据您运行的终端量身定制的clear
。
同样,echo $PROMPT_COMMAND | tee /dev/pts/{0..12}
对其他 shell 也没有执行任何操作。您当前的 shell 已扩展$PROMPT_COMMAND
(应该用双引号引起来),echo
将结果发送至tee
,tee
发送至多个终端。各航站楼打印提供的变量值当前的壳;没有涉及其他外壳。
一般来说,在 Linux 中没有简单的(即像>/dev/pts/…
或那样简单tee /dev/pts/…
)方法来注入一些字符串,就像你键入它一样。程序员可以使用TIOCTI。终端多路复用器和终端仿真器可以提供将击键发送到它们仿真的终端的方法(例如send-keys
tmux 的)。尽管如此,即使这样,注入命令通常也不是一种优雅的方式,因为“shell”可能有 bash 以外的东西,或者它(无论是否是 bash)可能正忙于执行其他可能消耗输入的东西,并可能通过执行以下操作来做出反应你不想要的东西。
此外,source ~/.bashrc
Enter即使直接在交互式 bash 的命令行中输入也可能会“行为不当”。~/.bashrc
意味着在一个干净的外壳中自动获取一次。在旧 shell 中获取新版本并不等同于启动新 shell。