简述

使用 linux 就离不开 shell,那么也就是说也离不开 shell 编程。很多时候服务器都需要编写一些计划任务来定时运行的,所以掌握一些基本的 shell 编程基础很有必要。

什么是 Shell 脚本

示例看个例子吧:

#!/bin/sh cd ~ mkdir shell_tut cd shell_tut for ((i=0; i<10; i++)); do     touch test_$i.txt done

示例解释:

第1行:指定脚本解释器,这里是用/bin/sh做解释器的

第2行:切换到当前用户的 home 目录

第3行:创建一个目录 shell_tut

第4行:切换到 shell_tut 目录

第5行:循环条件,一共循环10次

第6行:创建一个 test_1…10.txt 文件

第7行:循环体结束

 都是系统自带的程序,一般在/bin或者/usr/bin目录下。 是 sh 脚本语言的关键字。

"shell" 和 "shell脚本"的概念

shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。Ken Thompson的 sh 是第一种 Unix Shell,Windows Explorer 是一个典型的图形界面Shell。

shell 脚本(shell script),是一种为 shell 编写的脚本程序。

业界所说的 shell 通常都是指 shell脚本,但读者朋友要知道,shell 和 shell script 是两个不同的概念。由于习惯的原因,简洁起见,本文出现的“shell编程”都是指 shell 脚本编程,不是指开发 shell 自身(如 Windows Explorer 扩展开发)。

环境 shell 编程跟 java、php 编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。OS 当前主流的操作系统都支持 shell 编程,本文档所述的 shell 编程是指 Linux 下的 shell,讲的基本都是POSI X标准下的功能,所以,也适用于 Unix 及 BSD(如Mac OS)。

Linux 默认安装就带了 shell 解释器。

Mac OSMac OS 不仅带了 sh、bash 这两个最基础的解释器,还内置了 ksh、csh、zsh 等不常用的解释器。

Windows 上的模拟器 windows 出厂时没有内置 shell 解释器,需要自行安装,为了同时能用 grep, awk, curl 等工具,最好装一个 cygwin 或者 mingw 来模拟 linux 环境。

  • cygwin

  • mingw

脚本解释器 sh

即 Bourne shell,POSIX(Portable Operating System Interface)标准的 shell 解释器,它的二进制文件路径通常是/bin/sh,由 Bell Labs 开发。

bashBash 是 Bourne shell 的替代品,属 GNU Project,二进制文件路径通常是/bin/bash。业界通常混用 bash、sh、和 shell,比如你会经常在招聘运维工程师的文案中见到:熟悉 Linux Bash 编程,精通 Shell 编程。

在 CentOS 里,/bin/sh是一个指向/bin/bash的符号链接:

[root@centosraw ~]# ls -l /bin/*sh -rwxr-xr-x. 1 root root 903272 Feb 22 05:09 /bin/bash -rwxr-xr-x. 1 root root 106216 Oct 17  2012 /bin/dash lrwxrwxrwx. 1 root root      4 Mar 22 10:22 /bin/sh -> bash

但在 Mac OS 上不是,/bin/sh和/bin/bash 是两个不同的文件,尽管它们的大小只相差100字节左右:

iMac:~ wuxiao$ ls -l /bin/*sh -r-xr-xr-x  1 root  wheel  1371648  6 Nov 16:52 /bin/bash -rwxr-xr-x  2 root  wheel   772992  6 Nov 16:52 /bin/csh -r-xr-xr-x  1 root  wheel  2180736  6 Nov 16:52 /bin/ksh -r-xr-xr-x  1 root  wheel  1371712  6 Nov 16:52 /bin/sh -rwxr-xr-x  2 root  wheel   772992  6 Nov 16:52 /bin/tcsh -rwxr-xr-x  1 root  wheel  1103984  6 Nov 16:52 /bin/zsh

如何选择 shell 编程语言

熟悉 vs 陌生如果你已经掌握了一门编程语言(如PHP、Python、Java、JavaScript),建议你就直接使用这门语言编写脚本程序,虽然某些地方会有点啰嗦,但你能利用在这门语言领域里的经验(单元测试、单步调试、IDE、第三方类库)。

新增的学习成本很小,只要学会怎么使用 shell 解释器(Jshell、AdaScript)就可以了。

简单 vs 高级如果你觉得自己熟悉的语言(如Java、C)写 shell 脚本实在太啰嗦,你只是想做一些备份文件、安装软件、下载数据之类的事情,学着使用 sh,bash 会是一个好主意。

shell 只定义了一个非常简单的编程语言,所以,如果你的脚本程序复杂度较高,或者要操作的数据结构比较复杂,那么还是应该使用 Python、Perl 这样的脚本语言,或者是你本来就已经很擅长的高级语言。

因为 sh 和 bash 在这方面很弱,比如说:

  • 它的函数只能返回字串,无法返回数组

  • 它不支持面向对象,你无法实现一些优雅的设计模式

  • 它是解释型的,一边解释一边执行,连PHP那种预编译都不是,如果你的脚本包含错误(例如调用了不存在的函数),只要没执行到这一行,就不会报错

环境兼容性如果你的脚本是提供给别的用户使用,使用 sh 或者 bash,你的脚本将具有最好的环境兼容性,perl 很早就是 linux 标配了,python 这些年也成了一些 linux 发行版的标配,至于 mac os,它默认安装了 perl、python、ruby、php、java 等主流编程语言。

第一个 shell 脚本 编写打开文本编辑器,新建一个文件,扩展名为 sh( sh 代表 shell),扩展名并不影响脚本执行,见名知意就好,如果你用 php 写 shell 脚本,扩展名就用 php 好了。

输入一些代码,第一行一般是这样:

#!/bin/bash #!/usr/bin/php

“#!”是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行。

运行

运行 Shell 脚本有两种方法:

1、作为可执行程序

将上面的代码保存为 test.sh,并 cd 到相应目录:

  #使脚本具有执行权限

  #执行脚本

注意:

  • 一定要写成./test.sh,而不是 test.sh,运行其它二进制的程序也一样。

  • 直接写 test.sh,linux 系统会去 PATH 里寻找有没有叫 test.sh 的,只有/bin, /sbin, /usr/bin,/usr/sbin等在 PATH 里。

  • 你的当前目录通常不在 PATH 里,所以写成 test.sh 是会找不到命令的,要用./test.sh告诉系统说,就在当前目录找。

2、作为解释器参数

这种运行方式是,直接运行解释器,其参数就是shell脚本的文件名,如:

/bin/sh test.sh
/bin/php test.php

这种方式运行的脚本,不需要在第一行指定解释器信息,写了也没用。

变量

定义变量定义变量时,变量名不加美元符号($),如:

your_name="qinjx"

注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样:

  • 首个字母必须为字母(a-z,A-Z)。

  • 中间不能有空格,可以使用下划线。

  • 不能使用表单符号。

  • 不能使用 bash 里的关键字(如果不清楚,可以用help命令查看bash的保留关键字)。

除了显式地直接赋值,还可以用语句给变量赋值,如:

for file in `ls /etc`

说明:上面的命令的意思是实现将 /etc 下目录的文件名循环出来。

使用变量

使用一个定义过得变量,只要在变量名之前加上美元符号 $ 即可,比如:

your_name="qinjx" echo $your_name echo ${your_name}

变量名外面的花括号是可选的,可加可不加,加花括号是为了帮助解释器识别变量的边界,比如当遇到下面的情况时:

for skill in Ada Coffe Action Java; do     echo "I am good at ${skill}Script" done

如果不给 skill 变量加上花括号,变量写成 skillScript,那么解释器就识别不出 skill 了,那么代码的最终结果就跟我的预期相差甚远。

推荐给所有变量加上花括号,这是shell编程的好习惯。

对于已定义的变量,可以被重新定义,比如:

your_name="tom" echo $your_name your_name="alibaba" echo $your_name

注意第二次赋值的时候不能写成:

$your_name="alibaba"

只有在使用变量的时候才加美元符 $。

只读变量

使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。

下面的例子尝试更改只读变量,结果报错:

#!/bin/bash myUrl=" readonly myUrl myUrl="http://www.runoob.com"

运行脚本,结果如下:

/bin/sh: NAME: This variable is read only.

删除变量

使用 unset 命令可以删除变量。语法:

unset variable_name

变量被删除后不能再次使用。unset 命令不能删除只读变量。

案例:

#!/bin/sh myUrl=" unset myUrl echo $myUrl

上面的程序执行将没有任何输出。

变量类型

运行 shell 程序时,会同时存在三种变量:

  1. 局部变量: 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他 shell 启动的程序不能访问局部变量。

  2. 环境变量: 所有的程序,包括 shell 启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候 shell 脚本也可以定义环境变量。

  3. shell变量:shell 变量是由 shell 程序设置的特殊变量。shell 变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell 的正常运行.

    未完待续......