bash脚本编程基础

1.1.1 为什么学Shell

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

1.1.2 什么是shell

Shell是一个命令解释器,它在操作系统的最外层,负责直接与用户对话,把用户的输入解释给操作系统,并处理各种各样的操作系统的输出结果,输出屏幕返回给用户。

这种对话方式可以是:

交互的方式:从键盘输入命令,通过/bin/bash的解析,可以立即得到Shell的回应

[root@clsn ~]# ls            
anaconda-ks.cfg  
[root@clsn ~]# echo ls |bash 
anaconda-ks.cfg   

非交互的方式: 脚本

1.1.3 什么是Shell脚本

  命令、变量和流程控制语句等有机的结合起来

         shell脚本擅长处理纯文本类型的数据,而linux中,几乎所有的配置文件,日志,都是纯文本类型文件

1.1.4 脚本语言的种类

一、编译型语言

定义:指用专用的编译器,针对特定的操作平台(操作系统)将某种高级语言源代码一次性翻译成可被硬件平台直接运行的二进制机器码(具有操作数,指令、及相应的格式),这个过程叫做编译(./configure  make makeinstall );编译好的可执行性文件(.exe),可在相对应的平台上运行(移植性差,但运行效率高)。。

典型的编译型语言有, C语言、C++等。

另外,Java语言是一门很特殊的语言,Java程序需要进行编译步骤,但并不会生成特定平台的二进制机器码,它编译后生成的是一种与平台无关的字节码文件(*.class)(移植性好的原因),这种字节码自然不能被平台直接执行,运行时需要由解释器解释成相应平台的二进制机器码文件;大多数人认为Java是一种编译型语言,但我们说Java即是编译型语言,也是解释型语言也并没有错。

二、解释型语言

定义:指用专门解释器对源程序逐行解释成特定平台的机器码并立即执行的语言;相当于把编译型语言的编译链接过程混到一起同时完成的。

解释型语言执行效率较低,且不能脱离解释器运行,但它的跨平台型比较容易,只需提供特定解释器即可。

常见的解释型语言有, Python(同时是脚本语言)与Ruby等。

三、脚本语言

定义:为了缩短传统的编写-编译-链接-运行(edit-compile-link-run)过程而创建的计算机编程语言。

特点:程序代码即是最终的执行文件,只是这个过程需要解释器的参与,所以说脚本语言与解释型语言有很大的联系。脚本语言通常是被解释执行的,而且程序是文本文件。

典型的脚本语言有,JavaScript,Python,shell等。

其他常用的脚本语句种类

PHP是网页程序,也是脚本语言。是一款更专注于web页面开发(前端展示)的脚本语言,例如:Dedecms,discuz。PHP程序也可以处理系统日志,配置文件等,php也可以调用系统命令。

Perl脚本语言。比shell脚本强大很多,语法灵活、复杂,实现方式很多,不易读,团队协作困难,但仍不失为很好的脚本语言,存世大量的程序软件。MHA高可用Perl写的

Python,不但可以做脚本程序开发,也可以实现web程序以及软件的开发。近两年越来越多的公司都会要求会Python。

Shell脚本与php/perl/python语言的区别和优势?

shell脚本的优势在于处理操作系统底层的业务 (linux系统内部的应用都是shell脚本完成)因为有大量的linux系统命令为它做支撑。2000多个命令都是shell脚本编程的有力支撑,特别是grep、awk、sed等。例如:一键软件安装、优化、监控报警脚本,常规的业务应用,shell开发更简单快速,符合运维的简单、易用、高效原则.

  PHP、Python优势在于开发运维工具以及web界面的管理工具,web业务的开发等。处理一键软件安装、优化,报警脚本。常规业务的应用等php/python也是能够做到的。但是开发效率和复杂比用shell就差很多了。

系统环境说明

[root@clsn scripts]# cat /etc/redhat-release  #查看当前版本
CentOS Linux release 7.4.1708 (Core) 
[root@clsn scripts]# uname -r   #查看当前内核版本
3.10.0-693.el7.x86_64
[root@clsn scripts]# getenforce   #使用getenforce命令可以显示当前SELinux的应用模式,是强制、执行还是停用。98
Disabled
[root@clsn scripts]# systemctl status firewalld.service  #查看当前防火墙状态
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
   Active: inactive (dead)
     Docs: man:firewalld(1)

                     补充:

                              uname命令:操作系统信息的显示

                              uname 命令主要用于显示操作系统的信息,包括版本、平台的信息。

                                它的参数主要有以下:

                                        -a 显示全部信息

                                        -s 显示内核名称

                                        -n 显示主机名

                                        -r 显示当前系统的内核版本

                                        -m 显示主机的硬件名称

                                        -p 显示处理器的类型

                                        -i 显示主机的硬件平台

                                       -o 显示所使用的操作系统的名称

                             扩展:[root@redhat ~]# getconf LONG_BIT  //查看当前系统为32位

                                        [root@redhat ~]# cat /etc/issue    //查看当前系统的类型

1.1.5 系统中的shell

查看系统中的命解释器

[root@clsn ~]# cat /etc/shells   #显示系统拥有的shell
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin

常用操作系统的默认shell

1.Linux是Bourne Again shell(bash)

2.Solaris和FreeBSD缺省的是Bourne shell(sh)

3.AIX下是Korn Shell(ksh)

4.HP-UX缺省的是POSIX shell(sh)

[root@clsn ~]# echo $SHELL  #显示当前默认sell
/bin/bash

bash版本

[root@clsn scripts]# bash -version  #显示当前shell版本
GNU bash, 版本 4.2.46(2)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
许可证 GPLv3+: GNU GPL 许可证版本3或者更高 

这是自由软件,您可以自由地更改和重新发布。
在法律允许的范围内没有担保. 

1.2 脚本书写规范

1.2.1 脚本统一存放目录

[root@clsn ~]# mkdir -p /server/scripts/
[root@clsn ~]# cd /server/scripts/

1.2.2 选择解释器

注意格式 ↓

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

[root@clsn scripts]# head -1 /etc/init.d/*
==> /etc/init.d/functions <==
# -*-Shell-script-*-

==> /etc/init.d/netconsole <==
#!/bin/bash

==> /etc/init.d/network <==
#! /bin/bash

1.2.3 编辑脚本使用vim

使用 .vimrc 文件,能够快速的生成开头的注释信息

[root@clsn scripts]# cat  ~/.vimrc 
autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()"

func SetTitle()
    if expand("%:e") == 'sh'
        call setline(1,"#!/bin/bash")
        call setline(2, "##############################################################")
        call setline(3, "# File Name: ".expand("%"))
        call setline(4, "# Version: V1.0")
        call setline(5, "# Author: clsn")
        call setline(6, "# Organization: http://blog.znix.top")
        call setline(7, "# Created Time : ".strftime("%F %T"))
        call setline(8, "# Description:")
        call setline(9, "##############################################################")
        call setline(10, "")
    endif
endfunc

使用后的效果

[root@clsn scripts]# cat  scripts_test.sh 
#!/bin/bash
##############################################################
# File Name: scripts_test.sh
# Version: V1.0
# Author: clsn
# Organization: http://blog.znix.top
# Created Time : 2017-12-04 11:39:57
# Description:  First scripts file
##############################################################

在Shell脚本中,跟在#后面的内容表示注释。注释部分不会被执行,仅给人看。注释可以自成一行,也可以跟在命令后面,与命令同行。要养成写注释的习惯,方便自己与他人。

最好不用中文注释,因为在不同字符集的系统会出现乱码。(字符集为zh_CN.UTF-8,为中文)。

1.2.4 文件名规范

         名字要有意义,并且结尾以 .sh 结束

1.2.5 开发的规范和习惯小结

1) 放在统一的目录

2) 脚本以.sh为扩展名

3) 开头指定脚本解释器。

4) 开头加版本版权等信息,可配置~/.vimrc文件自动添加。

5) 脚本不要用中文注释,尽量用英文注释。

6) 代码书写优秀习惯

  a、成对的内容一次性写出来,防止遗漏,如[  ]、' '、" "等

  b、[  ]两端要有空格,先输入[  ],退格,输入2个空格,再退格写。

  c、流程控制语句一次书写完,再添加内容。(if 条件 ; then  内容;fi)ddd

  d、通过缩进让代码易读。

  f、脚本中的引号都是英文状态下的引号,其他字符也是英文状态。

1.3 shell脚本的执行

1.3.1 执行脚本的办法

sh/bash   scripts.sh 
chown +x   ./scripts.sh  && ./scripts.sh  
source scripts.sh
. (空格) scripts.sh
cat oldboyedu.sh |bash  # 效率较低

source 与 . (点) 的作用

soucre命令

[root@clsn ~]# help source  |head -2
source: source 文件名 [参数]
    在当前 shell 中执行一个文件中的命令。

. (点)

[root@clsn scripts]# help . |head -2
.: . 文件名 [参数]
    在当前 shell 中执行一个文件中的命令。

1.3.2 sh 于 source的区别

[root@clsn scripts]# sh  clsn_test.sh 
Hello World!
[root@clsn scripts]# echo $clsn
#  sh  新建一个Shell窗口(新建一个进程)执行一个文件中的命令。

[root@clsn scripts]# source clsn_test.sh 
Hello World!
[root@clsn scripts]# echo $clsn
Hello World!

补充:

Linux中执行 .sh 的方法
复制代码
linux下执行.sh文件的方法
   .sh文件就是文本文件,如果要执行,需要使用chmod a+x xxx.sh来给可执行权限。  
   
   是bash脚本么
  可以用touch test.sh #创建test.sh文件
  vi test.sh #编辑test.sh文件
  加入内容
  #!/bin/bash
   mkdir test
   保存退出。
  chmod a+x test.sh #给test.sh可执行权限
  如test,sh文件在 /home/work文件下
  执行
  方法一 本身目录下运行
  进入 cd /home/workwen文件下
  执行 ./test.sh
   命令会在当前目录下创建一个“test”目录。
  方法二 绝对路劲运行
  执行 /home/work/test.sh  
  方法三 本身目录下运行
  sh test.sh 
   最后建议:使用
  
   C代码 
  1.man sh    
   man sh 来看看sh 的介绍~


Linux.sh语法


介绍:
1 开头
 程序必须以下面的行开始(必须方在文件的第一行):
#!/bin/sh
  符号#!用来告诉系统它后面的参数是用来执行该文件的程序。在这个例子中我们使用/bin/sh来执行程序。
 当编写脚本完成时,如果要执行该脚本,还必须使其可执行。
 要使编写脚本可执行:
 编译 chmod +x filename 这样才能用./filename 来运行
2 注释
 在进行shell编程时,以#开头的句子表示注释,直到这一行的结束。我们真诚地建议您在程序中使用注释。
 如果您使用了注释,那么即使相当长的时间内没有使用该脚本,您也能在很短的时间内明白该脚本的作用及工作原理。
3 变量
 在其他编程语言中您必须使用变量。在shell编程中,所有的变量都由字符串组成,并且您不需要对变量进行声明。要赋值给一个变量,您可以这样写:
#!/bin/sh
  #对变量赋值:
 a=”hello world”
# 现在打印变量a的内容:
 echo “A is:”
 echo $a
有时候变量名很容易与其他文字混淆,比如:
 num=2
  echo “this is the $numnd”
 这并不会打印出”this is the 2nd”,而仅仅打印”this is the “,因为shell会去搜索变量numnd的值,但是这个变量时没有值的。可以使用花括号来告诉shell我们要打印的是num变量:
 num=2
  echo “this is the ${num}nd”
 这将打印: this is the 2nd
 4 环境变量
 由export关键字处理过的变量叫做环境变量。我们不对环境变量进行讨论,因为通常情况下仅仅在登录脚本中使用环境变量。
5 Shell命令和流程控制
 在shell脚本中可以使用三类命令:
1)Unix 命令:
  虽然在shell脚本中可以使用任意的unix命令,但是还是由一些相对更常用的命令。这些命令通常是用来进行文件和文字操作的。
 常用命令语法及功能
 echo “some text”: 将文字内容打印在屏幕上
 ls: 文件列表
 wc –l filewc -w filewc -c file: 计算文件行数计算文件中的单词数计算文件中的字符数
 cp sourcefile destfile: 文件拷贝
 mv oldname newname : 重命名文件或移动文件
 rm file: 删除文件
 grep ‘pattern’ file: 在文件内搜索字符串比如:grep ’searchstring’ file.txt
  cut -b colnum file: 指定欲显示的文件内容范围,并将它们输出到标准输出设备比如:输出每行第5个到第9个字符cut -b5-9 file.txt千万不要和cat命令混淆,
 这是两个完全不同的命令
 cat file.txt: 输出文件内容到标准输出设备(屏幕)上
 file somefile: 得到文件类型
 read var: 提示用户输入,并将输入赋值给变量
 sort file.txt: 对file.txt文件中的行进行排序
 uniq: 删除文本文件中出现的行列比如: sort file.txt | uniq
  expr: 进行数学运算Example: add 2 and 3expr 2 “+” 3
  find: 搜索文件比如:根据文件名搜索find . -name filename -print
  tee: 将数据输出到标准输出设备(屏幕) 和文件比如:somecommand | tee outfile
  basename file: 返回不包含路径的文件名比如: basename /bin/tux将返回 tux
  dirname file: 返回文件所在路径比如:dirname /bin/tux将返回 /bin
  head file: 打印文本文件开头几行
 tail file : 打印文本文件末尾几行
 sed: Sed是一个基本的查找替换程序。可以从标准输入(比如命令管道)读入文本,并将
 结果输出到标准输出(屏幕)。该命令采用正则表达式(见参考)进行搜索。不要和shell中的通配符相混淆。比如:将linuxfocus替换为 LinuxFocus :cat text.file | sed ’s/linuxfocus/LinuxFocus/’ >newtext.fileawk: awk 用来从文本文件中提取字段。缺省地,字段分割符是空格,可以使用-F指定其他分割符。
 catfile.txt | awk -F, ‘{print $1 “,” $3}’这里我们使用,作为字段分割符,同时打印第一个和第三个字段。如果该文件内容如下: Adam Bor, 34, IndiaKerryMiller, 22, USA命令输出结果为:Adam Bor, IndiaKerry Miller, USA
 2) 概念: 管道, 重定向和 backtick
  这些不是系统命令,但是他们真的很重要。
 管道 (|) 将一个命令的输出作为另外一个命令的输入。
 grep “hello” file.txt | wc -l
  在file.txt中搜索包含有”hello”的行并计算其行数。
 在这里grep命令的输出作为wc命令的输入。当然您可以使用多个命令。
 重定向:将命令的结果输出到文件,而不是标准输出(屏幕)。
 > 写入文件并覆盖旧文件
 >> 加到文件的尾部,保留旧文件内容。
 反短斜线
 使用反短斜线可以将一个命令的输出作为另外一个命令的一个命令行参数。
 命令:
 find . -mtime -1 -type f -print
  用来查找过去24小时(-mtime –2则表示过去48小时)内修改过的文件。如果您想将所有查找到的文件打一个包,则可以使用以下linux 脚本:
 #!/bin/sh
  # The ticks are backticks (`) not normal quotes (‘):
  tar -zcvf lastmod.tar.gz `find . -mtime -1 -type f -print`
 3) 流程控制
 1.if
  “if” 表达式 如果条件为真则执行then后面的部分:
 if ….; then
  ….
  elif ….; then
  ….
  else
  ….
  fi
  大多数情况下,可以使用测试命令来对条件进行测试。比如可以比较字符串、判断文件是否存在及是否可读等等…
 通常用” [ ] “来表示条件测试。注意这里的空格很重要。要确保方括号的空格。
 [ -f "somefile" ] :判断是否是一个文件
 [ -x "/bin/ls" ] :判断/bin/ls是否存在并有可执行权限
 [ -n "$var" ] :判断$var变量是否有值
 [ "$a" = "$b" ] :判断$a和$b是否相等
 执行man test可以查看所有测试表达式可以比较和判断的类型。
 直接执行以下脚本:
 #!/bin/sh
  if [ "$SHELL" = "/bin/bash" ]; then
  echo “your login shell is the bash (bourne again shell)”
 else
  echo “your login shell is not bash but $SHELL”
 fi
  变量$SHELL包含了登录shell的名称,我们和/bin/bash进行了比较。
 快捷操作符

 

你可能感兴趣的:(linux)