- 在脚本中,可以通过函数实现特定的功能,这些函数可以被其他脚本调用来完成更为复杂的逻辑。
- 如果在命令行上也能使用函数会更为方便,因为可以通过函数实现系统命令不具备的功能。
- 在命令行执行函数的方式就像执行普通的命令一样。如果在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进程的结束而销毁,要采用下面的方式。
-
直接在命令行创建函数的缺点是当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
-
可以看到拷贝的一个文件和一个目录都拷贝成功,使用函数可以简化工作。
-