iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >为什么要写Bash脚本
  • 855
分享到

为什么要写Bash脚本

2023-06-09 12:06:56 855人浏览 独家记忆
摘要

这篇文章主要介绍为什么要写Bash脚本,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!为什么要写Bash脚本其实关于Bash脚本最好的解释如下:The opposite of "it's like r

这篇文章主要介绍为什么要写Bash脚本,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

为什么要写Bash脚本

其实关于Bash脚本最好的解释如下:

The opposite of "it's like riding a bike" is "it's like programming in bash".

A phrase which means that no matter how many times you do something, you will have to re-learn it every single time.

— Jake Wharton (@JakeWharton)

December 2, 2020

意思就是,跟骑自行车相反,无论做了多少次,每次都感觉像重新学一样。

但是Bash脚本语言和其他一些广受欢迎的语言,例如javascript一样,他们不会轻易突然消失,虽然Bash脚本语言不太可能成为业界的主流语言,但实际他就在我们周围,无处不在。

Bash就像继承了shell的衣钵一样,在每台linux上都可以看到他的身影,这可是大多数后端程序运行的环境,因此当你需要编写服务器的应用程序启动、CI/CD步骤或集成测试用的脚本,Bash就在那里等着你。

将几个命令粘在一起,将输出从一个传递到另一个,然后只启动一些可执行文件,Bash是众多方案中最简单的一个。虽然用其他语言编写更大、更复杂的脚本更有效果,但你不能指望python、Ruby、fish或其他任何你认为最好的程序,可以在任何地方编译使用。所以在将其添加到某个prod server、Docker image或CI环境之前,往往会让人三思而后行。

当然啦,Bash还远远不够完美两个字。他的语法对初学者就像一个噩梦。错误处理也很困难。到处都是我们必须处理掉的陷阱。

Bash script template(Bash脚本模板)

废话不多说,献上我的模板

#!/usr/bin/env bashset -Eeuo pipefailtrap cleanup SIGINT SIGTERM ERR EXITscript_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd -P)usage() { cat <<EOFUsage: $(basename "${BASH_SOURCE[0]}") [-h] [-v] [-f] -p param_value arg1 [arg2...]Script description here.Available options:-h, --help   Print this help and exit-v, --verbose  Print script debug info-f, --flag   Some flag description-p, --param   Some param descriptionEOF exit}cleanup() { trap - SIGINT SIGTERM ERR EXIT # script cleanup here}setup_colors() { if [[ -t 2 ]] && [[ -z "${NO_COLOR-}" ]] && [[ "${TERM-}" != "dumb" ]]; then  NOFORMAT='\033[0m' RED='\033[0;31m' GREEN='\033[0;32m' ORANGE='\033[0;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' CYAN='\033[0;36m' YELLOW='\033[1;33m' else  NOFORMAT='' RED='' GREEN='' ORANGE='' BLUE='' PURPLE='' CYAN='' YELLOW='' fi}msg() { echo >&2 -e "${1-}"}die() { local msg=$1 local code=${2-1} # default exit status 1 msg "$msg" exit "$code"}parse_params() { # default values of variables set from params flag=0 param='' while :; do  case "${1-}" in  -h | --help) usage ;;  -v | --verbose) set -x ;;  --no-color) NO_COLOR=1 ;;  -f | --flag) flag=1 ;; # example flag  -p | --param) # example named parameter   param="${2-}"   shift   ;;  -?*) die "Unknown option: $1" ;;  *) break ;;  esac  shift done args=("$@") # check required params and arguments [[ -z "${param-}" ]] && die "Missing required parameter: param" [[ ${#args[@]} -eq 0 ]] && die "Missing script arguments" return 0}parse_params "$@"setup_colors# script logic heremsg "${RED}Read parameters:${NOFORMAT}"msg "- flag: ${flag}"msg "- param: ${param}"msg "- arguments: ${args[*]-}"

Choose Bash

#!/usr/bin/env bash

脚本为了获得最佳兼容性,它引用/usr/bin/env,而不是直接引用/bin/bash。

Fail fast

set -Eeuo pipefail

set命令可以更改脚本执行选项。例如,通常Bash不关心某个命令是否失败,返回非零退出状态代码。它只是快速地跳到下一个。现在考虑一下这个小脚本:

#!/usr/bin/env bashcp important_file ./backups/rm important_file

如果备份目录不存在,会发生什么情况?确切地说,你将在控制台中收到一条错误消息,但是在你能够做出反应之前,该文件已经被第二个命令删除。

Get the location

script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd -P)

这行代码尽其所能定义脚本的位置目录,然后我们对其进行cd配置。为什么?

通常,我们的脚本在相对于脚本位置的路径上运行,复制文件并执行命令,假设脚本目录也是一个工作目录。是的,只要我们从它的目录执行脚本。

但是,假设我们的CI配置执行脚本如下所示呢:

/opt/ci/project/script.sh

那么我们的脚本不是在项目目录中操作的,而是在CI工具的一些完全不同的工作目录中操作的。我们可以通过在执行脚本之前转到目录来修复它:

cd /opt/ci/project && ./script.sh

但从脚本的角度解决这个问题要好得多。因此,如果脚本从同一目录中读取某个文件或执行另一个程序,请按如下方式调用:

cat "$script_dir/my_file"

同时,脚本不会更改工作目录的位置。如果脚本是从其他目录执行的,并且用户提供了指向某个文件的相对路径,我们仍然可以读取它。

Try to clean up

trap cleanup SIGINT SIGTERM ERR EXITcleanup() { trap - SIGINT SIGTERM ERR EXIT # script cleanup here}

在脚本结束时,将执行cleanup()函数。你可以在这里尝试删除脚本创建的所有临时文件。

请记住,cleanup()不仅可以在最后调用,在任何时候都可以。

Display helpful help

usage() { cat <<EOFUsage: $(basename "${BASH_SOURCE[0]}") [-h] [-v] [-f] -p param_value arg1 [arg2...]Script description here....EOF exit}

尽量让usage()函数相对靠近脚本的顶部,有两种作用:

  • 要为不知道所有选项并且不想查看整个脚本来发现这些选项的人显示帮助。

  • 当有人修改脚本时,保存一个最小的文档(因为两周后,你甚至不记得当初是怎么写的)。

我不主张在这里记录每个函数。但是一个简短、漂亮的脚本使用这些消息是必需的。

Print nice messages

setup_colors() { if [[ -t 2 ]] && [[ -z "${NO_COLOR-}" ]] && [[ "${TERM-}" != "dumb" ]]; then  NOFORMAT='\033[0m' RED='\033[0;31m' GREEN='\033[0;32m' ORANGE='\033[0;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' CYAN='\033[0;36m' YELLOW='\033[1;33m' else  NOFORMAT='' RED='' GREEN='' ORANGE='' BLUE='' PURPLE='' CYAN='' YELLOW='' fi}msg() { echo >&2 -e "${1-}"}

首先,如果你还不想在文本中使用颜色,那么先删除setup_colors()函数。我保留它是因为我知道如果我不必每次都用谷歌编码的话,我会更频繁地使用颜色。

其次,这些颜色只用于msg()函数,而不是echo命令。

msg()函数用于打印不是脚本输出的所有内容。这包括所有日志和消息,而不仅仅是错误。引用
12 Factor CLI Apps的文章说法:

In short: stdout is for output, stderr is for messaging.

— Jeff Dickey, who knows a little about building CLI apps

stdout用于输出,stderr用于消息传递。

这就是为什么在大多数情况下你不应该为stdout使用颜色。

用msg()打印的消息被发送到stderr流并支持特殊的序列,比如颜色。如果stderr输出不是交互式终端,或者传递了一个标准参数,那么颜色将被禁用。
用法如下:

msg "This is a ${RED}very important${NOFORMAT} message, but not a script output value!"

要检查stderr是不是交互式终端时的行为,请在脚本中添加类似于上面的一行。然后执行它,将stderr重定向到stdout并通过管道将其发送到cat。管道操作使输出不再直接发送到终端,而是发送到下一个命令,因此颜色会被禁用。

$ ./test.sh 2>&1 | catThis is a very important message, but not a script output value!

Parse any parameters

parse_params() { # default values of variables set from params flag=0 param='' while :; do  case "${1-}" in  -h | --help) usage ;;  -v | --verbose) set -x ;;  --no-color) NO_COLOR=1 ;;  -f | --flag) flag=1 ;; # example flag  -p | --param) # example named parameter   param="${2-}"   shift   ;;  -?*) die "Unknown option: $1" ;;  *) break ;;  esac  shift done args=("$@") # check required params and arguments [[ -z "${param-}" ]] && die "Missing required parameter: param" [[ ${#args[@]} -eq 0 ]] && die "Missing script arguments" return 0}

如果在脚本中参数化有意义的话,我就通常就会去做,即使整个脚本只在一个地方使用。它使复制和重用它变得更容易,而这通常是早晚发生的。而且,即使某些东西需要硬编码,通常在比Bash脚本更高的级别上有更好的位置。

CLI参数有三种主要类型:标志、命名参数和位置参数。parse_params()函数支持所有这些参数。

这里没有处理的唯一一个公共参数模式是连接多个单字母标志。为了能够传递两个标志作为-ab,而不是-a-b,需要一些额外的代码。

while循环是一种手动解析参数的方法。在其他语言中,您应该使用一个内置的解析器或可用的库,但是,好吧,这是Bash。

模板中有一个示例标志(-f)和命名参数(-p)。只需更改或复制它们以添加其他参数。之后不要忘记更新usage()。

这里最重要的一点是,当您使用第一个Google结果进行Bash参数解析时,通常会丢失一个未知选项的错误。脚本收到未知选项的事实意味着用户希望它执行脚本无法完成的操作。所以用户的期望和脚本行为可能会有很大的不同。最好是在坏事发生之前完全阻止处决。

在Bash中解析参数有两种选择。是一个接一个的。有人赞成和反对使用它们。我发现这些工具不是最好的,因为默认情况下,MacOS上的getopt行为完全不同,getopts不支持长参数(比如--help)。

Using the template

复制粘贴它,就像你在网上找到的大多数代码一样。

复制后,只需更改4件事:

  • 包含脚本说明的usage()文本

  • cleanup()内容

  • parse_params()中的参数–保留--help和--no color,但替换示例:-f和-p

  • 实际的脚本逻辑

Portability

我在MacOS上测试了这个模板(使用默认的bash4.2)和几个Docker映像:Debian、ubuntuCentos、amazonlinux、Fedora。它的确起作用了。

显然,它不能在缺少Bash的环境中工作,比如alpinellinux。

Further reading

在用Bash或其他更好的语言创建CLI脚本时,有一些通用规则。这些资源将指导您如何使小型脚本和大型CLI应用程序可靠,参考如下:

Command Line Interface Guidelines(https://clig.dev/)
12 Factor CLI Apps(Https://medium.com/@jdxcode/12-factor-cli-apps-dd3c227a0e46)
Command line arguments anatomy explained with examples(https://betterdev.blog/command-line-arguments-anatomy-explained/)

Closing notes

我不会是第一个也不是最后一个创建Bash脚本模板的人。这个项目是一个很好的选择,虽然对我的日常需求来说有点太大了。毕竟,我尽量使Bash脚本尽可能小(而且很少使用)。

编写Bash脚本时,请使用支持ShellCheck linter的IDE,如JetBrains IDEs。它会阻止你做一堆适得其反的事情。

以上是“为什么要写Bash脚本”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注编程网精选频道!

--结束END--

本文标题: 为什么要写Bash脚本

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

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

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

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

下载Word文档
猜你喜欢
  • 为什么要写Bash脚本
    这篇文章主要介绍为什么要写Bash脚本,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!为什么要写Bash脚本其实关于Bash脚本最好的解释如下:The opposite of "it's like r...
    99+
    2023-06-09
  • 如何为Bash脚本写单元测试
    小编给大家分享一下如何为Bash脚本写单元测试,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!为什么要为 Bash 脚本写单元测试因为 Bash 脚本通常都是在执行...
    99+
    2023-06-15
  • Bash 脚本编写有哪些需要注意的地方?
    Bash 脚本是一种非常方便的编程语言,可以用于自动化任务、管理系统、实现批处理等多种应用场景。但是,由于 Bash 脚本的语法比较灵活,很容易出现错误,因此编写 Bash 脚本需要注意一些细节,以确保脚本的正确性和可靠性。本文将介绍 B...
    99+
    2023-07-23
    bash leetcode 并发
  • Bash脚本怎么用
    小编给大家分享一下Bash脚本怎么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、条件选择、判断条件选择if(1)用法格式if 判断条件 ...
    99+
    2023-06-15
  • Java 和 Bash,哪个更适合编写脚本?
    在编写脚本时,人们常常会犯迷惑,不知道该选择哪一种编程语言。Java 和 Bash 都是非常流行的编程语言,但它们的适用场景和优点各不相同。本文将分别介绍 Java 和 Bash 的特点,以及它们各自适合的场景和用途,最终得出结论:在编写...
    99+
    2023-08-31
    bash numy http
  • 写出健壮Bash Shell脚本技巧教程
    本篇内容介绍了“写出健壮Bash Shell脚本技巧教程”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!使用set -u你因为没有对变量初始化...
    99+
    2023-06-09
  • 怎么写出安全的、基本功能完善的Bash脚本
    这篇文章主要为大家分析了怎么写出安全的、基本功能完善的Bash脚本的相关知识点,内容详细易懂,操作细节合理,具有一定参考价值。如果感兴趣的话,不妨跟着跟随小编一起来看看,下面跟着小编一起深入学习“怎么写出安全的、基本功能完善的Bash脚本”...
    99+
    2023-06-28
  • 编写健壮的Bash脚本的方法教程
    这篇文章主要讲解了“编写健壮的Bash脚本的方法教程”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“编写健壮的Bash脚本的方法教程”吧!shell脚本在运行异常时会受到非常大的影响。本文介绍...
    99+
    2023-06-09
  • 编写可靠Bash脚本的技巧有哪些
    这篇文章主要讲解了“编写可靠Bash脚本的技巧有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“编写可靠Bash脚本的技巧有哪些”吧!在写脚本时,在一开始...
    99+
    2024-04-02
  • nodejs编写bash脚本的终极方案分享
    目录前言zx库$`command`cd()fetch()question()sleep()nothrow()chalkfsos$.shell$.quote传递环境变量传递数组总结前言...
    99+
    2024-04-02
  • 为什么要重写hashcode
    重写hashcode的原因在于,当对象之间是否相等需要根据对象的内容判断而不是通过对象存储的地址判断。这种情况下就需要重写equals和hashcode,因为在object类上约定**‘相等’**的2个对象hashCode方法需要返回相同的...
    99+
    2023-10-29
    重写 hashcode
  • python调用bash shell脚本的方法是什么
    本篇文章为大家展示了python调用bash shell脚本的方法是什么,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。1. os.system()help(os.system)1.1. d...
    99+
    2023-06-22
  • html5为什么只需要写
    HTML5是一种新一代的Web语言,相较于以往的HTML语言,它具有更加强大的功能和更加便捷的设计方式。HTML5可以轻松创建各种类型和大小的Web应用程序,包括视频和音频播放、动画和游戏等。但是,与传统的HTML语言相比,HTML5的一个...
    99+
    2023-05-14
  • c#怎么写脚本
    在 c# 中编写脚本可按以下步骤进行:创建一个 c# 控制台应用程序项目添加一个 c# 文件并编写脚本代码,其中包含脚本函数 "run()"编译脚本运行脚本编写交互式脚本可使用控制台输入...
    99+
    2024-05-12
    c#
  • 写 Python 脚本,一定要加上这个!
    使用 Python 的人,平时经常会写一些脚本,不管是为了提升工作效率,还是为了满足一些特定的需求,Python 脚本都是一个常见又有用的东西。但是,我最近发现了一个以前不曾察觉的问题,就是脚本里面是否添加 if __name__ == "...
    99+
    2023-05-14
    Python 函数 脚本
  • Linux中高效编写Bash脚本的技巧有哪些
    这篇文章主要介绍了Linux中高效编写Bash脚本的技巧有哪些,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Shell 脚本编程 是你在 Linux 下学习或练习编程的最简单...
    99+
    2023-06-16
  • shell脚本编写的步骤是什么
    编写shell脚本的步骤如下:1. 定义脚本的目的和功能:确定脚本要解决的问题或实现的功能。2. 编写脚本的头部:在脚本的第一行添加...
    99+
    2023-09-22
    shell
  • MySQL备份脚本的写法是什么
    这篇文章将为大家详细讲解有关MySQL备份脚本的写法是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。前言:数据库备份的重要性不言而喻,特别是在生产环境,任何数据的丢失...
    99+
    2024-04-02
  • Bash脚本中怎么使用here文档将数据写入文件
    这篇文章主要介绍“Bash脚本中怎么使用here文档将数据写入文件”,在日常操作中,相信很多人在Bash脚本中怎么使用here文档将数据写入文件问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Bash脚本中怎么...
    99+
    2023-06-16
  • 为什么要重写Flex组件
    这篇文章主要为大家展示了“为什么要重写Flex组件”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“为什么要重写Flex组件”这篇文章吧。重写Flex组件一、为什么要重写Flex组件在Flex已有F...
    99+
    2023-06-17
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作