Shell作为一个命令解释器,用于解释用户输入的命令及程序。当用户想在操作系统中完成一项操作时,通过Shell与用户进行交互。由此可见,Shell在Linux系统中具有重要地位,通过对Shell的灵活使用能够让我们更好、更便捷的使用Linux操作系统。
目录
1.Shell的作用
Shell是操作系统中介于软件和硬件之间的命令解释器,其主要的作用就是将用户想要在系统中执行的操作解释为计算机硬件能够执行的指令。当Shell接收用户的执行操作指令后,会将其相关指令解释给操作系统来执行。同样,当操作系统将其执行完毕之后,由Shell再将处理结果返回给用户。从直观使用上来看,当我们接触一个操作系统时常常能够直接接触到的就是这个操作系统的Shell,并通过Shell来完成各种各样的操作。另外,在网络数据传输中,GUI图形化数据的传输是远远慢于计算机shell指令的。
#图来自网络,侵删
Shell脚本是弱类型语言(无需定义变量类型即可使用),在Linux中主要有两大类Shell:一类是Bourne Shell,另一类是C Shell。Bourne Shell中包括有Bourne shell(sh)、Korn shell(ksh)、Bourne Again Shell(bash)三种类型,C Shell包括csh、tcsh两种类型。
Bourne shell是UNIX/Linux系统最初使用的shell,并且在每种UNIX/Linux上都可以使用。Bourneshell在shell编程方面相当优秀,但在处理与用户的交互方面做得不如其他几种shell。Bourne Again shell是Linux操作系统缺省的shell,也称为Bash,与Bourneshell完全向后兼容,并且在Bourneshell的基础上增加、增强了很多特性。Bash放在/bin/bash中,它有许多特色,可以提供如命令补全、命令编辑和命令历史表等功能,它还包含了很多Cshell和Korn shell中的优点,有灵活和强大的编程接口,同时又有很友好的用户界面。
Dash,GNU/Linux操作系统中的/bin/sh本是bash (Bourne-Again Shell)的符号链接,但鉴于bash过于复杂,有人把bash从NetBSD移植到Linux并更名为dash (Debian AlmquistShell),并建议将/bin/sh指向它,以获得更快的脚本执行速度。Dash Shell 比Bash Shell小的多,符合POSIX标准。在Debian和Ubuntu中,/bin/sh默认已经指向dash,这是一个不同于bash的shell,它主要是为了执行脚本而出现,而不是交互,它速度更快,但功能相比bash要少很多。csh随BSD UNIX发布,其流程控制语句和C语言和类似,能支持很多Bourne Shell所不支持的功能。tcsh是csh的增强版,加入了命令补全等功能。
可以通过以下方式查看当前系统所支持的shell:
ubuntu@localhost:~$cat /etc/shells
#/etc/shells: valid login shells
/bin/sh
/bin/bash
/bin/rbash
/bin/dash
/usr/bin/tmux
/usr/bin/screen
2.shell脚本规范
通常,手动在linux的终端中可以输入shell命令来逐个执行,但当需要执行的命令较多时就可以将其众多的执行操作放到文件中来批量执行,即采用shell脚本的方式来完成。这样采用非交互的方式执行命令,不但能够快速自动化完成所有的操作,而且可以减少在交互式执行时因为操作不当而造成的错误。Shell 脚本也有众多的命令、变量和流程控制,通过将这些进行适当的结合,可以大大提高对Linux系统管理的效率,并且可以完成检测系统报警等一系列工作。
shell脚本通常会在第一行说明其所调用的shell名称,如:
#!/bin/bash
Shell 脚本的执行方式有以下几种:
1)bash shellscript或sh shellscript :当脚本没有可执行权限时,或者脚本文件第一行没有指明所调用的shell解释器时使用;
2)path/shellscript或./shellscript:在当前路径下执行shellscript脚本,此种方式执行时shellscript脚本需要执行权限;
3)source shellscript或 . shellscript:使用source或“.”读入或加载指定的shell脚本文件,然后依次执行指定的shell脚本文件中的所有语句;
4)sh < shellscript 或cat shellcript |sh:利用重定向或管道来执行shell脚本。
3.shell变量
在Linux中使用一个shell变量时需要在这个变量名前面加上"$"符号,如 $username 或 ${username} 方式使用。其中,后一种使用{}的表示方式不易出错,特别是在针对变量名中含有空格的变量使用中。因为shell是弱类型语言,所以变量的定义也是很方便的,不必强调变量的数据类型。关于shell变量更详细的相关内容已经在【Linux管理篇-3】中进行了较为详细的阐述,此处不再做过多介绍。
4. Bash运行环境
通常我们登陆一个系统时会有一些欢迎语和对系统版本的相关描述,可以在/etc/issue中设置,通过网络登录的用户欢迎语可以在/etc/issue.net中设置。另外,关于Linux系统的环境变量设置有多个文件来完成,并且每个文件的使用范围不同。其中,/etc/profile是Linux系统的通用环境变量设置,~/.bash_profile 、~/.bash_login或 ~/.profile是每个用户的个人环境变量设置。
Linux中的用户账户在创建时,会从/etc/skel目录下复制一份默认的环境变量到其主目录中,给新创建的用户设置对应的环境变量。了解用户登录过程中环境变量的设置流程,有助于使用者更好的管理Linux系统,而不会出现由于在众多文件中修改后导致配置混乱的局面。在用户登录时,这些环境变量的具体设置顺序如下:
1) 用户通过远程ssh或图形化界面登录;
2) 读取/etc/profile文件中的环境变量设置;
3) 读取/etc/profile.d/*目录下的环境变量设置;
4) 依次选择读取~/.bash_profile 、~/.bash_login或 ~/.profile三个文件中之一的环境变量设置;
5) 读取~/.bashrc中的环境变量设置;
6) 读取/etc/bash.bashrc文件中环境变量设置。
5.通配符
在【Linux管理篇-2】中已经介绍过Linux中一些常见的符号,此处针对Linux中的通配符作以介绍:
通配符 | 说明 |
? | 匹配一个任意字符 |
* | 匹配0个或任意多个任意字符,即可以匹配任何内容 |
[] | 匹配中括号中任意一个字符。例如,[abc] 代表一定匹配一个字符,或者是 a,或者是 b,或者是 c |
[-] | 匹配中括号中任意一个字符,- 代表一个范围。例如,[a-z] 代表匹配一个小写字母 |
[^] | 逻辑非,表示匹配不是中括号内的一个字符。例如,[^0-9] 代表匹配一个不是数字的字符 |
示例如下:
1)使用?匹配任意一个字符:
ubuntu@localhost:/tmp/test$touch file{1..5}
ubuntu@localhost:/tmp/test$ls
file1 file2 file3 file4 file5
ubuntu@localhost:/tmp/test$touch file123 fileabc
ubuntu@localhost:/tmp/test$ls
file1 file123 file2 file3 file4 file5 fileabc
ubuntu@localhost:/tmp/test$ls file?
file1 file2 file3 file4 file5
2) 使用*匹配任意字符:
ubuntu@localhost:/tmp/test$ls file*
file1 file123 file2 file3 file4 file5 fileabc
ubuntu@localhost:/tmp/test$ls fi*
file1 file123 file2 file3 file4 file5 fileabc
3)匹配[]中的字符
ubuntu@localhost:/tmp/test$ls file[123]
file1 file2 file3
ubuntu@localhost:/tmp/test$ls file[13]
file1 file3
ubuntu@localhost:/tmp/test$
ubuntu@localhost:/tmp/test$ls file[135]
file1 file3 file5
4)匹配除[]之外的字符
ubuntu@localhost:/tmp/test$ls file[^2-9]
file1
ubuntu@localhost:/tmp/test$ls file[^3-9]
file1 file2
5)匹配以包含a和b中间的任意字符串
ubuntu@localhost:~$ cat testfile
abc
aasldnlnnfdnb
about
asadnfalsdfn
asdfdfdbdfn
ubuntu@localhost:~$ grep 'a.*b' testfile
abc
aasldnlnnfdnb
about
asdfdfdbdfn
注:可以看到"."表示任意字符,"*"表示匹配任意次,所以主要字符串中包含a和b,中间无论是什么字符都可以被匹配
6. bash常见内置命令
Bash shell中常见的内部命令有echo、eval、exec、read、shift、declare等。具体使用如下:
6.1 echo命令
echo命令用于在linux中输出信息到终端屏幕上。常用参数如下:
-n 不换行输出(不使用该参数时echo默认是输出后换行的)
-e 解析转义字符,常见字符有换行(\n)、回车(\r)、制表符(\t)、退格(\b)、纵向制表符(\v)等
示例如下:
ubuntu@localhost:~$ echo str1
str1
ubuntu@localhost:~$ echo str1;echo str2
str1
str2
ubuntu@localhost:~$ echo -n str1;echo str2
str1str2
ubuntu@localhost:~$ echo "str1\nstr2"
str1\nstr2
ubuntu@localhost:~$ echo -e"str1\nstr2"
str1
str2
注:常见的printf与echo功能类似,但printf更强大,当需要特殊复杂格式时才考虑使用printf。
6.2 eval命令
eval命令用于在shell脚本中读入参数args,并将其组合为一个新的命令来执行。格式如下:
eval args
示例如下:
ubuntu@localhost:~$cat testeval.sh
echo \$$*
ubuntu@localhost:~$bash testeval.sh arg1 abc 123
$arg1 abc 123
ubuntu@localhost:~$vim testeval.sh
ubuntu@localhost:~$cat testeval.sh
eval "echo\$$*"
ubuntu@localhost:~$bash testeval.sh arg1 abc 123
abc 123
说明:echo中的\$为转义输出$符,之后使用$*输出所有参数,所以第一次testeval.sh脚本执行结果为$符和所有参数(有4个参数:testeval.sh arg1 abc 123,分别为$0至$3)。第二次使用eval时,eval将“echo \$$*”作为参数,然后当做命令来执行,当“echo \$$*”命令执行时,需要提供所有参数,此时echo命令的参数为arg1 abc 123,分别为$0 $1 $2 ,因此$*的输出仅为$1 和$2组成的字符串。(关于$*等特殊变量的含义详见【Linux篇-3】shell变量。)
6.3 exec命令
exec命令在不创建新进程的前提下,转去执行指定命令。示例如下:
root@localhost:~#exec date
Mon May 25 11:23:32UTC 2020
ubuntu@localhost:~$
说明:exec在创建子进程的情况下执行date,当date执行完毕之后,当前进程也就退出了。
6.4 read命令
read从标准输入读入数据,传递给shell变量。常用参数如下:
-a 后跟一个变量,该变量会被认为是个数组,然后给其赋值,默认是以空格为分割符。
-d 后面跟一个标志符,其实只有其后的第一个字符有用,作为结束的标志,会举例说 明。
-p 后面跟提示信息,即在输入前打印提示信息。
-e 在输入的时候可以时候命令补全功能。
-n 后跟一个数字,定义输入文本的长度,很实用。
-r 屏蔽,如果没有该选项,则作为一个转义字符,有的话 就是个正常的字符了。
-s 安静模式,在输入字符时不再屏幕上显示,例如login时输入密码。
-t 后面跟秒数,定义输入字符的等待时间。
-u 后面跟fd,从文件描述符中读入,该文件描述符可以是exec新开启的。
示例如下:
输入字符,但不显示在终端中:
ubuntu@localhost:~$read -p password:
password:passwd
ubuntu@localhost:~$read -p password: -s
password:
从文件读取数据并输出:
ubuntu@localhost:~$cat testfile
1 2 3
abc
os sec
ubuntu@localhost:~$cat readtest.sh
#!/bin/bash
cat testfile | whileread line
do
echo $line
done
ubuntu@localhost:~$bash readtest.sh
1 2 3
abc
os sec
6.5 shift命令
shift将命令行参数左移,如若前移n设置为1,则将原来的$2位置的参数前移到$1,原$1的前移到$0中。示例如下:
ubuntu@localhost:~$cat testshift.sh
echo $*
shift 1
echo $*
shift 1
echo $*
ubuntu@localhost:~$bash testshift.sh 1 2 3 4 5
1 2 3 4 5
2 3 4 5
3 4 5
6.6 declare命令用于设置环境变量
declare [-aixr] variable
选项与参数:
-a :将后面名为 variable 的变量定义成为数组( array) 类型
-i :将后面名为 variable 的变量定义成为整数数字 ( integer) 类型
-x :用法与 export 一样, 就是将后面的 variable 变成环境变量;
-r:将变量设置成为readonly只读类型,该变量不可被更改内容,也不能 unset
如将变量设置为环境变量:
ubuntu@localhost:~$ var=123
ubuntu@localhost:~$ declare -x var
7.数值计算
7.1 双小括号"(())"运算符
“(())”的作用是进行数值运算与数值比较,效率较高,且用法灵活。常见用法如下:
运算方法 | 含义 |
((i=i+1)) | 运算后赋值法,即将i+1的运算结果赋值给变量i,可以将“(())”小括号整体当做一个变量 |
i=$((i+1)) | 在“(())”前加$符,表示将表达式运算后赋值给I |
((8>7&&5==5)) | 加入逻辑操作,进行比较 |
echo $((2+1)) | 直接输出结果的表达 |
7.2 let命令
let在大多数shell中只用于整数运算,使用let命令如下所示:
ubuntu@localhost:~$i=2
ubuntu@localhost:~$let i=i+8
ubuntu@localhost:~$echo $i
10
但在zsh shell中可以用于浮点数运算(“(())”双小括号同样也可以):
localhost% letvaluel=" 4 * 5.1 / 3.2 "
localhost% echo$valuel
6.3750000000
localhost% echo$((4*5.1))
20.399999999999999
7.3 expr命令
expr命令即可用于整数运算,也可用于相关字符串长度、匹配的运算处理。expr在进行数值运算时,若遇到在shell中用到的字符(如通配符)需要转义才能使用,如下所示:
ubuntu@localhost:~$expr 1 + 5
6
ubuntu@localhost:~$expr 3 < 2
-bash: 2: No suchfile or directory
ubuntu@localhost:~$expr 3 \< 2
0
ubuntu@localhost:~$expr 3 \* 2
6
使用expr配合变量计算:
ubuntu@localhost:~$i=10
ubuntu@localhost:~$e=`expr $i + 2`
ubuntu@localhost:~$echo $e
12
注意:此处expr使用反引号
7.4 $[]符号
bashshell为了保持跟Bourneshell的兼容而包含了expr命令,但它同样也提供了一种更简单的方法来执行数学表达式。在bash中,在将一个数学运算结果赋给某个变量时,可以用美元符和方括号($[ operation ])将数学表达式围起来。示例如下:
ubuntu@localhost:~$i=10
ubuntu@localhost:~$echo $[$i+12]
22
ubuntu@localhost:~$echo $[$i*2]
20
ubuntu@localhost:~$echo $[$i**2]
100
ubuntu@localhost:~$echo $[$i/2]
5
7.5 bc命令
bc命令可以支持浮点数,是bashshell内建的计算器。bc计算器实际上是一种编程语言,它允许在命令行中输入浮点表达式,然后解释并计算该表达式,最后返回结果。bash计算器能够识别数字(整数和浮点数)、变量(简单变量和数组)、注释(以#或C语言中的/* */开始的行)、表达式、编程语句(例如if-then语句)、函数等。
例如在shell下使用bc计算器(交互式):
ubuntu@localhost:~$ bc -q
12.1 *16.3
197.2
8.5 / 1.2
7
10 / 6
1
quit
注:-q表示使用安静模式,不输出bc命令的提示信息
在命令行中使用(非交互式):
ubuntu@localhost:~$echo 3+5 |bc
8
ubuntu@localhost:~$echo 3.3+1.2|bc
4.5
ubuntu@localhost:~$echo "scale=5;10/6" | bc
1.66666
注:scale是指定小数点后保留5位小数
8.逻辑预算
Linux中可以利用逻辑判断来实现多条指令的选择性执行,一般先通过$?获得前一个命令的执行结果返回值,然后再利用&&或||符号来进行逻辑判断处理。格式如下:
cmd1 && cmd2
cmd1 || cmd2
当使用&&时,cmd1命令执行返回值为0时,cmd2执行,即与操作
当使用||时,cmd1命令执行返回值为非0时,cmd2执行,即或操作
举例如下:
1) 创建文件并查看相关属性信息:
ubuntu@localhost:~$ touch testfile && ls -al testfile
-rw-rw-r-- 1 ubuntu ubuntu 49 May 9 12:03 testfile
2) 查看文件,当不存在时创建文件:
ubuntu@localhost:~$ ls -al testabc || touch testabc
ls: cannot access 'testabc': No such file or directory
ubuntu@localhost:~$ ls -al testabc || touch testabc
-rw-rw-r-- 1 ubuntu ubuntu 0 May 9 12:10 testabc
注:可以看到第一次执行时不存在该文件,所以执行touch命令创建。第二次执行时,ls命令查看执行成功,返回值为0,则touch命令不执行。
3)判断目录是否存在,并在该目录中创建文件:
ls /tmp/abc || mkdir /tmp/abc && touch /tmp/abc/filetest
注:shell命令是从左向右执行的,当目录abc不存在时,会执行mkdir命令创建目录,&&符号的左侧$?返回值为0,会进行filetest文件的创建。当目录abc存在时,ls命令执行成功,mkdir命令不执行,$?返回值向后传递也为0,也会进行filetest文件的创建。
4)判断文件是否存在:
ubuntu@localhost:~$ ls testabc && echo exist || echo not exist
testabc
exist
9.Test判断
上一小节中我们可以使用逻辑符号来判断目录或文件是否存在,test命令也可用来完成这些操作并用于流程控制语句的判断中,而且test命令所能够进行的判断类型更多。例如,可以使用如下方式来完成文件是否存在的判断,当文件存在时$?返回值为0。
ubuntu@localhost:~$ test -e testabc
ubuntu@localhost:~$ echo $?
0
更多的判断种类如下(摘自《鸟哥的Linux私房菜基础学习篇第四版》):
1. 关于某个文件名的“文件类型”判断,如test -e filename 判断文件是否存在
测试符号 | 代表意义 |
-e | 该“文件名”是否存在? ( 常用) |
-f | 该“文件名”是否存在且为文件( file) ? ( 常用) |
-d | 该“文件名”是否存在且为目录( directory) ? ( 常用) |
-b | 该“文件名”是否存在且为一个 block device 设备? |
-c | 该“文件名”是否存在且为一个 character device 设备? |
-S | 该“文件名”是否存在且为一个 Socket 文件? |
-p | 该“文件名”是否存在且为一个 FIFO ( pipe) 文件? |
-L | 该“文件名”是否存在且为一个链接文件? |
2. 关于文件的权限侦测,如test -r filename 表示是否可读(root权限例外)
测试符号 | 代表意义 |
-r | 侦测该文件名是否存在且具有“可读”的权限? |
-w | 侦测该文件名是否存在且具有“可写”的权限? |
-x | 侦测该文件名是否存在且具有“可执行”的权限? |
-u | 侦测该文件名是否存在且具有“SUID”的属性? |
-g | 侦测该文件名是否存在且具有“SGID”的属性? |
-k | 侦测该文件名是否存在且具有“Sticky bit”的属性? |
-s | 侦测该文件名是否存在且为“非空白文件”? |
3. 两个文件之间的比较,如:test file1 -nt file2
测试符号 | 代表意义 |
-nt | ( newer than) 判断 file1 是否比 file2 新 |
-ot | ( older than) 判断 file1 是否比 file2 旧 |
-ef | 判断 file1 与 file2 是否为同一文件, 可用在判断 hard link 的判定上。 主要意 义在判定, 两个文件是否均指向同一个 inode 哩! |
4. 关于两个整数之间的判定,例如test n1 -eq n2
测试符号 | 代表意义 |
-eq | 两数值相等 (equal) |
-ne | 两数值不等 (not equal) |
-gt | n1 大于 n2 (greater than) |
-lt | n1 小于 n2 ( less than) |
-ge | n1 大于等于 n2 ( greater than or equal) |
-le | n1 小于等于 n2 ( less than or equal) |
5. 判定字串的数据
测试符号 | 代表意义 |
test -z string | 判定字串是否为 0 ? 若 string 为空字串, 则为 true |
test -n string | 判定字串是否非为 0 ? 若 string 为空字串, 则为 false。 -n 亦可省略 |
test str1 == str2 | 判定 str1 是否等于 str2 , 若相等, 则回传 true |
test str1 != str2 | 判定 str1 是否不等于 str2 , 若相等, 则回传 false |
6. 多重条件判定, 例如:test -r filename -a -x filename
测试符号 | 代表意义 |
-a | ( and) 两状况同时成立! 例如 test -r file -a -x file, 则 file 同时具有 r 与 x 权限时, 才回传 true。 |
-o | ( or) 两状况任何一个成立! 例如 test -r file -o -x file, 则 file 具有 r 或 x 权限时, 就可回传 true。 |
! | 反相状态, 如 test ! -x file , 当 file 不具有 x 时, 回传 true |
10. 括号表达式判断
10.1 方括号判断
test命令能够用于流程控制语句的判断环节,也可以使用[]方括号来作为判断。如同样可以获得判断的返回值:
ubuntu@localhost:~$ [ -e example ]; echo $?
0
以下以if-then为例来介绍其用法(摘自Linux命令行与shell脚本编程大全第3版):
#!/bin/bash
value1=10
value2=11
#使用方括号来作为if-then条件判断语句的数值内容判断
if [ $value1 -gt 5 ]
then
echo "The test value $value1 is greater than 5"
fi
if [ $value1 -eq $value2 ]
then
echo "The values are equal"
else
echo "The values are different"
fi
10.2 双括号判断
双括号一般用于对数值型数据的判断,常用的符号类型如下:
符号 | 描述 |
val++ | 后增 |
val-- | 后减 |
++val | 先增 |
--val | 先减 |
! | 逻辑求反 |
~ | 位求反 |
** | 幂运算 |
<< | 左位移 |
>> | 右位移 |
& | 位与运算 |
| | 位或运算 |
&& | 逻辑与运算 |
|| | 逻辑或运算 |
举例如下:
#!/bin/bash
val1=10
if (( $val1 ** 2 > 90 ))
then
(( val2 = $val1 ** 2 ))
echo "The square of $val1 is $val2"
fi
10.3 双方括号判断
双方括号[[]]能够提供针对字符串比较的高级特性,并且能够使用正则表达式来进行模式匹配。不过双方括号在bash中支持良好,却并不是所有的shell都支持。如下所示,使用双等号(==)将右侧的字符串视为一个匹配模式:
#!/bin/bash
USER=rich
if [[ $USER == r* ]]
then
echo "Hello $USER"
else
echo "Sorry, I do not know you"
fi
11. 流程控制结构
关于流程控制结构,无非也就是与其他编程语言相类似的顺序结构、条件判断、循环结构等,所以这里只介绍条件判断和循环结构的基本语法。
11.1 if-then条件判断
单一条件判断结构:
if [ 条件判断式 ]; then
command
fi
分支条件判断结构:
if [ 条件判断式 ]; then
command1
else
command2
fi
多重条件判断结构:
if [ 条件判断式一 ]; then
command1
elif [ 条件判断式二 ]; then
command2
else
command3
fi
注意:if-then判断语句中的分号使用时,若if和then关键字放在同一行,则分号必须有,若then放在if的下一行,分号可有可无。
11.2 case条件判断
case $变量 in 迭代对象
"匹配内容1")
command1
;;
"匹配内容2")
command2
;;
*)
commandn
exit 1
;;
esac
case条件判断类似于其他语言中的switch-case结构,$变量依次迭代对象。每个选项中的匹配内容建议用双引号括起来,并且小括号作为关键字不可缺少,一个分支结束时使用两个分号表示。最后一项中使用星号"*"表示除之前所有选项之外的默认执行操作。例如:
#!/bin/bash
read USER
case $USER in
rich | barbara)
echo "Welcome, $USER"
echo "Please enjoy your visit"
;;
testing)
echo "Special testing account"
;;
jessica)
echo "Do not forget to log off when you're done"
;;
*)
echo "Sorry, you are not allowed here"
;;
esac
11.3 for循环
for循环的结构语法表示有如下两种方式:
for var in list
do
commands
done
以及:
for (( 初始值; 限制值; 执行步阶 ))
do
commands
done
其中,前一种方式中var为变量,list中包含多个由变量var进行迭代的数据,可以是字符串,也可以是数值型。后一种方式更类似于C语言中的for循环,用于数值型数据的处理中。举例如下(摘自Linux命令行与Shell脚本编程大全(第3版)):
for test in Alabama Alaska Arizona Arkansas California Colorado
do
echo "The next state is $test"
done
注:由多个字符串共同组成test迭代的选项
数值累加:
for (( i=1; i <= 10; i++ ))
do
echo "The next number is $i"
done
读取目录中的数据,判断是文件还是目录:
for file in /home/rich/test/*
do
if [ -d "$file" ]
then
echo "$file is a directory"
elif [ -f "$file" ]
then
echo "$file is a file"
fi
done
11.4 while循环
while循环的结构如下:
while test command
do
commands
done
其中的test command就是如test判断、方括号判断等最终能够拿到布尔逻辑值的内容。当条件满足时循环不断执行,直到test判断条件不满足时退出循环。
11.5 until循环
until循环结构如下:
until test command
do
commands
done
until循环和while循环的不同之处就在于test判断条件的设置,在同样的test判断条件下,while循环会在满足判断条件时继续执行循环,until会在不满足判断条件时继续执行循环,两者正好相反。
11.6 创建函数
函数的使用能够让shell语言更加具有结构化特点,具体的语法结构有以下两种:
#通过function关键字来创建函数
function name {
commands
}
#类似于其他语言的函数创建方式
name() {
commands
}
12. Shell 脚本示例
(部分摘自跟老男孩学Linux运维:web集群实战)
12.1 检测3306端口是否正常开放
#!/bin/bash
if [ `netstat -lnt | grep 3306 | awk -F "[ :]"+ '{print $5}'` -eq 3306 ]
then
echo "Mysql is Running."
else
echo "Mysql is Stopped."
/etc/init.d/mysqld start
fi
12.2 利用openssl生成随机数
#!/bin/bash
Path=/home/haha
[ -d "$Path" ]||mkdir -p $Path
for n in `seq 10`
do
random=$(openssl rand -base64 40 | sed 's#[^a-z]##g' |cut -c 2-11)
touch $Path/${random}_practices_file
done
12.3 批量创建用户,并设置随机数密码
#!/bin/bash
. /etc/init.d/functions
user="haha"
passfile="/tmp/user.log"
for num in `seq -w 16 20`
do
pass="`echo "test$RANDOM" |md5sum | cut -c 3-11`"
useradd $user$num &> /dev/null && echo "$pass" |passwd --stdin $user$num &>/dev/null && echo -e "user:$user$num\tpasswd:$pass">>$passfile
if [ $? -eq 0 ]
then
action "$user$num is ok" /bin/true
else
action "$user$num is fail" /bin/false
fi
done
echo ----------------------
cat $passfile && >$passfile
12.4 检测局域网存活主机IP地址
#!/bin/bash
CMD="ping -W 2 -c 2"
IP="172.16.31."
for n in $(seq 254)
do
{
$CMD $IP$n &> /dev/null
if [ $? -eq 0 ];then
echo "$IP$n is ok"
fi
}&
done
参考资料:
1. 《跟老男孩学Linux运维:Shell编程实战》
2. https://blog.csdn.net/weixin_39212776/article/details/81079727
3. https://www.jianshu.com/p/762d4cccee7e
4. https://www.cnblogs.com/lizhouwei/p/9991846.html
5. https://blog.csdn.net/linxi_hnh/article/details/8463853
6.《Linux命令行与Shell脚本编程大全(第3版)》
7.《跟老男孩学Linux运维:web集群实战》
博客与公众号同步发文,欢迎关注: