一、Shell 是什么
1、Shell 概述
Shell 是一个命令行解释器,它为用户提供了一个向 Linux 内核发送请求以便运行程序的界面系统级程序,用户可以用 Shell 来启动、挂起、停止甚至是编写一些程序。
Shell 处在内核与外层应用程序之间,起着协调用户与系统的一致性、在用户与系统之间进行交互的作用。图 1 是 Linux 系统层次结构图,Shell 接收用户输入的命令,并把用户的命令从类似 abed 的 ASCII 码解释为类似
0101 的机器语言,然后把命令提交到系统内核处理;当内核处理完毕之后,把处理结果再通过 Shell 返回给用户。
Shell 与其他 Linux 命令一样,都是实用程序,但它们之间还是有区别的。一旦用户注册到系统后,Shell 就被系统装入内存并一直运行到用户退出系统为止;而一般命令仅当被调用时,才由系统装入内存执行。
与一般命令相比,Shell 除了是一个命令行解释器,同时还是一门功能强大的编程语言,易编写,易调试,灵活性较强。作为一种命令级语言,Shell 是解释性的,组合功能很强,与操作系统有密切的关系,可以在 Shell
脚本中直接使用系统命令。大多数 Linux 系统的启动相关文件(一般在 /etc/rc.d 目录下)都是使用 Shell 脚本编写的。
同传统的编程语言一样,Shell 提供了很多特性,这些特性可以使 Shell 脚本编程更为有用,如数据变量、参数传递、判断、流程控制、数据输入和输出、子程序及中断处理等。
说了这么多,其实我们在 Linux 中操作的命令行界面就是 Linux 的 Shell,也就是 Bash,但是我们的图形界面是 Shell 吗?其实从广义讲,图形界面当然也是
Shell,因为它同样用来接收用户的操作,并传递到内核进行处理。不过,这里的 Shell 主要指的是 Bash。
2、常用 Shell 解析器
(1)查看系统内的 shell 解析器
[niujifei@njf ~]$ cat /etc/shells
/bin/bash
/bin/csh
/bin/dash
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
(2)bash 和 sh 的关系
[niujifei@njf bin]$ ls -l | grep bash
-rwxr-xr-x. 1 root root 964608 10月 31 2018 bash
lrwxrwxrwx. 1 root root 4 7月 11 2019 sh -> bash
(3)Centos 默认的解析器是 bash
[niujifei@njf bin]$ echo $SHELL
/bin/bash
二、Shell 脚本入门
1、脚本格式要求
- 脚本以#!/bin/bash 开头(指定解析器)
- 脚本需要有可执行权限
2、编写第一个 Shell 脚本
需求说明:创建一个 Shell 脚本,输出 hello world
#!/bin/bash
echo "hello world!"
3、脚本的常用执行方式
方式 1:采用 bash 或 sh+脚本的相对路径或绝对路径(不用赋予脚本+x 权限)
说明:不用赋予脚本+x 权限,直接执行即可,不推荐使用
(1)sh+脚本的相对路径
[niujifei@njf ~]$ sh ./helloWorld.sh
hello world!
(2)sh+脚本的绝对路径
[niujifei@njf ~]$ sh /home/niujifei/helloWorld.sh
hello world!
(3)bash+脚本的相对路径
[niujifei@njf ~]$ bash ./helloWorld.sh
hello world!
(4)bash+脚本的绝对路径
[niujifei@njf ~]$ bash /home/niujifei/helloWorld.sh
hello world!
方式 2:采用输入脚本的绝对路径或相对路径执行脚本(必须具有可执行权限+x)
- 首先要赋予 helloworld.sh 脚本的+x 权限
[niujifei@njf ~]$ chmod 744 helloWorld.sh
- 执行脚本
相对路径
[niujifei@njf ~]$ ./helloWorld.sh
hello world!
绝对路径
[niujifei@njf ~]$ /home/niujifei/helloWorld.sh
hello world!
注意:第一种执行方法,本质是 bash 解析器帮你执行脚本,所以脚本本身不需要执行 权限。第二种执行方法,本质是脚本需要自己执行,所以需要执行权限。
方式 3:在脚本的路径前加上“.”或者 source
创建一个脚本:
#!/bin/bash
echo "test"
分别使用 sh,bash,./ 和 . 的方式来执行,结果如下:
[niujifei@njf ~]$ bash test.sh
test
[niujifei@njf ~]$ sh test.sh
test
[niujifei@njf ~]$ ./test.sh
test
[niujifei@njf ~]$ . test.sh
test
[niujifei@njf ~]$ source test.sh
test
原因:
前两种方式都是在当前 shell 中打开一个子 shell 来执行脚本内容,当脚本内容结束,则 子 shell 关闭,回到父 shell 中。
后面三种,也就是使用在脚本路径前加“.”或者 source 的方式,可以使脚本内容在当前 shell 里执行,而无需打开子 shell!这也是为什么我们每次要修改完/etc/profile 文件以后,需要 source 一下的原因。
开子 shell 与不开子 shell 的区别就在于,环境变量的继承关系,如在子 shell 中设置的当前变量,父 shell 是不可见的。
注意:
在父 shell 中声明的局部变量可以通过 export 导出为全局变量,在子 shell 中也可以使用;
在子 shell 中声明或者修改了局部变量,只能在子 shell 中使用,使用 export 也无法在父 shell 中使用