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/bash

cd $(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 systemctl
    if [ $user_id -ne 0 ]; then
        echo "Must run as sudo"
        exit 1
    fi

}

 可以看到,在每个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/bash


user_id=`id -u`

# we want to snapshot the environment of the config user
if [ $user_id -eq 0 -a -z "$RUNNER_ALLOW_RUNASROOT" ]; then
    echo "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; do
    user=$(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; do
    user=$(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 - $username

expect {
    "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自动应答,免交互的形式,方便读者学习和使用。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

高刚性滚柱直线导轨有哪些应用场景?

滚柱型滚动体取代了滚珠,由滚柱与导轨和滑块的线接触方式,滚柱导轨能在高负载的情况下仍然保持刚性值和高精度。为实现超高刚性和超重负荷能力而设计,整体滚柱导轨达到四方向等高刚性、高负载、高精度能力的特点,非常适合高速自动…

麦肯锡精英高效阅读法笔记

系列文章目录 如何有效阅读一本书笔记 读懂一本书笔记 麦肯锡精英高效阅读法笔记 文章目录 系列文章目录序章 无法读书的5个理由无法读书的理由① 忙于工作,没时间读书无法读书的理由② 不知应该读什么无法读书的理由③ 没读完的书不断增多无法读书的理由④ 工作繁…

[华为OD]C卷 精准核算检测 100

题目: 为了达到新冠疫情精准防控的需要,为了避免全员核酸检测Q带来的浪费,需要精准圈定可 能被感染的人群。现在根据传染病流调以及大数据分析,得到了每个人之间在时间、空间上是 否存在轨迹的交叉现在给定一组确诊人员编号&…

java面向对象实现文字格斗游戏

面向对象编程(Object-Oriented Programming, OOP)是一种程序设计思想,它利用“对象”来封装状态和行为,使得代码更易于维护和扩展。 下面我们使用java中的面向对象编程,来实现一个文字格斗的游戏联系! 实…

多行字符串水平相加

题目来源与2023河南省ccpc statements_2.pdf (codeforces.com) ls [ ........ ........ .0000000 .0.....0 .0.....0 .0.....0 .0.....0 .0.....0 .0000000 ........ , ........ ........ .......1 .......1 .......1 .......1 .......1 .......1 .......1 ........, ......…

解决Gitlab集成Jira时报SSL证书问题

1. 问题描述 在gitlab中集成jira的时候,由于jira是企业内部网址,并使用自己签名的SSL证书,一直会报证书验证不过的问题,报错信息如下: Connection failed. Check your integration settings. SSL_connect returned1 …

Python专题:一、安装步骤

1、下载地址:Welcome to Python.org 勾选这个add 其他的全部下一步即可。 运行出现这个即代表安装成功。 Python自带编辑器。 2、推荐使用的sublime 编辑器下载 全部下一步安装。

快速了解OV证书和DV证书的区别及使用场景

OV(Organization Validation,组织验证)证书和DV(Domain Validation,域名验证)证书都是SSL/TLS证书,用于保护网站数据传输的安全性和提供身份验证,但两者在验证深度、信任级别、提供的…

知道了这个秘密,你也能在抖音上快速涨1000粉!巨量千川投流揭秘

随着抖音平台的快速发展,越来越多的人开始关注如何在这个平台上快速涨粉。毕竟,拥有大量的粉丝不仅可以提升个人影响力,还能为商业推广带来更多的曝光和机会。那么,抖音怎样快速涨粉呢?本文将为您揭秘其中的秘籍&#…

【Ajax零基础教程】-----第一课 Ajax简介

一、什么是ajax ajax即 Asynchronous javascript And XML (异步 javaScript 和 XML) 是一种创建交互式,快速动态应用的网页开发技术,无需重新加载整个网页的情况下,能够更新页面局部数据的技术。 二、为什么使用Ajax 通过在后台与服务器进行少…

Ansible自动运维工具之playbook

一.inventory主机清单 1.定义 Inventory支持对主机进行分组,每个组内可以定义多个主机,每个主机都可以定义在任何一个或多个主机组内。 2.变量 (1)主机变量 [webservers] 192.168.10.14 ansible_port22 ansible_userroot ans…

[SWPUCTF 2021 新生赛]PseudoProtocols、[SWPUCTF 2022 新生赛]ez_ez_php

[SWPUCTF 2021 新生赛]PseudoProtocols 打开环境,提示hint.php就在这里,且含有参数wllm 尝试利用PHP伪协议读取该文件 ?wllmphp://filter/convert.base64-encode/resourcehint.php//文件路径php://filter 读取源代码并进行base64编码输出。 有一些敏…

pip是的配置

1 疑惑 当你安装了python后打开cmd命令行输入pip发现运行不起来 疑惑了吧不是说python有内置的吗,怎么运行不起来,很简单没有配置环境变量所以运行不了 2 如何打开环境变量配置 打开电脑的设置 找到关于点开高级系统设置 点开环境变量 点开后有系统变…

Summer ‘24来啦!15个最热门的功能抢先看!

Salesforce Summer 24即将发布!本篇文章我们将深入了解Summer 24最热门的声明性功能。 01 自动化Lightning应用程序 新的自动化Lightning应用程序中包含所有与自动化相关的内容。访问该应用程序的用户可以在主应用程序中看到Flow、错误信息和其他基于社区的链接。…

民航电子数据库:replace into导致自增主键异常,新增数据时报错:违反唯一键约束

目录 场景异常原因解决方法一:删除数据重新insert方法二:刚刚自增主键的起始值 场景 1、对接民航电子数据库 2、由于truncate、drop命令会使数据库报错:执行失败,[E14011]资源忙(加锁超时),所以用了replace into命令…

XORM 框架的使用

1、xorm 1.1、xorm 简介 xorm 是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作非常简便。 特性 支持 struct 和数据库表之间的灵活映射,并支持自动同步事务支持同时支持原始SQL语句和ORM操作的混合执行使用连写来简化调用支持使用ID, In, Where, Limit,…

极致视觉盛宴,尽在Extreme Picture Finder!

在信息爆炸的时代,网络图片如同繁星点点,为我们的生活增添无尽的色彩。然而,如何在浩渺的网海中快速、准确地找到心仪的图片,却成了许多人的难题。此刻,Extreme Picture Finder如同一位贴心的向导,引领我们…

Java初识继承

继承 文章目录 继承为什么需要继承继承中变量的访问特点继承中方法的访问特点继承的优缺点 概念:在Java中,继承是面向对象编程的一个基本特性。它允许我们定义一个新类,它从另一个已经存在的类继承其属性和方法。被继承的类称为父类或超类,新…

JavaScript百炼成仙自学笔记——15

var num "0.01"; var num_arr num.split("."); var num_arr2 num_arr[1]; 0.10.20.3000000000000004 1.001*10001000.9999999999999; 小数运算丢失精度问题的解决办法: 前两种都有缺陷(第一种丢失精度&#xff0c…

(论文阅读-优化器)EFFICIENCY IN THE COLUMBIA DATABASE QUERY OPTIMIZER

目录 ABSTRACT Chapter 1. Introduction Chapter 2. Terminology 2.1 查询优化器 2.2 逻辑算子和查询树 2.3 物理算子和执行计划 2.4 Groups 2.3 搜索空间 2.6 规则 Chapter 3. Related Work 3.1 System R和Starburst优化器 3.2 Exodus和Volcano优化生成器 3.3 Cas…