使用Linux好几年了.一直没有系统的来学过Shell
脚本,零零散散的学了不少.但是使用的时候总是到处去找资料,所以趁此机会好好的系统的学习一遍Shell脚本的语法.记录所学.
Linux 是一个开源的操作系统,由分布在世界各地的多个组织机构或个人共同开发完成,每个组织结构或个人负责一部分功能,最后组合在一起,就构成了今天的 Linux。例如:
Linux
内核最初由芬兰黑客 Linus Torvalds 开发,后来他组建了团队,Linux 内核由这个团队维护。GNU
组织开发了很多核心软件和基础库,例如 GCC
编译器、C语言标准库
、文本编辑器 Emacs
、进程管理软件
、Shell
以及 GNOME 桌面环境
等。VIM
编辑器由荷兰人 Bram Moolenaar 开发。Windows
、Mac OS
、Android
等操作系统不一样,它们都由一家公司开发,所有的核心软件和基础库都由一家公司做决定,容易形成统一的标准,一般不会开发多款功能类似的软件。
而 Linux
不一样,它是“万国牌”,由多个组织机构开发,不同的组织机构为了发展自己的 Linux 分支可能会开发出功能类似的软件,它们各有优缺点,用户可以自由选择。Shell
就是这样的一款软件,不同的组织机构开发了不同的 Shell,它们各有所长,有的占用资源少,有的支持高级编程功能,有的兼容性好,有的重视用户体验。
Shell 既是一种脚本编程语言,也是一个连接内核和用户的软件。
常见的 Shell 有 sh、bash、csh、tcsh、ash 等。
sh
的全称是 Bourne shell
,由 AT&T 公司的 Steve Bourne开发,为了纪念他,就用他的名字命名了。
sh 是 UNIX 上的标准 shell,很多 UNIX 版本都配有 sh。sh 是第一个流行的 Shell。
sh 之后另一个广为流传的 shell 是由柏克莱大学的 Bill Joy 设计的,这个 shell 的语法有点类似C语言,所以才得名为 C shell ,简称为 csh
。
Bill Joy 是一个风云人物,他创立了 BSD 操作系统,开发了 vi 编辑器,还是 Sun 公司的创始人之一。
BSD 是 UNIX 的一个重要分支,后人在此基础上发展出了很多现代的操作系统,最著名的有 FreeBSD、OpenBSD 和 NetBSD,就连 Mac OS X 在很大程度上也基于BSD。
tcsh 是 csh 的增强版,加入了命令补全功能,提供了更加强大的语法支持。
一个简单的轻量级的 Shell,占用资源少,适合运行于低内存环境,但是与下面讲到的 bash shell 完全兼容。
bash shell 是 Linux 的默认 shell,本教程也基于 bash 编写。
bash 由 GNU 组织开发,保持了对 sh shell 的兼容性,是各种 Linux 发行版默认配置的 shell。
bash 兼容 sh 意味着,针对 sh 编写的 Shell 代码可以不加修改地在 bash 中运行。
尽管如此,bash 和 sh 还是有一些不同之处:
Shell
Shell 是一个程序,一般都是放在/bin
或者/user/bin
目录下,当前 Linux 系统可用的 Shell 都记录在/etc/shells
文件中。/etc/shells
是一个纯文本文件,你可以在图形界面下打开它,也可以使用 cat 命令查看它。
通过 cat 命令来查看当前 Linux 系统的可用 Shell:
$ cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh
在现代的 Linux 上,sh 已经被 bash 代替,/bin/sh
往往是指向/bin/bash
的符号链接。
如果你希望查看当前 Linux 的默认 Shell,那么可以输出 SHELL 环境变量:
$ echo $SHELL
/bin/bash
输出结果表明默认的 Shell
是 bash
。
打开文本编辑器(可以使用 vi/vim 命令来创建文件),新建一个文件 test.sh,扩展名为 sh(sh代表shell),扩展名并不影响脚本执行,见名知意就好,如果你用 php 写 shell 脚本,扩展名就用 php 好了。
输入一些代码,第一行一般是这样:
#!/bin/bash
echo "Hello World !"
#!
是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell
。
echo
命令用于向窗口输出文本。
运行 Shell 脚本有两种方法:
chmod +x ./test.sh #使脚本具有执行权限
./test.sh #执行脚本
注意,一定要写成
./test.sh
,而不是test.sh
,运行其它二进制的程序也一样,直接写test.sh
,linux 系统会去PATH
里寻找有没有叫test.sh
的,而只有/bin
,/sbin
,/usr/bin
,/usr/sbin
等在PATH
里,你的当前目录通常不在PATH
里,所以写成test.sh
是会找不到命令的,要用./test.sh
告诉系统说,就在当前目录找。
/bin/sh test.sh
/bin/php test.php
这种方式运行的脚本,不需要在第一行指定解释器信息,写了也没用。
启动终端模拟包或者从 Linux 控制台登录后,便可以看到 Shell 提示符。提示符是通往 Shell 的大门,是输入 Shell 命令的地方。
重点: 对于普通用户,
Base shell
默认的提示符是美元符号$
;对于超级用户
(root
用户),Bash Shell 默认的提示符是井号#
。该符号表示Shell
等待输入命令。
不同的 Linux 发行版使用的提示符格式不同。例如在 CentOS 中,默认的提示符格式为:
[dreamhai@localhost ~]$
这种格式包含了以下三个方面的信息:
~
是主目录的简写表示法。Shell 通过PS1
和PS2
两个环境变量来控制提示符格式:
PS1
控制最外层命令行的提示符格式。
PS2
控制第二层命令行的提示符格式。
在 Shell 中初次输入命令,使用的是 PS1
指定的提示符格式;如果输入一个命令后还需要输入附加信息,Shell 就使用 PS2
指定的提示符格式。请看下面的例子:
dreamhai@ubuntu-desktop:~$ echo "dreamhai"
dreamhai
dreamhai@ubuntu-desktop:~$ echo "dreamhai.com"
dreamhai.com
dreamhai@ubuntu-desktop:~$ echo "
> Dreamhai
> Tan
> Qing
> Hai
> "
Dreamhai
Tan
Qing
Hai
echo
是一个输出命令,可以用来输出数字
、变量
、字符串
等;本例中,我们使用 echo
来输出字符串。
字符串是一组由" "
包围起来的字符序列,echo 将第一个"
作为字符串的开端,将第二个"
作为字符串的结尾。此处的字符串就可以看做 echo
命令的附加信息。
本例中,前两次使用 echo 命令时都是在后面紧跟字符串,一行之内输入了完整的附加信息。第三次使用 echo 时,将字符串分成多行,echo 遇到第一个"
认为是不完整的附加信息,所以会继续等待用户输入,直到遇见第二个"
。输入的附加信息就是第二层命令,所以使用>
作为提示符。
要显示提示符的当前格式,可以使用 echo 输出 PS1
和 PS2
:
dreamhai@ubuntu-desktop:~$ echo $PS1
\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\u@\h:\w\$
dreamhai@ubuntu-desktop:~$ echo $PS2
>
Shell 使用以\
为前导的特殊字符来表示命令提示符中包含的要素,这使得 PS1
和PS2
的格式看起来可能有点奇怪。下表展示了可以在 PS1
和 PS2
中使用的特殊字符。
字符 | 描述 |
---|---|
\a | 铃声字符 |
\d | 格式为“日 月 年”的日期 |
\e | ASCII转义字符 |
\h | 本地主机名 |
\H | 完全合格的限定域主机名 |
\j | shell当前管理的作业数 |
\1 | shell终端设备名的基本名称 |
\n | ASCII换行字符 |
\r | ASCII回车 |
\s | shell的名称 |
\t | 格式为“小时:分钟:秒”的24小时制的当前时间 |
\T | 格式为“小时:分钟:秒”的12小时制的当前时间 |
@ | 格式为am/pm的12小时制的当前时间 |
\u | 当前用户的用户名 |
\v | bash shell的版本 |
\V | bash shell的发布级别 |
\w | 当前工作目录 |
\W | 当前工作目录的基本名称 |
! | 该命令的bash shell历史数 |
# | 该命令的命令数量 |
$ | 如果是普通用户,则为美元符号$;如果超级用户(root 用户),则为井号#。 |
\nnn | 对应于八进制值 nnn 的字符 |
\ | 斜杠 |
[ | 控制码序列的开头 |
] | 控制码序列的结尾 |
注意
所有的特殊字符均以反斜杠\
开头,目的是与普通字符区分开来。您可以在命令提示符中使用以上任何特殊字符的组合。
我们可以通过修改 PS1 变量来修改提示符格式,例如:
[dreamhai@localhost ~]$ PS1="[\t][\u]\$ "
[17:27:34][dreamhai]$
新的 Shell
提示符现在可以显示当前的时间和用户名。不过这个新定义的 PS1
变量只在当前 Shell 会话期间有效,再次启动 Shell 时将重新使用默认的提示符格式。