Shell脚本编程(未完待续)

原文:《Shell脚本编程30分钟入门

首先要安装一个wget插件

1
2
3
yum install -y wget
yum install -y setup
yum install -y perl

一、Shell脚本

1. 脚本示例

1
2
3
4
5
6
7
8
#!/bin/sh
cd ~
mkdir shell_tut
cd shell_tut

for ((i=0; i<10; i++)); do
touch test_$i.txt
done

2. 代码解释

  • 第1行:指定脚本解释器,这里是用/bin/sh做解释器的
  • 第2行:切换到当前用户的home目录
  • 第3行:创建一个目录shell_tut
  • 第4行:切换到shell_tut目录
  • 第6行:循环条件,一共循环10次
  • 第7行:创建一个test_0…9.txt文件
  • 第8行:循环体结束

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

二、Shell相关概念

1. 基础概念

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

shell脚本 ,shell script,是一种为shell编写的脚本程序。业界所说的shell通常都是指shell脚本。shell和shell script是两个不同的概念。由于习惯的原因,简洁起见,本文出现的“shell编程”都是指shell脚本编程,不是指开发shell自身(如Windows Explorer扩展开发)。

sh命令 是shell命令语言解释器,执行命令从标准输入读取或从一个文件中读取。通过用户输入命令,和内核进行沟通。

2. Shell类型

如果要查看某一个用户使用的是什么 shell 可以通过 finger [USERNAME]命令来查看。 (kt)sh,Ken Thompson Shell,历史上第一个Unix shell,1971年由肯·汤普逊写作出第一版并加入UNIX之中。它是一个简单的命令行解释器,但不能被用来运行 指令稿(Shell script)。它的许多特征影响了以后命令行界面的发展。至Version 7 Unix之后,被Bourne shell取代。

sh,Bourne Shell,是Version 7 Unix默认的Unix shell,替代执行文件同为.sh的Thompson shell。

bash ,Bourne Again Shell,Unix shell的一种,在1987年由布莱恩·福克斯为了GNU计划而编写,与Bourne Shell兼容,还继承了C Shell、Korn Shell等优点。

zsh, Z shell是一款可用作交互式登录的shell及脚本编写的命令解释器。Zsh对Bourne shell做出了大量改进,同时加入了Bash、ksh及tcsh的某些功能。

3. Shell模式

3.1 login shell 和 no-login shell

login shell 代表用户登入, 比如使用 su - 命令, 或者用 ssh 连接到某一个服务器上, 都会使用该用户默认 shell 启动 login shell 模式。

该模式下的 shell 会去自动执行 /etc/profile~/.profile 文件, 但不会执行任何的 bashrc 文件, 所以一般在 /etc/profile 或者 ~/.profile 里我们会手动去 source bashrc 文件。

no-login shell 的情况是我们在终端下直接输入 bash 或者 bash -c “CMD” 来启动的 shell。

该模式下是不会自动去运行任何的 profile 文件。

3.2 interactive shell 和 non-interactive shell

interactive shell 是交互式shell, 顾名思义就是用来和用户交互的, 提供了命令提示符可以输入命令。

该模式下会存在一个叫 PS1 的环境变量, 如果还不是 login shell 的则会去 source /etc/bash.bashrc~/.bashrc 文件。

non-interactive shell 则一般是通过 bash -c “CMD” 来执行的bash。

该模式下不会执行任何的 rc 文件 (不过还存在一种特殊情况这个我之后详细讲述)

4. profile和bashrc

profile用于交互式login shell,bashrc用于交互式non-login shell。系统中存在许多bashrc和profile文件。 /etc/profile~/.profile分别对应 所有用户单个用户(bashrc同理)。

4.1 profile

profile 是用户唯一的用来设置环境变量的地方, 因为用户可以有多个 shell 比如 bash, sh, zsh 之类的, 但像环境变量这种其实只需要在统一的一个地方初始化就可以了, 而这就是 profile。/etc/profile中设定的变量(全局)的可以作用于任何用户,profile文件是在用户登录的时候进行初始化的。

4.2 bashrc

bashrc 是专门用来给 bash 做初始化的比如用来初始化 bash 的设置, bash 的代码补全, bash 的别名, bash 的颜色. 以此类推也就还会有 shrc, zshrc 这样的文件存在了, 只是 bash 太常用了而已。~/.bashrc等中设定的变量(局部)只能继承/etc/profile中的变量,他们是"父子"关系。(此句话待考究!!!!)

三、环境

shell编程跟java、php编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。

1. OS

当前主流的操作系统都支持shell编程,本文档所述的shell编程是指Linux下的shell,讲的基本都是POSIX标准下的功能,所以,也适用于Unix及BSD(如Mac OS)。

Linux默认安装就带了shell解释器。Mac OS不仅带了sh、bash这两个最基础的解释器,还内置了ksh、csh、zsh等不常用的解释器。windows出厂时没有内置shell解释器,需要自行安装,为了同时能用grep, awk, curl等工具,最好装一个cygwin或者mingw来模拟linux环境。

2. 脚本解释器

2.1 sh

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

本文讲的是sh,如果你使用其它语言用作shell编程,请自行参考相应语言的文档。

2.2 bash

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

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

1
2
3
4
[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字节左右:

1
2
3
4
5
6
7
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

2.3 高级编程语言

理论上讲,只要一门语言提供了解释器(而不仅是编译器),这门语言就可以胜任脚本编程,常见的解释型语言都是可以用作脚本编程的,如:Perl、Tcl、Python、PHP、Ruby。Perl是最老牌的脚本编程语言了,Python这些年也成了一些linux发行版的预置解释器。

编译型语言,只要有解释器,也可以用作脚本编程,如C shell是内置的(/bin/csh),Java有第三方解释器Jshell,Ada有收费的解释器AdaScript。

如下是一个PHP Shell Script示例(假设文件名叫test.php):

1
2
3
4
#!/usr/bin/php
<?php
for ($i=0; $i < 10; $i++)
echo $i . "\n";

执行:

1
/usr/bin/php test.php

或者:

1
2
chmod +x test.php
./test.php
chmod命令用来变更文件或目录的权限

四、选择Shell编程语言

1. 熟悉 vs 陌生

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

新增的学习成本很小,只要学会怎么使用shell解释器(Jshell、AdaScript)就可以了。 ## 2. 简单 vs 高级 如果你觉得自己熟悉的语言(如Java、C)写shell脚本实在太啰嗦,你只是想做一些备份文件、安装软件、下载数据之类的事情,学着使用sh,bash会是一个好主意。

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

  • 它的函数只能返回字串,无法返回数组
  • 它不支持面向对象,你无法实现一些优雅的设计模式
  • 它是解释型的,一边解释一边执行,连PHP那种预编译都不是,如果你的脚本包含错误(例如调用了不存在的函数),只要没执行到这一行,就不会报错

3. 环境兼容性

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

五、 第一个Shell脚本

1. 编写

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

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

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

2. 运行

运行Shell脚本有两种方法: ### 2.1 作为可执行程序

1
2
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告诉系统说,就在当前目录找。 ./表示当前目录。

通过这种方式运行bash脚本,第一行一定要写对,好让系统查找到正确的解释器。

这里的"系统",其实就是shell这个应用程序(想象一下Windows Explorer),但我故意写成系统,是方便理解,既然这个系统就是指shell,那么一个使用/bin/sh作为解释器的脚本是不是可以省去第一行呢?是的。

2.2 作为解释器参数

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

1
2
/bin/sh test.sh
/bin/php test.php
这种方式运行的脚本,不需要在第一行指定解释器信息,写了也没用。

参考链接

  1. chmod命令
  2. Thompson shell
  3. Bourne shell
  4. bash
  5. 理解 bashrc 和 profile