Answers:
从man bash
下条件表达式:
-t fd
True if file descriptor fd is open and refers to a terminal.
假设fd 1是标准配置,if [ -t 1 ]; then
应该为您工作。《高级Shell脚本指南》声称-t
使用这种方式将进行故障转移ssh
,因此测试(使用stdin而非stdout)应为:
if [[ -t 0 || -p /dev/stdin ]]
-p
测试文件是否存在并且是命名管道。 但是,我会从经验上注意到这对我来说是不正确的:-p /dev/stdin
对于普通终端和ssh会话均失败,而if [ -t 0 ]
(或-t 1
)在两种情况下均有效(另请参见下面关于高级Shell脚本指南那部分内容的Gilles评论)。
如果主要问题是特定的上下文,您希望从中调用脚本以适合该上下文的方式运行,则可以回避所有这些技术知识,并使用包装器和自定义变量为自己省事:
!#/bin/bash
export SPECIAL_CONTEXT=1
/path/to/real/script.sh
调用此名称live_script.sh
或其他名称,然后双击该名称。您当然可以使用命令行参数完成相同的操作,但是仍然需要使用包装器来指向并单击GUI文件浏览器。
||
中[ … ]
这样呢?如果使用,[[ … ]]
则可以,但是通常||
使用来分隔命令,并且由于缺少最后[ -t 0
一个,因此是不正确的调用。通常也没有命令。我同意测试终端;那可能就是这样做的方式。这只是我所关心的语法。[
]
-p
||
在所需的最终]
参数之前出现[
。
PS1
判断外壳是否交互式的可靠测试。“如果脚本需要测试它是否在交互式外壳中运行”也令人困惑:应该是某些代码是否需要测试—脚本通常不在交互式外壳中运行(但可以,如果是源代码则可以) 。测试i
in $-
是测试外壳是否交互式的正确方法。测试-t 0
或是-t 2
判断脚本是否在终端中运行的正确方法,这不同于交互方式。
尽管Goldilocks的回答在典型情况下可能是正确的,但似乎确实存在一些极端情况。在我自己的情况下,我的xserver配置为从其启动,tty1
并且从不离开该tty。如果Xorg stdout
是一个TTY,那么默认情况下,客户端似乎会将TTY链接到其文件描述符。
这是我解决问题的方法:
#!/bin/bash
isxclient=$( readlink /dev/fd/2 | grep -q 'tty' && [[ -n $DISPLAY ]] ; echo $? )
if [[ ! -t 2 || $isxclient == "0" ]]; then
notify-send "Script wasn't started from an interactive shell"
else
echo "Script was started from an interactive shell"
fi
我还没有测试它是否可以在更标准的X配置上工作,我也非常怀疑这是唯一的优势。如果有人找到更通用的解决方案,请回来告诉我们。
另一个,使用bash选项设置内部变量$-
。
来自.bashrc
,
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
cmd | sh -i | cmd
。