当前位置: 首页 > Linux

Linux下如何复用外部shell脚本

时间:2023-04-07 01:10:03 Linux

在Linux开发中,经常会编写shell脚本来执行一些任务。通常,一个脚本只做一件事。随着任务的增多,脚本也会越来越多。重复使用的地方会逐渐增加。这时候就需要将脚本中的常用函数提取出来,放到一个通用的脚本中,以便其他脚本可以复用。本文介绍如何在shell脚本中执行外部脚本,以及如何调用它们。外部脚本中的函数,以及脚本重用执行外部脚本的相关方法如果当前目录下有a.sh脚本,内容如下#!/bin/bashecho"a.sh..."执行外部脚本在脚本中获取当前目录下的b.sh脚本中的外部脚本名主要有以下几种方式,内容如下:#!/bin/bashsourcea.shecho"b.sh..."execute./b.sh,结果如下[root@ecs-centos-7~]#./b.sha.sh...b.sh...脚本中的sourcea.sh命令会先在当前目录下执行a.sh脚本,所以结果会是先输出a.sh...,再输出b.sh脚本本身的打印点。外部脚本的名称。将b.sh脚本中执行a.sh脚本的语句修改为点+空格+a.sh,修改后的脚本内容如下:注意:点与a.sh之间必须加一个空格,否则执行时会报错#!/bin/bash。a.shecho"b.sh..."执行./b.sh,结果如下[root@ecs-centos-7~]#./b.sha.sh...b.sh...上面的脚本中,.a.sh会先执行a.sh脚本,结果会输出a.sh...然后输出b.sh...sh外部脚本名shexternal的两个方法scriptname和./externalscriptname是一样的,选择哪种方法无所谓,下面以前面的这个方法为例,将b.sh脚本中的sourcea.sh修改为sh灰。修改后的脚本内容如下:#!/bin/bashsha.shecho"b.sh..."执行./b.sh命令,结果如下[root@ecs-centos-7~]#。/b.sha.sh...b.sh...可以看出结果输出和上面两种方法是一样的,这两种方法有什么区别呢?调用外部脚本有3种方式:source外部脚本、dot外部脚本、sh外部脚本,它们之间有什么区别?其中,sourceexternalscript和dotexternalscript这两个方法是一样的。当前脚本继承外部脚本的全局变量和函数,相当于将外部脚本的函数和全局变量导入当前脚本修改a.sh和b.sh脚本,内容如下a.shscript#!/bin/bashVAR_A=10func_a(){echo"a.sh...pid:$$,param:$1"}b.shscript#!/bin/bashsourcea.shfunc_a$1echo"vara:$VAR_A"echo"b.sh...pid:$$"执行./b.sh5命令,结果如下[root@ecs-centos-7~]#./b.sh5a.sh...pid:21485,param:5vara:10b.sh...pid:21485两个脚本中的$$指的是脚本执行的进程ID。从结果可以看出,a.sh和b.sh都是在同一个进程中执行的,所以在b.sh脚本中执行sourcea.sh命令,会导入a中的全局变量VAR_A和函数func_a。shscriptintob.shinb.sh打印变量VAR_Ain,输出值与a.sh中相同,调用func_a函数,输出也显示调用了a.sh中的函数源。externalscript和dotexternalscript这两个方法是一样的,所以把b.sh里的sourcea.sh改成.a.sh,执行./b.sh5,结果还是一样。因为sh外部脚本的方式是当前脚本和外部脚本在两个不同的进程中执行,所以当前脚本不能直接使用外部脚本中的函数和全局变量来修改a.sh和b.sh脚本,内容如下a.shscript#!/bin/bashtest_a(){echo"a.sh...test_a"}echo"a.sh...pid:$$"b.shscript#!/bin/bashsha.shecho"b.sh...pid:$$"test_a执行./b.sh命令,结果如下[root@ecs-centos-7~]#./b.sha.sh...pid:21818b.sh...pid:21817./b.sh:line7:test_a:commandnotfound从结果可以看出,执行a.sh和b.sh的进程ID不同。b.sh脚本进程找不到test_a函数,所以在b.sh中调用test_a函数会提示找不到调用外部脚本中函数的命令。上一节提到sh外部脚本不能直接使用外部脚本中的函数和全局变量。这里有几种方法可以解决这个问题。Case分支选择这种方法类似于程序代码中的switchcase语句。通过开关选择不同的分支执行不同的逻辑。在shell脚本中是使用case关键字实现的a.sh脚本#!/bin/bashVAR_A=10test_a(){echo"test_a..pid:$$,p1:$1,p2:$2"}get_var(){echo${VAR_A}}case"$1"inta)test_a$2$3;;变种)get_var;;*)echo"parametererr..."esacb.shscript#!/bin/bashecho"b.sh...pid:$$"sha.shta35ret=$(sha.shvar)echo"ret:$ret”执行./b.sh命令,结果如下[root@ecs-centos-7~]#./b.shb.sh...pid:24813test_a..pid:24814,p1:3,p2:5ret:10脚本b.sh在sh开头打印调用自己的进程IDa.shta35语句是调用a.sh脚本,传入的三个参数分别是ta,3,5。执行a.sh时,传入的第一个参数ta会在大小写匹配后调用test_a函数,其余两个参数3和5作为参数,当函数ret=$(sha.shvar)语句传入,调用a.sh脚本,传入一个var参数,大小写匹配后调用get_var函数。该函数的作用是输出脚本中全局变量VAR_A的值。$()的作用是获取()中命令的返回值,这里是将a.sh脚本中get_var函数的返回值赋值给ret变量,所以这个变量的值为valuea.sh脚本中全局变量VAR_A的说明:如果想获取函数的返回值,可以使用echo打印函数中对应的输出值,然后使用$(函数名参数列表)来获取函数中的输出值打印的值,如上面b.sh脚本中的ret=$(sha.shvar)语句,变量ret的值就是a.sh脚本中get_var函数输出的值10。这里需要注意的是,如果函数Debug日志中有回显,那么debug日志也会将函数调用模板一起返回。使用case关键字来匹配和调用上述不同的函数有一个缺点。a.sh脚本每增加一个功能,case都需要增加一个分支。在分支中调用不同的函数,还需要注意函数是否传入了参数,参数个数是否正确。我们可以在每个外部调用脚本的末尾添加如下语句来解决上述问题。具体语句如下if[$#-ge1];thenname="$1"shift1$name"$@"fi上面的语句首先判断调用脚本时传入的参数个数,只有参数个数大于等于1才有效。传入的第一个参数表示函数的名称,从第二个参数到最后一个参数都会作为参数传入函数。这里的shift1是将传入脚本的参数向左移动一位。例如:传入脚本的参数有三个参数$1$2$3,向左移动一个位置后,$2移动到$1的位置,$3移动到$2的位置,参数个数变为2个原因:其中:传入脚本的参数,第一个参数是函数名,从第二个参数开始就是函数的参数。如果不进行左移处理,第一个参数的函数名也会作为参数传入函数。以下是完整的脚本内容a.shscript#!/bin/bashVAR_A=10test_a(){echo"test_a..pid:$$,p1:$1,p2:$2"}get_var(){echo${VAR_A}}if[$#-ge1];然后name="$1"shift1$name"$@"fib.shscript#!/bin/bashecho"b.sh...pid:$$"sha.shtest_a35ret=$(sha.shget_var)执行./b.sh命令,结果如下[root@ecs-centos-7~]#./b.shb.sh...pid:25086test_a..pid:25087,p1:3,p2:5ret:10可以看出上面case的结果和方法是一样的,其他脚本现在可以通过sha.sh函数名参数列表调用a.sh脚本函数中通过$(sha.sh函数名参数列表)获取a.sh脚本函数的返回值。将两者的优缺点与案例分支选择的方法进行了比较。只需要关心复用脚本中的函数名、函数入参、函数返回值,直接使用即可。缺点是如果多个脚本调用复用脚本中的函数,当复用脚本中的函数名发生变化时,需要修改所有调用的地方。函数调用模板法的缺点恰恰是case分支选择法的优点。当使用case分支选择方式时,根据传入的字符串参数调用不同的函数。这里的字符串参数相当于函数。别名,只要这个参数不变,脚本中函数的名字就可以任意更改在编写脚本的过程中,我们经常会遇到一些莫名其妙的问题。有些问题摸不着头脑也不知道怎么解决。脚本复用可以把一些公共的功能提取出来,一个一个的形成功能模块,这不仅有助于减少我们在编写脚本时犯的错误,对于后期的脚本维护也有很大的帮助。以上就是良虚教程网分享的如何在Linux下复用外部shell脚本。.