bash启动介绍

概述

0号/1号和2号进程

1
2
3
UID        PID  PPID  C STIME TTY      TIME     CMD
root 1 0 0 Aug08 ? 00:00:02 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
root 2 0 0 Aug08 ? 00:00:00 [kthreadd]

系统启动后,当用户登录到系统时,系统将启动一个用户态的shell进程。在shell进程中运行shell脚本程序时,系统将创建一个子shell,此时系统中将有两个shell,一个是登录时系统启动的shell,另一个是系统为运行脚本程序创建的shell。脚本执行运行完后,子shell将终止,并返回到执行脚本之前的shell。

tty终端的shell进程如下:

tty_shell

通过ssh连接到系统的shell进程如下:

1
2
3
4
5
6
7
8
9
10
[root@localhost ~]# echo $$
7338
[root@localhost ~]# ps -ef |grep -i 7338
root 7338 7331 0 03:48 pts/0 00:00:00 -bash
[root@localhost ~]# ps -ef |grep -i 7331
root 7331 3329 0 03:48 ? 00:00:12 sshd: root@pts/0,pts/1
root 7338 7331 0 03:48 pts/0 00:00:00 -bash
root 7344 7331 0 03:48 pts/1 00:00:00 -bash
[root@localhost ~]# ps -ef |grep -i 3329
root 3329 1 0 Aug08 ? 00:00:00 /usr/sbin/sshd -D

shell分类

交互式shell与非交互式shell

区分方法

  1. 可以通过打印“$-”变量的值(代表着当前shell的选项标志),查看其中的“i”选项(表示interactive shell)来区分交互式与非交互式shell。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    [root@localhost ~]# echo $$
    31991
    [root@localhost ~]# cat test.sh
    echo $-
    case "$-" in
    *i*) echo This shell is interactive;;
    *) echo This shell is not interactive;;
    esac

    [root@localhost ~]# bash test.sh
    hB
    This shell is not interactive
    [root@localhost ~]# echo $$
    31991
    [root@localhost ~]# bash -i test.sh
    himB
    This shell is interactive
    [root@localhost ~]# echo $$
    31991
  2. 通过检查$PS1的内容是否为空判断,在非交互式shell中不会设置该变量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    [root@localhost ~]# echo $$
    31991
    [root@localhost ~]# cat test.sh
    echo $-
    if [[ -z "$PS1" ]];then
    echo This shell is not interactive
    else
    echo This shell is interactive
    fi
    [root@localhost ~]# bash test.sh
    hB
    This shell is not interactive
    [root@localhost ~]# echo $$
    31991
    [root@localhost ~]# bash -i test.sh
    himB
    This shell is interactive
    [root@localhost ~]# echo $$
    31991
    [root@localhost ~]# echo $-
    himBH

himBH解释

交互式shell

顾名思义,shell等待用户输入,输入后系统立即执行并返回结果,并等待一下此输入。当退出后,shell也终止了。

启动交互式shell的方法

  • 启动shell时不带任何选项参数

  • 启动shell时指定-i选项参数

  • 启动shell时指定了-s且没有指定-c参数

非交互式shell

通常情况下,执行shell脚本文件时的子shell都是属于非交互式的。在这种场景下,shell读取存放在脚本文件中的内容然后执行,直到读到文件的结尾EOF,shell终止。

登录shell与非登录shell

登录式shell

需要用户名和密码登录后才能进入的shell,或者通过–login选项打开的shell。

非登录式shell

不需要输入用户名和密码即可打开的Shell,例如:直接命令“bash”就是打开一个新的非登录shell,在Gnome或KDE中打开一个“终端”(terminal)窗口程序也是一个非登录shell。

执行exit命令,退出一个shell(登录或非登录shell);执行logout命令,退出登录shell(不能退出非登录shell)

1
2
3
4
5
6
7
8
9
10
11
12
[root@localhost ~]# echo $$
2532
[root@localhost ~]# bash
[root@localhost ~]# echo $$
2709
[root@localhost ~]# logout
bash: logout: not login shell: use 'exit'
[root@localhost ~]# exit
exit
[root@localhost ~]# exit
logout
连接断开

bash是 login shell 时,其进程名为"-bash" 而不是"bash"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@localhost ~]# echo $$
2995
[root@localhost ~]# ps -ef |grep -i bash
root 2995 2985 0 08:55 pts/0 00:00:00 -bash
root 3001 2985 0 08:55 pts/1 00:00:00 -bash
[root@localhost ~]# bash
[root@localhost ~]# echo $$
3689
[root@localhost ~]# ps -ef |grep -i bash
root 2995 2985 0 08:55 pts/0 00:00:00 -bash
root 3001 2985 0 08:55 pts/1 00:00:00 -bash
root 3689 2995 0 08:56 pts/0 00:00:00 bash
[root@localhost ~]# exit
exit
[root@localhost ~]# echo $$
2995

shell分类组合情况

登录式 非登录式
交互式 1.登录系统时获得的顶层shell,无论是通过本地终端登录,还是通过网络ssh登录
2.使用bash –login命令启动的shell
3.使用su [-/-l/–login] [user]切换到其他用户时
1.使用bash命令启动的shell
2.使用su [user]切换到其他用户时
非交互式 在脚本中使用–login选项调用bash(比如在脚本第一行做如下指定:#!/bin/bash –login) 通常情况下执行bash脚本时运行脚本的子shell

bash启动时执行的启动文件

登录式 非登录式
交互式 如果/etc/profile存在,则首先执行该文件
依次查找存在并可读的~/.bash_profile, ~/.bash_login, ~/.profile中的第一个执行
如果启动时指定了--noprofile选项,则不执行上述两个步骤
退出时,如果~/.bash_logout存在则执行
如果~/.bashrc存在则执行
如果指定了--norc参数则不执行上述步骤
可以通过指定--rcfile file指定其他文件替代~/.bashrc
非交互式 同上 查找环境变量BASH_ENV,读取并执行BASH_ENV指向的文件中的内容

shell启动选项参数

-i 选项

强制子shell使用交互式方式运行

-c cmd_string 选项

表示子shell从字符串中读入命令,如果字符串后还有变量就被设定为从$0开始的位置参数

1
2
3
4
[root@localhost ~]# /bin/bash -c 'echo hello world'
hello world
[root@localhost ~]# /bin/bash -c 'echo $0 $1' hello kitty
hello kitty

ssh执行远程命令和bash -c string的用法

-s 选项

如果指定-s参数,那么表示子shell从标准输入中读入命令,直到输入exit。 该参数允许指定位置参数并将其传入子shell中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[root@localhost ~]# echo $$
9051
# 进入子shell中,未指定-c参数时,子shell为交互式shell
[root@localhost ~]# bash -s hello new world
[root@localhost ~]# echo $$
11211
[root@localhost ~]# echo $-
himBHs
[root@localhost ~]# echo $1
hello
[root@localhost ~]# echo $2
new
[root@localhost ~]# echo $3
world
[root@localhost ~]# exit
exit
# 退回父shell
[root@localhost ~]# echo $$
9051
# 如果指定-c参数,子shell为非交互式shell
[root@localhost ~]# bash -s -c 'echo $0' hello
hello
[root@localhost ~]# echo $$
9051
[root@localhost ~]# bash -s -c 'echo $-'
hBcs
[root@localhost ~]# echo $$
9051