jenkins的用户授权与管理

需要安装的插件 Role-Based Strategy(可以对构建的项目进行授权管理,让不同的用户管理不同的项目,将测试和生产环境分开) 选择授权策略 当Role-based Authorization Strategy 这个插件安装好之后,授权策略会多出一个Role-Based Strategy 选项,选择此项 添加配置权限 系统设置 » Manage and Assign Roles Manage Roles 设置全局角色(全局角色可以对jenkins系统进行设置与项目的操作) admin:对整个jenkins都可以进行操作 root:可以对所有的job进行管理 other:只有读的权限 other必须有,否则给用户分配角色时分配没有全局role会导致分配失效 Assign Roles为用户指派角色 项目角色是根据正则匹配的,

jenkins pipline demo

pipline demo https://jenkins.io/zh/doc/book/pipeline/syntax/ git 插件 https://jenkins.io/doc/pipeline/steps/git/ pipline pipeline{ agent any stages{ stage("build"){ steps{ echo "11111" } } } } pipeline总体介绍 基本结构 以下每一个部分都是必须的,少一个Jenkins都会报错 pipline pipeline{ agent any stages{ stage("build"){ steps{ echo "hellp" } } } } pipeline 代表整个流水线,包含整条流水线的逻辑 stage 阶段,代表流水线的阶段,每个阶段都必须有名称。 stages 流水线中多个stage的容器,stages部分至少包含一个stage. steps 代表stage中的一个活多个具体步骤的容器,steps部分至少包含一个步骤 agent 制定流水线的执行位置,流水线中每个阶段都必须在某个地方执行(master节点/slave节点/物理机/虚拟机/docker容器),agent部分指定具体在哪里执行。agent { label '***-slave'} 可选步骤 post 包含的是在整个pipeline或stage完成后的附件条件 always 论Pipeline运行的完成状态如何都会执行这段代码 changes 只有当前Pipeline运行的状态与先前完成的Pipeline的状态不同时,才能触发运行。 failure 当前状态为失败时执行 success 当前完成状态为成功时执行 demo 使用${test},可以引入自定义变量 pipeline post { always { script { allure includeProperties: false, jdk: '',report: 'jenkins-allure-report', results: [[path: 'allure-results']] } } failure { script { if (gitpuller == 'noerr') { mail to: "${email_list}", subject: "[jenkins Build Notification] ${JOB_NAME} - Build # ${BUILD_NUMBER} 构建失败", body: "'${env....

Go中的signal处理

什么是信号 在计算机科学中,信号是Unix、类Unix以及其他POSIX兼容的操作系统中进程间通讯的一种有限制的方式。它是一种异步的通知机制,用来提醒进程一个事件已经发生。 当一个信号发送给一个进程,操作系统中断了进程正常的控制流程,如果进程定义了对信号的处理,此时,程序将进入捕获到的信号对应的处理函数,否则执行默认的处理函数。 Linux中信号的介绍 在Linux系统共定义了64种信号,分为两大类:实时信号与非实时信号,1-31为非实时,32-64种为实时信号。 非实时信号: 也称为不可靠信号,为早期Linux所支持的信号,不支持排队,信号可能会丢失, 比如发送多次相同的信号, 进程只能收到一次. 信号值取值区间为1~31; 实时信号: 也称为可靠信号,支持排队, 信号不会丢失, 发多少次, 就可以收到多少次. 信号值取值区间为32~64 Linux操作系统中,在终端上执行 kill -l 便可看到系统定义的所有信号 信号表 POSIX.1-1990标准信号 此表参考自:POSIX信号 信号 值 动作 说明 SIGHUP 1 Term 终端控制进程结束(终端连接断开) SIGINT 2 Term 用户发送INTR字符(Ctrl+C)触发 SIGQUIT 3 Core 用户发送QUIT字符(Ctrl+/)触发 SIGILL 4 Core 非法指令(程序错误、试图执行数据段、栈溢出等) SIGABRT 6 Core 调用abort函数触发 SIGFPE 8 Core 算术运行错误(浮点运算错误、除数为零等) SIGKILL 9 Term 无条件结束程序(不能被捕获、阻塞或忽略) SIGSEGV 11 Core 无效内存引用(试图访问不属于自己的内存空间、对只读内存空间进行写操作) SIGPIPE 13 Term 消息管道损坏(FIFO/Socket通信时,管道未打开而进行写操作) SIGALRM 14 Term 时钟定时信号 SIGTERM 15 Term 结束程序(可以被捕获、阻塞或忽略) SIGUSR1 30,10,16 Term 用户保留 SIGUSR2 31,12,17 Term 用户保留 SIGCHLD 20,17,18 Ign 子进程结束(由父进程接收) SIGCONT 19,18,25 Cont 继续执行已经停止的进程(不能被阻塞) SIGSTOP 17,19,23 Stop 停止进程(不能被捕获、阻塞或忽略) SIGTSTP 18,20,24 Stop 停止进程(可以被捕获、阻塞或忽略) SIGTTIN 21,21,26 Stop 后台程序从终端中读取数据时触发 SIGTTOU 22,22,27 Stop 后台程序向终端中写数据时触发 更多的信号说明请查阅man7...

Go语言数据类型转换

string in mutual conversion go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 // int to int64 m := int64(n) // int64 to int n := int(m) // string to int int,err := strconv.Atoi(string) // string to int64 int64, err := strconv.ParseInt(string, 10, 64) // int to string string := strconv....

go语言的并发编程gorouting

并行和并发 并发编程是指在一台处理器上“同时”处理多个任务。 宏观并发:在一段时间内,有多个程序在同时运行。 微观并发:在同一时刻只能有一条指令执行,但多个程序指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段,使多个程序快速交替的执行。 并行 parallel:同一时刻,多条指令在多个处理器上同时执行。 并发 concurrency:在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段,通过cpu时间片轮转使多个进程快速交替的执行。 通俗来讲,并行是两组队列同时使用一个进程;并发是两个队列分别交替使用两个进程 进程并发 程序,以Go语言为例,是指编译好的二进制文件,在磁盘上,不占用系统资源(cpu、内存、打开的文件、设备、锁….) 进程,是一个抽象的概念,与操作系统原理联系紧密。以Go语言为例,将编译好的程序运行起来,在内存空间中形成一个独立的内存体,内存体有自己的独立空间,上级挂靠单位是操作系统。 进程是操作系统进行资源分配和调度的一个独立单位,一般由程序,数据集合和进程控制块三部分组成。 程序:描述进程完成的功能,是控制进程执行的指令集; 数据集合:程序在执行时所需要的数据和工作区; 程序控制块PCB:Program Control Block,包含进程的描述信息和控制信息,是进程存在的唯一标志。 进程是活跃的程序,占用系统资源。在内存中执行。同一个程序也可以加载为不同的进程(彼此之间互不影响) 进程状态 进程基本的状态有5种。分别为初始态,就绪态,运行态,挂起态与终止态。其中初始态为进程准备阶段,常与就绪态结合来看。 线程的任务调度 大部分操作系统的任务调度是采用时间片轮转的抢占式调度方式。 时间片轮转是指,在一个进程中,当线程任务执行几毫秒后,由操作系统内核进行调度,通过硬件计数器终端处理器,让线程强行暂停,并将该线程的寄存器放入内存中,通过查看线程列表决定接下来执行哪一个线程,并从内存中恢复该线程的寄存器,最后恢复该线程的执行,从而去执行下一个任务。 在时间片轮转中,任务执行那段时间叫做时间片,任务正在执行时的状态叫运行状态,被暂停的线程任务状态叫做就绪状态,意为等待下一个属于它的时间片的到来。 由于CPU的执行效率非常高,(i5 6600 约200亿/秒,奔腾4 约13亿/秒)CPU preformance 时间片非常短,在各个任务之间快速地切换,给人的感觉就是多个任务在“同时进行”,这也就是我们所说的并发。多任务运行过程的示意图如下: 进程实现并发时会出现的问题呢 孤儿进程: 父进程先于子进程结束,则子进程成为孤儿进程,子进程的父进程成为init进程,称为init进程领养孤儿进程。 僵尸进程: 进程终止,父进程尚未回收,子进程残留资源(PCB)存放于内核中,变成僵尸(Zombie)进程。 线程并发 在早期操作系统当中,没有线程的概念,进程是最小分配资源与执行单位,可以看做是一个进程中只有一个线程,故进程即线程。所以线程LWP被称为::Lightweight process,轻量级的进程,是程序执行中一个单一的顺序控制流程,在Linux操作系统下,线程的本质仍是进程。 线程有独立的PCB,但没有独立的地址空间,各个线程之间共享程序的内存空间。 进程和线程的区别 进程:最小分配资源单位,可看成是只有一个线程的进程。 线程:最小的执行单位 一个进程由一个或多个线程组成 进程之间相互独立,同一进程下的各个线程之间共享程序的内存空间 协程并发 协程 coroutines,是一种基于线程之上,但又比线程更加轻量级的存在,这种由程序来管理的轻量级线程叫做『用户空间线程』,具有对内核来说不可见的特性。 多数语言在语法层面并不直接支持协程,而是通过库的方式支持,但用库的方式支持的功能也并不完整,比如仅仅提供协程的创建、销毁与切换等能力。如果在这样的轻量级线程中调用一个同步 IO 操作,比如网络通信、本地文件读写,都会阻塞其他的并发执行轻量级线程,从而无法真正达到轻量级线程本身期望达到的目标。 协程和线程的区别 占用资源:线程,初始单位为1MB,固定不可变;协程初始一般为 2KB,可随需要而增大。 调度:线程,由操作系统内核完成,协程,由用户完成。 性能: 线程,占用资源高,频繁创建销毁带来性能问题。占用资源小,不会带来严重的性能问题。 数据: 线程,多线程需要锁机制确保数据一致性和可见性;而线程因为只有一个进程,不存在同时读/写冲突,协程中控制共享数据不用加锁,顾执行效率较线程高。 Go并发 goroutine Go语言在语言级别支持协程,叫goroutine。Go语言标准库提供的所有系统调用操作(包括所有同步IO操作),都会出让CPU给其他goroutine。这种轻量级线程的切换管理不依赖于系统的线程和进程,也不需要依赖于CPU的核心数量。 Go语言为并发编程而内置的上层API基于顺序通信进程模型CSP(communicating sequential processes)。这就意味着显式锁都是可以避免的,因为Go通过相对安全的通道发送和接受数据以实现同步,这大大地简化了并发程序的编写。 Go语言中的并发程序主要使用两种手段来实现。goroutine和channel。 什么是goroutine Go语言作者Rob Pike说, “Goroutine是一个与其他goroutines并发运行在同一地址空间的Go函数或方法。一个运行的程序由一个或更多个goroutine组成。它与线程、协程、进程等不同。它是一个goroutine*。...

Go协程通讯

channel是Go语言中的一个核心数据类型,channel是一个数据类型,主要用来解决协程的同步问题以及协程之间数据共享(数据传递)的问题。在并发核心单元通过它就可以发送或者接收数据进行通讯,这在一定程度上又进一步降低了编程的难度。 goroutine运行在相同的内存地址空间,channel可以避开所有内存共享导致的坑;通道的通信方式保证了同步性。数据通过channel:同一时间只有一个协程可以访问数据:所以不会出现数据竞争,确保并发安全。 channel的定义 channel是对应make创建的底层数据结构的引用。 创建语法: make(chan Type, capacity) go 1 2 3 4 5 6 7 channel := make(chan bool) //创建一个无缓冲的bool型Channel
,等价于make(chan Type, 0) channel := make(chan bool, 1024) //创建一个有缓冲,切缓冲区为1024的bool型Channel
channel <- x //向一个Channel发送一个值 <- channel //从一个Channel中接收一个值 x = <- channel //从Channel c接收一个值并将其存储到x中 x, ok = <- channel //从Channel接收一个值,如果channel关闭了或没有数据,那么ok将被置为false channel是一个引用类型,当复制一个channel或用于函数参数传递时,我们只是拷贝了一个channel引用,因此调用者和被调用者将引用同一个channel对象。和其它的引用类型一样,channel的零值(定义未初始化)也是nil。 在默认情况下,channel接收和发送数据都是阻塞的,(channel <- 1,写端写数据,读端不在读。写端阻塞; str := <-channel 读端读数据, 同时写端不在写,读端阻塞。)除非另一端已经准备好,这样就使得goroutine同步变的更加的简单,而不需要显式的lock。 示例 go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 package main import ( "fmt" "runtime" "time" ) var c = make(chan int32) func printstr(s string) { for _, value := range s { fmt....

Go协程安全

多路复用 Go语言中提供了一个关键字select,通过select可以监听channel上的数据流动。select的用法与switch语法类似,由select开始一个新的选择块,每个选择条件由case语句来描述。只不过,select的case有比较多的限制,其中最大的一条限制就是每个case语句里必须是一个IO操作。 select 语法如下: go 1 2 3 4 5 6 7 8 select { case <-chan1: // 如果chan1成功读到数据,则进行该case处理语句 case chan2 <- 1: // 如果成功向chan2写入数据,则进行该case处理语句 default: // 如果上面都没有成功,则进入default处理流程 } 在一个select语句中,会按顺序从头至尾评估每一个发送和接收的语句;如果其中的任意一语句可以继续执行(即没有被阻塞),那么就从那些可以执行的语句中任意选择一条来使用。如果没有任意一条语句可以执行(即所有的通道都被阻塞),那么有两种可能的情况:⑴ 如果给出了default语句,那么就会执行default语句,同时程序的执行会从select语句后的语句中恢复。⑵ 如果没有default语句,那么select语句将被阻塞,直到至少有一个channel可以进行下去。 在一般的业务场景下,select不会用default,当监听的流中再没有数据,IO操作就 会阻塞现象,如果使用了default,此时可以出让CPU时间片。如果使用了default 就形成了非阻塞状态,形成了忙轮训,会占用CPU、系统资源。 阻塞与非阻塞使用场景 阻塞: 如:在监听超时退出时,如果100秒内无操作,择退出,此时添加了default会形成忙轮训,超时监听变成了无效。 非阻塞: 如,在一个只有一个业务逻辑处理时,主进程控制进程的退出。此时可以使用default。 定时器 Go语言中定时器的使用有三个方法 time.Sleep() time.NewTimer() 返回一个时间的管道, time.C 读取管道的内容 time.After(5 * time.Second) 封装了time.NewTimer(),反回了一个 time.C的管道 示例 go 1 2 3 select { case <-time.After(time.Second * 10): } 锁和条件变量 Go语言中为了解决协程间同步问题,提供了标准库代码,包sync和sync/atomic中。 互斥锁 互斥锁是传统并发编程对共享资源进行访问控制的主要手段,它由标准库sync中的Mutex结构体类型表示。sync.Mutex类型只有两个公开的指针方法,Lock和Unlock。Lock锁定当前的共享资源,Unlock进行解锁。 go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package main import ( "fmt" "runtime" "sync" "time" ) var mutex sync....

Go面向对象

所谓的面向对象其实就是找一个专门做这个事的人来做,不用关心具体怎么实现的。所以说,面向过程强调的是过程,步骤。而面向对象强调的是对象,也就是干事的人。 Go语言:面向对象语言特性 方法 嵌入 接口 没有类 支持类型。 特别是, 它支持structs。 Structs是用户定义的类型。 Struct类型(含方法)提供类似于其它语言中类的服务。 Structs 一个struct定义一个状态。 这里有一个strudent struct。 它有一个Name属性和一个布尔类型的标志Real,告诉我们它是一个真实的strudent还是一个虚构的strudent。 Structs只保存状态,不保存行为。 go 1 2 3 4 type Creature struct { Name string Real bool } 为结构体添加方法 方法是对特定类型进行操作的函数。 它们有一个接收器条款,命令它们对什么样的类型可进行操作。 这里是一个Hello()方法,它可对student结构进行操作,并打印出它们的状态: go 1 2 3 func (s Student) Hello() { fmt.Printf("Name: '%s', Real: %t\n", s.Name, s.Real) } func (s Student) func_name(){} 这是一个不太常见的语法,但是它非常的具体和清晰,不像this的隐喻性。 一般在定义方法时,需要定义为结构体的指针,值类型的在修改结构体属性时,无法修改其内容 go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 package main import "fmt" type human struct { Name string Real bool } type Student struct { human Id int } func (h human) Hello() { fmt....

Go每日一库 - 使用go操作dbus

github https://github.com/godbus/dbus 增加一个端口 go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package main import ( "github.com/godbus/dbus/v5" ) func main() { cli, err := dbus.SystemBus() if err != nil { panic(err) } obj := cli.Object("org.fedoraproject.FirewallD1", "/org/fedoraproject/FirewallD1") call := obj.Call("oorg.fedoraproject.FirewallD1.zone.addPort", 0, "public", "81", "tcp", "30000") if call.Err != nil { panic(call.Err) } } go-dbus 简单教程 https://blog.csdn.net/mathmonkey/article/details/38095289

Go每日一库 - 时间格式化

该文可以快速在Go语言中获得时间的计算。 在Go中获取时间 如何获取当前时间 go 1 2 3 4 now := time.Now() fmt.Printf("current time is :%s", now) current time is :2009-11-10 23:00:00 +0000 UTC m=+0.000000001 如何获取UNIX Timestamp go 1 2 cur_time := time.Now().Unix() fmt.Printf("current unix timestamp is :%v\n", cur_time ) 如何获取当日0:00:00 0:00:00 go 1 2 3 4 5 now := time.Now() date := time.Date(now.Year(), now.Month(), now.Day(),0, 0, 0, 0, time.Local) fmt.Printf("date is :%s", date) date is :2021-04-13 00:00:00 +0800 如何获取时区时间 标准时间 time....

Go 运算符

算术运算符 运算符 示例 结果 + 10 + 5 15 - 10 - 5 5 * (除数不能为0) 10 * 5 50 / 10 / 5 2 % (除数不能为0) 10 % 3 1 ++ a = 0; a++ a = 1 – a = 2; a– a = 1 总结 除法/取余运算除数不能为0 只有后自增/减,没有前自增/减。没有 ++a 或 --a 只有 a++ 或 a-- 输入半径,计算圆的面积和周长并打印出来(PI为3.14) go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 package main import "fmt" func main() { const PI = 3....

Go 数据结构

Go语言将数据类型分为四类:基础类型、复合类型、引用类型和接口类型。 基础数据类型包括: 基础类型: - 布尔型、整型、浮点型、复数型、字符型、字符串型、错误类型。 复合数据类型包括: - 指针、数组、切片、字典、通道、结构体、接口。 基础数据类型 布尔值和布尔表达式 布尔类型的变量取值结果要么是真,要么是假,用bool关键字进行定义 布尔类型默认值为 false 指定格式的输出 %t 语法 描述/结果 !b 逻辑非操作符 b值为true 则 操作结果为false a || b 短路逻辑或,只要布尔值 a b 中任何一个为true表达式结果都为true a && b 短路逻辑与,两个表达式a b都为true,则整个表达式结果为true x > y 表达式x的值小于表达式Y的值,则表达式的结果为true 数值类型 go语言提供了大内置的数值类型,标准库也提供了big.Int类型的整数,和big.Rat类型的有理数,这些都是大小不限(只限于机器内存) 整型 GO语言提供了11种整型,包含5种有符号,和5种无符号的与一种用于存储指针的整数类型。Go语言允许使用byte来作为无符号uint8类型的同义词,在使用单个字符时提倡使用rune来替代 int32 类型 存储空间 取值范围 byte 8-bit 同uint8 int 系统决定 依赖不通平台实现,32位操作系统为int32的值范围,64位操作系统为int64的值范围 int8 8-bit [-128, 127] ,表示 UTF-8 字符串的单个字节的值,对应 ASCII 码的字符值 int16 16-bit [-32678, 32767] int32 32-bit [2147483648, 2147483647] int64 64-bit [-9223372036854775808 , 9223372036854775807] rune 32-bit 同uint32,表示 单个 Unicode 字符 uint 系统决定 依赖不通平台下的实现,可以是uint32或uint64 uint8 8-bit uint16 16-bit [0, 65535] uint32 32-bit [0, 4294967295] uint64 64-bit [0, 18446744073709551615] uintptr 系统决定 一个可以恰好容纳指针值得无符号整数类型(32位操作系统为uint32的值范围,64位系统为uint64的值范围) 浮点类型 Go语言提供了两种类型的浮点类型和两种类型的复数类型,...

Go 函数 function

golang保留的函数 init(), main()是golang的保留函数,有如下特点: main() 只能用在main包中,仅可定义一个,init() 可定义任意包,可重复定义,建议只定义一个 两个函数定义时不能有任何返回值 只能由go自动调用,不可被引用 init() 先于 main() 执行,并不能被其他函数调用,执行时按照main import顺序执行。 包的执行顺序 Go的初始化和执行总是从main.main函数(main包导入其它的包) 同包下的不同 .go 文件,按照以文件名或包路径名的字符串顺序“从小到大”排序顺序执行 其他的包只有被main包 import 才会执行,按照 import 的先后顺序执行; 如果某个包被多次导入的话,在执行的时候只会导入一次; 当一个包被导入时,如果它还导入了其它的包,则先将其它的包包含进来; 导入顺序与初始化顺序相反 main => p1 => p2 | p2 => p1 => p main被最后一个初始化,因其总是依赖其他包 函数 函数是将具有独立功能的代码组织成为一个整体,使其具有特殊功能的代码集。在Go语言中,函数是一种数据类型,其特性有如下: 支持匿名函数 支持带有变量名的返回值 支持多值返回 支持匿名函数 不支持重载,一个包中不能有两个名字一样的函数。 定义语法 go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 func test(){ } func test(a int, b int){ } func test(a,b int){ } func test(a,b int list....

Go socket TCP协议实现

在TCP/IP协议中,“IP地址+TCP或UDP端口号”唯一标识网络通讯中的一个进程。“IP地址+端口号”就对应一个socket。欲建立连接的两个进程各自有一个socket来标识,那么这两个socket组成的socket pair就唯一标识一个连接。因此可以用Socket来描述网络连接的一对一关系。 常用的Socket类型有两种:流式Socket(SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。流式是一种面向连接的Socket,针对于面向连接的TCP服务应用;数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用。 套接字通讯原理示意 TCP的C/S架构 在整个通信过程中,服务器端有两个socket参与进来,但用于通信的只有conn这个socket。它是由 listener创建的。隶属于服务器端。客户端有一个socket参与进来。 net.Listen() 建立一个用于连接监听的套接字 listen.Accept() // 阻塞监听客户端连接请求,成功用于连接,返回用于通信的socket net.Dial() 客户端向服务端发起连接建立一个socket连接 并发的C/S模型通信 Server Accept()函数的作用是等待客户端的链接,如果客户端没有链接,该方法会阻塞。如果有客户端链接,那么该方法返回一个Socket负责与客户端进行通信。所以,每来一个客户端,该方法就应该返回一个Socket与其通信,因此,可以使用一个死循环,将Accept()调用过程包裹起来。 需要注意,实现并发处理多个客户端数据的服务器,就需要针对每一个客户端连接,单独产生一个Socket,并创建一个单独的goroutine与之完成通信。 go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 package main import ( "fmt" "net" "strings" ) func handleConnect(conn net....

go net/http使用

Go语言标准库内建提供了net/http包,涵盖了HTTP客户端和服务端的具体实现。使用net/http包,我们可以很方便地编写HTTP客户端或服务端的程序。 http服务端的创建流程 在使用http/net包创建服务端只需要两个步骤 绑定处理器函数 func(ResponseWriter, *Request)与 启用监听 http.ListenAndServe。 go 1 2 3 4 5 6 7 8 9 10 package main import "net/http" func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("123")) }) http.ListenAndServe(":8080", nil) } 通过分析net/http包中server.go 在执行创建http服务端主要执行了下面几个步骤: http.HandleFunc 绑定处理函数 所有的操作的方法都属于一个结构体 ServeMux m: 用户传入的路由和处理方法的映射表,路由和处理函数被定义为结构体muxEntry的属性 mu: 实例化出来的对象的读写锁 调用DefaultServeMux.Handle() 在DefaultServeMux.Handle()中调用DefaultServeMux.HandleFunc(pattern, handler) 在将传入http.HandleFunc()的回调函数,与路由的映射信息,放到该DefaultServeMux的属性中 映射map中 muxEntry http.ListenAndServe 启动服务监听 实例化一个server结构体 调用 ListenAndServe() ListenAndServe()中 net.Listen("tcp", addr) 启动tcp服务监听 Serve()中 appcet()处理用户连接,go c.serve(connCtx) 处理业务段(如判断信息,拼接http、找到对应处理函数) 综上所述,net/http server.go 一切的基础为ServeMux 和 Handler...

Go mod

自从Go官方推出 1.11 之后,增加新的依赖管理模块并且更加易于管理项目中所需要的模块。模块是存储在文件树中的 Go 包的集合,其根目录中包含 go.mod 文件。 go.mod 文件定义了模块的模块路径,它也是用于根目录的导入路径,以及它的依赖性要求。每个依赖性要求都被写为模块路径和特定语义版本。 从 Go 1.11 开始,Go 允许在 $GOPATH/src 外的任何目录下使用 go.mod 创建项目。在 $GOPATH/src 中,为了兼容性,Go 命令仍然在旧的 GOPATH 模式下运行。从 ==Go 1.13== 开始,模块模式将成为默认模式。 使用模块开发 Go 代码时出现的一系列常见操作: 创建一个新模块。 添加依赖项。 升级依赖项。 删除未使用的依赖项。 要使用go module,首先要设置 ==GO111MODULE=on== ,如果没设置,执行命令的时候会有提示。 ==GO111MODULE== 的取值为 off, on, or auto (默认值,因此前面例子里需要注意2个重点)。 off: GOPATH mode,查找vendor和GOPATH目录 on:module-aware mode,使用 go module,忽略GOPATH目录 auto:如果当前目录不在$GOPATH 并且 当前目录(或者父目录)下有go.mod文件,则使用GO111MODULE, 否则仍旧使用 GOPATH mode。 sh 1 2 export GO111MODULE=on export GOPROXY=https://goproxy.io ## 设置代理 go mod 参数说明 commond 说明 download download modules to local cache (下载依赖的module到本地cache)) edit edit go....

centos安装powershell和powercli

poershell github 本次采用github下载对应的rpm进行安装 windows下安装方法 离线安装包下载地址 text 1 yum install -y https://github.com/PowerShell/PowerShell/releases/download/v7.0.0/powershell-lts-7.0.0-1.rhel.7.x86_64.rpm 安装完成后再终端输入以下命令 pwsh。在一个PowerShell会话,您可以通过运行以下命令来检查的PowerShell的版本。 text 1 2 3 4 5 6 7 PS /root> $PSVersionTable.PSVersion Major Minor Patch PreReleaseLabel BuildLabel ----- ----- ----- --------------- ---------- 7 0 0 Set-PSRepository -Name "PSGallery" -InstallationPolicy "Trusted" 接下来,运行以下命令来安装VMware.PowerCLI模块。这将发现和在PSGallery安装最新版本的模块 text 1 Find-Module "VMware.PowerCLI" | Install-Module -Scope "CurrentUser" -AllowClobber 完成后,通过运行以下命令进行检查,以确保该模块安装。 text 1 2 3 4 5 6 7 8 9 10 11 12 13 Get-Module "VMware.PowerCLI" -ListAvailable | FT -Autosize PS /root> Get-Module "VMware....

理解ldap - Linux系统接入OpenLDAP做认证后端

openldap合集 ch1 理解ldap - 什么是ldap ch2 理解ldap - OpenLDAP安装 ch3 理解ldap - OpenLDAP客户端命令行使用 ch4 理解ldap - OpenLDAP架构与Schema设计 ch5 理解ldap - OpenLDAP使用SSL/TLS通信安全 ch6 理解ldap - OpenLDAP中的4种复制机制 ch7 理解ldap - OpenLDAP访问控制(ACL) ch8 理解ldap - OpenLDAP备份与恢复策略 ch9 理解ldap - openldap中的一些高级配置 ch10 理解ldap - Linux系统接入OpenLDAP做认证后端 ch11 理解ldap - 使用SSSD接入OpenLDAP实现身份验证 Overview 如果要使Linux账号通过LDAP进行身份认证,就需要配置Linux的 身份验证模块 (Pluggable Authentication Modules) 与 名称服务交换系统 (Name Service Switch) 与LDAP交互。 PAM 和 NSS [3] NSS (name service switch) 通俗理解为是一个数据库系统,他作用是用于如何将操作系统与各种名称的解析机制关联起来,例如主机名,用户名,组名等内容的查找;例如UID查找使用 passwd 库,GID的查找使用 group 库,并且还可以告知查找的来源,如文件,LDAP等...

Ceph RBD - 初识块存储RBD

什么是块存储 RBD Ceph RBD (RADOS Block Device) 是 Ceph 提供的三种存储类型之一 (块存储 RBD, 文件存储 CephFS, 对象存储 RGW),也是另外两个存储类型 (文件存储 CephFS, 对象存储 RGW) 的底座,位于 RADOS 架构中的最底层,由下图可以看出 图:Ceph RADOS架构图 Source:https://www.supportsages.com/ceph-part-3-technical-architecture-and-components/ RADOS 是可信赖的自动分布式对象存储 (Reliable Autonomous Distributed Object Store) 的简写,通俗来说,RADOS 代表的就是整个 Ceph 集群,数据对象在集群中的存储方式会“将对象复制为多副本” 以实现容错,所以 Ceph 集群的底座就是 RADOS,一个 RADOS 集群的组件通常包含三个,OSD Daemon , MDS, MON Object Storage Device (OSD) Daemon:RADOS集群中负责存储守护进程,与 OSD (数据的物理或逻辑存储单元【通常指一个硬盘】)交互。集群中的每个 Ceph Node 都必须运行 OSD Daemon。对于每个 OSD,可以有一个关联的硬盘 (通常一个OSD Daemon 对应一个存储单元)。 MONITORS (Mon Daemon):Monitor (ceph-mon) 不是集群存储组件的一部分,但它通过监视 OSD 状态并生成 “Cluster Map” 而成为 RADOS 不可或缺的一部分。它监视 OSD 并跟踪在给定时间点哪些 OSD 处于运行状态、哪些 OSD 处于对等状态、OSD 的状态等。一般来说,它充当存储集群中所有 OSD 的 Monitor Manager (MGR Daemon):Manager (ceph-mgr) 是与 ceph-mon 一同运行的守护进程,为外部监控和管理系统提供额外的监视和接口。默认情况下,ceph-mgr 除了确保其正在运行之外不需要其他配置。如果没有运行 ceph-mgr,ceph -s 将会看到一条 WARN;不管是使用什么方式部署的集群 ( ceph-deploy, cephadm),ceph-mgr 总会 与 ceph-mon 同时运行在一个节点上,也可单独运行在 Ceph Node 之上。 通常 Monitor (ceph-mon) 不构成“存储”集群的一部分,只是通过监视 OSD 状态并生成 Cluster map 而成为 ceph存储集群中不可缺少的组件。它通过监视 OSD 并跟踪在给定时间点哪些 OSD 处于运行状态、哪些 OSD 处于对等状态、OSD 的状态等。...

理解ldap配置 - openldap中的一些高级配置

openldap合集 ch1 理解ldap - 什么是ldap ch2 理解ldap - OpenLDAP安装 ch3 理解ldap - OpenLDAP客户端命令行使用 ch4 理解ldap - OpenLDAP架构与Schema设计 ch5 理解ldap - OpenLDAP使用SSL/TLS通信安全 ch6 理解ldap - OpenLDAP中的4种复制机制 ch7 理解ldap - OpenLDAP访问控制(ACL) ch8 理解ldap - OpenLDAP备份与恢复策略 ch9 理解ldap - openldap中的一些高级配置 ch10 理解ldap - Linux系统接入OpenLDAP做认证后端 ch11 理解ldap - 使用SSSD接入OpenLDAP实现身份验证 memberOf 默认情况下,openldap提供的Posixgroup组,实际上并不能很有效的区分组与用户之间的关系。而 memberOf 则可以有效地检索用户与组的关系 在OpenLDAP配置MemberOf模块 步骤一:可以检查在允许的slapd服务是否已经启用该模块 bash 1 $ slapcat -n 0 | grep olcModuleLoad 对于新部署的服务,可以按照如下方式添加 text 1 2 3 4 dn: cn=module,cn=config objectClass: olcModuleList cn: module olcModuleload: memberof....