• 作者:老汪软件技巧
  • 发表时间:2024-09-13 11:01
  • 浏览量:

1.什么是 shell

熟悉 Mac OS 的程序员都应该对 shell 有一定的了解。

在工作中,我们经常会使用一些 shell 命令来进行一些文件操作,比如下面这个 shell 命令:

# 在当前目录下创建了一个 learn 文件夹
mkdir learn

shell 是和系统内核指令打交道的一座桥梁。我们通过键盘输入一种自己容易记忆识别的符号标识(shell命令),有 shell解析这些命令再反馈给内核去执行一系列操作。

2.shell类型

shell的类型分为很多种。不同的 shell 语法可能会有不同。

系统某些服务在运行过程中,会去检查用户能够使用的 shells,而这些 shells 的查询就是借助 /etc/shells 这个文件,使用 cat /etc/shells 命令查看当前系统支持哪些 SHELL脚本。

可以看见Mac系统支持了很多种shell类型的使用。

目前最常用的就是sh、 bash 和 zsh。接下来会重点说这 3 个。

常用的shell - sh

sh 是 shell 的缩写。

是 Unix/Linux 系统的默认 shell,也是最古老的 shell之一。

sh 是标准的 POSIX shell,有许多不同版本和实现,如 Bourne shell 和 POSIX shell。

常用的shell - bash

bash全称是Bourne Again shell ,目前被绝大多数 Linux 系统所使用。

它是对Bourne shell的重新实现。

那么为什么要费劲巴拉的重新写一遍这个呢?这不是在重复造轮子嘛!

因为Bourne shell是Unix系统的一部分,自由软件之父Richard Stallman在1983年开始发起了GNU运动,GNU运动的目标是实现一个免费自由的操作系统,以解决Unix系统收费的一些限制。

要做一个类似的 Unix 系统,理所当然的 Unix 上有的,都得自己重新实现一套,因为 Unix 上的东西都是有版权限制的,自然对于shell也是如此。

Unix上的Shell是Bourne shell,于是GNU也做了一个Shell,名称就是Bourne Again shell,简称Bash。

而Linux之父在1991年发布的Linux内核中,最开始只有两个程序,一个是GCC,另一个则是Bash了,它们都是GNU软件。

至于后面发展起来的Linux操作系统,我在以前的文章中也说过了,其实就是Linux内核 + GNU软件,所以Linux操作系统也叫GNU/Linux操作系统。

这就是为什么Linux发行版本中,大多使用的是Bash的原因了。

常用的shell - zsh

Zsh其实是对Bash的扩展,它基于Bash之上添加了很多新特性,它包括了Bash,Ksh以及tsch的一些特性的集合。

所以Zsh可以说是更好的Shell,但由于Linux上述讲述的历史原因,大多数Linux发行版本仍然是用的Bash。

3.苹果为什么要将默认的Shell从bash转成zsh

因为License限制。

其实在Catalina版本之前,MacOS一直使用的都是Bash。

但是由于Bash在版本3.2之后,将开源协议由GPLv2更换为了GPLv3。

GPLv3是GPLv2的改进版本,它解决了GPLv2的一些缺点与不足,其中一个重要的点就是,扩大了GPL强制传染力的约束。

也就是如果你的产品使用了GPLv3的类库或框架,你的产品不管是否包含独立可区分的部分,也一定也同样的按照GPLv3协议进行开源。(GPLv2时,使用了GPLv2的产品,如果包含可区分的独立部分,非全部派生自开源软件,则可以不受GPL传染力约束)。

可想而知,这不是Apple希望看到的结果,这也是苹果长久时间一直使用的Bash 3.2的原因所在。使用Bash 3.2的MacOS仍然可以不用开源,但如果使用GPLv3的话,则MacOS也一定得开源了。

但是如果一直使用一个相当陈旧的Bash版本,对MacOS操作系统并不是一个合适的选择,于是Apple在MacOS Catalina后,选择了将Shell迁移至开源协议更友好的Zsh。

而Zsh使用的是MIT开源协议,MIT完全不限制商业使用,所以在Catalina版本之后,苹果就采用了Zsh作为默认的Shell。

4.如何查看当前终端所使用的Shell版本

_Mac程序员需要知道的Shell相关知识_Mac程序员需要知道的Shell相关知识

可以直接用内置的echo命令来进行打印。

echo $SHELL

5.如何切换shell

上节课我们学习了如果查询当前终端使用的shell版本。

那么我们是否可以切换shell呢?当然也是可以的。

# 改变默认的 shell 为 bash
chsh -s /bin/bash

通过 chsh -s 可切换为其他已安装的 shell。 更改后需重启终端,以使命令生效。

6.shell的两种运行模式登陆模式(login模式)

用户输入登录系统时 / 使用SSH与系统获得连接时启动的第一个 shell 称为登录 shell。在这个过程中,用户需要提供用户名和密码。

login shell 会读取系统配置文件 ( /etc/profile) 来设置系统的整体环境,同时也会读取用户个人的配置文件( ~/.bash_profile 或 ~/.bash_login)来设置用户个人的环境。

获取 shell 时需要完整登入流程的,从tty1~6终端登入系统输入账号密码,就是 login shell。

非登录模式(non-login模式)

用户登录后启动的shell。non-login shell 可直接从 login shell 中继承环境和配置,主要用于执行用户在桌面环境下的交互式任务,如打开终端、编辑文件等。这些不需要输入账号密码。

无需重复登入流程的,比如在系统内部启动 tty1~6,不用输入账号密码,就为 non-login shell。

总结

简单来说,登录 shell 更像是用户进入系统时的入口点,它负责加载用户的环境配置,而非登录 shell 则更像是在现有环境中执行临时任务或脚本的工具。如果你使用终端模拟器打开一个新的标签页或窗口,那么你得到的是一个非登录 shell。而如果你通过 SSH 连接到远程主机,并且该连接是作为登录会话开始的,则你会得到一个登录 shell。

7. #!/bin/sh究竟是干嘛用的

你经常可以看到在一个Shell脚本中的最上面写了这样一行代码。

#!/bin/sh
echo "这是一个SHELL脚本,我用的是/bin/sh"

这一行代码告诉系统使用哪个解释器来执行脚本。在这个例子中,/bin/sh 指定了使用 Bourne shell来解释脚本。

通常情况下,我们都是使用/bin/sh,因为它是所有系统中都基本是存在的。而/bin/zsh这样的,不一定会存在。

8. 如何新建一个shell脚本

#!/bin/sh
echo "我没有文件后缀,但是我依然是一个shell";

#!/bin/sh
echo "我文件后缀是sh,所以我是一个shell";

#!/bin/bash
echo "我文件后缀是bash,所以我是一个shell";

#!/bin/zsh
echo "我文件后缀是zsh,所以我是一个shell";

9. 如何执行一个shell脚本1. 工作目录执行

指的是执行脚本时,先进入到脚本所在的目录,然后使用 ./脚本方式执行。

这里会遇到权限错误。这里需要赋权。使用chmod 764 learn.sh赋权后就可以正常执行了

2. 绝对路径执行

绝对路径中执行,指的是直接从根目录/到脚本目录的绝对路径。

3. sh执行

sh执行,指的是用脚本对应的sh或bash来接着脚本执行。

4. shell环境执行

shell环境执行,指的是在当前的shell环境中执行,可以使用 source 接脚本。