在bash脚本(.bashrc等)中检测X会话


16

最近我放到xset b off了我的.bashrc。现在,当我通过tty或ssh登录(即在X会话外部)登录时弹出的错误让我很烦。

我想到的第一件事是[[ -z "$SOME_VAR" ]] && xset b off(嗯,事实证明,设置测试变量与清空测试变量是一个不同的问题)。但是哪个SOME_VAR是正确的呢?

因此,我将tty的set输出和urxvt的set输出进行了比较,以查看X中设置了哪些变量而tty中缺少了哪些变量。如预期的那样,存在很多差异(仅列出那些与我相关的差异):

  • DESKTOP_SESSION
  • DISPLAY
  • GDMSESSION
  • SESSION_MANAGER
  • WINDOWID
  • WINDOWPATH
  • XAUTHORITY
  • XDG_SESSION_COOKIE
  • XDG_CONFIG_DIRS
  • XDG_DATA_DIRS
  • XDG_MENU_PREFIX

为了检测我是否在X会话中,哪个是最正确,最通用的测试?可以在尽可能多的发行版,平台和桌面环境中工作的东西吗?

还是有比测试环境变量更好的方法?

Answers:


8

一种简单有效的测试显示服务器是否可用且有效的方法是使用进行测试xhost。您不能总是依靠检查DISPLAY变量中的值,因为它可能设置为无效值。

if xhost >& /dev/null ; then echo "Display exists"
else echo "Display invalid" ; fi

之所以这样做,是因为我在用户crontab中运行了多个脚本,这些脚本在存在时在显示器上进行操作,但在不存在时以不同的方式工作。在我的顶部crontab,我将DISPLAY变量设置为,:0即使它尚不存在。不管您是否有显示crontab,以开头的脚本@reboot都将启动。这将使您能够动态检测您的显示何时在同一脚本中来来去去。

注意:>&只能在bash> = 4中使用。否则请使用> /dev/null 2>&1


不错,还通过了测试ssh -X;工作良好!
Alois Mahdal

13

我认为检查DISPLAY是最好的方法。

  • 它处理远程登录(例如ssh -X)。
  • 它在大多数(如果不是全部)平台中都可用。
  • 它独立于窗口管理器/ DE。

2
我也愿意这样做DISPLAY,或者只是简单地抑制错误消息。/dev/null不时给予一些爱。
frostschutz

3
@frostschutz不,我正在尝试仅运行脚本的相关部分。禁止错误消息不会朝那个方向迈出任何一步。实际上,这可能会导致严重的混乱,对其他可能会破坏的事物进行故障排除。
Alois Mahdal

1
我在回答后不久就开始使用这种方法,并且ssh直到现在,当我开始ssh -X使用- 时,它都可以与简单的s 完美配合,以便能够在ssh上使用Vim,以便可视模式选择的内容可以到达本地X剪贴板,为此您不需要服务器端的xserver。因此,即使不存在xserver和xset,也将DISPLAY设置为仅启用转发的效果。
Alois Mahdal


1
您的DISPLAY变量可以指向实际上没有运行X服务器的显示(例如,在脚本中对其进行硬编码或在设置变量后关闭X服务器时)。
n.st

6

我通常使用TERM变量在脚本中测试X。

TERM通常linux在TTY和xtermX 上设置为。
我在这里使用“通常”一词,因为GNU Screen和TMux之类的应用程序似乎与TERMVariable 混为一谈。


尝试echo $TERM在不同的控制台中找到mashine上的richt设置。我[ $TERM == "linux" ] && echo do some stuff在Ubuntu上使用
rubo77'9

3

这应该工作得很好:

[ ! -t 0 ] && xset b off                                  

http://tldp.org/LDP/abs/html/fto.html

-t

    file (descriptor) is associated with a terminal device

    This test option may be used to check whether the stdin [ -t 0 ] 
    or stdout [ -t 1 ] in a given script is a terminal.

因此,当其结果为false([ ! -t 0 ])时,我们就处于GUI环境中。


这样,我在X和控制台中都得到了相同的结果,[ -t 0 ]并且[ -t 1 ]都成立。
伊曼纽尔·伯格

奇怪,当我将其放入远程主机时,它对我有用。
terdon

[ -t 0 ]在Ubuntu(使用CTRL ALT F1)的控制台上可以正常工作
rubo77'9

0

有很多方法可以做到这一点。

用bash尝试

function xruns {
    if [[ `pstree -As $$ | grep xinit | wc -l` == 1 ]]; then
        echo "You are in X."
    else
        echo "You are not in X."
    fi
}

或者,在zsh中,尝试

#!/usr/bin/zsh

CURRENT_VT=`tty`

if [[ ${CURRENT_VT[6]} == "p" ]];        # or `${CURRENT_VT:5:1}` in bash
then
   # X stuff
else 
   # non-X stuff      
fi

点了,但是您在发布之前测试代码吗?第一个有语法错误,实际上并不会检测到我们是否处于X会话中,因此echo 1如果X正在运行并且您通过tty1-6或ssh登录,它将第一个出现。另一个总是执行“非X的东西”-我认为这${CURRENT_VT[6]}意味着第6行而不是第6个字符。
Alois Mahdal

@AloisMahdal:啊哈,我的东西在bash中不起作用(我使用zsh)。没想到。好吧,您可以在zsh(类型zsh)中尝试使用它,如果愿意,可以进行一些修改,使其在bash中运行。
伊曼纽尔·伯格

@AloisMahdal:好的,我更改了它。至于“通过tty1-6登录”,这就是我要做的,然后使用第二种解决方案(上面)并设置一个变量。看看 .zshrc和搜索export VT。我使用变量保存我所在的Linux VT / console / tty(对于zsh提示符),但是在X中,我只是将其设置为“ X”(尽管不是VT)。但这很详细,您可以使用相同的原理在bash中以任何方式解决。
伊曼纽尔·伯格

我在第二个示例中添加了bash版本的条件。但是,我认为第一个仍然是错误的。也许只有ps打印祖先会有所帮助。不过,我不确定是否可行。
Alois Mahdal

@AloisMahdal:签出编辑。包括tty在内,对我来说就是这样。
伊曼纽尔·伯格

0

if [[ $DISPLAY ]]

在同一台计算机上,$DISPLAY例如将0:0在终端仿真器中返回,但在实际终端中什么也不会返回。可以使用CtrlAltF1vs 轻松测试CtrlAltF7

bash基于的条件$DISPLAY如下所示:

if [[ $DISPLAY ]]; then 
  
fi
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.