如何检查 shell 是否是登录/交互式/批处理

Ame*_*ina 182 shell

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

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

我正在寻找一个命令或条件(返回truefalse),我也可以放在 if 语句中。例如:

if [[ condition ]]
   echo "This is a login shell"
fi
Run Code Online (Sandbox Code Playgroud)

Chr*_*own 216

我假设有一个bashshell 或类似的,因为标签中没有列出 shell。

要检查您是否在交互式 shell 中:

[[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'
Run Code Online (Sandbox Code Playgroud)

要检查您是否在登录 shell 中:

shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'
Run Code Online (Sandbox Code Playgroud)

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

  • 对于`zsh` 用户,可以通过以下方式检查登录shell:`if [[ -o login ]] ...` (20认同)
  • @ErikAronesty 并非所有哑终端都是 cron 会话。 (13认同)
  • “我假设是 bash shell 或类似的,因为标签中没有列出 shell。” ——这句话的逻辑真美!:) (4认同)
  • 同样对于 zsh 用户,检查交互式会话:[[ -o interactive ]] (3认同)
  • @HelloGoodbye `[[ $- == *i* ]]` 检查 `$-` (shell 参数)是否在任何地方包含 `i`。`echo *i*` 与它实际上没有太大关系。 (2认同)

Gil*_*il' 48

在任何 Bourne 风格的 shell 中,该i选项指示 shell 是否是交互式的:

case $- in
  *i*) echo "This shell is interactive";;
  *) echo "This is a script";;
esac
Run Code Online (Sandbox Code Playgroud)

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


ohs*_*ite 25

鱼壳

这是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"
Run Code Online (Sandbox Code Playgroud)

Fish 文档:初始化

  • 如果有人对@NickBastin 的评论感到疑惑,他的观点很合理,所以我进行了编辑。原来的尖酸刻薄现在减半了。 (12认同)
  • -1 用于不必要的编辑。 (5认同)

小智 21

csh / tcsh

对于cshtcsh我已经在我的以下.cshrc文件:

if($?prompt) then               # Only interactive shells set $prompt
    ...
endif
Run Code Online (Sandbox Code Playgroud)

专门为tcsh,该变量loginsh是为登录 shell 设置的:

if($?loginsh) then              # A login shell..
    ...
endif
Run Code Online (Sandbox Code Playgroud)

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

  • `PS1` 不能用于测试交互式 shell。它几乎总是在交互式中设置,但您可以取消设置。它通常设置在非交互式 shell 中,因为许多系统在 `/etc/profile` 中附带了 `export PS`。 (2认同)

Adr*_*ish 17

另一种方法是检查结果 tty

if [ "`tty`" != "not a tty" ]; then
Run Code Online (Sandbox Code Playgroud)

  • 这是一个不同的测试。可能有一个非交互式 shell,其输入是终端(任何时候您在终端中运行脚本!),并且有可能(尽管很少)有一个交互式 shell,而不是从终端接收输入。 (13认同)
  • ... 或者使用 `[ -t 0 ]` 来测试 STDIN 是否是一个 tty。您还可以根据需要使用 1 (STDOUT) 或 2 (STDERR)。 (12认同)
  • @AquariusPower 那么你要测试的不是交互式shell,而是标准输入是否是终端。使用`[ -t 0 ]`。PS 在我之前的评论中,我写道“有很强的相关性”——我忘记了“除了以`#!/bin/sh` 或类似开头的脚本的极其常见的情况之外”,这是非交互式的,但可以连接到终端。 (6认同)

小智 14

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

if tty -s
then
echo Terminal
else
echo Not on a terminal
fi
Run Code Online (Sandbox Code Playgroud)


Ang*_*elo 13

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

if [ -t 0 ]
then
    echo "Hit enter"
    read ans
fi
Run Code Online (Sandbox Code Playgroud)


小智 11

对于 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"
Run Code Online (Sandbox Code Playgroud)

参考:2.1.1:什么是登录外壳?简单的测试


sch*_*ily 5

i不是要寻找的正确选项。-i是强制非交互式 shell 变为交互式 shell。正确的自动启用选项是-s,但不幸的是 Bash 没有正确处理这个问题。

您需要检查是否$-包含s(这被授予自动激活)或是否包含i(这未被授予自动激活,但正式仅耦合到-ishell 的命令行选项)。

  • 我注意到 POSIX 似乎不需要 $- contains i (它似乎需要 s),我将提出关于 austin-group ML 的问题。 (3认同)
  • 我想指出的是,原始的 Bourne Shell 在 $- 中没有“i”,即使它旨在进行交互。 (2认同)