Skip to content

Latest commit

 

History

History
225 lines (184 loc) · 9.86 KB

在命令行使用函数.md

File metadata and controls

225 lines (184 loc) · 9.86 KB

在命令行使用函数

  • 在脚本中,可以通过函数实现特定的功能,这些函数可以被其他脚本调用来完成更为复杂的逻辑。
  • 如果在命令行上也能使用函数会更为方便,因为可以通过函数实现系统命令不具备的功能。
  • 在命令行执行函数的方式就像执行普通的命令一样。如果在Shell进程中定义了函数,在此Shell进程退出前,都可以调用执行此函数,在同一进程中定义的函数只能在此进程中是可见的
  • 如果想在命令行调用函数,首先要注意的就是函数在当前Shell进程中是可见的。另外,需要了解的是函数的可见性只与执行脚本的进程有直接关系,而环境变量PATH与函数库脚本文件的所在位置有关。如果想在多个脚本中执行函数库脚本文件,这个脚本文件应该在PATH环境变量指定的目录下。

一、命令行创建函数

在命令行上可以创建函数,函数创建后在当前Shell进程中都可以直接调用函数,但是需要注意的是只能在当前进程中可见定义的函数,如果在当前进程中启动新的Shell进程运行脚本,在新的进程中对函数是不可见的。

在命令行定义函数有两种方式:

  • 第一种方式是在一行上定义整个函数,每个命令结束后要用分号,命令解析器会根据分号判断一条命令结束。

    • 1、例子:

         $ add(){ echo $[ $1 + $2 ];} 
         $ add 12 12
         24
         $ function mult(){ echo $[ $1 * $2 ];}
         $ mult 12 12
         144
      
      • 上面的两种方式都是可以的,注意:一条命令结束后要使用分号,哪怕只有一条命令也需要加分号
    • 2、只要当前Shell进程不结束,函数都是可见的,如果启动新的Shell进程,在新的Shell进程中对函数是不可访问的,如下所示。注:在创建函数的Shell进程中函数是可以访问的,直到Shell进程结束

        $ mult 12 12
        144
        $ add 11 11
        22
        注:命令bash不会启动一个新的Shell进程,是当前进程的子进程
        $ bash
        注:在新的进程中函数是不可访问的,即便是子Shell进程
        $ add 100 10
        bash: add: command not found
        注:同上
        $ mult 100 10
        bash: mult: command not found
        注:命令exit终止当前进程,也就是退出子Shell进程
        $ exit
        Exit
        注:从子Shell进程中退出到父进程后,创建的函数又可见了,创建函数的进程
            不结束,创建的函数会一直保存在内存
        $ add 100 10
        110
        注:同上
        $ mult 100 10
        1000
      
    • 上面在命令行创建函数的方式对于简单的函数是可以的,但是如果函数的复杂度很高,存在循环、分支等语句,编写函数就比较麻烦,所以对于较复杂的函数不采用这种方式。

  • 在命令行创建函数的第二种方式是在多行上编写函数不用在每条命令后面添加分号,按回车键换行,在函数最后使用大括号结束,但是要注意,大括号最好换行,如下例子。

      $ function printFile(){
      > for var in /home/yarn/bash01/*
      > do
      >   if [ $var = "/home/yarn/bash01/bash10.sh" ]
      >   then
      >     echo "File $var is exist"
      >   fi
      > done
      > }
      $ printFile
      File /home/yarn/bash01/bash10.sh is exist
    
    • 可以看到第二种方式比第一种方式更清晰,但是不方便修改。函数的使用方式同上例。通过这种方式创建的函数只要Shell进程一结束,创建的函数都将从内存中销毁。另外需要注意的是如果存在同名的函数,后面创建的函数将覆盖之前创建的函数。如果想将创建的函数不会随着Shell进程的结束而销毁,要采用下面的方式。

二、使用.bashrc文件创建命令行函数

  • 直接在命令行创建函数的缺点是当Shell进程结束后,定义的函数将会被销毁。如果想将创建的函数在每一个Shell进程中都可以调用,就需要使用.bashrc配置文件,此配置文件是用户级别的配置文件,每个用户都有自己的.bashrc配置文件。更重要的是当用户登录Shell或每当启动一个新的Bash Shell进程时都会首先执行此脚本文件,在此脚本文件中定义的变量和函数在每个Shell进程中都是可见的。但是这些配置只针对特定的用户。

  • 使用.bashrc文件定义函数有两种方式:

    • 第一种是直接在.bashrc配置文件中定义函数

    • 第二种方式是先创建函数库脚本文件,在.bashrc配置文件中启动脚本。

    • 配置文件.bashrc:

        .bashrc
      
        # Source global definitions
        if [ -f /etc/bashrc ]; then
        	. /etc/bashrc
        fi
      
        # 用户定义的别名和自定义函数
        # User specific aliases and functions
        # …
      
  • 第一种方式是在.bashrc配置文件中直接定义函数,例子如下。.bashrc文件:

      # .bashrc
    
      # Source global definitions
      if [ -f /etc/bashrc ]; then
      	. /etc/bashrc
      fi
    
      # User specific aliases and functions
      # 定义的函数,通过一个命令直接切换到hadoop配置文件目录
      # 不需要使用cd命令和后面的很长的目录
      hadoopConfig(){
        cd /usr/local/hadoop/etc/hadoop
      }
      # 通过函数可以直接切换到hadoop的主目录
      hadoopHome(){
        cd /usr/local/hadoop
      }
      # 通过函数可以切换到hadoop的日志文件目录
      hadoopLog(){
        cd /usr/local/hadoop/logs
      }
      # 通过函数可以切换到hadoop的数据文件目录
      hadoopData(){
        cd /usr/local/hadoop/data
      }
    
    • 上面的四个函数简单但很实用,只要通过一个函数就可以直接跳转到指定的目录,而不用输入很长的目录名。

    • 注意:当定义好函数后函数还不能直接使用,要通过source命令或点操作符允许配置文件,定义好的函数才能保存到内存,如下命令。

       source /home/yarn/.bashrc
       . /home/yarn/.bashrc
      
    • 配置文件运行后定义的函数就可以使用了,如下所示。

       [root@localhost ~]$ pwd
       /home/hadoop01
       [root@localhost ~]$ hadoopConfig
       [root@localhost hadoop]$ pwd
       /usr/local/hadoop/etc/hadoop
       [root@localhost hadoop]$ hadoopLog
       [root@localhost logs]$ pwd
       /usr/local/hadoop/logs
       [root@localhost logs]$ hadoopHome
       [root@localhost hadoop]$ pwd
       /usr/local/hadoop
       [root@localhost hadoop]$ hadoopData
       [root@localhost data]$ pwd
       /usr/local/hadoop/data
      
    • 自定义函数在使用上就像命令,方便使用。第一种方式需要在.bashrc配置文件中添加大量的代码,如果自定义函数很少,这种方式是可以的,如果自定义函数很多,还可以采用第二种方式,将事先定义好的函数库文件在.bashrc配置文件中启动执行。

  • 第二种方式是将定义好的函数脚本文件在配置文件中启动

    • 每启动一个Shell进程都会启动.bashrc配置文件,在配置文件中的命令都将执行。首先创建一个函数脚本文件,如下。hadoopInit.sh:

        #!/bin/bash
      
        # 定义的函数,通过一个命令直接切换到hadoop配置文件目录
        # 不需要使用cd命令和后面的很长的目录
        hadoopConfig(){
          cd /usr/local/hadoop/etc/hadoop
        }
        # 通过函数可以直接切换到hadoop的主目录
        hadoopHome(){
          cd /usr/local/hadoop
        }
        # 通过函数可以切换到hadoop的日志文件目录
        hadoopLog(){
          cd /usr/local/hadoop/logs
        }
        # 通过函数可以切换到hadoop的数据文件目录
        hadoopData(){
          cd /usr/local/hadoop/data
        }
        # 定义一个函数,需要一个参数,将文件或目录拷贝到共享文件夹下
        hadoopCp(){
          if [ $# -eq 1 ]
          then
            if [ -f $1 ]
            then
              cp $1 /mnt/hgfs/LinuxSharedFile
            fi
            if [ -d $1 ]
            then
              cp -r $1 /mnt/hgfs/LinuxSharedFile
            fi
          else
            echo "Input parameter error!"
          fi
        }
      
    • 函数库文件编写完成,脚本文件的所在目录是/home/hadoop01/bash01,在.bashrc配置文件中启动脚本文件,如下例子。.bashrc文件:

       # .bashrc
      
       # Source global definitions
       if [ -f /etc/bashrc ]; then
       	. /etc/bashrc
       fi
      
       # User specific aliases and functions
       # 在当前进程中运行函数库文件
       # 定义变量
       file=/home/yarn/bash01/hadoopInit.sh
       # 判断脚本文件是否存在并且是文件
       if [ -f $file ]
       then
         if [ -x $file ]
         then
           # 在当前Shell进程中运行脚本文件
       . $file
         fi
       fi
      
    • 注意通过source命令运行.bashrc配置文件是库文件生效。可以使用hadoopCp命令将文件或目录拷贝到共享文件夹下,如下所示。

       [root@localhost bash01]$ hadoopCp bash10.sh
       [root@localhost bash01]$ cd ..
       [root@localhost ~]$ hadoopCp bash01
       [root@localhost ~]$ cd /mnt/hgfs/LinuxSharedFile
       [root@localhost LinuxSharedFile]$ dir
       2009		     HadoopPseudo		  jdk-8u51-linux-i586.tar.gz	     sqoop
       2009all		     hbase			  logs2				     startlogs.log
       2009t		     hdfs01			  mapreduce01			     workflow1
       bash01		     hive			  mapreduce02			     workflow2
       bash10.sh	     hive_log			  mr1				     YARN_bak
       class20151221	     hive-site.xml		  mysql-5.5.44-linux2.6-i686.tar.gz  zip
       edit		     hive-site.xml.local	  parquet-avro-1.4.1.jar	     zookeeper-3.4.6.tar.gz
       hadoop1		     hive-site.xml.remort	  pdsh-2.26.tar.bz2		     桌面
       hadoop2		     jdk-6u11-dlj-linux-i586.bin  pig-0.15.0.tar.gz
       hadoop-2.7.0.tar.gz  jdk-8u51-linux-i586.rpm	  rw
      
    • 可以看到拷贝的一个文件和一个目录都拷贝成功,使用函数可以简化工作。