BoyChai's Blog - 开源软件 2024-04-25T00:51:00+00:00 Typecho https://blog.boychai.xyz/index.php/feed/atom/category/%E5%BC%80%E6%BA%90%E8%BD%AF%E4%BB%B6/ <![CDATA[[Nginx]ngx_lua模块]]> https://blog.boychai.xyz/index.php/archives/71/ 2024-04-25T00:51:00+00:00 2024-04-25T00:51:00+00:00 BoyChai https://blog.boychai.xyz 概述

淘宝开发的ngx_lua模块通过将lua解释器解释器集成Nginx,可以采用lua脚本实现业务逻辑,由于lua的紧凑、快速以及内建协程,所以在保证高并发服务能力的同时极大降低了业务逻辑实现成本。

安装方式1(已弃用)

lua-nginx-module

LuaJIT是采用C语言编写的Lua代表的解释器。
官网: http://luajit.org
在官网找到对应下载地址: https://github.com/LuaJIT/LuaJIT/tags

[root@work env]# wget https://github.com/LuaJIT/LuaJIT/archive/refs/tags/v2.0.5.tar.gz
[root@work env]# tar xvf v2.0.5.tar.gz 
[root@work env]# cd LuaJIT-2.0.5/
[root@work LuaJIT-2.0.5]# make && make install
make[1]: Leaving directory '/opt/env/LuaJIT-2.0.5/src'
==== Successfully built LuaJIT 2.0.5 ====
==== Installing LuaJIT 2.0.5 to /usr/local ====
mkdir -p /usr/local/bin /usr/local/lib /usr/local/include/luajit-2.0 /usr/local/share/man/man1 /usr/local/lib/pkgconfig /usr/local/share/luajit-2.0.5/jit /usr/local/share/lua/5.1 /usr/local/lib/lua/5.1
cd src && install -m 0755 luajit /usr/local/bin/luajit-2.0.5
cd src && test -f libluajit.a && install -m 0644 libluajit.a /usr/local/lib/libluajit-5.1.a || :
rm -f /usr/local/bin/luajit /usr/local/lib/libluajit-5.1.so.2.0.5 /usr/local/lib/libluajit-5.1.so /usr/local/lib/libluajit-5.1.so.2
cd src && test -f libluajit.so && \
  install -m 0755 libluajit.so /usr/local/lib/libluajit-5.1.so.2.0.5 && \
  ldconfig -n /usr/local/lib && \
  ln -sf libluajit-5.1.so.2.0.5 /usr/local/lib/libluajit-5.1.so && \
  ln -sf libluajit-5.1.so.2.0.5 /usr/local/lib/libluajit-5.1.so.2 || :
cd etc && install -m 0644 luajit.1 /usr/local/share/man/man1
cd etc && sed -e "s|^prefix=.*|prefix=/usr/local|" -e "s|^multilib=.*|multilib=lib|" luajit.pc > luajit.pc.tmp && \
  install -m 0644 luajit.pc.tmp /usr/local/lib/pkgconfig/luajit.pc && \
  rm -f luajit.pc.tmp
cd src && install -m 0644 lua.h lualib.h lauxlib.h luaconf.h lua.hpp luajit.h /usr/local/include/luajit-2.0
cd src/jit && install -m 0644 bc.lua v.lua dump.lua dis_x86.lua dis_x64.lua dis_arm.lua dis_ppc.lua dis_mips.lua dis_mipsel.lua bcsave.lua vmdef.lua /usr/local/share/luajit-2.0.5/jit
ln -sf luajit-2.0.5 /usr/local/bin/luajit
==== Successfully installed LuaJIT 2.0.5 to /usr/local ====

lua-nginx-module

nginx第三方模块lua-nginx-module
官网: https://github.com/openresty/lua-nginx-module

[root@work env]# wget https://github.com/openresty/lua-nginx-module/archive/refs/tags/v0.10.26.tar.gz
[root@work env]# tar xvf v0.10.26.tar.gz 
[root@work env]# ln -s lua-nginx-module-0.10.26 lua-nginx-module

环境变量设置

[root@work ~]# tail -n2 /etc/profile
export LUAJIT_LIB=/usr/local/lib
export LUAJIT_INC=/usr/local/include/luajit-2.0
[root@work ~]# source /etc/profile

扩展nginx模块

打开nginx编译安装的位置 进行重新编译安装

[root@work nginx-1.24.0]# ./configure  --prefix=/usr/local/nginx  --sbin-path=/usr/local/nginx/sbin/nginx --conf-path=/usr/local/nginx/conf/nginx.conf --error-log-path=/var/log/nginx/error.log  --http-log-path=/var/log/nginx/access.log  --pid-path=/var/run/nginx/nginx.pid --lock-path=/var/lock/nginx.lock  --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module --with-http_gzip_static_module --http-client-body-temp-path=/var/tmp/nginx/client/ --http-proxy-temp-path=/var/tmp/nginx/proxy/ --http-fastcgi-temp-path=/var/tmp/nginx/fcgi/ --http-uwsgi-temp-path=/var/tmp/nginx/uwsgi --http-scgi-temp-path=/var/tmp/nginx/scgi --with-pcre --add-module=/opt/package/nginx/lua-nginx-module
[root@work nginx-1.24.0]# make && make install

扩展的重点是--with-pcre --add-module=/opt/package/nginx/lua-nginx-module
这里就相当于重新安装了,之前安装的模块还需要再这里再添加一遍

错误

libluajit-5.1.so.2

当在扩展号nginx模块后执行nginx相关命令出现以下错误

[root@work ~]# nginx -V
nginx: error while loading shared libraries: libluajit-5.1.so.2: cannot open shared object file: No such file or directory

这个错误表明 Nginx 在启动时无法找到名为 libluajit-5.1.so.2 的共享库文件。这很可能是由于 Nginx 模块依赖 LuaJIT 库,但系统中缺少了该库所致。解决办法如下

[root@work ~]# ln -s /usr/local/lib/libluajit-5.1.so.2 /lib64/liblua-5.1.so.2

reason: module 'resty.core' not found

[root@work conf]# nginx
nginx: [alert] detected a LuaJIT version which is not OpenResty's; many optimizations will be disabled and performance will be compromised (see https://github.com/openresty/luajit2 for OpenResty's LuaJIT or, even better, consider using the OpenResty releases from https://openresty.org/en/download.html)
nginx: [alert] failed to load the 'resty.core' module (https://github.com/openresty/lua-resty-core); ensure you are using an OpenResty release from https://openresty.org/en/download.html (reason: module 'resty.core' not found:
    no field package.preload['resty.core']
    no file './resty/core.lua'
    no file '/usr/local/share/luajit-2.0.5/resty/core.lua'
    no file '/usr/local/share/lua/5.1/resty/core.lua'
    no file '/usr/local/share/lua/5.1/resty/core/init.lua'
    no file './resty/core.so'
    no file '/usr/local/lib/lua/5.1/resty/core.so'
    no file '/usr/local/lib/lua/5.1/loadall.so'
    no file './resty.so'
    no file '/usr/local/lib/lua/5.1/resty.so'
    no file '/usr/local/lib/lua/5.1/loadall.so') in /usr/local/nginx/conf/nginx.conf:117

原因似乎是缺少lua-resty-core模块,这里手动编译安装一下
项目地址: https://github.com/openresty/lua-resty-core

[root@work nginx]# tar xvf v0.1.28.tar.gz 
tar xvf
make install

安装方式2

概述

直接使用OpenRestry,它是由淘宝工程师开发的,它是基于Nginx与Lua的高性能Web平台,其内部集成了大量精良的Lua库,第三方模块以及大多数的依赖项,用于方便搭建能够处理高并发、扩展性极高的动态Web应用、Web服务和动态网关。所以本身OpenResty内部就已经集成了Nginx和Lua,我们用起来会更加方便

安装

参考: https://openresty.org/cn/linux-packages.html
配置:/usr/local/openrestry/nginx/conf

关于OpenRestry

OpenRestry,它是由淘宝工程师开发的,它是基于Nginx与Lua的高性能Web平台,其内部集成了大量精良的Lua库,第三方模块以及大多数的依赖项,用于方便搭建能够处理高并发、扩展性极高的动态Web应用、Web服务和动态网关。所以本身OpenResty内部就已经集成了Nginx和Lua,我们用起来会更加方便。
PS:本文只讲ngx_lua的使用,其他的基本和nginx配置无区别。

ngx_lua相关指令块

使用Lua编写Nginx脚本的基本构建块是指令。指令用于指定何时运行用户Lua代码以及如何使用结果。下图显示了执行指令的顺序。
顺序

先来解释一下*的作用

*:无 , 即 xxx_by_lua ,指令后面跟的是 lua指令
*:_file,即 xxx_by_lua_file 指令后面跟的是 lua文件
*:_block,即 xxx_by_lua_block 在0.9.17版后替换init_by_lua_file

init_by_lua*

该指令在每次Nginx重新加载配置时执行,可以用来完成一些耗时模块的加载,或者初始化一些全局配置。

init_worker_by_lua*

该指令用于启动一些定时任务,如心跳检查、定时拉取服务器配置等。

set_by_lua*

该指令只要用来做变量赋值,这个指令一次只能返回一个值,并将结果赋值给Nginx中指定的变量。

rewrite_by_lua*

该指令用于执行内部URL重写或者外部重定向,典型的如伪静态化URL重写,本阶段在rewrite处理阶段的最后默认执行。

access_by_lua*

该指令用于访问控制。例如,如果只允许内网IP访问。

content_by_lua*

该指令是应用最多的指令,大部分任务是在这个阶段完成的,其他的过程往往为这个阶段准备数据,正式处理基本都在本阶段。

header_filter_by_lua*

该指令用于设置应答消息的头部信息。

body_filter_by_lua*

该指令是对响应数据进行过滤,如截断、替换。

log_by_lua*

该指令用于在log请求处理阶段,用Lua代码处理日志,但并不替换原有log处理。

balancer_by_lua*

该指令主要的作用是用来实现上游服务器的负载均衡器算法

ssl_certificate_by_*

该指令作用在Nginx和下游服务开始一个SSL握手操作时将允许本配置项的Lua代码。

案例1

需求

输出内容

配置

  location /lua {
            default_type 'text/html';
            content_by_lua 'ngx.say("<h1>HELLO,OpenResty</h1>")';
        }

案例2

需求

http://xxx/?name=张三&gender=1
Nginx接收到请求后根据gender传入的值,如果是gender传入的是1,则展示张三先生,如果是0则展示张三女士,如果都不是则展示张三。

配置

  location /getByGender {
                default_type 'text/html';
                set_by_lua $param "
                        -- 获取请求URL上的参数对应的值
                        local uri_args = ngx.req.get_uri_args()
                        local name = uri_args['name']
                        local gender = uri_args['gender']
                        -- 条件判断 if gender 1 先生 0 女士
                        if gender == '1' then
                                return name..'先生'
                        elseif gender == '0' then
                                return name..'女士'
                        else
                                return name
                        end
                ";
                # 解决中文乱码
                charset utf-8;
                # 返回数据
                return 200 $param;
        }

ngx.req.get_uri_args()返回的是一个table类型

案例3

需求

动态获取docker容器ip,做代理

配置

server{
         listen       80;
         server_name  code.boychai.xyz;
         client_max_body_size 4096M;
     set_by_lua $param '
             local name = "gitea"
                local port = "3000"
                local command = string.format("echo -n `docker inspect --format=\'{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}\' %s`", name)
                local handle = io.popen(command)
                local result = handle:read("*a")
                handle:close()
                return "http://"..result..":"..port
     ';
         location / {
                if ( $param = 'http://:3000' ) {
                        return 500 "Error in obtaining site IP";
                }
            proxy_pass     $param;
                proxy_set_header     Host $proxy_host;
                proxy_set_header        X-Real-IP $remote_addr;
                proxy_set_header     X-Forwarded-For $proxy_add_x_forwarded_for;
         }
}
]]>
<![CDATA[[Tekton] 报错: more than one PersistentVolumeClaim is bound]]> https://blog.boychai.xyz/index.php/archives/70/ 2024-04-24T11:45:00+00:00 2024-04-24T11:45:00+00:00 BoyChai https://blog.boychai.xyz 复现

task-nodejs.yaml

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: build-node-project
spec:
  workspaces:
    - name: cache
      mountPath: /root/.npm
    - name: source
    - name: output
  params:
    - name: imgTag
      type: string
    - name: run
      type: string
    - name: dir
      type: string
  steps:
    - name: build
      workingDir: "$(workspaces.source.path)/$(params.dir)"
      image: "node:$(params.imgTag)"
      script: |
        rm -rf package-lock.json
        npm install --registry=https://registry.npmmirror.com/
        npm run $(params.run)
        cp -r dist/* $(workspaces.output.path)/

taskrun.yaml

apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
  generateName: build-node-project-run-
  generation: 1
  namespace: cicd-services
spec:
  params:
  - name: dir
    value: frontend
  - name: imgTag
    value: 21.6.2
  - name: run
    value: build
  serviceAccountName: default
  taskRef:
    kind: Task
    name: build-node-project
  workspaces:
  - name: cache
    persistentVolumeClaim:
      claimName: node-cache-pvc
  - name: source
    persistentVolumeClaim:
      claimName: test-tekton-vue-pvc
  - name: output
    persistentVolumeClaim:
      claimName: test-tekton-vue-output-pvc

运行之后会出现下面报错

TaskRunValidationFailed [User error] more than one PersistentVolumeClaim is bound

原因

报错翻译TaskRunValidationFailed[用户错误]绑定了多个PersistentVolumeClaim,很明确他允许绑定多个pvc,这个蛮离谱的,cicd的过程中用到多个存储应该是很正常的事,tekton却默认不支持绑定多个pvc。

解决

修改tekton的配置把参数disable-affinity-assistant修改为true,即可

kubectl -n tekton-pipelines edit cm feature-flags

这个参数的作用如下

设置为 true 将阻止 Tekton 为共享了 workspace 的每个 TaskRun 创建 Affinity Assistant Pod。 这样就可以保证这些 pod 运行在同一个节点上,避免了跨节点访问 pvc 的问题。

还有就是这个功能在v0.60会被弃用,未来估计不会因为这个问题报这个错了。

参考

ISSUE: https://github.com/tektoncd/pipeline/issues/6543
TektonDocs: https://github.com/tektoncd/pipeline/blob/main/docs/affinityassistants.md
配置参考: https://www.soulchild.cn/post/tekton-operator%E9%85%8D%E7%BD%AE%E5%8F%82%E6%95%B0%E8%AF%A6%E8%A7%A3/

]]>
<![CDATA[[Lua]快速入门]]> https://blog.boychai.xyz/index.php/archives/69/ 2024-04-17T08:01:00+00:00 2024-04-17T08:01:00+00:00 BoyChai https://blog.boychai.xyz Lua

概念

Lua是一种轻量、小巧的脚本语言,用标准的C语言编写并以源代码形式开发。设计目的是为了嵌入其他的程序中,从而为应用程序提供灵活的扩展和定制功能。

特性

和他语言相比,Lua有其自身的特点:
(1)轻量级

lua用标准C语言编写并以源代码形式开发,编译后仅仅一百余千字节,可以很方便的嵌入道其他程序中。

(2)可扩展

lua提供非常丰富易于使用的扩展接口和机制,由宿主语言(通常是C或C++)提供功能,lua可以使用它们,就像内置的功能一样。

(3)支持面向过程编程和函数式编程

应用场景

游戏开发、独立应用脚本、web应用脚本、扩展和数据库插件、系统安全上。

安装

官网: https://www.lua.org/

[root@work env]# wget https://www.lua.org/ftp/lua-5.4.6.tar.gz
[root@work env]# tar xvf lua-5.4.6.tar.gz 
[root@work lua-5.4.6]# make linux test
[root@work lua-5.4.6]# make install
cd src && mkdir -p /usr/local/bin /usr/local/include /usr/local/lib /usr/local/man/man1 /usr/local/share/lua/5.4 /usr/local/lib/lua/5.4
cd src && install -p -m 0755 lua luac /usr/local/bin
cd src && install -p -m 0644 lua.h luaconf.h lualib.h lauxlib.h lua.hpp /usr/local/include
cd src && install -p -m 0644 liblua.a /usr/local/lib
cd doc && install -p -m 0644 lua.1 luac.1 /usr/local/man/man1
[root@work lua-5.4.6]# lua -v
Lua 5.4.6  Copyright (C) 1994-2023 Lua.org, PUC-Rio

语法

他的语法和C/C++语法非常相似,整体上比较清晰,简洁。条件语句、循环语句、函数调用都与C/C++基本一致。

交互式HelloWorld

[root@work env]# lua
Lua 5.4.6  Copyright (C) 1994-2023 Lua.org, PUC-Rio
> print('hello world!!') 
hello world!!
> 

脚本式HelloWorld

第一种方式

[root@work ~]# mkdir lua_demo
[root@work ~]# cd lua_demo/
[root@work lua_demo]# vim hello.lua
[root@work lua_demo]# cat hello.lua 
print('hello world!!!')
[root@work lua_demo]# lua hello.lua 
hello world!!!

第二种方式

[root@work lua_demo]# vim hello.lua
[root@work lua_demo]# cat hello.lua 
#! /usr/local/bin/lua
print('hello world!!!')
[root@work lua_demo]# chmod +x hello.lua 
[root@work lua_demo]# ./hello.lua 
hello world!!!

注释

%% 单行注释 %%
-- print("111")
%% 多行注释 %%
--[[
    print("222")
--]]
%% 取消多行注释 %%
---[[
    print("222")
--]]

测试

[root@work lua_demo]# vim demo2.lua
[root@work lua_demo]# cat demo2.lua 
-- print("111")
--[[
    print("222")
--]]
---[[
    print("333")
--]]
[root@work lua_demo]# lua demo2.lua 
333

标识符

标识符就是变量名,Lua定义变量名以 一个字母A到Z或a到z或下划线_开头后加上0个或者多个字母,下划线,数字(0-9)。这块建议最好不要使用下划线加大写字母的标识符,因为Lua的保留字也是这样定义的,容易发生冲突。注意Lua是区分大小写字母的。

关键字

下面Lua的关键词,大家在定义常量、变量或其他用户定义标识符都要避免使用一下关键字

andbreakdoelse
elseifendfalsefor
functionifinlocal
nilnotorrepeat
returnthentrueuntil
whilegoto

一般约定,一以下划线开头连接一串大写字母的名字(比如_VERSION)被保留用于Lua内部全局变量。这个也是上面我们不建议这么定义标识符的原因

运算符

Lua中支持的运算符有算数运算符、关系运算符、逻辑运算符、其他运算符。

算数运算符

+ 加
- 减
* 乘
/ 除
% 取余
^ 乘幂
- 负号

关系运算符

== 等于
~= 不等于
> 大于
< 小于
>= 大于等于
<= 小于等于

逻辑运算符

and 与 同时true返回true 
or 或 一个true返回true
not 非 取反

其他运算符

.. 连接两个字符串
#  一元预算法,返回字符串或表的长度

例如

[root@work lua_demo]# lua 
Lua 5.4.6  Copyright (C) 1994-2023 Lua.org, PUC-Rio
> 
> print('HELLO '..'WORLD') 
HELLO WORLD
> print(#'hello')         
5

全局变量&局部变量

在Lua语言中,全局变量无须声明即可使用。在默认情况下,变量总是认为是全局的,如果未提前赋值,默认为nil。如果想要声明一个局部变量需要使用local来声明。

[root@work lua_demo]# lua
Lua 5.4.6  Copyright (C) 1994-2023 Lua.org, PUC-Rio
> b=10
> print(b)
10
> local a = 100
> print(a)
nil
> local a = 100; print(a)   
100
> 

数据类型

全部的类型

Lua有8个数据类型

nil(空,无效值)
boolean(布尔,true/false)
number(数值)
string(字符串)
function(函数)
table(表)
thread(线程)
userdata(数据用户)

可以使用type函数测试给定变量或者类型:

[root@work lua_demo]# lua
Lua 5.4.6  Copyright (C) 1994-2023 Lua.org, PUC-Rio
> print(type(nil))
nil
> print(type("aaa"))
string
> 

nil

nil是一种只有一个nil值的类型,他的作用可以用来与其他所有值进行区分,也可以当想要移除一个变量时,只需要将该变量名赋值为nil,垃圾回收就会释放该变量所占用的内存。

boolean

boolean类型具有两个值,true和false。在Lua中,只会将false和nil视为假,其他都是真,特别是在条件检测中0和空字符串都会认为是真,这个和我们熟悉的大多语言不太一样。

number

在lua5.3开始,lua语言为数值格式提供了两种选择:integer(整型)和float(双精度浮点型)[和其他语言不太一样,floatu代表单精度类型],u不管是整形还是双精度浮点型,使用type()函数来取其类型,返回的都是number。还有就是他们之间是可以直接相互转换的。

string

Lua语言中的字符串可以标识单个字符,也可以标识一整本书籍。在Lua语言中,操作100k或者1M个字母组成的字符串的程序很常见。如果字符串数据很多可以这样写

a = [[
<html>
xxx
xxxx
xxx
</html>
]]

table

table是lua语言中最主要和强大的数据结构。使用表,Lua语言可以以一种简单、统一且高效的方式标识数组、合集、记录和其他很多数据结构。Lua语言中的表本质上是一种辅助数组。这种数组比Java中的数组更加灵活,可以使用数值做索引,也可以使用字符串或其他任意类型的值做索引(nil除外)

[root@work lua_demo]# lua
Lua 5.4.6  Copyright (C) 1994-2023 Lua.org, PUC-Rio
> a = {}
> arr = {"TOM","JERRY","ROSE"}
> print(arr[0])  
nil
> print(arr[1])     
TOM
> print(arr[2]) 
JERRY
> print(arr[3]) 
ROSE
> arr={}
> arr["X"]=10
> arr["Y"]=20
> arr["Z"]=30
> print(arr["X"])
10
> print(arr["Y"])
20
> print(arr["Z"])
30
> arr.X
10
> arr.Y
20
> arr.Y
20
> arr={"TOM",X=10,"JERRY",Y=20,"ROSE",Z=30}
> arr[1]
TOM
> arr[2]
JERRY
> arr[3]
ROSE
> arr[4]
nil
> arr.X
10
> arr["X"]  
10
> arr.Z
30
> 

function

在Lua语言中,函数(Function)是对语句和表达式进行抽象的主要方式
定义函数:

function functionName(params)
    code
end

函数被调用的时候,传入的参数个数与定义函数时使用的参数个数不一致的时候,Lua会通过抛弃多余参数和将不足的参数设为nil的方式来调整数的个数。

[root@work lua_demo]# lua
Lua 5.4.6  Copyright (C) 1994-2023 Lua.org, PUC-Rio
> function f(a,b)
>> print(a,b)
>> end
> f()
nil    nil
> f(2)
2    nil
> f(2,6)
2    6
> f(2,6,8)
2    6

可变参数

[root@work lua_demo]# lua
Lua 5.4.6  Copyright (C) 1994-2023 Lua.org, PUC-Rio
> function add(...)
>> local a,b,c=...                   
>> print(a,b,c)
>> end
> add(1,2,3)
1    2    3
> add(1)  
1    nil    nil
> add(1,2,3,4,5,6)
1    2    3
> 

返回值

[root@work lua_demo]# lua
Lua 5.4.6  Copyright (C) 1994-2023 Lua.org, PUC-Rio
> function add(a,b)
>> return b,a
>> end
> x,y=add(100,200)
> print(y) 
100
> print(x)
200
> 

控制结构

Lua语言提供了一组精简且常用的控制结构,包括用于条件执行的if以及用户循环的while、repeat和for。所有的控制语法上都有一个显示的终结符:end用于中介if、for以及while结构,until用于中介repeat结构。

if语句

if语句先测试其条件,并根据条件是否满足执行响应的then部分或else部分。else部分是可选的。

[root@work lua_demo]# lua
Lua 5.4.6  Copyright (C) 1994-2023 Lua.org, PUC-Rio
> function testif(a)
>> if a>0 then
>> print("a是正数")
>> end
>> end
> testif(2)   
a是正数
> testif(1)
a是正数
> testif(-1)
> function testif(a)
>> if a>0 then
>> print("a是正数")
>> else
>> print("a是负数")
>> end
>> end
> testif(1) 
a是正数
> testif(-1)
a是负数
> 

嵌套IF相关案例如下

[root@work lua_demo]# lua
Lua 5.4.6  Copyright (C) 1994-2023 Lua.org, PUC-Rio
> function show(age)    
>> if age <= 18 then
>> return "qingshaonian" 
>> elseif age>18 and age <=45 then
>> return "qingnian"
>> elseif age>45 and age <=60 then
>> return "zhongnianren"
>> else
>> return "laonianren" 
>> end
>> end
> print(show(17))              
qingshaonian
> print(show(19))
qingnian
> print(show(56))
zhongnianren
> print(show(80))
laonianren

while循环

语法如下

while 条件 do
    循环体
end

案例

[root@work lua_demo]# lua
Lua 5.4.6  Copyright (C) 1994-2023 Lua.org, PUC-Rio
> function testwhile()
>> local i=1
>> while i<=10 do
>> print(i)
>> i=i+1
>> end
>> end
> testwhile()
1
2
3
4
5
6
7
8
9
10

repeat循环

repeat-until语句回重复执行其循环体直到条件为真时结束。由于条件测试在循环体之后执行,所以至少会循环执行一次。
语法如下

repeat
    循环体
until 条件

案例如下

[root@work lua_demo]# lua
Lua 5.4.6  Copyright (C) 1994-2023 Lua.org, PUC-Rio
> function testRepeat()
>> local i = 10
>> repeat
>> print(i)
>> i=i-1
>> until i < 1
>> end
> testRepeat()
10
9
8
7
6
5
4
3
2
1

for循环

数值型

语法如下

for param=exp1,exp2,exp3 do
    循环体
end

param的值从exp1变化到exp2之前的每次循环会执行循环体,并在每次循环结束的时候步长,和python的for差不多。
案例如下

[root@work lua_demo]# lua
Lua 5.4.6  Copyright (C) 1994-2023 Lua.org, PUC-Rio
> for i = 1,100,10 do 
>> print(i)
>> end
1
11
21
31
41
51
61
71
81
91
泛型

泛型for循环是通过一个迭代器函数来遍历所有的值,类似于java中的foreach语句
语法

for i,v in ipairs(x) do
    循环体
end

i是数组索引,v是对应索引的数组元素值,ipairs是Lua提供的一个迭代器函数,用来迭代数组,x是要遍历的数组。只后pairs也是Lua提供的夜歌迭代函数,他和ipairs的区别是pairs可以迭代一些指定键的table。
案例如下

[root@work lua_demo]# lua
Lua 5.4.6  Copyright (C) 1994-2023 Lua.org, PUC-Rio
> arr = {"TOME","JERRY","ROWS","LUCY"}
> for i,v in ipairs(arr) do
>> print(i,v)
>> end
1    TOME
2    JERRY
3    ROWS
4    LUCY
[root@work lua_demo]# lua
Lua 5.4.6  Copyright (C) 1994-2023 Lua.org, PUC-Rio
> arr = {"TOM","JERRY","ROSES",x="JACK","LUCY"}
> function testfor(arr)
>> for i,v in pairs(arr) do 
>> print(i,v)
>> end
>> end
> testfor(arr)
1    TOM
2    JERRY
3    ROSES
4    LUCY
x    JACK
]]>
<![CDATA[[排错笔记]Vue3+Electron构建报错]]> https://blog.boychai.xyz/index.php/archives/68/ 2024-02-19T15:25:00+00:00 2024-02-19T15:25:00+00:00 BoyChai https://blog.boychai.xyz 使用环境
"Node":"21.6.2"
"@vue/cli-service": "~5.0.0",
"electron": "^13.0.0",

问题一

报错

background.js from Terser
Error: error:0308010C:digital envelope routines::unsupported
    at new Hash (node:internal/crypto/hash:68:19)
    at Object.createHash (node:crypto:138:10)
    at E:\前端\assist\node_modules\vue-cli-plugin-electron-builder\node_modules\webpack\node_modules\terser-webpack-plugin\dist\index.js:217:37
    at Array.forEach (<anonymous>)
    at TerserPlugin.optimizeFn (E:\前端\assist\node_modules\vue-cli-plugin-electron-builder\node_modules\webpack\node_modules\terser-webpack-plugin\dist\index.js:160:259)
    at _next0 (eval at create (E:\前端\assist\node_modules\vue-cli-plugin-electron-builder\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:8:1)
    at eval (eval at create (E:\前端\assist\node_modules\vue-cli-plugin-electron-builder\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:23:1)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)

原因

用了高版本的node.js

解决

给NODE_OPTIONS添加环境变量--openssl-legacy-provider,低版本的不需要,默认忽略ssl验证

set NODE_OPTIONS=--openssl-legacy-provider

问题二

报错

Error output:
!include: could not find: "E:\前端\assist\node_modules\app-builder-lib\templates\nsis\include\StdUtils.nsh"
Error in script "<stdin>" on line 1 -- aborting creation process

    at ChildProcess.<anonymous> (E:\前端\assist\node_modules\builder-util\src\util.ts:250:14)
    at Object.onceWrapper (node:events:634:26)
    at ChildProcess.emit (node:events:519:28)
    at ChildProcess.cp.emit (E:\前端\assist\node_modules\builder-util\node_modules\cross-spawn\lib\enoent.js:34:29)
    at maybeClose (node:internal/child_process:1105:16)
    at Process.ChildProcess._handle.onexit (node:internal/child_process:305:5) {
  exitCode: 1,
  alreadyLogged: false,
  code: 'ERR_ELECTRON_BUILDER_CANNOT_EXECUTE'
}

原因

路径有中文路径

解决

切换项目目录给copy到个全英路径的位置

问题三

报错

打开页面全白

原因

路由模式用的history

解决

路由模式切换成hash模式

问题四

报错



<router-view>标签不生效

原因

不清楚为什么会这样 反正我这个版本打包后 electron不会进入”/“路径下 但是在本地访问的时候会

解决

在App.vue中直接push到/

import { useRouter } from "vue-router";

const router = useRouter();
router.push(`/`);

要注意的是router.back();路由跳转我这边也不生效了,需要都替换成push('/')

问题五

报错

 • cannot get, wait  error=Get "https://service.electron.build/find-build-agent?no-cache=1it6rqj": dial tcp 51.15.76.176:443: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
                      attempt=0
                      waitTime=2
  • cannot get, wait  error=Get "https://service.electron.build/find-build-agent?no-cache=1it6rqj": dial tcp 51.15.76.176:443: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
                      attempt=1
                      waitTime=4
  • cannot get, wait  error=Get "https://service.electron.build/find-build-agent?no-cache=1it6rqj": dial tcp 51.15.76.176:443: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
                      attempt=2
                      waitTime=6
  ⨯ Get "https://service.electron.build/find-build-agent?no-cache=1it6rqj": dial tcp 51.15.76.176:443: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.

win跨平台构建linux从service.electron.build下载资源失败,换代理也没用

原因

这个站点service.electron.build似乎在2020年就关闭,一直也没人来修这个玩意

解决

换linux主机构建或者采用docker的容器进行构建
ISSUES:https://github.com/electron-userland/electron-build-service/issues/9

]]>
<![CDATA[[MYSQL]SQL优化]]> https://blog.boychai.xyz/index.php/archives/64/ 2023-09-05T04:51:00+00:00 2023-09-05T04:51:00+00:00 BoyChai https://blog.boychai.xyz 插入数据
  • 批量插入数据推荐使用下面语句
INSERT INTO 表名(字段1,字段2,......) VALUES (值1,值2,......),(值1,值2,......),(值1,值2,......);
  • 如果数据量过于庞大,数据条数大于1000推荐使用文件导入的方式进行插入,方法如下
## 登录mysql的时候需要添加--local-infile参数
mysql --local-infile -u root -p
## 登录之后设置local_infile为1,开启从本地加载文件导入数据的开关
set global local_infile=1;
## 使用load命令导入数据
load data local infile '文件' into table `表名` fields terminated by `文件里面的分隔符` lines terminated by '\n';

文件里面的内容格式如下

1,a,b,c
2,b,c,d

PS:主键顺序插入性能高于乱序插入

主键优化

  • 数据组织方式

在InnoDB存储引擎中,表数据都是根据逐渐顺序组织存放的,这种存储方式的表成为索引组织表(index organized table IOT)

  • 页分裂

页可以为空 ,也可以填充一半,也可以填充100%。每个页包含了2-N行数据(如果 一行数据多大,会溢出),根据主键排列。

  • 页合并

当删除一条记录时,实际上记录并没有被物理删除,只是被标记(flaged)为啥暗处并且他的空间变得允许被其他记录声明使用。当页面中删除的记录达到MERGE_THRESHOLD(默认为页的50%),InnoDB会开始寻找最靠近的页(前或后)看看是否可以将两个页合并已优化空间使用。

  • 主键设置原则
  1. 满足业务要求的情况下,尽量降低主键长度。
  2. 插入数据的时,尽量选择顺序插入,选择使用AUTO_INCREMENT自增主键。
  3. 尽量不要使用UUID做主键或者是其他自然主键,如身份证。
  4. 业务操作时,避免对主键的修改。

order by优化

  • Using filesort

通过表的索引或全表扫描,读取满足条件的数据行,然后在排序缓冲区sort buffer中完成排序操作,所有不是通过索引直接返回排序结果的排序都叫FileSort排序。

  • Using index

通过有序索引顺序扫描直接返回有序数据,这种情况即为using index,不需要额外排序,操作效率更高。

  • 优化
  1. 根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则。
  2. 尽量使用覆盖索引。
  3. 多字段排序,一个升序一个降序,此时需要注意联合索引在创建时的规则(ASC/DESC)
  4. 如果不可避免出现filesort,大数据量排序时,可以适当增大排序缓冲区大小sort_buffer_size(默认256k)。

group by优化

  • 分组操作时,可以通过索引来提高效率。
  • 分组操作时,索引的使用也是满足最左前缀法则的。

limit优化

一般分页查询时,通过创建 覆盖索引 能够比较好的提高性能,可以通过覆盖索引加子查询形式进行优化。

count优化

  • 在MyISAM引擎把一个表的总行数存在了磁盘上,因此执行count(*)的时候会直接返回这个数,效率很高。
  • InnoDB引擎就麻烦了,他执行count(*)的时候,需要把数据一行一行的从引擎里面读出来,让后累计计数。
  • count(主键)

InnoDB引擎会遍历整张表,把每一行的主键id值都取出来,返回给服务层。服务层拿到主键后,直接按行累加(主键不可能为null)。

  • count(字段)

没有not null约束时: InnoDB疫情会便利整张表把每一行的字段值都取出来,返回给服务层,服务层判断是否为null,不为null,计数累加。

有not null约束时: InnoDB疫情会便利整张表把每一行的字段值都取出来,返回给服务层们直接按行进行累加。

  • count(1)

InnoDB疫情遍历整张表,但不取值。服务层对于返回的每一行,放一个数字“1”进去,直接按行累加。

  • count(*)

InnoDB疫情并不会把全部字段取出来,而是专门做了优化,不取值,服务层直接按行进行累加。

  • 优化方案

    1. 可以自己做count,使用缓存数据库做这类工作。
    2. 按照效率排序的话,count(字段)<count(主键)<count(1)≈count(*),所以尽量使用count(*)。

update优化

InnoDB的行锁是针对索引加的锁,不是针对记录家的锁,并且该索引不能失效,否则会从行锁升级为表锁。规避这种情况就需要在对应字段创建索引。

]]>
<![CDATA[[资源]容器镜像代理站、加速站收集]]> https://blog.boychai.xyz/index.php/archives/63/ 2023-08-30T07:25:40+00:00 2023-08-30T07:25:40+00:00 BoyChai https://blog.boychai.xyz <![CDATA[数据库通用语言-SQL]]> https://blog.boychai.xyz/index.php/archives/61/ 2023-08-10T05:36:00+00:00 2023-08-10T05:36:00+00:00 BoyChai https://blog.boychai.xyz SQL分类
类别全称概述
DDLData Definition Language数据定义语言,用来定义数据库对象(数据库,表,字段)
DMLData Manipulation Language数据操作语言,用来对数据库表中的数据进行删增改查
DQLData Query Language数据查询语言,用来查询数据库中表的记录
DCLData Control Language数据控制语言,用来创建数据库用户,控制数据库的访问权限

DDL

数据库操作

查询

  • 查询所有数据库
SHOW DATABASES;
  • 查询当前数据库
SELECT  DATABASE();

创建

CREATE DATABASE [ IF NOT EXISTS ] 数据库名称 [ DEFAULT CHARSET 字符集 ] [ COLLATE 排序规则 ];

使用时可以在数据库名称前面加入"IF NOT EXISTS",意为当数据库不存在则创建否则不作为。

删除

DROP DATABASE [ IF EXISTS ] 数据库名称;

使用时可以在数据库名称前面加入"IF EXISTS",意为当数据库存在则删除否则不作为。

使用

USE 数据库名称;

表操作

ps:表操作需要使用数据库之后才能操作

查询

  • 查询当前数据库中所有的表

SHOW TABLES;

  • 查询表字段结构

DESC 表名称;

  • 查询指定表的建表语句

SHOW CREATE TABLE 表名;

创建

CREATE TABLE 表名(

​ 字段1 字段1数据类型 [ COMMENT 字段1注释 ],

​ 字段2 字段2数据类型 [ COMMENT 字段2注释 ],

​ 字段3 字段3数据类型 [ COMMENT 字段3注释 ]

​ ......

) [ COMMENT 表格注释 ];

修改

修改表名称

ALTER TEABLE 表名 RENAME TO 新表名;

删除

  • 删除表

DROP TABLE [ IF EXISTS ] 表名;

"IF EXISTS" 意为有则删除否则不作为

  • 删除指定表,并且重新创建该表(一般用于格式化)

TRUNCATE TABLE 表名;

字段操作

修改

  • 添加字段

ALTER TABLE 表名 ADD 字段名 类型(长度) [ COMMENT 注释 ] [约束];

  • 修改数据类型

ALTER TABLE 表名 MODIFY 字段名 新数据类型(长度);

  • 修改字段名和字段类型

ALTER TABLE 表名 CHANGE 旧字段名 新字段名 类型(长度) [ COMMENT 注释 ] [约束];

删除

ALTER TABLE 表名 DROP 字段名

数据类型

概述

MYSQL的数据类型主要分为三种:数值类型、字符串类型、日期时间类型。

数值类型

类型大小有符号范围(SIGNED)无符号范围(UNSIGNED)概述
TINYINT1 byte(-128,127)(0,255)小整数值
SMALLINT2 byte(-32768,32767)(0,65535)大整数值
MEDIUMINT3 byte(-8388608,8388607)(0,16777215)大整数值
INT或INTEGER4 byte(-8388608,8388607)(0,4294967295)大整数值
BIGINT8 byte(-2^63,2^63-1)(0,2^64-1)极大整数值
FLOAT4 byte(-3.402823466 E+38,3.402823466351 E+38)0 和 (1.175494351 E38,3.402823466 E+38)单精度浮点数值
DOUBLE8 byte(-1.7976931348623157E+308,1.7976931348623157E+308)0 和(2.2250738585072014E-308,1.7976931348623157E+308)双精度浮点数值
DECIMAL 依赖于M(精度)和D(标度)的值依赖于M(精度)和D(标度)的值小数值(精确定点数)

字符串类型

类型大小概述
CHAR0-255 bytes定长字符串(需要指定长度)
VARCHAR0-65535 bytes变长字符串(需要指定长度)
TINYBLOB0-255 bytes不超过255个字符的二进制数据
TINYTEXT0-255 bytes短文本字符串
BLOB0-65 535 bytes二进制形式的长文本数据
TEXT0-65 535 bytes长文本数据
MEDIUMBLOB0-16 777 215 bytes二进制形式的中等长度文本数据
MEDIUMTEXT0-16 777 215 bytes中等长度文本数据
LONGBLOB0-4 294 967 295 bytes二进制形式的极大文本数据
LONGTEXT0-4 294 967 295 bytes 极极大文本数据

日期类型

类型大小范围格式概述
DATE31000-01-01 至 9999-12-31YYYY-MM-DD日期值
TIME3-838:59:59 至 838:59:59HH:MM:SS时间值或持续时间
YEAR11901 至 2155YYYY年份值
DATETIME81000-01-01 00:00:00 至9999-12-31 23:59:59YYYY-MM-DDHH:MM:SS混合日期和时间值
TIMESTAMP41970-01-01 00:00:01 至2038-01-19 03:14:07YYYY-MM-DDHH:MM:SS混合日期和时间值,时间戳

DML

添加数据

  • 给指定字段添加数据

INSERT INTO 表名(字段1,字段2,......) VALUES (值1,值2,......);

  • 给全部字段添加数据

INSERT INTO 表名 VALUES (值1,值2,......);

  • 批量添加数据

INSERT INTO 表名(字段1,字段2,......) VALUES (值1,值2,......),(值1,值2,......),(值1,值2,......);

INSERT INTO 表名 VALUES (值1,值2,......),(值1,值2,......),(值1,值2,......);

修改数据

UPDATE 表名 SET 字段1=值1,字段2=值2,...... [ WHERE 条件 ]

删除数据

DELETE FROM 表名 [ WHERE 条件 ]

注意

修改删除数据的时候,如果不加where判断条件则调整的整张表的内容。

DQL

语法

SELECT

​ 字段列表

FROM

​ 表名列表

WHERE

​ 条件列表

GROUP BY

​ 分组字段列表

HAVING

​ 分组后条件列表

ORDER BY

​ 排序字段列表

LIMIT

​ 分页参数

基本查询

  • 查询多个字段

SELECT 字段1,字段2,.... FROM 表名;

SELECT * FRIN 表名;

  • 设置别名

SELECT 字段1 [ AS '别名' ],字段2 [ AS '别名2' ] FROM 表名;

输出的时候字段名称会 替换成别名,这段SQL中的AS可以不写,例如

SELECT 字段 '别名' FROM 表名;

  • 去除重复记录

SELECT distinct 字段列表 FROM 表名;

条件查询

语法

SELECT 字段列表 FROM 表名 WHERE 条件列表;

条件

比较运算符

运算符功能
>大于
\>=大于等于
<小于
<=小于等于
=等于
<> 或 !=不等于
BETWEEN ... AND ...在某个范围之内(含最小,最大值)
IN(...)在in之后的列表中的值,多选一
LIKE 占位符模糊匹配(_匹配单个字符,%匹配任意多个字符)
IS NULL是NULL

逻辑运算符

运算符功能
AND 或 &&并且(多个条件同时成立)
OR 或 \\ 或者(多个条件任意一个成立)
NOT 或 !非,不是

聚合函数

语法

SELECT 聚合函数(字段) FROM 表名;

函数

函数功能
count统计数量
max最大值
min最小值
avg平均值
sum求和

分组查询

语法

SELECT 字段列表 FROM 表名 [ WHERE 条件 ] GROUP BY 分组字段名 [ HAVING 分组后过滤条件 ]

排序查询

语法

SELECT 字段列表 FROM 表名 ORDER BY 字段1 排序方式1, 字段2,排序方式2

排序方式

ASC:升序(默认)

DESC:降序

分页查询

语法

SELECT 字段列表 FROM 表名 LIMIT 起始索引,查询记录数;

执行顺序

DQL的执行顺序为FROM 表 > WHERE 条件查询 > GROUP BY 分组查询 > SELECT 字段查询 > ORDER BY 排序查询 > LIMIT 分页查询

DCL

用户管理

  • 查询用户
USE mysql;
SELECT * FROM user;
  • 创建用户
CREATE USER `用户名`@`主机名` IDENTIFIED BY `密码`;
  • 修改用户密码
ALTER USER `用户名`@`主机名` IDENTIFIED WITH mysql_native_password BY `新密码`;
  • 删除用户
DROP USER `用户名`@`主机名`;

权限管理

权限

常用权限如下表

权限说明
ALL,ALL PRIVILEGES所有权限
SELECT数据查询
INSERT插入数据
UPDATE更新数据
DELETE删除数据
ALTER修改表
DROP删除数据库、表、试图
CREATE创建数据库、表

这是常用的 其他的可以去官网查看

管理

  • 查询权限
SHOW GRANTS FOR `用户名`@`主机名`;
  • 授予权限
GRANT 权限列表 ON 数据库名.表名 TO `用户名`@`主机名`;
  • 撤销权限
REVOKE 权限列表 ON 数据库名.表名 FROM `用户名`@`主机名`;
]]>
<![CDATA[HELM-Kubernetes包管理工具(Chart包简单使用)]]> https://blog.boychai.xyz/index.php/archives/57/ 2023-05-29T04:34:00+00:00 2023-05-29T04:34:00+00:00 BoyChai https://blog.boychai.xyz 目录结构

文档地址:https://helm.sh/zh/docs/topics/charts/

通过下面命令创建一个chart,指定chart名:mychart

[root@Kubernetes charts]# helm create mychart
Creating mychart
[root@Kubernetes charts]# tree mychart
mychart
├── charts
├── Chart.yaml
├── templates
│   ├── deployment.yaml
│   ├── _helpers.tpl
│   ├── hpa.yaml
│   ├── ingress.yaml
│   ├── NOTES.txt
│   ├── serviceaccount.yaml
│   ├── service.yaml
│   └── tests
│       └── test-connection.yaml
└── values.yaml

3 directories, 10 files
目录介绍
charts存放子chart的目录,目录里存放这个chart依赖的所有子chart
Chart.yaml保存chart的基本信息,包括名字、描述信息及版本等,这个变量文件都可以被template目录下文件所引用
templates模板文件目录,目录里面存放所有yaml模板文件,包含了所有部署应用的yaml文件
templates/deployment.yaml创建deployment对象的模板文件
templates/_helpers.tpl_放置模板助手的文件,可以在整个chart中重复使用,是放一些templates目录下这些yaml都有可能会用的一些模板
templates/hpa.yaml
templates/ingress.yaml
templates/NOTES.txt存放提示信息的文件,介绍chart帮助信息,helm install部署后展示给用户,如何使用chart等,是部署chart后给用户的提示信息
templates/serviceaccount.yaml
templates/service.yaml
templates/tests用于测试的文件,测试完部署完chart后,如web,做一个连接,看看是否部署成功
templates/tests/test-connection.yaml用于渲染模板的文件(变量文件,定义变量的值)定义templates目录下的yaml文件可能引用到的变量
values.yamlvalues.yaml用于存储templates目录中模板文件中用到变量的值,这些变量定义都是为了让templates目录下yaml引用

案例1

需求

编写一个chart,不引用内置对象的变量值(用HELM3发布创建一个ConfigMap,创建到K8s集群中,发布其他应用也一样,我们由浅入深进行学习)

创建实例

编写Chart:

[root@Kubernetes charts]# helm create myConfigMapChart
Creating myConfigMapChart
[root@Kubernetes charts]# cd myConfigMapChart/templates/
[root@Kubernetes templates]# rm -rf ./*
[root@Kubernetes templates]# vim configmap.yaml
# 文件内容如下
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-cm-chart
data:
  myValue: "Hello,World"

创建release实例:

[root@Kubernetes charts]# ls
mychart  myConfigMapChart  
[root@Kubernetes charts]# helm install mycm ./myConfigMapChart/
NAME: mycm
LAST DEPLOYED: Thu May 11 00:26:16 2023
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

查看release实例:

[root@Kubernetes charts]# helm list
NAME    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
mycm    default         1               2023-05-11 00:26:16.392817959 +0800 CST deployed        myConfigMapChart-0.1.0  1.16.0  

查看release的详细信息:

[root@Kubernetes charts]# helm get manifest mycm
---
# Source: myConfigMapChart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-cm-chart
data:
  myValue: "Hello,World"

删除release实例:

[root@Kubernetes charts]# helm uninstall mycm
release "mycm" uninstalled
[root@Kubernetes charts]# helm list
NAME    NAMESPACE       REVISION        UPDATED STATUS  CHART   APP VERSION

案例2

需求

案例1只是简单的创建一个configmap实际和直接apply没啥区别,案例2将引入变量进行创建chart,把configmap的名称改为变量的方式进行创建。

创建实例

修改Chart:

[root@Kubernetes charts]# vim myConfigMapChart/templates/configmap.yaml 
[root@Kubernetes charts]# cat myConfigMapChart/templates/configmap.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  # name: my-cm-chart
  name: {{ .Release.Name }}-configmap
data:
  # myValue: "Hello,World"
  myValue: {{ .Values.MY_VALUE }}
[root@Kubernetes charts]# > myConfigMapChart/values.yaml
[root@Kubernetes charts]# vim myConfigMapChart/values.yaml 
[root@Kubernetes charts]# cat !$
cat myConfigMapChart/values.yaml
MY_VALUE: "Hello,World"

创建实例:

[root@Kubernetes charts]# helm install mycm2 ./myConfigMapChart/
NAME: mycm2
LAST DEPLOYED: Thu May 11 00:49:06 2023
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

查看实例:

[root@Kubernetes charts]# helm list 
NAME    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
mycm2   default         1               2023-05-11 00:49:06.855993522 +0800 CST deployed        myConfigMapChart-0.1.0  1.16.0
[root@Kubernetes charts]# kubectl get cm
NAME               DATA   AGE
kube-root-ca.crt   1      77d
mycm2-configmap    1      87s

YAML解释:

apiVersion: v1
kind: ConfigMap
metadata:
  # name: my-cm-chart
  name: {{ .Release.Name }}-configmap
data:
  # myValue: "Hello,World"
  myValue: {{ .Values.MY_VALUE }}
  • {{ .Release.Name }}-configmap
    最前面的.从作用域最顶层命名空间开始,即:在顶层命名空间中开始寻找Release对象,再查找Name对象。这个就是通过内置对象获取内置对象的变量值(Release的名称)作为拼接成ConfigMap的名字。
  • {{ .Values.MY_VALUE }}
    这个是其他变量会去values.yaml文件中寻找对应的变量

引用内置对象或其他变量的好处:
如果metadata.name中色湖之的值就是一个固定值,这样的模板是无法在k8s中多次部署的,所以我们可以试着在每次安装chart时,都自动metadata.name的设置为release的名称,因为每次部署release的时候实例名称是不一样的,这样部署的时候里面的资源名也就可以作为一个分区,而可以进行重复部署。

测试渲染

HELM提供了一个用来渲染模板的命令,该命令可以将模板内容渲染出来,但是不会进行任何安装的操作。可以用该命令来测试模板渲染的内容是否正确。语法如下:

helm install [release实例名] chart目录 --debug --dry-run

例:

[root@Kubernetes charts]# helm install mycm3 ./myConfigMapChart/ --debug --dry-run
install.go:200: [debug] Original chart version: ""
install.go:217: [debug] CHART PATH: /root/charts/myConfigMapChart

NAME: mycm3
LAST DEPLOYED: Thu May 11 01:03:15 2023
NAMESPACE: default
STATUS: pending-install
REVISION: 1
TEST SUITE: None
USER-SUPPLIED VALUES:
{}

COMPUTED VALUES:
MY_VALUE: Hello,World

HOOKS:
MANIFEST:
---
# Source: myConfigMapChart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  # name: my-cm-chart
  name: mycm3-configmap 
data:
  # myValue: "Hello,World"
  myValue: Hello,World
[root@Kubernetes charts]# helm list
NAME    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
]]>
<![CDATA[HELM-Kubernetes包管理工具(介绍与安装)]]> https://blog.boychai.xyz/index.php/archives/56/ 2023-05-13T01:27:00+00:00 2023-05-13T01:27:00+00:00 BoyChai https://blog.boychai.xyz 传统部署方式

传统服务部署到K8s集群的流程:
拉取代码-----》打包编译-----》构建镜像-----》准备相关的yaml文件-----》kubectl apply进行部署

传统方式部署引发的问题:

  1. 随着引用的增多,需要维护大量的yaml文件
  2. 不能根据一套yaml文件来创建多个环境,需要手动进行修改。
    PS: 一般环境都分为dev、预生产、生产环境,部署完了dev这套环境,后面再部署预生产和生产环境,还需要复制出两套,并手动修改才行。

什么是HELM

Helm是K8s的包管理工具,可以方便地发现、共享和构建K8s应用
Helm是k8s的包管理器,相当于centos系统中的yum工具,可以将一个服务相关的所有资源信息整合到一个chart中,并且可以使用一套资源发布到多个环境中,可以将应用程序的所有资源和部署信息组合到单个部署包中。
就像Linux下的rpm包管理器,如yum/apt等,可以很方便的将之前打包好的yaml文件部署到k8s上。

HELM的组件

  1. Chart:就是helm的一个整合后的chart包,包含一个应用所有的K8s声明模板,类似于yum的rpm包或者apt的dpkg文件。helm将打包的应用程序部署到k8s并将它们构成chart。这些chart将所有预配置的应用程序资源以及所有版本都包含再一个已于管理的包中。
  2. HELM客户端:helm的客户端组件,负责和K8s apiserver通信
  3. Repository:用于发布和存储chart包的仓库,类似yum仓库和docker仓库。
  4. Release:用chart包部署的一个实例。通过chart在K8s中部署的应用都会产生一个唯一的Release,统一chart部署多次就会产生多个Release。

HELM2和HELM3

  1. helm3移除了Tiller组件 helm2中helm客户端和K8s通信时通过Tiller组件和K8s通信,helm3移除了Tiller组件,直接使用kubeconfig文件和K8s apiserver通信。
  2. 删除release命令变更
    helm delete release-name --purge --------》 helm uninstall release-name
  3. 查看charts信息命令变更
    helm inspect release-name -------》 helm show chart-name
  4. 拉取charts包命令变更
    helm fetch chart-name -------》 helm pull chart-name
  5. helm3中必须指定release名称,如果需要生成一个随机名称,需要加选项--generate-name,helm2中如果不指定release名称,可以自动生成一个随机名称
    helm install ./mychart --generate-name

    安装HELM

    相关连接:
    Github:https://github.com/helm/helm/releases
    官网:https://helm.sh/zh/docs/intro/install/

下载好对应的版本上传到服务器进行解压缩

[root@Kubernetes helm]# ls
helm-v3.11.3-linux-amd64.tar.gz
[root@Kubernetes helm]# tar xvf helm-v3.11.3-linux-amd64.tar.gz 
linux-amd64/
linux-amd64/LICENSE
linux-amd64/README.md
linux-amd64/helm

之后配置一下系统环境,让命令可以在系统中随机调用

[root@Kubernetes helm]# ls
helm-v3.11.3-linux-amd64.tar.gz  linux-amd64
[root@Kubernetes helm]# cd linux-amd64/
[root@Kubernetes linux-amd64]# pwd
/opt/helm/linux-amd64
[root@Kubernetes linux-amd64]# vim /etc/profile
#追加下面内容
export PATH=$PATH:/opt/helm/linux-amd64
[root@Kubernetes linux-amd64]# source /etc/profile

检查一下是否安装成功

[root@Kubernetes ~]# helm version
version.BuildInfo{Version:"v3.11.3", GitCommit:"323249351482b3bbfc9f5004f65d400aa70f9ae7", GitTreeState:"clean", GoVersion:"go1.20.3"}
]]>
<![CDATA[[分区工具]Fdisk(MBR分区工具)]]> https://blog.boychai.xyz/index.php/archives/52/ 2023-03-30T12:22:00+00:00 2023-03-30T12:22:00+00:00 BoyChai https://blog.boychai.xyz 概述

fdisk是一种用于管理磁盘分区的工具,常用于Linux和其他Unix-like操作系统中。它可以用于创建、删除和修改磁盘分区,并支持多种文件系统类型,例如FAT、ext2、ext3等。

fdisk还可以显示当前系统中所有磁盘的分区信息,包括磁盘标识符、分区类型、分区大小等。使用fdisk,用户可以轻松地管理磁盘空间,为不同的操作系统或应用程序分配不同的存储空间。

除此之外,fdisk还支持MBR(Master Boot Record)分区方案,它是一种常见的磁盘分区方案,能够在BIOS引导下启动操作系统。

MBR

MBR(Master Boot Record)分区是指使用MBR分区方案的磁盘分区方式。MBR分区方案是一种常见的分区方案,能够在BIOS引导下启动操作系统。MBR分区方案将磁盘的前512个字节(即MBR)用于存储分区表和引导程序。其中分区表记录了磁盘分区的信息,包括分区类型、分区起始位置、分区大小等。MBR分区方案最多支持4个主分区或3个主分区和1个扩展分区,扩展分区可以划分为多个逻辑分区。MBR分区方案已经存在了很长时间,但是它有一个缺点,即它只支持最大2TB的磁盘容量。如果需要使用更大的磁盘,就需要使用GPT(GUID Partition Table)分区方案。

环境

系统:Rocky Linux release 8.5

工具:fdisk from util-linux 2.32.1

硬盘:虚拟机添加了一块20G的硬盘

虚拟机属性

实践

主分区

[root@host ~]# lsblk -p                           // 通过lsblk来查看一下新增的硬盘位置(/dev/sdb)
NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
/dev/sda                  8:0    0   20G  0 disk 
├─/dev/sda1               8:1    0    1G  0 part /boot
└─/dev/sda2               8:2    0   19G  0 part 
  ├─/dev/mapper/rl-root 253:0    0   17G  0 lvm  /
  └─/dev/mapper/rl-swap 253:1    0    2G  0 lvm  [SWAP]
/dev/sdb                  8:16   0   20G  0 disk 
/dev/sr0                 11:0    1 1024M  0 rom
[root@host ~]# fdisk /dev/sdb                    // 使用fdisk工具对/dev/sdb这块硬盘进行分区

Welcome to fdisk (util-linux 2.32.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0x178d8de5.

Command (m for help): n                         // 输入n进行新建分区操作
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p                            // p是创建主分区,e是创建逻辑分区
Partition number (1-4, default 1): 1             // 选择分区号,默认为1,这里可以改其他的(MBR分区最多有4个分区)
First sector (2048-41943039, default 2048):      // 起始扇区选择默认即可
Last sector, +sectors or +size{K,M,G,T,P} (2048-41943039, default 41943039): +5G    //设置分区大小我这里设置5G

Created a new partition 1 of type 'Linux' and of size 5 GiB.    //提示创建成功

Command (m for help): p                     // p查看分区表
Disk /dev/sdb: 20 GiB, 21474836480 bytes, 41943040 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x178d8de5

Device     Boot Start      End  Sectors Size Id Type
/dev/sdb1        2048 10487807 10485760   5G 83 Linux                // 创建好的分区

Command (m for help): w                                        // 保存之前的分区操作
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
[root@host ~]# mkfs.xfs /dev/sdb1                          // 格式化创建好的分区
meta-data=/dev/sdb1              isize=512    agcount=4, agsize=327680 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1
data     =                       bsize=4096   blocks=1310720, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
[root@host ~]# mkdir /sdb1                           // 创建挂载位置
[root@host ~]# mount /dev/sdb1 /sdb1                  // 将格式化好的分区进行挂载
[root@host ~]# lsblk -p                                // 查看分区情况
NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
/dev/sda                  8:0    0   20G  0 disk 
├─/dev/sda1               8:1    0    1G  0 part /boot
└─/dev/sda2               8:2    0   19G  0 part 
  ├─/dev/mapper/rl-root 253:0    0   17G  0 lvm  /
  └─/dev/mapper/rl-swap 253:1    0    2G  0 lvm  [SWAP]
/dev/sdb                  8:16   0   20G  0 disk 
└─/dev/sdb1               8:17   0    5G  0 part /sdb1          // 已经挂载好可以使用了
/dev/sr0                 11:0    1 1024M  0 rom

逻辑分区

[root@host ~]# fdisk /dev/sdb                            // 对/dev/sdb进行分区

Welcome to fdisk (util-linux 2.32.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Command (m for help): n                            // 创建分区
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): e                           // 创建逻辑分区
Partition number (2-4, default 2):              // 分区号
First sector (10487808-41943039, default 10487808):       // 设置起始扇区选择默认即可
Last sector, +sectors or +size{K,M,G,T,P} (10487808-41943039, default 41943039):       // 设置大小,逻辑分区的默认大小是剩余全部存储空间,这里我选择默认。 

Created a new partition 2 of type 'Extended' and of size 15 GiB.  

Command (m for help): p                                 // 查看分区表
Disk /dev/sdb: 20 GiB, 21474836480 bytes, 41943040 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x178d8de5

Device     Boot    Start      End  Sectors Size Id Type
/dev/sdb1           2048 10487807 10485760   5G 83 Linux
/dev/sdb2       10487808 41943039 31455232  15G  5 Extended               // 创建好了一个逻辑分区大小为15G

Command (m for help): w                      // 保存分区操作
The partition table has been altered.
Syncing disks.
[root@host ~]# lsblk -p
NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
/dev/sda                  8:0    0   20G  0 disk 
├─/dev/sda1               8:1    0    1G  0 part /boot
└─/dev/sda2               8:2    0   19G  0 part 
  ├─/dev/mapper/rl-root 253:0    0   17G  0 lvm  /
  └─/dev/mapper/rl-swap 253:1    0    2G  0 lvm  [SWAP]
/dev/sdb                  8:16   0   20G  0 disk 
├─/dev/sdb1               8:17   0    5G  0 part /sdb1
└─/dev/sdb2               8:18   0   15G  0 part 
/dev/sr0                 11:0    1 1024M  0 rom

逻辑子分区

创建好逻辑分区之后就可以在逻辑分区里面创建无数个子分区,这样就逃离了MBR分区方式的分区限制。

[root@host ~]# fdisk /dev/sdb    // 对/dev/sdb进行分区

Welcome to fdisk (util-linux 2.32.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Command (m for help): n         // 新建分区
All space for primary partitions is in use.
Adding logical partition 5      // 当创建好逻辑分区之后就会发现分区号会从5开始增加
First sector (10489856-41943039, default 10489856):             // 磁盘起始位置,默认即可
Last sector, +sectors or +size{K,M,G,T,P} (10489856-41943039, default 41943039): +1G     //设置大小

Created a new partition 5 of type 'Linux' and of size 1 GiB.

Command (m for help): n                 // 继续创建
All space for primary partitions is in use.
Adding logical partition 6  
First sector (12589056-41943039, default 12589056): 
Last sector, +sectors or +size{K,M,G,T,P} (12589056-41943039, default 41943039): +1G

Created a new partition 6 of type 'Linux' and of size 1 GiB.

Command (m for help): n            // 继续创建
All space for primary partitions is in use.
Adding logical partition 7
First sector (14688256-41943039, default 14688256): 
Last sector, +sectors or +size{K,M,G,T,P} (14688256-41943039, default 41943039): +1G

Created a new partition 7 of type 'Linux' and of size 1 GiB.

Command (m for help): w              // 保存
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
[root@host ~]# lsblk -p                  // 查看分区表
NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
/dev/sda                  8:0    0   20G  0 disk 
├─/dev/sda1               8:1    0    1G  0 part /boot
└─/dev/sda2               8:2    0   19G  0 part 
  ├─/dev/mapper/rl-root 253:0    0   17G  0 lvm  /
  └─/dev/mapper/rl-swap 253:1    0    2G  0 lvm  [SWAP]
/dev/sdb                  8:16   0   20G  0 disk 
├─/dev/sdb1               8:17   0    5G  0 part /sdb1
├─/dev/sdb2               8:18   0    1K  0 part 
├─/dev/sdb5               8:21   0    1G  0 part 
├─/dev/sdb6               8:22   0    1G  0 part 
└─/dev/sdb7               8:23   0    1G  0 part 
/dev/sr0                 11:0    1 1024M  0 rom

这里会发现sdb磁盘一共创建了7个分区。

删除分区

以sdb1为例,sdb1这个分区已经挂载到了/sdb1目录已经在使用了,在删除分区前需要取消挂载。具体操作方法如下

[root@host ~]# lsblk -p                                      // 查看分区状态   
NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
/dev/sda                  8:0    0   20G  0 disk 
├─/dev/sda1               8:1    0    1G  0 part /boot
└─/dev/sda2               8:2    0   19G  0 part 
  ├─/dev/mapper/rl-root 253:0    0   17G  0 lvm  /
  └─/dev/mapper/rl-swap 253:1    0    2G  0 lvm  [SWAP]
/dev/sdb                  8:16   0   20G  0 disk 
├─/dev/sdb1               8:17   0    5G  0 part /sdb1         // 发现/dev/sdb1已经挂载到/sdb1目录下
├─/dev/sdb2               8:18   0    1K  0 part 
├─/dev/sdb5               8:21   0    1G  0 part 
├─/dev/sdb6               8:22   0    1G  0 part 
└─/dev/sdb7               8:23   0    1G  0 part 
/dev/sr0                 11:0    1 1024M  0 rom  
[root@host ~]# umount /sdb1                                 // 取消挂载
[root@host ~]# lsblk -p                                              
NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
/dev/sda                  8:0    0   20G  0 disk 
├─/dev/sda1               8:1    0    1G  0 part /boot
└─/dev/sda2               8:2    0   19G  0 part 
  ├─/dev/mapper/rl-root 253:0    0   17G  0 lvm  /
  └─/dev/mapper/rl-swap 253:1    0    2G  0 lvm  [SWAP]
/dev/sdb                  8:16   0   20G  0 disk 
├─/dev/sdb1               8:17   0    5G  0 part            // 已经取消挂载了
├─/dev/sdb2               8:18   0    1K  0 part 
├─/dev/sdb5               8:21   0    1G  0 part 
├─/dev/sdb6               8:22   0    1G  0 part 
└─/dev/sdb7               8:23   0    1G  0 part 
/dev/sr0                 11:0    1 1024M  0 rom  
[root@host ~]# fdisk /dev/sdb

Welcome to fdisk (util-linux 2.32.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Command (m for help): d                                // d(delete)删除分区
Partition number (1,2,5-7, default 7): 1               // 删除分区号,这里选择1

Partition 1 has been deleted.

Command (m for help): w                                // 保存位置
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

[root@host ~]# lsblk -p                          // 查看磁盘状态
NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
/dev/sda                  8:0    0   20G  0 disk 
├─/dev/sda1               8:1    0    1G  0 part /boot
└─/dev/sda2               8:2    0   19G  0 part 
  ├─/dev/mapper/rl-root 253:0    0   17G  0 lvm  /
  └─/dev/mapper/rl-swap 253:1    0    2G  0 lvm  [SWAP]
/dev/sdb                  8:16   0   20G  0 disk      // 发现sdb1已经消失         
├─/dev/sdb2               8:18   0    1K  0 part 
├─/dev/sdb5               8:21   0    1G  0 part 
├─/dev/sdb6               8:22   0    1G  0 part 
└─/dev/sdb7               8:23   0    1G  0 part 
/dev/sr0                 11:0    1 1024M  0 rom

使用分区

格式化分区

创建好分区之后需要格式化之后才可以挂载使用,格式化需要使用mkfs工具,这里不多讲。关于格式化的格式可以使用mkfs.来查看

[root@host ~]# mkfs.
mkfs.cramfs  mkfs.ext2    mkfs.ext3    mkfs.ext4    mkfs.minix   mkfs.xfs

这里使用xfs来格式化创建的分区(逻辑分区只能格式化子分区不能直接格式化逻辑分区)。

[root@host ~]# lsblk -p                          // 查看分区状态
NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
/dev/sda                  8:0    0   20G  0 disk 
├─/dev/sda1               8:1    0    1G  0 part /boot
└─/dev/sda2               8:2    0   19G  0 part 
  ├─/dev/mapper/rl-root 253:0    0   17G  0 lvm  /
  └─/dev/mapper/rl-swap 253:1    0    2G  0 lvm  [SWAP]
/dev/sdb                  8:16   0   20G  0 disk 
├─/dev/sdb2               8:18   0    1K  0 part 
├─/dev/sdb5               8:21   0    1G  0 part 
├─/dev/sdb6               8:22   0    1G  0 part 
└─/dev/sdb7               8:23   0    1G  0 part 
/dev/sr0                 11:0    1 1024M  0 rom  
[root@host ~]# mkfs.xfs /dev/sdb5              // 使用xfs类型格式化sdb5
meta-data=/dev/sdb5              isize=512    agcount=4, agsize=65536 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1
data     =                       bsize=4096   blocks=262144, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
[root@host ~]# mkfs.xfs /dev/sdb6               // 使用xfs类型格式化sdb6
meta-data=/dev/sdb6              isize=512    agcount=4, agsize=65536 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1
data     =                       bsize=4096   blocks=262144, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
[root@host ~]# mkfs.xfs /dev/sdb7              // 使用xfs类型格式化sdb7                 
meta-data=/dev/sdb7              isize=512    agcount=4, agsize=65536 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1
data     =                       bsize=4096   blocks=262144, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
[root@host ~]# lsblk -p                        // 查看分区状态
NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
/dev/sda                  8:0    0   20G  0 disk 
├─/dev/sda1               8:1    0    1G  0 part /boot
└─/dev/sda2               8:2    0   19G  0 part 
  ├─/dev/mapper/rl-root 253:0    0   17G  0 lvm  /
  └─/dev/mapper/rl-swap 253:1    0    2G  0 lvm  [SWAP]
/dev/sdb                  8:16   0   20G  0 disk 
├─/dev/sdb2               8:18   0    1K  0 part 
├─/dev/sdb5               8:21   0    1G  0 part 
├─/dev/sdb6               8:22   0    1G  0 part 
└─/dev/sdb7               8:23   0    1G  0 part 
/dev/sr0                 11:0    1 1024M  0 rom

挂载分区

当格式化分区之后可以通过mount来进行挂载,挂载好的分区就可以使用了。

[root@host ~]# mkdir -p /disk/sdb{5..7}     // 创建挂载目录
[root@host ~]# mount /dev/sdb5 /disk/sdb5   // 挂载sdb5
[root@host ~]# mount /dev/sdb6 /disk/sdb6   // 挂载sdb6
[root@host ~]# mount /dev/sdb7 /disk/sdb7   // 挂载sdb7
[root@host ~]# lsblk -p          // 查看分区状态
NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
/dev/sda                  8:0    0   20G  0 disk 
├─/dev/sda1               8:1    0    1G  0 part /boot
└─/dev/sda2               8:2    0   19G  0 part 
  ├─/dev/mapper/rl-root 253:0    0   17G  0 lvm  /
  └─/dev/mapper/rl-swap 253:1    0    2G  0 lvm  [SWAP]
/dev/sdb                  8:16   0   20G  0 disk 
├─/dev/sdb2               8:18   0    1K  0 part 
├─/dev/sdb5               8:21   0    1G  0 part /disk/sdb5
├─/dev/sdb6               8:22   0    1G  0 part /disk/sdb6
└─/dev/sdb7               8:23   0    1G  0 part /disk/sdb7
/dev/sr0                 11:0    1 1024M  0 rom
]]>