Shell脚本示例

Shell基础之控制流结构


一、控制结构

几乎所有的脚本里都有某种流控制结构,很少有例外。流控制是什么?假定有一个脚本,包含下列几个命令:

#!/bin/sh




# make a directory mkdir /home/dave/mydocs # copy all doc files cp *.docs /home/dave/docs # delete all doc files rm *.docs

上述脚本问题出在哪里?如果目录创建失败或目录创建成功文件拷贝失败,如何处理?这里需要从不同的目录中拷贝不同的文件。必须在命令执行前或最后的命令退出前决定处理方法。shell会提供一系列命令声明语句等补救措施来帮助你在命令成功或失败时,或需要处理一个命令清单时采取正确的动作。这些命令语句大概分两类:

1、循环和流控制
  • if 语句
    提供条件测试。测试可以基于各种条件。例如文件的权限、长度、数值或字符串的比较。这些测试返回值或者为真(0),或者为假(1)。基于此结果,可以进行相关操作。在讲到条件测试时已经涉及了一些测试语法。
  • case语句
    允许匹配模式、单词或值。一旦模式或值匹配,就可以基这个匹配条件作其他声明。
2、循环

循环或跳转是一系列命令的重复执行过程,本书提到了3种循环语句:

  • for 循环
    每次处理依次列表内信息,直至循环耗尽。
  • Until 循环
    此循环语句不常使用, until循环直至条件为真。条件部分在循环末尾部分。
  • While 循环
    while循环当条件为真时,循环执行,条件部分在循环头。
    流控制语句的任何循环均可嵌套使用,例如可以在一个for循环中嵌入另一个for循环。

二、实例讲解

现在开始讲解循环和控制流,并举一些脚本实例。

从现在起,脚本中语句使用LINUX或BSD版本,也就是说使用echo方法echo -e -n,意即从echo结尾中下一行执行命令。

1、grep输出检查

不必拘泥于变量或数值测试,也可以测知系统命令是否成功返回。对grep使用if语句找出,grep是否成功返回信息。下面的例子中grep用于查看Dave是否在数据文件data.file中,注意’Dave>‘用于精确匹配。
[root@localhost ~]# cat grepif.sh 




#!/bin/sh # grepif.sh if grep 'Dave\>' data.file > /dev/null 2>&1 then                echo "Great Dave is in the file" else                echo "No Dave is not in the file" fi [root@localhost ~]# ./grepif.sh No Dave is not in the file

2、用变量测试grep输出

正像前面看到的,可以用grep作字符串操作。下面的脚本中,用户输入一个名字列表,grep在变量中查找,要求其包含人名Peter
[root@localhost ~]# cat grepstr.sh 




#!/bin/sh # grepstr echo -n "Enter a list of names:" read list if echo $list | grep "Peter" > /dev/null 2>&1 then                echo "Peter is here"                # could do some processing here... else                echo "Peter's not in the list. No comment!" fi [root@localhost ~]# ./grepstr.sh Enter a list of names:John Louise Peter James Peter is here

3、文件拷贝输出检查

下面测试文件拷贝是否正常,如果cp命令并没有拷贝文件myfile到myfile.bak,则打印错误信息。注意错误信息中basename $0打印脚本名。如果脚本错误退出,一个好习惯是显示脚本名并将之定向到标准错误中。用户应该知道产生错误的脚本名。
 [root@localhost ~]# cat ifcp.sh 




#!/bin/sh # ifcp.sh if cp myfile myfile.bak; then                echo "good copy" else                echo "`basename $0`: error could not copy the file" >&2 fi [root@localhost ~]# ./ifcp.sh cp: cannot stat `myfile': No such file or directory ifcp.sh: error could not copy the file
注意,文件可能没找到,系统也产生本身的错误信息,这类错误信息可能与输出混在一起。既然已经显示系统错误信息获知脚本失败,就没必要显示两次。要去除系统产生的错误和系统输出,只需简单的将标准错误和输出重定向即可。修改脚本为: >/dev/null 2>&1。
[root@localhost ~]# cat ifcp.sh 




#!/bin/sh # ifcp.sh if cp myfile myfile.bak > /dev/null 2>&1; then                echo "good copy" else                echo "`basename $0`: error could not copy the file" >&2 fi [root@localhost ~]# ./ifcp.sh ifcp.sh: error could not copy the file
上面当中>/dev/null表示任何标准输出都定向到那个无尽的“黑洞”/de/null中,然后2>&1表示错误输出也是到/dev/null中,&1表示前面的那个/dev/null,脚本运行时,所有输出包括错误重定向至系统垃圾堆。

4、当前目录测试

当运行一些管理脚本时,可能要在根目录下运行它,特别是移动某种全局文件或进行权限改变时。一个简单的测试可以获知是否运行在根目录下。下面脚本中变量DIRECTORY使用当前目录的命令替换操作,然后此变量值与” / “字符串比较( /为根目录)。如果变量值与字符串不等,则用户退出脚本,退出状态为1意味错误信息产生。
[root@localhost ~]# cat ifpwd.sh 




#!/bin/sh # ifpwd.sh DIRECTORY=`pwd` # grab the current dirctory if [ " DIRECTORY" != "/" ]; then
                # is it the root directory ?
                # no, the direct output to standard error, which is the screen
                # by default.
                echo "You need to be in the root directory no
DIRECTORY" != "/" ]; then                # is it the root directory ?                # no, the direct output to standard error, which is the screen                # by default.                echo "You need to be in the root directory no
DIRECTORY to run                this script" >&2                # exit with a value of 1, an error                exit 1 fi [root@localhost ~]# ./ifpwd.sh You need to be in the root directory no /root to run                this script

5、文件权限测试

可以用i f语句测试文件权限,下面简单测试文件test.txt是否被设置到变量LOGNAME,测试test.txt文件是否具有写的权限。下面的脚本先建立一个test.txt的空白文档,列出它的相关权限。然后执行脚本测试其是否可以写入,然后显示相关信息。
[root@localhost ~]# touch test.txt
[root@localhost ~]# ls -l test.txt
-rw-r--r-- 1 root root 0 Nov 21 15:21 test.txt
[root@localhost ~]# chmod u+x ifwr.sh 
[root@localhost ~]# cat ifwr.sh 




#!/bin/sh # ifwr.sh LOGFILE=test.txt echo LOGFILEif[!w" L O G F I L E i f [ ! − w " LOGFILE" ]; then                echo " You cannot write to LOGFILE" >&2
else
                echo " You can write to
LOGFILE" >&2else                echo " You can write to
LOGFILE" >&2 fi [root@localhost ~]# ./ifwr.sh test.txt You can write to test.txt

6、测试传递到脚本中的参数

if语句可用来测试传入脚本中参数的个数。使用特定变量$#,表示调用参数的个数。可以测试所需参数个数与调用参数个数是否相等。以下测试确保脚本有三个参数。如果没有,则返回一个可用信息到标准错误,然后代码退出并显示退出状态。如果参数数目等于3,则显示所有参数。
 [root@localhost ~]# cat ifparam.sh 




#!/bin/sh # ifparam if [ # -lt 3 ]; then
                # less than 3 parameters called, echo a usage message and exit
                # 如果少于三个参数则显示使用的信息,然后退出。
                echo "Usage: `basename
# -lt 3 ]; then                # less than 3 parameters called, echo a usage message and exit                # 如果少于三个参数则显示使用的信息,然后退出。                echo "Usage: `basename
0`arg1 arg2 arg3" >&2                exit 1 fi # good, received 3 params, let's echo them # 好,现在接受了三个参数,让我们开始显示他们 echo "arg1: 1"echo"arg2: 1 " e c h o " a r g 2 : 2" echo "arg3: $3" [root@localhost ~]# ./ifparam.sh cup medal Usage: ifparam.sharg1 arg2 arg3 [root@localhost ~]# ./ifparam.sh cup medal trophy arg1: cup arg2: medal arg3: trophy
从上面的运行信息可以看出,如果只传入两个参数,则显示一可用信息,然后脚本退出。只有正确传入了三个参数了,才显示所有的参数然后退出。

7、决定脚本是否为交互模式

有时需要知道脚本运行是交互模式(终端模式)还是非交互模式(cron或at)。脚本也许需要这个信息以决定从哪里取得输入以及输出到哪里,使用test命令并带有-t选项很容易确认这一点。如果test返回值为1,则为交互模式。假如我是在一个终端下运行下面这个脚本。
[root@localhost ~]# cat ifinteractive.sh 




#!/bin/sh # ifinteractive.sh if [ -t ]; then                echo "We are interactive with a terminal" else                echo "We must be running from some background process probably                cron or at" fi [root@localhost ~]# ./ifinteractive.sh We are interactive with a terminal

8、变量设置测试

下面的例子测试环境变量EDITOR是否已设置。如果EDITOR变量为空,将此信息通知用户。如果已设置,在屏幕上显示编辑类型。
 [root@localhost ~]# cat ifeditor.sh 
 #!/bin/sh
 # ifeditor.sh
 if [ -z $EDITOR ]; then
                # the variable has not been set
                # 变量没有设置
                echo "Your EDITOR environment is not set"
 else
                # let's see what it is
                # 如果设置了,让我们来看看它到底是什么
                echo "Using $EDITOR as the default editor"
 fi
 [root@localhost ~]# ./ifeditor.sh 
 Your EDITOR environment is not set

9、将脚本参数传入系统命令

可以向脚本传递位置参数,然后测试变量。这里,如果用户在脚本名字后键入目录名,脚本将重设$1特殊变量为一更有意义的名字。即DIRECTORY。这里需测试目录是否为空,如果目录为空,ls -A将返回空,然后对此返回一信息。
# ifdirec.sh




# assigning 1toDIRECTORYvariableDIRECTORY= 1 t o D I R E C T O R Y v a r i a b l e D I R E C T O R Y = 1 if [ "`ls -A DIRECTORY`" == "" ]; then
        # if it's an empty string, then it's empty
        echo "
DIRECTORY`" == "" ]; then        # if it's an empty string, then it's empty        echo "
DIRECTORY is indeed empty" else            # otherwise it is not        echo "$DIRECTORY is not empty" fi
也可以使用下面的脚本替代上面的例子并产生同样的结果
[root@localhost ~]# cat ifdirec2.sh 




#!/bin/sh # ifdirec2 DIRECTORY= 1if[z"lsA 1 i f [ − z " ‘ l s − A DIRECTORY`" ] then                echo " DIRECTORYisindeedempty"elseecho" D I R E C T O R Y i s i n d e e d e m p t y " e l s e e c h o " DIRECTORY is not empty" fi

10、null命令用法

到目前为止,条件测试已经讲完了then和else部分,有时也许使用者并不关心条件为真或为假。不幸的是if语句各部分不能为空—一些语句已经可以这样做。为解决此问题, shell提供了:空命令。空命令永远为真(也正是预想的那样)。回到前面的例子,如果目录为空,可以只在then部分加入命令。
[root@localhost ~]# cat ifdirectory.sh 




#!/bin/sh # ifdirectory.sh DIRECTORY= 1if["lsA 1 i f [ " ‘ l s − A DIRECTORY`" == "" ] then                echo "$DIRECTORY is indeed empty" else :                # do nothing fi [root@localhost ~]# ./ifdirectory.sh testd testd is indeed empty
03-28
### MCP API 的文档与使用教程 MCP 是一种用于增强大型语言模型 (LLM) 功能的技术框架,它通过提示(Prompts)、资源(Resources)以及工具(Tools)这三种核心原语来扩展 LLM 能力[^2]。Apifox 平台也认识到 MCP 技术在 API 开发领域的重要作用,并将其应用于实际场景中[^1]。 为了实现将 `/Users/syw/project/wechatAr` 文件夹下的所有文件上传至远程服务器 `47.93.xx.xx` 用户名 `root` 下的 `/opt/ll` 目录的操作,可以基于 MCP 工具功能构建一个自定义的服务逻辑。以下是具体实现方法: #### 实现方案 利用 SCP 命令完成文件传输任务,并结合 MCP 的 Tool 功能封装此操作以便于后续调用。当关键词为“上传微信目录”时,触发该工具执行相应动作。 ```python import subprocess def upload_wechat_directory(): source_dir = "/Users/syw/project/wechatAr/*" target_server = "root@47.93.xx.xx:/opt/ll/" try: result = subprocess.run(["scp", "-r", source_dir, target_server], check=True) return {"status": "success", "message": f"All files from {source_dir} have been uploaded to {target_server}"} except Exception as e: return {"status": "error", "message": str(e)} # 将上述函数注册为 MCP 中的一个 tool tools = { "upload_wechat_directory_tool": upload_wechat_directory, } # 定义 prompt 和 resource 配置部分省略... ``` 以上代码片段展示了如何创建一个名为 `upload_wechat_directory_tool` 的工具并将其集成到 MCP 系统里去[^3]。每当接收到匹配条件的消息比如含有特定关键字的时候就会激活对应的行为即启动SCP进程从而达成目标需求。 #### 进一步学习资料推荐 对于希望深入研究或者实践更多关于 MCP 应用案例的人士来说,《MCP 教程进阶篇》提供了丰富的实例分析和技术细节值得参考阅读;另外《MCP 极简入门:超快速上手运行简单的 MCP 服务和 MCP 客户端》同样是非常好的起点材料之一可以帮助初学者迅速掌握基础概念及其运作机制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值