我从存储库创建脚本中学到的 8 件事
小时候,我总是不愿意做家务。我只是觉得每天重复做同样的事情很无聊。随着我长大,这种心态有所改变(感谢上帝),并且在我的职业生涯中,以下这句话滑稽地取代了这种心态:
如果耗时超过 30 秒,则自动执行。
最近,我接到一个任务,要为一个由 Google Developers 支持的 DSC-VIT 项目 维护的组织创建大约 18 个代码库。所有这些代码库都需要为我们计划在 2020 年前两个季度开展的项目创建。我决定为它编写一个 Shell 脚本,以下是我在这个过程中学到的一些经验。
指数
在这里查找代码:
导入函数
我希望我的代码立即实现模块化。这意味着我需要将代码拆分成更小的文件,每个文件包含更小的函数,然后创建一个入口点(CLI)来执行它们。我 create
批量创建了代码库, delete
也 revert
批量创建了代码库。我还添加了一个功能,如果有人点击,它会显示一个简洁的小手册 help
。
├── functions
│ ├── config.sh
│ ├── create.sh
│ ├── manual.sh
│ └── revert.sh
├── gitcr
├── .env
├── README.md
└── repos.txt
Enter fullscreen mode
Exit fullscreen mode
我必须进行两种导入:
两者都可以通过简单的语法实现:
# in gitcr
. ./functions/config.sh
. ./functions/create.sh
. ./functions/manual.sh
. ./functions/revert.sh
Enter fullscreen mode
Exit fullscreen mode
包含文件中的所有函数和导出变量都可以直接在主文件中使用。注意,我使用了 a .
来导入上述内容,因为它可以被 sh
Shell 识别。你也可以使用 source
关键字将它们包含在 Bash中,但 sh 无法识别 。
Echo 无法处理 JSON
我想将每次迭代的输出写入控制台或 JSON 文件,具体操作由用户指定。我首先想到的是使用 echo
命令并将其通过管道输出到文件或控制台。echo在这方面 表现 很差,因为它本身就不是为 JSON 格式化而构建的。因此,我使用了 jq
相同的方法。结果如下:
jq
处理垃圾格式,并从中解析出完整格式化的 JSON。然后可以将其随意传输到文件中。
Shell 中的数组
为了在每次迭代中存储 JSON 输出,我使用了一个数组。shell 中的数组可以通过以下方式声明和使用:
result = () # an empty array
result =( "abcd" ) # an array with 0-th index = "abcd"
echo ${ result [0] } # printing out the index
result[1] = "defg" # assigning value to an index
echo ${ result [@] } # the '@' can be used for returning the whole array
result[$iterator ] = 2 # variables can be used as indices.
Enter fullscreen mode
Exit fullscreen mode
请注意,数组的内存不能在 shell 中预先分配。
检查 curl 请求是否成功
curl
命令有一个 -i
标志,可以打印出请求的详细信息,例如返回的状态码和消息。这些信息可以从请求中提取出来,并用于检查请求是否成功。
以下代码返回有关 curl 请求的第一行信息。
$ res = ` curl -i -s -XDELETE https://api.github.com/repos/$owner_name /$line -H "Authorization: token $token " | head -1 `
$ echo $res
HTTP/1.1 401 Unauthorized
Enter fullscreen mode
Exit fullscreen mode
该 res
变量可以分解为以下方式获取响应的 HTTP 状态代码及其消息:
# To get the status code
$ code = ` echo $res | cut -d " " -f2 `
$ echo $code
401
# To get the status code response
$ status_of_res = ` echo $res | cut -d " " -f3-5 `
$ echo $status_of_res
Unauthorized
Enter fullscreen mode
Exit fullscreen mode
现在这里发生了什么?
请注意,该命令会返回任何输入的第一行文本。我们使用该 命令获取第一行文本,并以 空格 作为分隔符 head -1
进行拆分。 cut -d" " -f2
-f2
标志表示我们需要分割字符串中的第二个标记。请注意,此编号从 1 开始,而不是从 0 开始。 f3-5
表示我们需要 3 到 5 之间的标记,因为 HTTP 状态代码消息的长度可能超过一个单词,并且句子在此之后没有其他单词。
现在我们可以使用获取到的状态码来检查请求是否成功。GitHub API在请求成功 后会返回 状态码 204 DELETE
,因此简单的检查应该如下所示:
if [[ $code -eq 204 ]]
then
echo "Request Succeeded"
else
echo "Request Failed"
fi
Enter fullscreen mode
Exit fullscreen mode
GitHub API 速率限制
GitHub API v3 的速率限制为 5000 requests
每位经过身份验证的用户每小时约 1 次,未经身份验证的用户每小时最多 60 次请求。每当向 API 发送请求时,它都会以响应标头的形式返回用户的总速率限制和剩余速率:
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4998
Enter fullscreen mode
Exit fullscreen mode
因此,如果您正在考虑使用 GitHub API 的批量交易应用程序,请 在此处 阅读有关速率限制的更多信息。
对我来说,在脚本中添加验证很容易:
读取用户想要创建的存储库数量
如果数量大于 5000,则失败
可以通过以下方式轻松编程:
# Read number of words in repos.txt
repo_count = ` wc -w < repos.txt`
if [ $repo_count -gt $GITHUB_MAX_REQUESTS ]
then
echo "You are only allowed 5000 repos"
exit 1
fi
Enter fullscreen mode
Exit fullscreen mode
更实用的方法是 X-RateLimit-Remaining
通过 ping GitHub API 来检查标头,然后决定用户可以创建多少个存储库,这也可以通过文本处理 curl 响应标头轻松完成。
remaining = ` curl -i -s -XDELETE https://api.github.com/repos/L04DB4L4NC3R/BOGUS_REPO -H "Authorization: token $token " | grep X-RateLimit-Remaining | head -1 | cut -d ":" -f2 `
Enter fullscreen mode
Exit fullscreen mode
这里, grep
搜索 X-RateLimit-Remaining 标头, head -1
仅取第一句话,并 cut -d":" -f2
使用冒号分隔符从标头键值对中提取数字,然后将其存储在名为的变量中 remaining
。
壳中的开关盒
shell 中的 Switch-case 语句具有非常独特的语法:
cli(){
case $1 in
create)
create $@
;;
revert)
revert $@
;;
* )
helpFunc
;;
esac
}
Enter fullscreen mode
Exit fullscreen mode
请注意,终止词 esac
实际上与 相反 case
。此语法的设计旨在简化 CLI 应用程序的编程。 与其他编程语言相比, )
词素用作 case 语句,而 case
关键字用作 switch 语句。在用户输入 CLI 无法处理的内容的情况下,通配符 *
可用于匹配大小写。 default
、 和 是函数。在 Shell 中,调用函数时无需括号。参数可以通过在函数调用后以空格分隔的格式写入来传递给函数。有趣的是,用来将所有参数(我们在执行 CLI 时获取的 create
) 传递给被调用的函数。 revert
helpFunc
$@
./gitcr create --out = json
# $@ in the gitcr function = "./gitcr" "create" "--out=json"
# When passed to the create function, it retains all of the
# original parameters
Enter fullscreen mode
Exit fullscreen mode
跨平台执行
我在编写此脚本时面临的挑战之一是使其 跨平台。Docker 帮了我大忙!您可以使用 bash
仅占用 15 MB 空间的容器。
以下步骤可用于跨平台 CLI 作业:
Dockerfile 如下所示:
FROM bash
RUN apk update && apk add curl && apk add jq
RUN mkdir -p /usr/app/cli
WORKDIR /usr/app/cli
COPY . .
RUN chmod +x gitcr
Enter fullscreen mode
Exit fullscreen mode
运行时可以执行以下命令:
docker run --rm --mount type = bind ,source= "{PATH}" ,target= /usr/app/cli/ angadsharma1016/gitcr -c "bash /usr/app/cli/gitcr create"
Enter fullscreen mode
Exit fullscreen mode
这里发生了什么?
此命令基于特定镜像运行一个容器,该镜像包含所有代码。在运行时,它会将用户定义的文件(例如 .env
和 ) repos.txt
作为卷挂载到容器内,然后运行 CLI。您的系统无需安装 bash 和其他工具。
非官方的 bash 严格模式
始终使用以下几行来启动你的 bash 脚本:
set -euo pipefail
IFS = $' \n\t '
Enter fullscreen mode
Exit fullscreen mode
它意味着以下事情:
set -e
:如果任何命令抛出返回代码 1,则退出脚本
set u
:引用任何未声明的变量都将导致错误
set -o pipefail
:管道中的命令不会默默失败
IFS
: 内部字段分隔符 控制 bash 对单词的调用
如果遵循非官方的 Bash 严格模式,可以节省数小时的调试时间。点击 此处了解更多信息。
结论
一晚上我都在敲打我的 zsh ,假装自己知道自己在做什么,这让我学到了很多东西,比如如何编写实用的脚本,自动完成很多现在必须做或近期必须做的工作。最好能从手头的任务中抽出一些时间,真正思考一个更好的解决方案,以便将来能够持续地完成这些任务。
只要是为了个人学习(或者推出比市场上同类产品更好的产品),不必介意编写代码或使用别人开发过的工具。保持求知若渴,保持愚昧!
文章来源:https://dev.to/l04db4l4nc3r/7-things-i-learnt-from-a-script-for-repository-creation-4cbk