iis服务器助手广告
返回顶部
首页 > 资讯 > 精选 >如何写好shell脚本
  • 556
分享到

如何写好shell脚本

2023-06-09 14:06:38 556人浏览 安东尼
摘要

这篇文章给大家分享的是有关如何写好shell脚本的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。前言产品的最终用户通常不懂技术,所以不管你怎么折腾产品代码都无所谓。但脚本代码不一样,它们是开发人员写给开发人员的。有

这篇文章给大家分享的是有关如何写好shell脚本的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

前言

产品的最终用户通常不懂技术,所以不管你怎么折腾产品代码都无所谓。但脚本代码不一样,它们是开发人员写给开发人员的。

有多少次,你运行./script.sh,然后输出一些东西,但却不知道它刚刚都做了些什么。这是一种很糟糕的脚本用户体验。我将在这篇文章中介绍如何写出具有良好开发者体验的 shell 脚本。

产品的最终用户通常不懂技术,所以不管你怎么折腾产品代码都无所谓。但脚本代码不一样,它们是开发人员写给开发人员的。

这样会导致一些问题:

  • 混乱的脚本——我知道,我们都是工程师,读得懂代码,但即使这样,也请为我们这些对 Shell 脚本不是很熟练的人考虑一下(我们在写代码时也会为你们考虑的)。

  • 满屏的日志和错误输出——就算我们也是工程师,并不代表我们了解你所做的一切。

  • 弄得一团糟却没有做好清理工作——是的,我们可以顺着你的脚本手动撤销变更,但你真的会让那些信任你的脚本的人这么做吗?

所以,我们可以通过一些方法来为自己和别人写出更好的 shell 脚本。这里给出的所有示例都可以使用与 POSIX 标准兼容的 shell 运行(#!/bin/sh),因为它是最常用的。嫌文章太长了可以只看以下总结部分:

  • 提供--help标记

  • 检查所有命令的可用性

  • 独立于当前工作目录

  • 如何读取输入:环境变量 vs. 标记

  • 打印对系统执行的所有操作

  • 如果有必要,提供--silent选项

  • 重新开启显示

  • 用动画的方式显示进度

  • 用颜色编码输出

  • 出现错误立即退出脚本

  • 自己执行清理工作

  • 在退出时使用不同的错误码

  • 在结束时打印一个新行

有时间的话可以接着往下看具体内容:

提供--help标记

安装在系统上的二进制文件通常带有man帮助文档,但对于脚本来说就不一定了。因此我们通常需要为脚本提供-h或--help标记来打印有关如何使用脚本的信息。如果其他工程师需要修改脚本,这也可以作为脚本的内联文档:

#!/bin/shif [ ${#@} -ne 0 ] && [ "${@#"--help"}" = "" ]; then printf -- '...help...\n'; exit 0;fi;

这段脚本先计算参数长度(${#@} -ne 0),只有当参数长度不为零时才会检查--help标记。下一个条件会检查参数中是否存在字符串“--help” 。第一个条件是必需的,如果参数长度为零则不需要打印帮助信息。

检查所有命令的可用性

脚本通常会调用其他脚本或二进制文件。在调用可能不存在的命令时,请先检查它们是否可用。可以使用“command -v 二进制文件名称”来执行此操作,看看它的退出代码是否为零。如果命令不可用,可以告诉用户应该如何获得这个二进制文件:

#!/bin/sh_=$(command -v Docker);if [ "$?" != "0" ]; then printf -- 'You don\'t seem to have Docker installed.\n'; printf -- 'Get it: https://www.docker.com/commUnity-edition\n'; printf -- 'Exiting with code 127...\n'; exit 127;fi;# ...

独立于当前工作目录

从不同的目录执行脚本可能会发生错误,这样的脚本没有人会喜欢。要解决这个问题,请使用绝对路径(/path/to/something)和脚本的相对路径(如下所示)。

可以使用dirname $0引用脚本的当前路径:

#!/bin/shCURR_DIR="$(dirname $0);"printf -- 'moving application to /opt/app.jar';mv "${CURR_DIR}/application.jar" /opt/app.jar;

如何读取输入:环境变量 vs. 标记

脚本通过两种方式接受输入:环境变量和选项标记(参数)。根据经验,对于不影响脚本行为的值,可以使用环境变量,而对于可能触发脚本不同流程的值,可以使用脚本参数。

不影响脚本行为的变量可能是访问令牌和 ID 之类的东西:

#!/bin/sh# do thisexport AWS_ACCESS_TOKEN='xxxxxxxxxxxx';./provision-everything# and not./provisiong-everything --token 'xxxxxxxxxxx';

影响脚本行为的变量可能是需要运行实例的数量、是异步还是同步运行、是否在后台运行等参数:

#!/bin/sh# do this./provision-everything --async --instance-count 400# and notINSTANCE_COUNT=400 ASYNC=true ./provision-everything

打印对系统执行的所有操作

脚本通常会对系统执行有状态的更改。不过,由于我们不知道用户何时会向发送SIGINT,也不知道脚本错误何时可能导致脚本意外终止,因此很有必要将正在做的事情打印在终端上,这样用户就可以在不去查看脚本的情况下回溯这些步骤:

#!/bin/shprintf -- 'Downloading required document to ./downloaded... ';wget -o ./downloaded Https://some.site.com/downloaded;printf -- 'Moving ./downloaded to /opt/downloaded...';mv ./downloaded /opt/;printf -- 'Creating symlink to /opt/downloaded...';ln -s /opt/downloaded /usr/bin/downloaded;

在必要时提供--silent选项

有些脚本是为了将其输出传给其他脚本。虽说脚本都应该能够单独运行,不过有时候也有必要让它们把输出结果传给另一个脚本。可以利用stty -echo来实现--silent标记:

#!/bin/shif [ ${#@} -ne 0 ] && [ "${@#"--silent"}" = "" ]; then stty -echo;fi;# ...# before point of intended output:stty +echo && printf -- 'intended output\n';# silence it again till end of scriptstty -echo;# ...stty +echo;exit 0;

重新开启显示

在使用stty -echo关闭脚本显示之后,如果发生致命错误,脚本将终止,而且不会恢复终端输出,这样对用户来说是没有意义的。可以使用trap来捕捉SIGINT和其他操作系统级别的信号,然后使用stty echo打开终端显示:

#!/bin/sherror_handle() { stty echo;}if [ ${#@} -ne 0 ] && [ "${@#"--silent"}" = "" ]; then stty -echo; trap error_handle INT; trap error_handle TERM; trap error_handle KILL; trap error_handle EXIT;fi;# ...

用动画的方式显示进度

有些命令需要运行很长时间,并非所有脚本都提供了进度条。在用户等待异步任务完成时,可以通过一些方式告诉他们脚本仍在运行。比如在while循环中打印一些信息:

#!/bin/shprintf -- 'PerfORMing asynchronous action..';./trigger-action;DONE=0;while [ $DONE -eq 0 ]; do ./async-checker; if [ "$?" = "0" ]; then DONE=1; fi; printf -- '.'; sleep 1;done;printf -- ' DONE!\n';

或者可以做一些更好玩的小玩意儿,比如 http://mywiki.wooledge.org/BashFAQ/034。

用颜色编码输出

在脚本中调用其他二进制文件或脚本时,对它们的输出进行颜色编码,这样就可以知道哪个输出来自哪个脚本或二进制文件。这样我们就不需要在满屏的黑白输出文本中查找想要的输出结果。

理想情况下,脚本应该输出白色(默认的,前台进程),子进程应该使用灰色(通常不需要,除非出现错误),使用绿色表示成功,红色表示失败,黄色表示警告。

#!/bin/shprintf -- 'doing something... \n';printf -- '\033[37m someone else's output \033[0m\n';printf -- '\033[32m SUCCESS: yay \033[0m\n';printf -- '\033[33m WARNING: hmm \033[0m\n';printf -- '\033[31m ERROR: fubar \033[0m\n';

可以使用\033[Xm,其中X代表颜色代码。有些脚本使用\e而不是\033,但要注意\e不适用于所有的 UNIX 系统。

如何写好shell脚本

正确示范

可在.sh 中使用的所有颜色和修饰符 https://misc.floGISoft.com/bash/tip_colors_and_formatting。

出现错误立即退出脚本

set -e表示从当前位置开始,如果出现任何错误都将触发EXIT。相反,set +e表示不管出现任何错误继续执行脚本。

如果脚本是有状态的(每个后续步骤都依赖前一个步骤),那么请使用set -e,在脚本出现错误时立即退出脚本。如果要求所有命令都要执行完(很少会这样),那么就使用set +e。

#!/bin/shset +e;./script-1;./script-2; # does not depend on ./script-1./script-3; # does not depend on ./script-2set -e;./script-4;./script-5; # depends on success of ./script-4# ...

自己执行清理工作

大多数脚本在出现错误时不会执行清理工作,能够做好这方面工作的脚本实属罕见,但这样做其实很有用,还可以省下不少时间。前面已经给出过示例,让stty恢复正常,并借助trap命令来执行清理工作:

#!/bin/shhandle_exit_code() { ERROR_CODE="$?"; printf -- "an error occurred. cleaning up now... "; # ... cleanup code ... printf -- "DONE.\nExiting with error code ${ERROR_CODE}.\n"; exit ${ERROR_CODE};}trap "handle_exit_code" EXIT;# ... actual script...

在退出时使用不同的错误码

在绝大多数 shell 脚本中,exit 0 表示执行成功,exit 1 表示发生错误。对错误与错误码进行一对一的映射,这样有助于脚本调试。

#!/bin/sh# ...if [ "$?" != "0" ]; then printf -- 'X happened. Exiting with status code 1.\n'; exit 1;fi;# ...if [ "$?" != "0" ]; then printf -- 'Y happened. Exiting with status code 2.\n'; exit 2;fi;

这样做有另一个额外的好处,就是其他脚本在调用你的脚本时,可以根据错误码来判断发生了什么错误。

在结束时打印一个新行

如果你有在遵循脚本的最佳实践,那么可能会使用printf代替echo(它在不同系统中的行为有所差别)。问题是printf在命令结束后不会自动添加一个新行,导致控制台看起来是这样的:

如何写好shell脚本

看起来是多么的平淡

这样一点也不酷,可以通过简单的方式打印一个新行:

#!/bin/sh# ... your awesome script ...printf -- '\n';exit 0;

这样就可以得到:

如何写好shell脚本

感谢各位的阅读!关于“如何写好shell脚本”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

--结束END--

本文标题: 如何写好shell脚本

本文链接: https://www.lsjlt.com/news/256379.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何写好shell脚本
    这篇文章给大家分享的是有关如何写好shell脚本的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。前言产品的最终用户通常不懂技术,所以不管你怎么折腾产品代码都无所谓。但脚本代码不一样,它们是开发人员写给开发人员的。有...
    99+
    2023-06-09
  • 如何学好shell脚本
    这篇文章主要介绍“如何学好shell脚本”,在日常操作中,相信很多人在如何学好shell脚本问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何学好shell脚本”的疑惑有所帮助!接下来,请跟着小编一起来学习吧...
    99+
    2023-06-09
  • linux如何编写shell脚本
    编写Linux的shell脚本可以使用任何文本编辑器,如vi、nano、gedit等。以下是编写shell脚本的一般步骤:1. 打开...
    99+
    2023-09-15
    linux shell
  • 如何编写Linux Shell脚本
    这篇文章主要为大家展示了“如何编写Linux Shell脚本”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何编写Linux Shell脚本”这篇文章吧。代码风格规范开头有“蛇棒”所谓sheba...
    99+
    2023-06-16
  • 如何编写Shell脚本注释
    本篇内容介绍了“如何编写Shell脚本注释”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、单选注释以“#”开头的行就是注释,会被解释器忽略...
    99+
    2023-06-09
  • linux中如何编写shell脚本
    在Linux中,可以使用任何文本编辑器编写Shell脚本。以下是编写Shell脚本的一般步骤: 打开终端并创建一个新的文本文件,...
    99+
    2023-10-23
    linux shell
  • 如何写出健壮可靠的shell脚本
    如何写出健壮可靠的shell脚本,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。如果秉承着能跑就行的态度写shell脚本,是很自在的,但是如果你想要写出健壮,可靠...
    99+
    2023-06-16
  • Windows下如何使用PHP编写Shell脚本?
    在Windows操作系统下,使用PHP编写Shell脚本可以帮助我们自动化执行各种任务,从而提高效率。接下来,我们将介绍如何在Windows下使用PHP编写Shell脚本。 首先,我们需要安装PHP。可以在PHP官网下载Windows版本的...
    99+
    2023-07-01
    path windows shell
  • 如何编写shell脚本实现循环语句
    这篇文章主要介绍“如何编写shell脚本实现循环语句”,在日常操作中,相信很多人在如何编写shell脚本实现循环语句问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何编写shell脚本实现循环语句”的疑惑有所...
    99+
    2023-06-09
  • 如何编写shell对比文件内容脚本
    这篇文章主要讲解了“如何编写shell对比文件内容脚本”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何编写shell对比文件内容脚本”吧!代码如下:#!/bin/shfunction _d...
    99+
    2023-06-09
  • 如何编写CentOS下redis自启动shell脚本
    这篇文章主要讲解了“如何编写CentOS下redis自启动shell脚本”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何编写CentOS下redis自启动shell脚本”吧!用这个脚本管理...
    99+
    2023-06-09
  • 在Nodejs中如何用zx库编写Shell脚本
    这篇文章主要介绍“在Nodejs中如何用zx库编写Shell脚本”,在日常操作中,相信很多人在在Nodejs中如何用zx库编写Shell脚本问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望...
    99+
    2024-04-02
  • shell如何监控脚本
    这篇文章主要介绍了shell如何监控脚本,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1 准备监控机 linux 系统,普通服务器即可,要求: 安装ssh 客户端,如果要发送...
    99+
    2023-06-09
  • Shell脚本如何使用
    小编给大家分享一下Shell脚本如何使用,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧! shell前言Shell 能够接收用户输入的命令,并对命令进行处理,处理完毕后再将结果反馈给用户,比如输出到显示器、写入到文...
    99+
    2023-06-15
  • 【shell脚本编写】shell 数组的使用
    数组 shell基础-04 数组(定义数组、查看数组、访问数组、删除数组、关联数组、二维数组) shell脚本之数组 打印数组_shell数组和字典 速查 操作命令作用创建数组declare ...
    99+
    2023-09-03
    php 开发语言 linux
  • 如何备份shell脚本
    小编给大家分享一下如何备份shell脚本,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!backup_run.sh代码如下:    #...
    99+
    2023-06-09
  • 如何编写Shell脚本模拟多线程功能
    这篇文章主要讲解了“如何编写Shell脚本模拟多线程功能”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何编写Shell脚本模拟多线程功能”吧!代码如下:#!/bin/bashfunctio...
    99+
    2023-06-09
  • python如何写脚本
    python写脚本的方法在电脑中找到“idle”,他是Python自带的,通过idle进行编写。打开文本编辑器editplus,notepad等,编写后将文件保存成 .py格式即可。...
    99+
    2024-04-02
  • Windows 系统下如何使用 Go 编写 Shell 脚本?
    Shell 脚本是一种在操作系统上运行的脚本语言,可以用于管理文件、程序和系统设置等。在 Linux 和 macOS 等 Unix 系统中,Shell 脚本是一种非常常见的工具。但是,在 Windows 系统中,Shell 脚本并不像在 ...
    99+
    2023-07-10
    windows shell path
  • 如何编写Shell脚本批量添加扩展名
    本篇内容介绍了“如何编写Shell脚本批量添加扩展名”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!方法1:代码如下:for file in&...
    99+
    2023-06-09
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作