Linux之Shell脚本

  • Shell是在命令行模式下面让我们与系统沟通的一个工具接口
  • Shell脚本就是针对Shell所写的剧本
  • Shell的作用是解释执行用户的命令,用户输入一条命令,Shell就解释执行一条,这种方式称为交互式,Shell还有一种执行命令的方式称为批处理,用户事先写一个Shell脚本(Script),其中有很多条命令,让Shell一次把这些命令执行完,而不必一条一条地敲命令。Shell脚本是解释执行的,不需要编译,Shell程序从脚本中一行一行读取并执行这些命令,相当于一个用户把脚本中的命令一行一行敲到Shell提示符下执行
  • 当用户在字符终端登录或者打开图形终端窗口时就会自动执行/bin/bash

1.Shell执行命令

用户在命令行输入命令后,一般情况下Shell会fork并exec该命令,但是Shell的内建命令例外,执行内建命令相当于调用Shell进程中的一个函数,并不创建新的进程.cd、alias、umask、exit等命令即是内建命令

#!/bin/bash                                                                  
PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/sbin:/usr/sbin
export PATH
cd ..
ls

我们可以像这样用vim写一个.sh的脚本再进行sh test.sh
也可以使用sh命令打开bash

~$ sh(在bash提示符下输入sh命令)
$(出现sh的提示符)
$(按Ctrl-d或者输入exit命令)
~$(回到bash提示符)

接下来在sh下写

#! /bin/sh
cd ..
ls

也能得到一样的结果
Shell脚本中用#表示注释,但如果#位于第一行开头,并且是#!(称为Shebang行)则例外,它表示该脚本使用后面指定的解释器/bin/sh解释执行

如果要执行这个test.sh脚本

sh test.sh
./test.sh

不过这种要加可执行权限

$ chmod +x test.sh

当我们执行时Shell会fork一个子进程并调用exec执行./test.sh这个程序,exec系统调用应该把子进程的代码段替换成./test.sh程序的代码段,并从它的_start开始执行。然而script.sh是个文本文件,根
本没有代码段和_start函数,exec就执行另外一种机制,如果要执行的是一个文本文件,并且第一行用Shebang行指定了解释器,则用解释器程序的代码段替换当前进程,并且从解释器的_start开始执行,而这个文本文件被当作命令行参数传给解释器。因此,执行上述脚本相当于执
行程序

$ /bin/sh ./test.sh

以这种方式执行不需要先前的test.sh文件具有可执行权限
于是,以上便有三种执行Shell脚本的方法

$ ./test.sh(要用chmod加x权限)
$ sh ./test.sh
$ /bin/bash ./test.sh

自从我们可以看到这样一个过程是
在这里插入图片描述

  • 交互Shell(bash)fork/exec一个子Shell(sh)用于执行脚本,父进程bash等待子进程sh终止。
  • sh读取脚本中的cd …命令,调用相应的函数执行内建命令,改变当前工作目录为上一级目录。
  • sh读取脚本中的ls命令,fork/exec这个程序,列出当前工作目录下的文件,sh等待ls终止。
  • ls终止后,sh继续执行,读到脚本文件末尾,sh终止。
  • sh终止后,bash继续执行,打印提示符等待用户输入。

举个粟子:

  1. 如果将命令行下输入的命令用()括号括起来,那么也会fork出一个子Shell执行小括号中的命令,一行中可以输入由分号;隔开的多个命令
    (cd ..;ls)
    和上面两种方法执行Shell脚本的效果是相同的,cd …命令改变的是子Shell的pwd,而不会影响到交互式Shell.意思就是不会伴随cd ..的命令退出当前目录,直接在当前目录下显示前一个目录的ls功能
  2. 然而命令
    cd ..;ls
    则有不同的效果,cd ..命令是直接在交互式Shell下执行的,改变交互式Shell的pwd,这种方式相当于这样执行Shell脚本:
    source ./test.sh
    . ./test.sh
    source或者.命令是Shell的内建命令,这种方式也不会创建子Shell,而是直接在交互式Shell下逐行执行脚本中的命令。

2.Shell语法

1.变量

在Shell中定义或赋值一个变量时注意等号两边都不能有空格,否则会被Shell解释成命令和命令行参数

2.文件名代换:* ? []
*匹配0个或多个任意字符
?匹配一个任意字符
[若干字符]匹配方括号中任意一个字符的一次出现
3.命令替换:`或 $()

用于算术计算,将$(())中的Shell变量取值将转换成整数,只能用+-*/和()运算符,并且只能做整数运算

4.转义字符:\

\在Shell中被用作转义字符,用于去除紧跟其后的单个字符的特殊意义(回车除外),即紧跟其后的字符取字面值
在\后敲回车表示续行,Shell并不会立刻执行命令,而是把光标移到下一行,给出一个续行提示符>,等待用户继续输入,最后把所有的续行接到一起当作一个命令执行。
ls \
> -l
`(ls -l命令的输出)``

5.单引号

Shell脚本中的单引号和双引号一样都是字符串的界定符,而不是字符的界定符。单引号用于保持引号内所有字符的字面值,即使引号内的\和回车也不例外,但是字符串中不能出现单引号。如果引号没有配对就输入回车,Shell会给出续行提示符,要求用户把引号配上对。

6.双引号

双引号用于保持引号内所有字符的字面值(回车也不例外),但以下情况除外:

  • $加变量名可以取变量的值
  • 反引号仍表示命令替换
  • $表示$的字面值
  • '表示’的字面值
  • \ "表示"的字面值
  • \表示\的字面值
    除以上情况之外,在其它字符前面的\无特殊含义,只表示字面值

3.Shell脚本语法

1.条件测试:test[

命令test或[可以测试一个条件是否成立
[命令的参数,它们之间必须用空格隔开

[ EXPR1 -a EXPR2 ]-a表示逻辑与
[ EXPR1 -o EXPR2 ]-o表示逻辑或
2. if/then/elif/else/fi
3. case/esac

esac表示case语句块的结束。C语言的case只能匹配整型或字符型常量表达式,而Shell脚本的case可以匹配字符串和Wildcard,每个匹配分支可以有若干条命令,末尾必须以;;结束,执行时找到第一个匹配的分支并执行相应的命令,然后直接跳到esac之后,不需要像C语言一样用break跳出。

4. for/do/done
5.位置参数和特殊变量
$0相当于C语言main函数的argv[0]
$1、$2…这些称为位置参数,相当于C语言main函数的argv[1]、argv[2]…
$#相当于C语言main函数的argc - 1,注意这里的#后面不表示注释
$@表示参数列表"$1" “$2” …,例如可以用在for循环中的in后面
$?上一条命令的Exit Status
$$当前Shell的进程号

位置参数可以用shift命令左移。比如shift 3表示原来的$4现在变成$1,原来的$5现在变成$2等等,原来的$1、$2、$3丢弃,$0不移动。不带参数的shift命令相当于shift 1。

6.函数

意函数体的左花括号{和后面的命令之间必须有空格或换行,如果将最后一条命令和右花括号}写在同一行,命令末尾必须有;号。

4.Shell脚本调试

  • sh -n:读一遍脚本中的命令但不执行,用于检查脚本中的语法错误
  • sh -v:一边执行脚本,一边将执行过的脚本命令打印到标准错误输出
  • sh -x:提供跟踪执行信息,将执行的每一条命令和结果依次打印出来
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值