一起学习Shell脚本

Posted ItStar

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一起学习Shell脚本相关的知识,希望对你有一定的参考价值。

 什么是shell脚本? 

  脚本最初是从演艺界中的一个词,指表演戏剧、拍摄电影等所依据的底本或者书稿的底本。后来,IT行业引用了这个词,我们现在所说的脚本(script)是使用一种特定的描述性语言,依据一定的格式编写的可执行文件,又称作宏或批处理文件。脚本通常可以由应用程序临时调用并执行。shell脚本就是脚本语言中的一种。它不是一门正式的编程语言,因为跑在Linux的shell中,所以就称它为shell脚本。说白了,shell脚本就是一些命令的集合。我们可以利用shell脚本将很多个操作指令记录到一个文档中,然后调用文档中的指令,一次完成所有指令的操作。例如在hadoop中我们启动集群常用到start-all.sh来启动集群中的多个服务。这个start-all.sh就是一个shell脚本,我们今天就来看看start-all是怎样启动集群的。

学习之前,我们要指定两项规定:

  • 我们的自定义脚本建议都放在/user/local/sbin/目录下边,这样做是为了以后更好管理文档,也让以后接管你工作的同事知道脚本放在哪里。

  • 我们的shell脚本文件要将其设置为.sh文件。这样做的目的是为了让别人一看就知道这是一个shell脚本。


下面我们就来写一个Hello World的shell脚本:

  • 创建一个文件:

   
     
     
   
vi shellTest.sh
  • 编写shell脚本

   
     
     
   
#!/bin/bash echo "hello World" #这是一条输出语句
输出结果为: hello World

脚本解析:

  • 第一行中的#是一个约定标记,他告诉系统这个脚本需要什么解释器来执行,后面的/bin/bash就是指明了解释器的具体位置。

  • 第二行echo命令用于向标准输出文件(Standard Output,stdout,一般就是指显示器)输出文本。在.sh文件中使用命令与在终端直接输入命令的效果是一样的。

  • 第二行的#及其后面的内容是注释。(shell中除了开头的#!不是注释,其他的#都是注释)


后续文档参考命令符解释:

$ #$加变量名代表引用这个变量$0 #Shell本身的文件名$1~$n #添加到Shell的各参数值。$1是第1参数、$2是第2参数…。$# #是传给脚本的参数个数. #如果使用” . "执行,则程序继承当前shell中的环境变量,同时,若在程序中改变了当前shell中的环境变量,则当前shell中该环境变量的值也会改变另外一个区别点在于, “ ./ "只能用于拥有执行权限的文件, 而 ” . " 则可以暂时提升执行权限if *** fi #判断语句类似于Java中if{}-f #判断给定的是不是文件case *** in *** esac #类似java中的caseshift #命令表示参数向左偏移,后面可跟数字(数字大小在参数个数范围内)

下面我们再来写一个稍微复杂一点的脚本:

   
     
     
   
#!/usr/bin/env bash bin=`dirname "${BASH_SOURCE-$0}"` bin=`cd "$bin"; pwd` #bin中存储当前脚本所在路径
DEFAULT_LIBEXEC_DIR="$bin"/../libexec #获取HADOOP_LIBEXEC_DIR路径,如果系统环境变量已经配置则用环境变量中路径,否则用获取到的默认的路径 HADOOP_LIBEXEC_DIR=${HADOOP_LIBEXEC_DIR:-$DEFAULT_LIBEXEC_DIR} . $HADOOP_LIBEXEC_DIR/hadoop-config.sh
# start hdfs daemons if hdfs is present if [ -f "${HADOOP_HDFS_HOME}"/sbin/start-dfs.sh ]; then "${HADOOP_HDFS_HOME}"/sbin/start-dfs.sh --config $HADOOP_CONF_DIR fi
# start yarn daemons if yarn is present if [ -f "${HADOOP_YARN_HOME}"/sbin/start-yarn.sh ]; then "${HADOOP_YARN_HOME}"/sbin/start-yarn.sh --config $HADOOP_CONF_DIR fi

脚本解析:

第一行是指定我们的解释器,并指明了解释器的具体位置。


第二行相当于我们将文件目录的字符串赋值给了bin变量,${BASH_SOURCE-$0}这一串是为了获取当前执行的脚本文件的全路径,于是我们的bin就得到了脚本文件的全路径。


第三行我们首先执行了cd "$bin"($加上变量名可以用来引用这个变量),进入了脚本的目录环境,然后又输出了当前目录,并把这个目录给了bin变量。执行完这行之后我们就进入了脚本文件目录环境。并且bin值成为了当前脚本的所在文件。


第四行中我们获取绝对路径以备后用:
${HADOOP_HOME}/libexec

第五行为HADOOP_LIBEXEC_DIR变量三元赋值。如果HADOOP_LIBEXEC_DIR为空或者环境变量没有配置,就赋值默认的绝对路径,为下一步执行该目录下面的脚本做准备。


   第六行执行下面脚本。为后面执行启动各节点和启动YARN做预处理:
   
     
     
   
${HADOOP_HOME}/libexec/hadoop-config.sh
另外要提的是:
如果使用" ./ " 执行,可以理解为程序运行在一个全新的shell中不继承当前shell的环境变量的值同时若在程序中改变了当前shell中的环境变量(不使用export)则当前shell的环境变量值不变。如果使用" . "执行,则程序继承当前shell中的环境变量同时,若在程序中改变了当前shell中的环境变量则当前shell中该环境变量的值也会改变另外一个区别点在于" ./ "只能用于拥有执行权限的文件而 " . "则可以暂时提升执行权限。
第七行执行启动脚本,if是判断语句(类似于Java)fi是if的字母倒序,表示if判断语句结束;-f 做判断是不是文件类型。这段脚本的意图是:
如果${HADOOP_HDFS_HOME}/sbin/start-dfs.sh为文件,则联合--config参数及其后面的参数值执行start-dfs.sh。start-dfs.sh后面做详细分析。


第八行执行YRAN调度服务,这段脚本的意图是:
如果${HADOOP_HDFS_HOME}/sbin/start-yarn.sh为文件,则联合--config参数及其后面的参数值执行start-yarn.sh。start-yarn.sh后面做详细分析。


这就是完整的start-all.sh的shell执行流程。其中涉及到的start-yarn.sh和start-dfs.sh脚本,两个脚本十分类似,我们再看看start-dfs.sh脚本。
#!/usr/bin/env bash# Start hadoop dfs daemons.  # Optinally upgrade or rollback dfs state.  # Run this on master node.    usage="Usage: start-dfs.sh [-upgrade|-rollback]"  #定义usage变量,即start-dfs.sh的使用说明,在后面的内容可以看到,当参数输入错误时,会打印该消息  bin=`dirname "$0"`  bin=`cd "$bin"; pwd`    . "$bin"/hadoop-config.sh    # get arguments  if [ $# -ge 1 ]; then      nameStartOpt=$1      shift      case $nameStartOpt in        (-upgrade)          ;;        (-rollback)           dataStartOpt=$nameStartOpt          ;;        (*)            echo $usage            exit 1          ;;      esac  fi    # start dfs daemons  # start namenode after datanodes, to minimize time namenode is up w/o data  # note: datanodes will log connection errors until namenode starts  "$bin"/hadoop-daemon.sh --config $HADOOP_CONF_DIR start namenode $nameStartOpt  "$bin"/hadoop-daemons.sh --config $HADOOP_CONF_DIR start datanode $dataStartOpt  "$bin"/hadoop-daemons.sh --config $HADOOP_CONF_DIR --hosts masters start secondarynamenode


     前面的代码我们上面已经解释过,不再赘述,要提的是,$0是指shell本身的文件名,其他的类似。后面的完整的判断语句的意思是:如果参数值的个数大于等于1的时候(代表还有服务需要开启),如果参数是upgrade,则设置nameStartOpt变量以备后用;如果是rollback,则设置dataStartOpt变量以备后用。


后面的脚本分别则是用来启动NameNode、DataNode、Master。


以上是关于一起学习Shell脚本的主要内容,如果未能解决你的问题,请参考以下文章

shell 脚本 片段

用于确保在任何给定时间仅运行一个 shell 脚本的 shell 片段 [重复]

Shell脚本的模块化和脚本复用

shell脚本学习总结

常用python日期日志获取内容循环的代码片段

shell脚本引用expect