什么是交互式shell和非交互式shell?

交互式shell,指的是你可以输入命令并获得执行结果的shell。而非交互式shell,一般是执行一个命令、一个脚本的shell,它们通常不需要人工干预,例如系统维护脚本、后台脚本等。

本文基于Bash总结一下交互式shell的定义和与非交互式shell的区别。

交互式定义

交互式shell定义:

An interactive shell is one started without non-option arguments and without the -c option whose standard input and error are both connected to terminals (as
determined by isatty(3)), or one started with the -i option. PS1 is set and $- includes i if bash is interactive, allowing a shell script or a startup file to
test this state.

option和argument是什么?

上面这段英文定义里面有一个“non-option arguments”比较难理解。在Linux中,命令行使用空格分割为一个个的argument,例如:

以上图为例,命令执行时,在ls脚本的内部,可以使用$0来获取到ls这个字符串,同理,$1可以获取到-l,使用$2来获取到-a选项等等。“arguments”就是$0, $1, $2….等等以空格分割命令行后的每个部分。

-l-a这种可以改变ls命令的行为的,叫做选项(即option),它们一般会被写在命令使用文档中:

再回到交互式shell定义里面的non-option arguments,指的是不属于选项的参数

例如上述命令中,参数/path/to/folder既不是-l选项的值,也不是-a选项的值,它不属于任何一个option,所以它是一个non-option arguments

交互式shell定义总结

弄明白了non-option arguments的含义,再看交互式shell的定义就比较简单了,翻译如下:

交互式shell指的是没有【不属于任何选项的参数】也没有-c选项,并且标准输入流和错误流都连接到终端的shell,或者启动shell时有-i选项的shell。

如果一个shell是交互式shell,$PS1变量会被设置,且$-变量包含i字符,在shell脚本中可以使用这两个变量来判断当前shell是不是交互式shell。

非交互式shell

有了交互式shell的定义,反过来就是非交互式shell。

  • shell启动时有-c选项的是非交互式shell
  • 标准输入流和错误流没有连接到终端的shell,例如系统启动脚本、维护脚本,它们不需要交互。
  • 没有$PS1变量。
  • $-变量中不包含i字符。

验证一下

打开一个命令行窗口,打印$PS1变量:

1
2
[root@mail ~]# echo $PS1
[\u@\h \W]\$

有输出,说明当前shell是个交互式shell。再测试$-:

1
2
[root@mail ~]# echo $-
himBH

输出中包含字符i,也说明是个交互式shell。

使用bash命令的-c选项来执行上述命令:

1
2
3
4
[root@mail ~]# bash -c "echo \$PS1"

[root@mail ~]# bash -c "echo \$-"
hBc

$PS1没有任何输出,$-输出中也不包含字符i,都能说明执行echo命令的shell不是交互式shell。可以理解为,执行bash -c "echo \$-"命令的时候,实际上由当前shell启动了一个非交互式shell,然后让这个非交互式去执行echo $-命令。

最后,测试一下,启动shell时带有【不属于任务选项的参数】。

  1. 首先创建一个test.sh文件,写入以下内容:

    1
    2
    #! /bin/bash
    echo $-
  2. 调用bash来执行这个脚本:

    1
    2
    3
    4
    [root@mail ~]# bash test.sh 
    hB
    [root@mail ~]# bash -i test.sh
    himB

从结果中可以看出:

  • 使用-i选项时,是交互式shell,
  • 没有-i选项时,是非交互式shell。

有什么区别?

交互式shell和非交互式shell启动时会加载不同的环境配置文件,不同的配置文件会有不同的初始化脚本和环境变量。

参考:Linux Bash环境配置文件详解