Shell脚本

Shell脚本


宗旨:技术的学习是有限的,分享的精神的无限的。


一、shell简介

Shell的作用是解释执行用户的命令,用户输入一条命令, Shell就解释执行一条,这种方式称为交 互式( Interactive),Shell还有一种执行命令的方式称为批处理( Batch),用户事先写一 个Shell脚本( Script) ,其中有很多条命令,让Shell一次把这些命令执行完,而不必一条一条地敲 命令。 Shell脚本和编程语言很相似,也有变量和流程控制语句,但Shell脚本是解释执行的,不需 要编译, Shell程序从脚本中一行一行读取并执行这些命令,相当于一个用户把脚本中的命令一行一行敲到Shell提示符下执行。

默认的shell/bin/bash  可以用【echo $SHELL】查看。

$ cat /etc/shells

/bin/sh

/bin/ash

/bin/bash

/bin/dash

/bin/mksh

/bin/pdksh

/bin/posh

/bin/tcsh

/bin/zsh

/usr/bin/sh

/usr/bin/ash

/usr/bin/bash

/usr/bin/dash

/usr/bin/mksh

/usr/bin/pdksh

/usr/bin/posh

/usr/bin/tcsh

/usr/bin/zsh

 

二、shell执行命令

1、执行交互式命令

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

man bash-builtins可以查看有哪些内建命令,type可以看该命令是内部、外部命令。

2、执行脚本

先编写一个脚本名为hello.sh

#! /bin/bash
cd ..
ls

Shell脚本中用#表示注释,相当于C语言的//注释。但如果#位于第一行开头,并且是#!(称为Shebang)则例外,它表示该脚本使用后面指定的解释器/bin/bash解释执行。

Shell会fork一个子进程并调用exec执行./script.sh这个程序,exec系统调用应该把子进程的代码段替换成./ hello.sh程序的代码段,并从它的_start开始执行。然而hello.sh是个文本文件,根本没有代码段和_start函数,怎么办呢?其实exec还有另外一种机制,如果要执行的是一个文本文件,并且第一行用Shebang指定了解释器,则用解释器程序的代码段替换当前进程,并且从解释器的_start开始执行,而这个文本文件被当作命令行参数传给解释器。

执行前加权限chmod+x hello.sh

两种执行Shell脚本的方法:./script.sh    sh./script.sh

执行过程:

(1). 交互Shell( bash)fork/exec一个子Shell(sh)用于执行脚本,父进程bash等待子进程sh终止。

(2).sh读取脚本中的cd..命令,调用相应的函数执行内建命令,改变当前工作目录为上一级目录。

(3).sh读取脚本中的ls命令,fork/exec这个程序,列出当前工作目录下的文件, sh等待ls终止。

(4).ls终止后,sh继续执行,读到脚本文件末尾,sh终止。

(5).sh终止后,bash继续执行,打印提示符等待用户输入。

 

三、Shell的基本语法

1、变量

环境变量和本地变量。

export命令可以把本地变量导出为环境变量:$ exportVARNAME=value

2、文件名代换【: *  ?  []——通配符

* —— 匹配一个或多个任意字符

? —— 匹配任意一个字符

[] —— 匹配方括号中任意一个字符的一次出现

3、命令代换:`$()

如:

  DATE=`date`

echo $DATE

4、算术代换:$(())——转换成整数

$(())中只能用+-*/和()运算符,并且只能做整数运算。

VAR = 99

echo $(($VAR + 3))

5、转义字符\——除紧跟其后的单个字符的特殊意义

6、单引号——保持引号内所有字符的字面值,即使引号内的\和回车也不例外

7、双引号——双引号用于保持引号内所有字符的字面值(回车也不例外)

下面例外:

$加变量名可以取变量的值   反引号仍表示命令替换    \$表示$的字面值   

\`表示`的字面值   \"表示"的字面值   \\表示\的字面值

 

四、bash启动脚本

1、交互登录Shell

交互Shell是指用户在提示符下输命令的Shell而非执行脚本的Shell,登录Shell就是在输入用户名和密码登录后得到的Shell,比如从字符终端登录或者用telnet/ssh从远程登录,但是从图形界面的窗口管理器登录之后会显示桌面而不会产生登录Shell(也不会执行启动脚本),在图形界面下打开终端窗口得到的Shell也不是登录Shell。

这样启动bash会自动执行以下脚本:

 (1).首先执行/etc/profile,系统中每个用户登录时都要执行这个脚本,如果系统管理员希望某个设置对所有用户都生效,可以写在这个脚本里

(2).然后依次查找当前用户主目录的~/.bash_profile、~/.bash_login和~/.profile三个文件,找到第一个存在并且可读的文件来执行,如果希望某个设置只对当前用户生效,可以写在这个脚本里,由于这个脚本在/etc/profile之后执行,/etc/profile设置的一些环境变量的值在这个脚本中可以修改,也就是说,当前用户的设置可以覆盖(Override)系统中全局的设置。~/.profile这个启动脚本是sh规定的,bash规定首先查找以~/.bash_开头的启动脚本,如果没有则执行~/.profile,是为了和sh保持一致。

(3).顺便一提,在退出登录时会执行~/.bash_logout脚本(如果它存在的话)。

2、交互非登录Shell

比如在图形界面下开一个终端窗口,或者在登录Shell提示符下再输入bash命令,就得到一个交互非登录的Shell,这种Shell在启动时自动执行~/.bashrc脚本。

如果要在启动脚本中做某些设置,使它在图形终端窗口和字符终端的Shell中都起作用,最好就是在~/.bashrc中设置。

3、非交互启动

为执行脚本而fork出来的子Shell是非交互Shell,启动时执行的脚本文件由环境变量BASH_ENV定义,相当于自动执行以下命令:
if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi

如果环境变量BASH_ENV的值不是空字符串,则把它的值当作启动脚本的文件名,source这个脚本。

 

五、Shell脚本语法

1、条件测试:test

命令test或[可以测试一个条件是否成立,如果测试结果为真,则该命令的ExitStatus为0,如果测试结果为假,则命令的ExitStatus为1(注意与C语言的逻辑表示正好相反)。

$ var=2
$ test  $var  -gt  1
$ echo  $?
0
$ test  $var  -gt  3
$ echo  $?

[ -d DIR ]

如果DIR存在并且是一个目录则为真

[ -f FILE]

如果FILE存在且是一个普通文件则为真

[ -z STRING ]

如果STRING的长度为零则为真

[ -n STRING ]

如果STRING的长度非零则为真

[ STRING1= STRING2]

如果两个字符串相同则为真

[ STRING1!= STRING2]

如果字符串不相同则为真

[ ARG1 OP ARG2 ]

ARG1和ARG2应该是整数或者取值为整数的变量, OP是-eq(等于) -ne(不等于) -lt(小于) -le(小于等于) -gt(大于) -ge(大于等 于)之中的一个

[ ! EXPR ]

EXPR可以是上表中的任意一种测试条件, !表示逻辑反

[ EXPR1 -a EXPR2]

 

EXPR1和EXPR2可以是上表中的任意一种测试条件, -a表示逻辑与

[ EXPR1 -o EXPR2]

EXPR1和EXPR2可以是上表中的任意一种测试条件, -o表示逻辑或

 

2if/then/elif/else/fi    case/esac  

3for/do/done  while/do/done

4、位置参数和特殊变量

$0相当于C语言main函数的argv[0]
$1
$2... 这些称为位置参数( Positional Parameter,相当于C语言main函数argv[1]argv[2]...
$#
相当于C语言main函数的argc - 1,注意这里的#后面不表示注释
$@
表示参数列表"$1" "$2" ...,例如可以用在for循环中的in后面。
$?
上一条命令的Exit Status
$$
当前Shell的进程号

5、函数 —— 没有返回值也没有参数列表

#! /bin/sh
foo(){ echo "Function foo is called";}
echo "-=start=-"
foo
echo "-=end=-"

 

 

你可能感兴趣的:(编程语言,技术,shell,脚本,shell脚本)