day51-小白都能学的懂的 shell 实战编程

1. 如何才能学好Shell编程。

1.1 为什么要学Shell编程?

Shell脚本语言是实现Linux/UNIX系统管理及自动化运维所必备的重要工具,Linux/UNIX系统的底层及基础应用软件的核心大都涉及Shell脚本的内容。每一个合格的Linux系统管理员或运维工程师,都需要能够熟练的编写Shell脚本语言,并能够阅读系统及各类软件附带的Shell脚本内容。只有这样才能提升运维人员的工作效率,适应日益复杂的工作环境,减少不必要的重复工作。

1.2 学好Shell编程所需的Linux基础

1)熟练使用vim编辑器。
2)熟练掌握120个左右Linux运维基础命令。
3)熟练掌握Linux正则表达式及三剑客。

1.3 如何才能学好Shell编程

1)掌握Shell脚本基本语法的方法。
2)掌握Shell脚本的各种常见语法。
3)从简单做起,简单判断,简单循环。
4)锻炼编程思维,形成自己的脚本开发风格,要多试着去解决企业实际问题。切记拿来主义。

1.3 学好Shell编程最关键的条件

1)多练习,多敲。学好Shell编程,没有捷径可走。

2. Shell脚本初步入门

2.1 什么是Shell

Shell就是一个命令解释器,它的作用就是解释执行用户输入的命令及程序等,用户输入的每一条命令,Shell就解释执行一条。这种从键盘一输入命令,就可以立即得到回应的对话方式,称为交互式的方式。下图就是一个命令解释器Shell在操作系统中所处位置的基本图解。


day51-小白都能学的懂的 shell 实战编程_第1张图片

2.2 什么是Shell脚本

当命令或程序语句不在命令行执行,而是通过一个程序文件来执行时,该程序就被称为Shell脚本,也就是说,Shell脚本就是由命令、变量、流程控制语句等组成的。
初学者如果想要快速的掌握Shell脚本的编写方法,最有效的思路就是采用电子游戏中过关的方式,如下:

第一关:必须是root才能执行脚本,否则给出友好提示并终止脚本运行。
第二关:切换目录的时候,必须要成功切换才行,否则给出友好提示并终止脚本运行。
第三关:清理日志文件时,若清理成功,则给出正确提示。
第四关:通关成功或通关失败,分别给出相应的提示。

2.3 Shell脚本在Linux运维工作中的地位

Shell脚本语言很适合用于处理纯文本类型的数据,在Linux系统中几乎所有的配置文件、日志文件及绝大多数的启动文件都是纯文本类型的文件。那么可想而知,Shell脚本在Linux运维中的地位有多重要了,就如下图所示一样:

day51-小白都能学的懂的 shell 实战编程_第2张图片

2.4 脚本语言的种类

2.4.1 Shell脚本语言的种类

Shell脚本语言是弱类型语言(无须定义变量的类型即可使用),在Unix\Linux中主要有两大类Shell:一类是Bourne shell,另一类是C shell。

1. Bourne shell

Bourne shell 又包括了Bourne shell(sh)、Korn shell(ksh)、Bourne Again shell(bash)三种类型。

2. C shell

C shell 又包括csh、tcsh两种类型。
可以通过以下命令查看CentOS7系统的Shell支持情况。

[root@web01 ~]# cat /etc/shells 
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash

2.4.2 其他常用的脚本语言种类

1. PHP语言

PHP是网页程序语言,同时也是脚本语言。它是一款更专注于Web页面开发(前端展示)的语言。

2. Perl语言

Perl脚本语言比Shell脚本语言更加强大,它的语法灵活、复杂,在实现不同的功能时可以用多种不同的方式,缺点是不易读,团队协作困难。

3. Python语言

Python不但可以用于脚本程序开发,还可以实现Web页面程序开发,甚至还可以实现软件的开发、游戏开发、大数据开发、移动端开发。

2.4.3 Shell脚本语言的优势

Shell脚本语言的优势在于处理偏操作系统底层的业务。对于一些常见的系统脚本,使用Shell脚本开发会更简单、更快速,例如:让软件一键自动化安装、优化,监控报警脚本,软件启动脚本,日志分析脚本等。

2.5 常用操作系统默认的Shell

Linux系统下默认的Shell是Bourne Again shell(bash);Solaris和FreeBSD下默认的是Bourne(sh);AIX下默认的是Korn Shell(ksh)。
通过以下两种方法可以查看CentOS Linux系统默认的Shell。
方法1:

[root@web01 ~]# echo $SHELL
/bin/bash

方法2:

[root@web01 ~]# grep "^root" /etc/passwd|awk -F ":" '{print $NF}'
/bin/bash

2.6 Shell脚本的建立和执行

2.6.1 Shell脚本的建立

1. 脚本开头(第一行)

一个规范的Shell脚本在第一行会指出由哪个程序(解释器)来执行脚本中的内容,如下:

#!/bin/bash
或
#!/bin/sh

期中,开头的#号又称为幻数符,在执行bash脚本的时候,内核会根据“#!”后的解释器来确定用哪个程序解释这个脚本中的内容。

2. bash与sh的区别

sh为bash的软连接,大多数情况下,脚本开头使用“#!/bin/bash”和“#!/bin/sh”是没有区别的,但更加规范的写法是在脚本的开头使用“#!/bin/bash”。

[root@m01 ~]# ll /bin/sh
lrwxrwxrwx. 1 root root 4 Apr 28 19:23 /bin/sh -> bash

Linux中常用脚本开头的写法如下:

#!/bin/sh
#!/bin/bash
#!/usr/bin/awk
#!/bin/sed
#!/usr/bin/tcl
#!/usr/bin/expect       #<===expect语言解释器
#!/usr/bin/perl         #<===perl语言解释器
#!/usr/bin/env python   #<===python语言解释器

如果在脚本开头的第一行不指定解释器,那么就要用对应的解释器来执行脚本,这样才能确保脚本正确执行。例如:

Shell脚本,用bash或sh test.sh来执行。
Python脚本,用python test.py来执行。
expect脚本,用expect test.exp来执行。

3. 脚本注释

在Shell脚本中,#号后面的内容表示注释,用来对脚本进行注释说明,注释部分不会被当做程序来执行,仅仅是给开发者和使用者看的。注释的时候尽量不要用中文,脚本内容中也不要有中文。

2.6.2 Sehll脚本的执行

当Shell脚本运行时,它会先查找系统环境变量ENV,该变量指定了环境变量文件(加载顺序通常是/etc/profile、~/.bash_profile、~/.bash、/etc/bashrc等),在加载了上述环境变量文件后,Shell就开始执行Shell脚本中的内容。
Shell脚本执行的顺序是从上至下、从左至右依次执行每一行的命令及语句的,即执行完了一个命令后再执行下一个,如果在Shell脚本中遇到子脚本(即脚本嵌套)时,就会先执行子脚本的内容,完成后再返回父脚本继续执行父脚本内后续的命令及语句。
通常情况下,在执行Shell脚本时,会向系统内核请求启动一个新的进程,以便在该进程中执行脚本的命令及子Shell脚本,基本流程如下所示:

day51-小白都能学的懂的 shell 实战编程_第3张图片

特别注意:设置Linux的crond任务时,最好能在定时任务脚本中重新定义系统环境变量,否则,一些系统环境变量将不会被加载。

Shell脚本执行的方式

1)bash script-name 或 sh script-name:这是当脚本文件本身没有可执行权限时常用的方法。
2)cat script-name|sh
3)sh 4)./script-name:在当前路径下执行脚本文件,需要脚本文件本身有可执行权限。
5)source script-name 或 . script-name:不需要脚本文件有可执行权限。

范例2-4:创建模拟脚本test.sh。
第1种方法执行:

[root@m01 ~]# echo 'echo I am oldboy' > test.sh
[root@m01 ~]# cat test.sh
echo I am oldboy
[root@m01 ~]# sh test.sh
I am oldboy
[root@m01 ~]# bash test.sh
I am oldboy

第2种方法执行:

[root@m01 ~]# ll test.sh 
-rw-r--r-- 1 root root 17 May 27 19:50 test.sh
[root@m01 ~]# ./test.sh  
-bash: ./test.sh: Permission denied  #<===由于没有可执行权限,所以执行失败,甚至连tab补全都不可以
[root@m01 ~]# . test.sh #<===虽然没有可执行权限,但是可以用.或source来执行
I am oldboy
[root@m01 ~]# source test.sh  #<===.或source命令功能相同,都是读入脚本并执行脚本
I am oldboy

给test.sh添加可执行权限,命令如下:

[root@m01 ~]# chmod u+x test.sh 
[root@m01 ~]# ./test.sh 
I am oldboy

第3种方法执行:

[root@m01 ~]# echo 'userdir=`pwd`' > testsource.sh
[root@m01 ~]# cat testsource.sh
userdir=`pwd`
[root@m01 ~]# sh testsource.sh   #<===执行后没有内容显示
[root@m01 ~]# echo $userdir   #<===echo 变量也没有内容显示,解决方法如下

[root@m01 ~]# source testsource.sh
[root@m01 ~]# echo $userdir
/root

上述结果总结:

通过source或“.”加载执行过的脚本,由于是在当前Shell中执行脚本,因此脚本运行结束后,脚本中的变量(包括函数)值在当前Shell依然存在,而sh和bash执行脚本都会启动新的子Shell执行,执行完后回退到父Shell。 因此,变量(包括函数)值等无法保留。在进行Shell脚本开发时,如果脚本中有引用或执行其他脚本的内容或配置文件需求时,最好用“.”或source先加载该脚本或配置文件,处理后,再将它们加载到脚本下面,就可以调用source加载的脚本及配置文件中的变量函数等内容了。

第4种方法执行:

[root@web01 /server/scripts]# ll oldboy.sh
-rw-r--r-- 1 root root 246 May 31 15:24 oldboy.sh
[root@web01 /server/scripts]# cat oldboy.sh
#!/bin/bash
##############################################################
# File Name: test.sh
# Version: V1.0
# Author: oldboy
# Organization: www.oldboyedu.com
##############################################################
echo 'I am oldboy.'
[root@web01 /server/scripts]# sh < oldboy.sh    <===不推荐使用这种方法
I am oldboy.
[root@web01 /server/scripts]# cat oldboy.sh|bash
I am oldboy.

已知如下命令返回结果,请问echo $used的返回结果为()?

[root@web01 /server/scripts]# cat test.sh
#!/bin/bash
##############################################################
# File Name: test.sh
# Version: V1.0
# Author: oldboy
# Organization: www.oldboyedu.com
##############################################################
user=`whoami`
[root@web01 /server/scripts]# sh test.sh
[root@web01 /server/scripts]# echo $user

参考答案如下:
a)当前用户
b)root
c)没有内容输出

通过上述面试题得出如下结论:
子Shell脚本会直接继承父Shell脚本的变量、函数等,反之则不能。
如果希望父Shell也能够继承子Shell的脚本变量、函数等,就要使用source或.在父Shell脚本中事先加载子Shell脚本,也就是先把结果弄出来。

2.6.3 Shell脚本开发的基本习惯推荐

1)Shell脚本的第一行是指定脚本解释器,通常为:

#!/bin/bash
或
#!/bin/sh                                                                                                                               
~                                                                                                                                       
~ 

2)Shell脚本的开头会加版本、版权等信息:

#!/bin/bash
##############################################################
# File Name: 1.sh
# Version: V1.0
# Author: oldboy
# Organization: www.oldboyedu.com
##############################################################   

3)在Shell脚本中尽量不要用中文(不限于注释)。

4)Shell脚本的命名应以.sh为扩展名。

[root@web01 /server/scripts]# ls
1.sh  222.sh  9_1.sh  9_2_2.sh  9_2_3.sh  9_2.sh  oldboy.sh  oldgirl.sh  plush_color.sh  test.sh

5)Shell脚本应存放在固定的路径下。

[root@web01 /server/scripts]#

以下则是Shell脚本代码书写的良好习惯。

1)成对的符号应尽量一次性写出来,然后退格在符号里增加内容,以防止遗漏。这些成对的符号包括:

{ }
[ ]
' '
` `
" " 

2)中括号([ ])两端至少要有一个空格。

[ $a -eq 0 ]

3)对于流程控制语句,应一次性将格式写完,再添加内容。
比如,一次性完成if语句的格式,应为:

#!/bin/bash
##############################################################
# File Name: 5.sh
# Version: V1.0
# Author: oldboy
# Organization: www.oldboyedu.com
##############################################################
if
then
fi     

一次性完成for循环语句的格式,应为:

#!/bin/bash
##############################################################
# File Name: 5.sh
# Version: V1.0
# Author: oldboy
# Organization: www.oldboyedu.com
##############################################################
for
do
done  

4)通过缩进让代码更易读,比如:

#!/bin/bash
##############################################################
# File Name: 5.sh
# Version: V1.0
# Author: oldboy
# Organization: www.oldboyedu.com
##############################################################
if [ 条件内容 ]
  then
    内容                                                                                                                                
fi

5)对于常规变量的字符串定义变量应加双引号,并且等号前后不能有空格,需要强引用的(指所见即所得的字符引用),则用单引号(’’),如果是命令的引用,则用反引号(``)。例如:

#!/bin/bash
##############################################################
# File Name: 5.sh
# Version: V1.0
# Author: oldboy
# Organization: www.oldboyedu.com
##############################################################
OLDBOY="test.txt"
a=`who`

6)脚本中的单引号、双引号及反引号必须为英文状态下的符号,其实所有的Linux字符及符号都应该是英文状态下的符号,这点需要特别注意。

你可能感兴趣的:(day51-小白都能学的懂的 shell 实战编程)