我想我了解交互式,登录和批处理Shell之间的区别。请参阅以下链接以获取更多帮助:



'Login'和'Interactive'bash shell有什么区别(来自其他站点:serverfault.com)

2.1:外壳类型:交互外壳和登录外壳(从Z-Shell用户指南开始)

我的问题是,如何使用命令/条件进行测试如果我是在交互式,登录名或批处理shell中?

我正在寻找命令或条件(返回truefalse),并且也可以在if语句上放置。例如:

if [[ condition ]]
   echo "This is a login shell"
fi


评论

还有另一个问题:STDIN和/或STDOUT是否连接到tty(终端)或管道(文件或进程)?这是一个相关但截然不同的测试,如以下一些评论所述。

#1 楼

我假设使用bash外壳或类似的外壳,因为标签中没有列出外壳。

要检查您是否在交互式外壳中: />
要检查您是否在登录外壳中:

[[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'


通过“批处理”,我假设您的意思是“非交互式”,因此检查交互式外壳就足够了。

评论


对于zsh用户,可以使用以下命令检查登录shell:if [[-o login]] ...

–chb
2013年6月27日5:05



如果您想知道“用户”相对于“ cron”是否运行了程序。 [[TERM ==“ dumb”]] && echo“在cron中运行。

– Erik Aronesty
2013年12月3日17:49



@ErikAronesty并非所有的哑终端都是cron会话。

–克里斯唐(Chris Down)
13年12月4日在22:11

同样对于zsh用户,要检查交互式会话:[[-o交互式]]

–弗兰克·特贝克(Frank Terbeck)
15年8月10日在16:50

“我假设是bash shell或类似的东西,因为标签中没有列出shell。” –此声明的逻辑确实很漂亮! :)

–MichaëlLe Barbier
15年12月14日在8:44

#2 楼

在任何Bourne风格的外壳程序中,i选项都表明该外壳程序是否是交互式的:

case $- in
  *i*) echo "This shell is interactive";;
  *) echo "This is a script";;
esac


没有可移植且完全可靠的方法来测试登录外壳程序。 Ksh和zsh将l添加到$-中。 Bash设置了login_shell选项,您可以使用shopt -q login_shell进行查询。可移植地,测试-是否以-开头:外壳程序通常知道它们是登录外壳程序,因为调用者在参数0(通常是可执行文件的名称或路径)上添加了ash -l前缀。这无法检测到特定于Shell的调用登录Shell的方式(例如q4312079q)。

评论


(...),因为呼叫者–我认为此片段中缺少某些内容。

–彼得·多布罗格斯特(Piotr Dobrogost)
15年7月20日在12:22



如果$ 0始终以-开头,则不管它如何开始,这都是理想的。但是至少有一个例外:对于bash,这并不总是正确的,即使它应该是登录shell。在您的框中尝试一下:调用bash --login,然后$ 0仍读取bash。

– irawan Purwanto
15-10-16在20:35

@WirawanPurwanto我不确定我是否理解您的评论。那不是我在最后一句话中写的吗?

–吉尔斯'所以-不再是邪恶的'
15年10月18日在19:19

@吉尔斯:你是对的。对不起,我错过了你的最后一句话。

– irawan Purwanto
15年10月20日在17:58

#3 楼

鱼壳

这是fish的答案,以防其他用户偶然发现此页面。

if status --is-interactive
    # ...
end

if status --is-login
    # ...
end

echo "darn, I really wanted to have to use globs or at least a case statement"


鱼类文档:初始化

评论


-1用于不必要的编辑。

–尼克·巴斯汀(Nick Bastin)
15年8月20日在17:22

如果有人对@NickBastin的评论感到惊讶,他的观点很合理,所以我进行了编辑。原来的贪睡已经减少了一半。

–哎呀
2015年8月21日,下午3:56

#4 楼

csh / tcsh

对于cshtcsh我在.cshrc文件中具有以下内容:

if($?prompt) then               # Only interactive shells set $prompt
    ...
endif


专门针对tcsh,设置了变量loginsh对于登录Shell:

if($?loginsh) then              # A login shell..
    ...
endif


tcsh还有一个变量shlvl,该变量设置为嵌套shell的数量,其中登录shell的值为1。)

评论


PS1无法测试交互式外壳。它几乎总是以交互方式设置,但是您可以取消设置。通常将其设置在非交互式外壳中,因为许多系统在/ etc / profile中附带了导出PS。

–吉尔斯'所以-不再是邪恶的'
2011-12-14 11:35

@Gilles感谢您的纠正和编辑

–安德鲁·斯坦(Andrew Stein)
2011-12-14 15:26

这就是Gold:tcsh也有一个变量shlvl,它设置为嵌套shell的数量,其中登录shell的值为1。

– Israr
19-10-28在23:01



#5 楼

另一种方法是检查tty的结果

if [ "`tty`" != "not a tty" ]; then


评论


...或使用[-t 0]测试STDIN是否为tty。您还可以根据需要使用1(STDOUT)或2(STDERR)。

–德罗伯特
2011-12-13 23:17



@derobert-感谢您向我展示一些新东西

– Adrian Cornish
2011年12月14日,下午3:12

这是一个不同的测试。可能有一个非交互式外壳,其输入是终端(无论何时在终端中运行脚本!),也有可能(尽管很少)有一个交互式外壳而不是从终端接收输入。

–吉尔斯'所以-不再是邪恶的'
2011-12-14 11:34

@Gilles,如果外壳是交互式的,并且关闭了,让一个孩子消失了,还活着,那么tty最好知道它不再是交互式的,而$-并没有改变;我仍然对最佳方法感到困惑。

–水瓶座力量
2014年7月25日下午6:14

@AquariusPower然后,您要测试的不是交互式外壳,而是标准输入是否为终端。使用[-t 0]。附言在我之前的评论中,我写道“存在很强的相关性”-我忘记了“除了以#!/ bin / sh之类的脚本开头的极其常见的情况”,该脚本是非交互式的,但可以连接到一个终端。

–吉尔斯'所以-不再是邪恶的'
2014年7月25日7:55



#6 楼

UNIX / Linux有一个命令来检查您是否在终端上。

if tty -s
then
echo Terminal
else
echo Not on a terminal
fi


评论


这在破折号中也有效。

–肯·夏普
17年11月30日在12:27

#7 楼

您可以检查stdin是否为终端:

if [ -t 0 ]
then
    echo "Hit enter"
    read ans
fi


#8 楼

适用于Zsh
 # Checking Interactive v.s. Non-Interactive
[[ -o interactive ]] && echo "Interactive" || echo "Non-Interactive"
#
# Checking Login v.s. Non-Login
[[ -o login ]] && echo "Login" || echo "Non-Login"
 

参考:2.1.1:什么是登录shell?简单测试

#9 楼

i不是要查找的正确选项。 -i将强制否则为非交互式的shell进行交互。正确的自动启用的
选项是-s,但遗憾的是Bash无法正确处理。

您需要检查$-是否包含s(这被授予为
auto-已激活)或它是否包含i(这不是授予
自动激活的权限,而是正式地仅与-i命令行

评论


如果外壳程序从stdin读取命令,则不是,而不是它是否是交互式的。交互式外壳程序不一定从stdin读取命令(尝试zsh -i
–StéphaneChazelas
15年8月18日在13:59

我想指出的是,即使是旨在进行交互的,原始的Bourne Shell也没有在$-中包含“ i”。

–schily
15年8月18日在14:07

可以,但是在U&L上,“外壳”往往是指现代外壳。 Bourne shell通常被认为是一种传统,并且您自己的变体还不够主流,无法期望人们知道您在说什么,除非您明确指出。提到的问题[[]]暗示ksh / bash / zsh。作为历史记录,您有一点要说,在Bourne shell中检查$-中的i无效。但是然后检查s也不可靠。您还需要检查[-t 0]或i;即使那样,在回声'exec
–StéphaneChazelas
2015年8月18日14:24



最初的Bourne Shell附带Solaris直至Solaris 10,甚至包括门槛在内的窗台。自SVr4以来,shell中已知存在10个错误。因此,在Bourne Shell上添加提示并非如您所愿。另一端的zsh兼容性不足,例如当您尝试使用zsh运行“配置”时失败,因此请注意将/ bin / sh设置为指向zsh。顺便说一句:我的Bourne Shell在默认情况下设置-i以防万一,它决定是交互式的。

–schily
15年8月18日在14:30

我注意到POSIX似乎不需要$-包含i(它似乎需要s),我将在奥斯汀集团ML上提出这个问题。

–StéphaneChazelas
15年8月18日在15:09

#10 楼

要检查脚本是在交互式外壳程序中还是在非交互式外壳程序中运行,
我在脚本中检查是否存在存储在$PS1变量中的提示:

if [ -z $PS1 ] # no prompt?
### if [ -v PS1 ]   # On Bash 4.2+ ...
then
  # non-interactive
  ...
else
  # interactive
  ...
fi


这是我在这里学到的:https://www.tldp.org/LDP/abs/html/intandnonint.html

#11 楼

奇怪的是,在MacOS中从桌面启动的脚本与手工启动的脚本具有相同的环境。 (他们将标准输入作为电传打字机tty,未设置login_shell商店,将"$-"设置为ehxB
如果我将脚本带到桌面的首选方法是创建从~/Desktop到脚本的符号链接,我可以仅通过检查"q4312079q"是否为绝对路径(即以斜杠开头)来猜测它是通过单击启动的。