为什么我最初的方法是错误的

为什么我最初的方法是错误的

我正在编写一个 bash 脚本,在其中假装打开一个新的终端窗口(在本例中为 gnome 终端),执行一些命令并更改终端窗口的标题。

为了更改终端窗口的标题,我正在使用该函数设置标题如提议的这个答案。当我手动打开一个新终端并在终端内输入时,该方法非常有效设置标题 MY_TITLE。但在这种情况下,从 bash 脚本中它不起作用,即使我来源.bashrc文件。

#!/bin/bash

gnome-terminal -- /bin/bash -c "echo Hello from terminal 1; set-title Terminal 1; exec /bin/bash";

gnome-terminal -- /bin/bash -c "source ~/.bashrc; echo Hello from terminal 2; set-title Terminal 2; exec /bin/bash";

新打开的两个终端显示同样的错误:

/bin/bash: set-title: command not found

很明显bash解释器没有找到set-title这个函数,但是我不知道如何强制加载.bashrc打开 gnome 终端时的文件。

答案1

我将回答我自己的问题,但在解释我找到的两个解决方案之前,我将解释为什么我试图做的事情不起作用。

为什么我最初的方法是错误的

如果您的系统中有自定义功能~/.bashrc文件,就像我的例子中的文件一样设置终端窗口的标题,这些函数在从以自动方式执行命令的 bash 脚本打开的终端窗口中将不可用(如我的问题的示例)。

谢谢用户414777为提示。你是绝对正确的。我的 ~/.bashrc 文件开头包含以下代码:

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

通过打印选项标志,$-结果是HB(正如预期的那样,这不是一个交互式外壳),所以显然set-title我在结尾处拥有的功能~/.bashrc,永远不会被添加到 shell 中。

解决方案1(推荐):使用xfce4-terminal

作为薛迪杰的好奇心建议,这是解决该问题的最简单的方法。您可能不喜欢安装另一个终端工具;如果(就像我的情况一样)你使用的是 Gnome 并且默认使用 gnome-terminal,但好的一面是你可以使用xfce4-terminalbash 脚本和gnome-terminal“人机”交互,所以除了标题之外,你还可以使用额外的分类级别(如果您打开了许多终端窗口)。

它的xfce4-terminal工作方式与 bash 脚本中的工作方式有点不同gnome-terminal,但没有什么是你无法真正弄清楚的。无论如何,您都可以在下面找到解决方案xfce4-terminal

#!/bin/bash

xfce4-terminal --title "Terminal 1" -e "bash -c 'echo Hello from terminal 1; exec /bin/bash'" &

xfce4-terminal --title "Terminal 2" -e "bash -c 'echo Hello from terminal 2; exec /bin/bash'" &

解决方案 2:使用 xdotool

我发现该问题的另一个解决方案是使用xdotool.xdotool是一个命令行工具,可以在X11窗口系统中模拟/自动化人类交互。

这种解决方案过度设计了最初的问题,因为它会产生其他问题,例如 bash 脚本和 X windows 系统之间的同步,因此有必要sleep在 bash 脚本中引入命令,以便为 X 窗口管理器提供时间来处理事件。这种同步问题使得该解决方案不可靠,因为它不能在 100% 的情况下工作,并且睡眠时间需要适应窗口系统的速度。

尽管我不建议针对问题中暴露的问题采用此解决方案,但我决定在答案中引入该解决方案以保证抖动完整性。其他人可能会发现将此方法应用于其他目的很有用:

#!/bin/bash

function set-title(){
    sleep 0.2
    
    # local WINDOW_ID=`xdotool getactivewindow`
    # local P_ID=`xdotool getactivewindow getwindowpid`
    # echo "the window id is: $WINDOW_ID with PID: $P_ID"

    xdotool type "set-title $@"
    xdotool key KP_Enter
    sleep 0.2
}


gnome-terminal -- /bin/bash -c "echo Hello from terminal 1;echo $-; exec /bin/bash";
# xdotool search --onlyvisible --class 'gnome-terminal'
set-title "Terminal 1"


gnome-terminal -- /bin/bash -c "echo Hello from terminal 2; exec /bin/bash";
# xdotool search --onlyvisible --class 'gnome-terminal'
set-title "Terminal 2"

在这种情况下,该函数set-title包含在~/.bashrc文件将起作用,因为在 中执行命令后gnome-terminal,最后一条指令是/bin/bash.它再次加载 shell,并使用 转发下一个命令到终端xdotool,这会创建与人类使用输入设备(鼠标、键盘等)生成的事件相同的事件。

相关内容