05-06 周一 Shell工程目录划分和开发最佳实践

05-06 周一 Shell工程目录划分和开发最佳实践
时间版本修改人描述
2024年5月6日10:34:13V0.1宋全恒新建文档
2024年5月6日11:07:12V1.0宋全恒完成

简介

 之前楼主曾经完成过一个shell工程的开发,记得当时项目名称叫做campus-shell,主要是用来一键完成多个模块的部署。当时的模块主要包括:

  • 多个java工程
  • python服务
  • AI芯片上的服务

 其实这也是之前积累的经验。主要是在构造这样的工程时,应该如何分配目录以及存放的东西。

shell工程结构

image-20240506104351907

注意事项

相对路径

 由于在shell工程,主要是通过相对路径进行工作的,在执行shell时,要妥善的处理相对路径。如下所示:

yangfei@ubuntu:~/ci-deploy/module$ cat check_prelinimary.sh 
#!/bin/bashcd $(dirname $0)
pwd
config_file=../config/config.json# 验证当前用户具有sudo权限
validate_sudo() {user_id=`id -u`# systemctl must run as sudo# this script is a convenience wrapper around systemctlif [ $user_id -ne 0 ]; thenecho "Must run as sudo"exit 1fi}

 可以看到,在每个module中的shell执行时,最上层都有如下的代码

cd $(dirname $0)
pwd
config_file=../config/config.json

 上述的代码的主要含义,是切换到当前shell所在的工作目录,并在当前的工作目录下定义配置文件的位置,当然是使用相对路径。这样整体就一致了。

配置文件处理

 配置文件也是一个非常重要的点,因为在shell中,不像python处理ini或者json有比较良好的库,因此我们在处理shell的时候,也需要比较复杂的结构,以相同的策略,也可以使用json的配置文件,然后读取时采用相应的库。

 具体可以参考 04-23 周二 shell环境下读取使用jq 读取json文件

 接下来演示一个案例:

配置文件内容

yangfei@ubuntu:~/ci-deploy$ cat config/config.json 
{"repositories": [{"repo_name": "LLMs_Inference","runner_name": "LLMs_Inference_runner","user": "zhangyi","passwd": "123456","url": "https://github.com/CodexDive/LLMs_Inference","token": "BCTEUWMMR7EU7BFLLO76ADTGFHF3M","directory": "actions-ci","tags": ["inference","gpu","self-hosted", "Linux", "X64"]},{"repo_name": "LLMChat","runner_name": "LLMChat_runner","user": "zhangweixing","passwd": "123456","url": "https://github.com/CodexDive/LLMChat","token": "BCTEUWJ76AILP3ZL54L25JDGE5WBS","directory": "actions-ci","tags": ["application","self-hosted", "Linux", "X64"]}]
}

 上述为一个json的配置文件,这个仓库的主要目标是一件完成为团队的仓库配置CI,想要固话这个目录,标签以及必要的信息。如上所示,我们为每个仓库配置了仓库的名称,运行器名称,以及token,和tags,在json中包含了数组结构,字符串结构,是一个相对复杂的结构。

读取配置文件

yangfei@ubuntu:~/ci-deploy$ cat config_runners.sh 
#!/bin/bashuser_id=`id -u`# we want to snapshot the environment of the config user
if [ $user_id -eq 0 -a -z "$RUNNER_ALLOW_RUNASROOT" ]; thenecho "Must not run with sudo"exit 1
fi
cd $(dirname $0)
config_file="config/config.json"jq -c '.repositories[]' "$config_file" | while IFS= read -r repository; douser=$(echo "$repository" | jq -r '.user')passwd=$(echo "$repository" | jq -r '.passwd')ci_dir=$(echo "$repository" | jq -r '.directory')url=$(echo "$repository" | jq -r '.url')token=$(echo "$repository" | jq -r '.token')tags=$(echo "$repository" | jq -r '.tags | join(",")')runner_name=$(echo "$repository" | jq -r '.runner_name')echo "tags: $Tags"work_dir_cmd="cd /home/$user/$ci_dir"cmd="./config.sh --unattended --url $url --token $token --labels "$tags" --name $runner_name"echo "$cmd"utils/expect_exec_cmd.sh "$user" "$passwd" "$work_dir_cmd" "$cmd"

 上述代码演示了使用jq来读取配置文件的过程(一般我们在部署时,需要先配置好),具体含义,就不再赘述了。

 可以看出上述的额代码,主要是读取配置文件之后,然后组装cmd命令,读取了user和passwd命令,并将这些参数以位置参数的形式传递给了脚本expect_exec_cmd.sh

shell脚本调用

 其实在配置文件处理中已经描述了这个过程。

shell调用参数组织

jq -c '.repositories[]' "$config_file" | while IFS= read -r repository; douser=$(echo "$repository" | jq -r '.user')passwd=$(echo "$repository" | jq -r '.passwd')ci_dir=$(echo "$repository" | jq -r '.directory')url=$(echo "$repository" | jq -r '.url')token=$(echo "$repository" | jq -r '.token')tags=$(echo "$repository" | jq -r '.tags | join(",")')runner_name=$(echo "$repository" | jq -r '.runner_name')echo "tags: $Tags"work_dir_cmd="cd /home/$user/$ci_dir"cmd="./config.sh --unattended --url $url --token $token --labels "$tags" --name $runner_name"echo "$cmd"utils/expect_exec_cmd.sh "$user" "$passwd" "$work_dir_cmd" "$cmd"

 通过读取配置文件中一些参数项的内容,我们完成了expect_exec_cmd.sh的脚本调用参数的组织,该脚本需要四个参数

$1: 用户名

$2: 密码

$3: 命令执行目录

$4: 待执行的命令

注,在调用shell文件的时候,依然采用的事相对位置的调用形式,如上述代码采用的是

utils/expect_exec_cmd.sh "$user" "$passwd" "$work_dir_cmd" "$cmd"

 这表明在执行这部分代码时,是位于ci-deploy目录下的,所以执行环境可以正确找到utils/expect_exec_cmd.sh

shell脚本采用expect自动应答的形式执行命令

yangfei@ubuntu:~/ci-deploy$ cat utils/expect_exec_cmd.sh 
#!/usr/bin/expect -f# author: songquanheng
# date: 2024年4月24日16:17:43
# desc: 该脚本用于使用expect判断用户是否存在以及用户名密码是否匹配# 设置超时时间,这里设置为10秒
set timeout 10# 通过命令行参数传递用户名和密码
set username [lindex $argv 0]
set password [lindex $argv 1]
set work_dir_cmd [lindex $argv 2]
set cmd [lindex $argv 3]puts "username $username"
puts "password $password"
puts "word_dir_cmd $work_dir_cmd"
set status_code 42# puts "username: $username"
# puts "password: $password"
# 启动交互式程序
spawn su - $usernameexpect {"Password:" {# 提供密码send "$password\r"}-re "exist" {puts "user $username does not exist"exit 4}
}expect {-re "Authentication failure" {puts "Login failed. password wrong."exit 1 }-re "$username@" {puts "Login success."}timeout { puts "Login failed. Connection timed out."; exit 2}
}
send "$work_dir_cmd\r"
send "$cmd\r"
expect {"Settings Saved" {puts "runner authentication、registration、settings executes successfully"; exit 0}
}exit $status_code

 当时为开发这个ci-deploy工程,上述代码也是失败的主要原因,因为该命令设置了Timeout 10,但是由于配置运行器需要和github进行交互,需要下载许多的网络资源,一因此执行时间不太保证,所以就失败了,这也是这个工程没有继续执行下去的核心原因所在。

 但,这不影响,shell脚本调用的演示。

 上述shell为expect脚本,主要的作用是接收几个参数来确定执行的用户,以及密码,并在指定目录下执行命令的过程。

注: 该脚本也演示了expect脚本设置变量,打印变量,并使用退出码来判断执行结果的演示,也演示了从调用处读取位置参数

总结

 该文件主要是记录了一个shell工程的最佳实践和目录划分,并且给出了在开发这样工程时的三个注意事项:

  1. 相对路径
  2. 配置文件处理
  3. shell脚本调用

 并且行文在演示shell脚本调用时,采用的是expect自动应答,免交互的形式,方便读者学习和使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3015939.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Web Component fancy-components

css-doodle 组件库 fancy-components 组件库使用 yarn add fancy-components使用: import { FcBubbles } from fancy-components new FcBubbles() //要用哪个就new哪个 new 这里可能会报错eslink,eslintrc.js中处理报错 module.exports {rules: {no-new: off} …

OceanBase 如何实现多层面的资源隔离

OceanBase的资源隔离涵盖了多个方面,如物理机器间的隔离、不同租户之间的隔离、同一租户内的隔离,以及针对大型查询请求的隔离等。在实际应用OceanBase的过程中,我们经常会遇到这些操作场景或产生相关需求。这篇文章针对这些内容进行了简要的…

PWN入门--栈溢出

PWN入门–栈溢出 栈概要 介于网上各种wp在栈溢出利用脚本方面浅入浅出,深入讲一下栈溢出利用时,地址如何计算,栈中垃圾数据如何填充,函数调用时 参数 在栈中的分布, 栈帧的生成,函数返回值ip在栈中的摆放…

国内如何下载TikTOK,手机刷机教程

最近很多玩家都来问怎么刷机?手机环境怎么搭建?这里给大家整理了苹果IOS刷机教程 1.iOS下载教程 : 步骤一:手机调试 苹果手机系统配置推荐:iPhone6S以上,16G。 注意:如果是选择购入二手手机…

【北京迅为】《iTOP-3588开发板源码编译手册》-第4章 Android12/Linux设备树简介

RK3588是一款低功耗、高性能的处理器,适用于基于arm的PC和Edge计算设备、个人移动互联网设备等数字多媒体应用,RK3588支持8K视频编解码,内置GPU可以完全兼容OpenGLES 1.1、2.0和3.2。RK3588引入了新一代完全基于硬件的最大4800万像素ISP&…

千川投流助力直播间场观,快速增粉满足500有效粉标准,轻松开通带货权限和直播间真实流量的提升!

随着短视频带货的兴起,抖音成为了越来越多商家和创业者的首选平台。然而,最近一项新政策给广大抖音创作者带来了一定的挑战:只有拥有500有效粉的账号才能开通带货权限。为了帮助用户满足这一要求,抖音官方渠道推出了巨量千川投流服…

Python实验代码定时调起

Python代码实验调参需要等待1小时运行完成,自动将提前设置的5组参数(每组参数有8个)间隔1小时之后让Python代码再次自动依次调起运行其中的一组参数,每次跑完将实验结果写一个文件在本地存储通过邮件发送运行结果到指定QQ邮箱 im…

effective python学习笔记_pythonic思维

查py版本 import sys sys.version sys.version_info 遵循PEP8 PEP8,Python Enhancement Proposal #8 章节列了几个点,也可以看原文PEP 8 – Style Guide for Python Code | peps.python.org 导包顺序建议:先导标准库模块,再导三方模块&…

【论文阅读】Fuzz4All: Universal Fuzzing with Large Language Models

文章目录 摘要一、介绍二、Fuzz4All的方法2.1、自动提示2.1.1、自动提示算法2.1.2、自动提示的例子2.1.3、与现有自动提示技术的比较 2.2、fuzzing循环2.2.1、模糊循环算法2.2.2、Oracle 三、实验设计3.1、实现3.2、被测系统和baseline3.3、实验设置以及评估指标 四、结果分析4…

uniapp-ios支付

uniapp安卓包中的微信,支付宝逻辑放在iOS测试包中也能使用. 但询问iOS开发者后得知,有支付相关功能的app要上架苹果,必须先有苹果支付,不然苹果审核不给过.甚至没有支付逻辑,但打包时有支付相关的SDK也不行,苹果会认为你偷偷做了支付逻辑,想要绕开他. 一. 去苹果开发者后台把…

Labels and Databases for Mac:强大的标签与数据库管理工具

Labels and Databases for Mac是一款集标签制作与数据库管理于一体的强大工具,专为Mac用户打造,旨在提供高效、便捷的标签制作与数据管理体验。 这款软件拥有丰富的内置标签格式,用户可轻松创建各种标签、信封和卡片,满足个性化需…

某东抢购某台脚本——高版本

某东抢购某台脚本——高调 小白操作-学习参考 说明 这个脚本用于自动化京东的秒杀过程,特别是对于高需求商品如茅台。它展示了通过自动化工具模拟用户行为的能力,但同时也涉及到了使用自动化脚本可能违反网站使用条款的问题。使用此类脚本前应确保合…

ATFX汇市:日本央行或3万亿干预,日元升值势头显著

​ATFX汇市:4月29日,USDJPY创出历史新高160.21,随后进入快速回落阶段。五个交易日,最低价触及151.86点,相比最高价暴跌835基点,约5.21%。同期的美元指数跌幅仅为0.96%,两者跌幅严重不匹配&#…

编程语言QT、C++、C#、Matlab、SQL Server开发日志总结

目录 引言 正文 1、Qt连接SQL server数据库 2、C#使用chart绘制实时折线图,波形 3、ORACLEXE数据库 4、QT通过ODBC驱动连接Oracle数据库 5、Microsoft SQL Server 2014 安装图解 6、SQL Server 2014应用 7、C/C​​​​​​​ 8、QT…

全国33个省228189个矿产地位置分布数据,含经纬度坐标/CSV格式

全国矿产地分布(2021版) 数据来源: 全国矿产地数据库2021版 (ngac.org.cn) http://data.ngac.org.cn/mineralresource/index.html 数据获取方法:树谷资料库大全(2024年4月19日更新) 进入网站后&#xf…

记一次favicon.ico的折腾

某项目需要将前端和后台整合在一起 我也不知道为啥要整合 上面有要求就整呗 正常前端npm run build打包后 dist内会根据设置自动生成favicon.ico文件在根目录下 但由于前后端整合 需要打包后将图标放在dist下的static文件夹里 需要的效果 打包后 index.html里 <link rel&…

网络基础(1)详解

目录 1.计算机网络背景 2.网络协议 3.网络中的地址管理 1.计算机网络背景 1.1 网络发展 (1)计算机从独立模式到网络互联(多态计算机连接共享数据)再到局域网LAN(通过交换机和路由器连接)接着是广域网WAN 1.2 协议 协议就是双方的一种约定. 为什么要有协议? 因为在数据长距…

c++ cpp 在类中执行线程 进行恒定计算

在编程中&#xff0c;顺序执行是常见的模式&#xff0c;但是对cpu的利用率不是很高&#xff0c;采用线程池&#xff0c;又太麻烦了&#xff0c;原因是还得不断地把任务拆分&#xff0c;扫描返回值。 如果 初始化n个类的时候&#xff0c;传递数据自身即可异步计算&#xff0c;那…

Cobalt Strike DNS Beacon使用

0. 前言 1. 实验运行流程 2. 环境搭建 2.1.1 安装虚拟机软件VMware……大家应该都有装吧&#xff0c;这里就不教了 2.1.2 Windows 10虚拟机&#xff08;受害机&#xff09; 2.1.3 Ubuntu虚拟机&#xff08;攻击机&#xff09; 2.1 安装虚拟机 2.2 安装Java 2.3 安装Dock…

CRM定义是什么?

CRM&#xff0c;即客户关系管理&#xff0c;是一种综合性的管理策略&#xff0c;旨在通过一系列技术手段和业务流程&#xff0c;建立、维护和优化企业与客户之间的关系。它不仅仅是一种技术工具&#xff0c;更是一种以客户为中心商业哲学&#xff0c;是现代企业提升竞争力、实现…