bash和sh的区别,以及执行脚本的几种方式

Shell 中文意思贝壳,寓意类似内核的壳。Shell是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。

Shell 脚本(shell script)是一种为 shell 编写的脚本程序。常说的shell通常都是指 shell 脚本,但shell和shell script是两个不同的概念。通常说“shell编程”都是指 shell 脚本编程,不是指开发 shell 自身。

sh(Bourne Shell)是一个早期的重要shell,1978年由史蒂夫·伯恩编写,并同Version 7 Unix一起发布。

bash(Bourne-Again Shell)是一个为GNU计划编写的Unix shell。1987年由布莱恩·福克斯创造。主要目标是与POSIX标准保持一致,同时兼顾对sh的兼容,是各种Linux发行版标准配置的Shell,在Linux系统上/bin/sh往往是指向/bin/bash的符号链接。

#!是一个特殊标记,说明这是一个可执行的脚本。除了第一行,其他以#开头的都不再生效,为注释。

#!后面是脚本的解释器程序路径。这个程序可以是shell,程序语言或者其他通用程序,常用的是bash、sh

sh 跟bash的区别,实际上是bash有没开启POSIX模式的区别。

 

cat /etc/shells 查看系统可使用的shell类型

sh

sh 的全称是 Bourne shell,由 AT&T 公司的 Steve Bourne开发,为了纪念他,就用他的名字命名了。

sh 是 UNIX 上的标准 shell,很多 UNIX 版本都配有 sh。sh 是第一个流行的 Shell。

csh

sh 之后另一个广为流传的 shell 是由柏克莱大学的 Bill Joy 设计的,这个 shell 的语法有点类似C语言,所以才得名为 C shell ,简称为 csh。

Bill Joy 是一个风云人物,他创立了 BSD 操作系统,开发了 vi 编辑器,还是 Sun 公司的创始人之一。

BSD 是 UNIX 的一个重要分支,后人在此基础上发展出了很多现代的操作系统,最著名的有 FreeBSD、OpenBSD 和 NetBSD,就连 Mac OS X 在很大程度上也基于BSD。

tcsh

tcsh 是 csh 的增强版,加入了命令补全功能,提供了更加强大的语法支持。

ash

一个简单的轻量级的 Shell,占用资源少,适合运行于低内存环境,但是与下面讲到的 bash shell 完全兼容。

bash

由 GNU 组织开发,保持了对 sh shell 的兼容性,是各种 Linux 发行版默认配置的 shell。

在现代的 Linux 上,sh 已经被 bash 代替,/bin/sh往往是指向/bin/bash的符号链接。

shell运行的原理

当我们在Linux下输入:

ls -al 或者 cd ..

在解释原理之前,我们必须分清楚的是:我们在Linux输入的命令是有区别的,具体来说,分为内部命令(built-in)以及外部命令,向ls,cat,mkdir这些都属于外部命令,而echo,cd,pwd这些都属于内置命令,如何区分这些命令是否是内置,外部命令,可以利用type命令来辨别

输入ls,cd这些内部或者外部的命令有什么区别?具体而言:

像cd,pwd这些内置命令是属于Shell的一部分,当Shell一运行起来就随Shell加载入内存,因此,当我们在命令行上输入这些命令就可以像调用函数一样直接使用,效率非常高。

而如ls,cat这些外部命令却不是如此,当我们在命令行输入cat,当前的Shell会fork一个子进程,然后调用exec载入这个命令的可执行文件,比如bin/cat,因此效率上稍微低了点。

理解了单个命令的运行原理,我们现在探究当编写一个Shell脚本运行的原理,首先需要的说明的是,Shell,和Python一样,都是一门解释性语言,所谓的解释性语言就是不用编译,执行一行解释一行。

在Linux命令输入./ test.sh时(需要加可执行权限)时,我们在这个文本文件开头指定了bash为默认的解释器,因此当前的交互式Shell会fork一个子进程,用bash解释器的代码去替换(也就是exec),而这个文本文件被当作是命令行参数传给这个子bash,等这个子bash执行完就会到我们的交互式bash了。

为了验证我们所说的交互式bash会fork/exec一个子bash来执行命令而非交互式bash,我们做个测试:

1.直接在交互式bash输入:

cd ..

2.编写脚本test.sh,然后运行:

//其中test.sh内容如下:
#!/bin/bash
cd ..
在Linux命令行输入 ./test.sh

我们发现同样都是cd ..,为什么执行完脚本当前bash目录不变,因为cd改变的是子shell的工作目录,而非当前shell的命令,这就证明了我们所说的是由子bash执行,而非交互式bash,那么如何交互式bash执行脚本呢,我们可以使用. 或者source命令,

source通知当前shell读入路径为filename的文件并依次执行文件中的所有语句。

通常用于重新执行刚修改的初始化文件,使之立即生效,而不必注销并重新登录。例如,当我们修改了/etc/profile文件,并想让它立刻生效,而不用重新登录,就可以使用source命令,如“source /etc/profile”。

source命令是bash shell的内置命令。而点命令(即“.”命令)则是source的另一名称。这两个命令都以一个脚本为参数该脚本将作为当前shell的环境执行,即不会启动一个新的子进程。所有在脚本中设置的变量将成为当前Shell的一部分

Shell脚本执行的四种方法

  • bash(或sh) [脚本的相对路径或绝对路径
  • source(或.) [脚本的相对路径或绝对路径].(点)是等同于source的,最常见的使用是在重新加载环境变量时。
  • sh < [脚本名称]或者cat [脚本名称] | sh(或bash)
  • 脚本的相对路径或绝对路径,使用该方法,脚本必须拥有执行权限 ./a.sh

方法比较

当shell脚本具有可执行权限时,用sh filename与./filename是没有区别的。./filename是因为当前目录没有在PATH中,所以"."是用来表示当前目录的。

sh filename会重新建立一个子shell,在子shell中执行脚本里面的语句,该子shell继承父shell的环境变量,但子shell是新建的,其改变的变量不会被带回父shell,除非使用export。

source filename读取脚本里面的语句依次在当前shell里面执行,没有建立新的子shell。那么脚本里面所有新建、改变变量的语句都会保存在当前shell里面。

方法举例

新建一个test.sh脚本,内容为:A=1;
修改其可执行权限:chmod +x test.sh;
运行sh test.sh后,echo $A,显示为空,因为A=1并未传回给当前shell;
运行./test.sh后,也是一样的效果;
运行source test.sh 或者 . test.sh,然后echo $A,则会显示1,说明A=1的变量在当前shell中;

Shell内置命令

Shell 命令分为外部命令和内置命令:

比较内置命令外部命名
定义Bash Shell 自带的命令Linux 系统中的应用程序
执行效率
执行过程调用当前 Shell 进程的一个函数触发磁盘 I/O,fork 出一个单独的进程,执行完成后退出

内建命令

定义

内建命令是由 Bash 自身提供的命令,而不是文件系统中的某个可执行文件

內建命令及说明

命令    说明
:    扩展参数列表,执行重定向操作
.    读取并执行指定文件中的命令(在当前 shell 环境中)
alias    为指定命令定义一个别名
bg    将作业以后台模式运行
bind    将键盘序列绑定到一个 readline 函数或宏
break    退出 for、while、select 或 until 循环
builtin    执行指定的 shell 内建命令
caller    返回活动子函数调用的上下文
cd    将当前目录切换为指定的目录
command    执行指定的命令,无需进行通常的 shell 查找
compgen    为指定单词生成可能的补全匹配
complete    显示指定的单词是如何补全的
compopt    修改指定单词的补全选项
continue    继续执行 for、while、select 或 until 循环的下一次迭代
declare    声明一个变量或变量类型。
dirs    显示当前存储目录的列表
disown    从进程作业表中刪除指定的作业
echo    将指定字符串输出到 STDOUT
enable    启用或禁用指定的内建shell命令
eval    将指定的参数拼接成一个命令,然后执行该命令
exec    用指定命令替换 shell 进程
exit    强制 shell 以指定的退出状态码退出
export    设置子 shell 进程可用的变量
fc    从历史记录中选择命令列表
fg    将作业以前台模式运行
getopts    分析指定的位置参数
hash    查找并记住指定命令的全路径名
help    显示帮助文件
history    显示命令历史记录
jobs    列出活动作业
kill    向指定的进程 ID(PID) 发送一个系统信号
let    计算一个数学表达式中的每个参数
local    在函数中创建一个作用域受限的变量
logout    退出登录 shell
mapfile    从 STDIN 读取数据行,并将其加入索引数组
popd    从目录栈中删除记录
printf    使用格式化字符串显示文本
pushd    向目录栈添加一个目录
pwd    显示当前工作目录的路径名
read    从 STDIN 读取一行数据并将其赋给一个变量
readarray    从 STDIN 读取数据行并将其放入索引数组
readonly    从 STDIN 读取一行数据并将其赋给一个不可修改的变量
return    强制函数以某个值退出,这个值可以被调用脚本提取
set    设置并显示环境变量的值和 shell 属性
shift    将位置参数依次向下降一个位置
shopt    打开/关闭控制 shell 可选行为的变量值
source    读取并执行指定文件中的命令(在当前 shell 环境中)
suspend    暂停 Shell 的执行,直到收到一个 SIGCONT 信号
test    基于指定条件返回退出状态码 0 或 1
times    显示累计的用户和系统时间
trap    如果收到了指定的系统信号,执行指定的命令
type    显示指定的单词如果作为命令将会如何被解释
typeset    声明一个变量或变量类型。
ulimit    为系统用户设置指定的资源的上限
umask    为新建的文件和目录设置默认权限
unalias    刪除指定的别名
unset    刪除指定的环境变量或 shell 属性
wait    等待指定的进程完成,并返回退出状态码
 

 

 

  • 40
    点赞
  • 77
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: bashsh都是Unix/Linux系统中的Shell,它们都是提供命令行界面的工具。主要的区别在于,bash是GNU项目发布的一种更加高级的Shell,支持很多sh不支持的特性,如循环、数组、函数等。而sh是一种更加基础的Shell,它的语法更加简单,但功能比较有限。在Linux系统中,/bin/sh默认指向bash,但也可以配置成指向其他Shell。 ### 回答2: bashsh都是常见的用于执行shell脚本的工具,它们之间的主要区别如下: 1. 解释器:bash是Bourne Again Shell的缩写,是sh的升级版本,它兼容sh的语法,同时提供了更多功能和特性。shShell的缩写,通常指的是Bourne shell,它是Unix系统早期的标准shell。 2. 功能:bash相比sh拥有更多功能和扩展,例如命令补全、命令历史记录、变量和数组等。bash还支持更多的内置命令和选项,使得脚本编写更加便捷和灵活。 3. 兼容性:由于bashsh的升级版本,并兼容sh的语法,因此使用bash编写的脚本可以在大多数支持sh的系统上运行,但反过来不一定成立。使用sh编写的脚本可能会在一些bash特定的功能上出现不兼容的问题。 4. 目标环境:在某些嵌入式或限制资源的系统中,可能没有足够的空间或资源安装bash,而只能使用sh执行shell脚本。 总之,bash相比sh提供了更多功能和特性,更适合编写复杂的脚本和日常使用。而sh作为早期的标准shell,更适合在一些特殊环境下运行,或者为了兼容性考虑编写简单的脚本。在大多数情况下,如果系统中已经安装了bash,通常会首选使用bash执行shell脚本。 ### 回答3: Bash(Bourne Again SHell)和Sh(Bourne SHell)是两种常用的Unix/Linux系统下的Shell编程语言。它们之间有以下几点区别: 1. 命令语法:BashSh的超集,它兼容Sh的所有基本语法,并在此基础上扩展了许多新特性。Bash支持更多的命令和选项,包括数组、关联数组、循环语句、逻辑判断等,更加方便和灵活。 2. 交互功能:Bash提供了更多的交互功能,如命令行编辑、命令历史记录、自动补全等。这些功能使得在命令行下使用更加方便和高效。 3. 脚本执行Bash执行脚本时,脚本需要以#!/bin/bash开头,即指定使用Bash作为解释器。而Sh则以#!/bin/sh开头。由于BashSh的超集,因此以#!/bin/bash开头的脚本也可以在Sh下运行,但一些特定的Bash语法可能会引起问题。 4. 执行效率:由于Bash提供了更多的功能和特性,因此在执行某些特定脚本时,Bash所需的资源和执行时间可能会比Sh更多。对于一些简单的脚本Sh可能会更快。 综上所述,Bash相比于Sh具有更多且更强大的功能。在大多数情况下,我们更倾向于使用Bash,因为它提供了更多的灵活性和便利性。但对于一些简单的脚本或在特定环境要求下,使用Sh也是可以的。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值