Linux shell 简介

一、简介

Linux shell 是 Linux 操作系统中的命令行界面,也称为 shell 终端。它是用户与操作系统进行交互的一种方式,可以通过输入命令来控制系统的行为。Linux shell 提供了一个强大的命令行环境,可以让用户使用各种工具和命令来完成系统管理、软件开发、网络管理等任务。

Linux shell 是基于文本的界面,用户输入的命令都是文本形式的,而系统输出的结果也是文本形式的。Linux shell 支持自动补全、命令历史、命令别名等功能,可以提高用户的工作效率。

Linux shell 有许多不同的实现,其中最常见的是 Bash(Bourne-Again SHell)。Bash 是 Linux 系统默认的 shell,它是一种功能强大的 shell,具有丰富的功能和语法。除了 Bash,还有其他的 shell 实现,如 Korn shell(ksh)、C shell(csh)、Z shell(zsh)等,它们各自具有不同的特点和用途。

Bash 是 Linux 系统默认的 shell:

[root@localhost strace]# ps
  PID TTY          TIME CMD
10882 pts/2    00:00:00 ps
23950 pts/2    00:00:00 bash

Linux shell 可以执行许多不同的任务,包括但不限于:

文件和目录操作:Linux shell 提供了各种命令来管理文件和目录,如 ls、cd、cp、mv、rm 等。

系统管理:Linux shell 可以用于管理系统,如设置环境变量、管理用户和组、安装和卸载软件包、管理服务等。

网络管理:Linux shell 可以连接网络、配置网络设置、管理网络协议和服务等。

脚本编程:Linux shell 具有编写脚本的能力,可以编写 shell 脚本来自动化任务、批处理操作等。

二、shell 执行命令的过程

2.1 简介

Linux shell运行命令的过程包括内置命令和外部命令,其完整过程如下:

(1)用户在终端中输入命令。

(2)Shell解释器接收到用户输入的命令,并将其解析成命令名和参数。

(3)Shell解释器检查是否有内置命令。如果命令是内置命令,则Shell解释器直接执行它,不需要创建新的进程。否则,它将查找外部命令。

// cd 是内置命令
# type cd
cd 是 shell 内嵌

// ls 是外部命令
# type -a ls
ls 是 `ls --color=auto' 的别名
ls 是 /usr/bin/ls

(4)如果命令是内置命令,则Shell解释器执行它。内置命令是由Shell解释器自己处理的命令,例如cd、echo和alias等命令。Shell解释器会调用内置命令的函数来执行该命令。

(5)如果命令是外部命令,则Shell解释器查找命令路径。它会在系统的PATH环境变量指定的目录中查找命令可执行文件。

(6)Shell解释器创建新的进程。它使用fork()系统调用创建一个新的进程,该进程将执行用户输入的命令。

(7)Shell解释器将命令参数传递给新进程。它使用exec()系统调用将用户输入的命令及其参数传递给新进程。

(8)新进程执行用户输入的命令。它将命令及其参数解释为操作系统可以理解的指令,并执行这些指令。

(9)新进程将执行结果返回给Shell解释器。如果命令执行成功,新进程将返回0;否则,它将返回一个非零值。Shell解释器接收到返回值后,将其转换为适当的文本信息。

# ls

# echo $?
0

(10)Shell解释器显示执行结果。它将执行结果输出到终端上,以供用户查看。

(11)用户可以继续在终端中输入命令,重复以上步骤。

总的来说,Linux shell运行命令的过程是将用户输入的命令解析成操作系统可以理解的指令,并创建新进程来执行这些指令。如果命令是内置命令,则Shell解释器直接处理它,不需要创建新进程。执行结果通过新进程返回给Shell解释器,最终在终端上显示给用户。

2.2 Linux shell 执行外部命令过程

2.2.1 简介

在 Linux shell 中,执行外部命令的过程通常包括以下步骤:

(1)解析命令:Shell 会解析用户输入的命令,并将其转换为可执行的程序或脚本。

(2)创建子进程:Shell 会使用 fork() 系统调用创建一个子进程,该子进程是原进程的一个副本,包括代码、数据和堆栈等信息。

(3)执行命令:在子进程中,Shell 会使用 exec() 系统调用来执行命令。exec() 函数会将新的程序加载到进程空间中,并开始执行它。

(4)等待子进程结束:在原进程中,Shell 会使用 wait() 系统调用来等待子进程执行完毕并返回。

shell -> fork--> 子进程shell --> exec --> 可执行的程序或脚本

比如 ps -f :

# ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
root     23950 23932  0 16:49 pts/2    00:00:00 -bash
root     32411 23950  0 17:08 pts/2    00:00:00 ps -f

当前终端的shell解释器的 pid是 23950 ,执行 ps -f 后,调用 fork + exec 创建了一个子进程,其 pid 是 32411,父 pid 是 shell解释器的 pid 23950。

bash(23950) -> fork + exec -> ps -f(32411 )
# ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
root      1020 23950  0 17:11 pts/2    00:00:00 bash
root      1090  1020  0 17:11 pts/2    00:00:00 ps -f
root     23950 23932  0 16:49 pts/2    00:00:00 -bash
bash(23950 ) -> fork +exec -> bash(1020 ) -> fork + exec -> ps -f (1090)

下面以执行 ls 命令为例,详细说明执行过程:

[root@localhost ~]# which ls
alias ls='ls --color=auto'
        /usr/bin/ls

(1)解析命令:Shell 接收到用户输入的 ls 命令,会将其解析为可执行程序 /usr/bin/ls。

(2)创建子进程:Shell 使用 fork() 系统调用创建一个子进程shell。此时,子进程shell是原进程Shell的一个副本,包括命令解析后得到的可执行程序 /usr/bin/ls。

(3)执行命令:在子进程shell中,Shell 使用 exec() 系统调用来执行命令。具体来说,Shell 会调用 execv(“/usr/bin/ls”, args),其中 args 是一个指向字符串数组的指针,包含了 ls 命令的参数。

# strace ls -l
execve("/usr/bin/ls", ["ls", "-l"], 0x7ffdb93d0cc8 /* 33 vars */) = 0

(4)等待子进程结束:在原进程中,Shell 使用 wait() 系统调用等待子进程执行完毕并返回。在这个例子中,当 ls 命令执行完毕后,子进程会返回一个状态码,Shell 根据这个状态码来判断命令是否执行成功

因此,执行 ls 命令的过程是 fork() + exec()。Shell 会先创建一个子进程Shell,然后在子进程Shell中使用 exec() 系统调用来执行命令。

2.2.3 详细介绍

当用户在 Linux shell 中输入命令时,Shell 会调用 fork() 系统调用来创建一个新的子进程。子进程是原进程的一个副本,包括代码、数据和堆栈等信息。然后,Shell 在子进程中使用 exec() 系统调用来加载可执行程序或脚本,并开始执行它。exec() 函数会将新的程序加载到进程空间中,并替换当前进程的代码和数据等信息。因此,原进程的执行流程并不会被中断或改变,它会继续执行剩余的代码。

在执行命令期间,Shell 还会进行一些额外的操作,比如:

(1)解析命令行参数:Shell 会将用户输入的命令行参数解析为程序或脚本所需的参数,并将它们传递给 exec() 函数。

(2)管道操作:Shell 还支持管道操作,可以将一个命令的输出作为另一个命令的输入。例如,ls | grep file 命令会将 ls 命令的输出传递给 grep 命令进行过滤。

(3)重定向:Shell 还支持重定向操作,可以将命令的输入或输出重定向到文件或设备中。例如,ls > files.txt 命令会将 ls 命令的输出重定向到 files.txt 文件中。

在命令执行完毕后,Shell 还会使用 wait() 系统调用等待子进程执行完毕并返回。wait() 函数会阻塞当前进程,直到子进程结束,并返回子进程的退出状态码。Shell 根据这个状态码来判断命令是否执行成功,如果状态码为 0,则表示命令执行成功;否则,表示命令执行失败。

总之,Linux shell 执行命令的过程包括 fork() + exec() + wait(),Shell 会创建一个子进程来执行命令,并在命令执行完毕后等待子进程结束并返回状态码。同时,Shell 还支持一些额外的操作,如管道、重定向等。

三、/usr/bin/ 和 /bin/ 目录

3.1 简介

在Linux系统中,/bin和/usr/bin是两个常见的二进制文件目录,它们存储了许多系统命令和程序。下面分别介绍这两个目录:

/bin目录:/bin目录是一个重要的系统目录,它存储了一些最基本的系统命令和程序。这些命令和程序对于系统的正常运行非常重要,它们通常是在系统启动时被广泛使用的。例如,/bin目录中存储了cat、ls、cp、rm、mv、mkdir、rmdir、echo、bash等命令。/bin目录通常包含了系统启动过程中必须的程序,因为在启动过程中,/bin目录中的程序是最早被加载的。

/usr/bin目录:/usr/bin目录是一个常见的二进制文件目录,它存储了许多Linux系统命令和程序。这些命令和程序通常是由Linux发行版提供的,它们可以扩展系统的功能和性能,但不是系统启动所必需的。例如,/usr/bin目录中存储了gcc、vim、python、perl、ssh、git等命令。/usr/bin目录通常包含了一些较高级别的应用程序和工具,这些应用程序和工具可以扩展系统的功能和性能。

值得注意的是,/bin和/usr/bin目录中的程序都是二进制文件,它们通常是可执行文件,可以通过在终端中输入相应的命令来调用它们。这些命令和程序是Linux系统中的核心组件之一,它们非常重要,因为它们提供了许多系统功能和服务。

3.2 区别

3.2.1 简单区分

在Linux系统中,/bin和/usr/bin目录是两个不同的目录,它们之间有以下区别:

(1)/bin目录存储了一些最基本的系统命令和程序,例如cat、ls、cp、rm、mv、mkdir、rmdir、echo和bash等命令。这些命令对于系统的正常运行非常重要,因为它们在系统启动过程中被广泛使用。

(2)/usr/bin目录存储了更多的Linux系统命令和程序,例如gcc、vim、python、perl、ssh和git等命令。这些命令通常是由Linux发行版提供的,它们可以扩展系统的功能和性能,但不是系统启动所必需的。

(3)/bin目录通常被认为是系统的一部分,而/usr/bin目录通常被认为是用户安装的软件的一部分。这是因为/bin目录中的命令和程序是在系统安装时就已经存在的,而/usr/bin目录中的命令和程序是在系统安装后由用户安装的。

(4)在一些较小的Linux发行版中,/usr/bin目录可能被合并到/bin目录中,以减小系统的大小。但是,在大多数Linux发行版中,这两个目录是分开的。

总的来说,/bin目录和/usr/bin目录是用于存储Linux系统命令和程序的两个不同的目录。/bin目录中存储了最基本的系统命令和程序,而/usr/bin目录中存储了更多的Linux系统命令和程序,它们通常是由用户安装的软件的一部分。

3.2.2 详细区分

这两个目录的主要区别如下:

(1)存储位置:/bin目录存储在根目录下,而/usr/bin目录存储在/usr目录下。

(2)包含内容:/bin目录中包含了一些最基本的系统命令和程序,这些命令对于系统的正常运行非常重要,例如cat、ls、cp、rm、mv、mkdir、rmdir、echo和bash等命令。而/usr/bin目录中包含了更多的Linux系统命令和程序,这些命令通常是由Linux发行版提供的,例如gcc、vim、python、perl、ssh和git等命令。/usr/bin目录中的命令和程序通常是由用户安装的软件的一部分,可以扩展系统的功能和性能。

(3)系统启动:/bin目录中的命令和程序是在系统启动过程中被广泛使用的,因为在启动过程中,/bin目录中的程序是最早被加载的。而/usr/bin目录中的命令和程序通常不是系统启动所必需的。

(4)权限:/bin目录和/usr/bin目录中的命令和程序的权限可能不同。在某些系统中,/bin目录中的命令和程序可能具有root所有权和root执行权限,而/usr/bin目录中的命令和程序可能具有其他所有权和权限。

(5)系统可引导性:/bin目录中的程序是在系统可引导性期间使用的,因为在启动时需要加载一些程序来建立基本的环境。这些程序必须位于根文件系统的根目录中,这也是/bin目录存在的原因。而/usr/bin目录中的程序通常是在系统引导完成后使用的。

(6)文件系统:/bin目录通常存储在根文件系统中,而/usr/bin目录通常是一个单独的文件系统。这意味着,/usr/bin目录可以独立于根文件系统进行升级和维护,这有助于提高系统的可靠性和稳定性。

(7)软件包管理:在大多数Linux发行版中,/bin目录中的程序是由系统软件包管理器进行管理的,而/usr/bin目录中的程序通常是由第三方软件包管理器或手动安装的。这是因为,/bin目录中的程序是系统所必需的组件,需要受到严格控制和管理。

(8)系统升级:在进行系统升级时,/bin目录中的程序通常被认为是系统必需的核心组件,因此会受到更严格的控制和管理。而/usr/bin目录中的程序通常不是系统所必需的组件,因此可以更容易地进行升级和更改。

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值