Docker容器中与主机上文件的相互复制

搞笑的是,我之前从容器中把文件复制到宿主机上时,一直都是直接到/var/lib/docker/containers/中直接寻找的.我尼玛,这要是只有一两个在跑的容器那找到对应目录还是比较简单的,但要是跑上数十个容器岂不得找到疯. 知道今天才知道原来存在docker cp命令,之前难道是我眼瞎???? 居然一直都没看到docker help下的帮助提示. 命令格式为: docker cp [container id /container name]:/path /hostpath docker cp /hostpath [container id /container name]:/path

Read More

Go的sync.Pool

sync.Pool是来自Go 1.3版本加入的特性,可以被看做是存放可被重用的值的容器,这个容器具有以下特性: 1. 可自动伸缩 2. 高效 3. 并发安全 因此这个类设计的目的是用来保存和复用临时对象,以减少内存分配,降低CG压力,但是由于这个原因,所以它并不可靠,因此每次GC,都会首先清楚缓冲区,假如一个slice是存放在 Pool 中,而又没有其他地方引用,则会被当成垃圾清理掉,因此切勿用sync.Pool创建socket连接. 通过sync.Pool的源码,可以看出Pool创建的时候是不能指定大小的,所有sync.Pool的缓存对象数量是没有限制的,它只受限于内存大小. 通过Get方法获取到的值是任意的.如果一个临时对象池的Put方法未被调用过,且它的New字段也未曾被赋予一个非nil的函数值,那么它的Get方法返回的结果值就一定会是nil. Get方法返回的不一定就是存在于池中的值.不过,如果这个结果值是池中的,那么在该方法返回它之前就一定会把它从池中删除掉. 一个例子: var bytePool = sync.Pool{ New: func() interface{} { b := make([]byte, 1024) return &b }, } func main() { a … “Go的sync.Pool”

Read More

Go的defer

defer⽤于延迟一个函数或者方法(或者当前所创建的匿名函数)的执行,并且defer语句只能出现在函数或方法的内部. defer语句经常被用于处理成对的操作,如文件的打开与关闭、连接的建立与断开、加锁、释放锁. 通过defer机制,不论函数逻辑多复杂都能保证在任何执行路径下资源被释放.释放资源的defer应该直接跟在请求资源的语句后. 如果一个函数中有多个defer语句,它们会以后进先出的顺序执行,哪怕函数或某个延迟调用发生错误,这些调用依旧保证会被执⾏. 多个defer: func test(x int) { fmt.Println(1 / x)//x为0时,产生异常 } func main() { defer fmt.Println(“aaaaaaaa”) defer test(0) defer fmt.Println(“bbbbbbbb”) defer fmt.Println(“cccccccc”) } 输出: cccccccc bbbbbbbb aaaaaaaa panic: runtime error: integer divide by … “Go的defer”

Read More

Go的slice

经常用C中的数组,就会知道数组存在一个不足,那就是一旦容量分配了,那就是固定长度,无法再更改. 而Golang中的slice并不是数组或数组指针,其本质上是一个数组的某个部分的引用。在源码runtime/slice.go源码中定义了slice的结构: type slice struct { array unsafe.Pointer len int cap int } 可以看到slice是一个包含3个字段的结构体: array: 指向slice第一个元素的指针 len: slice的长度,长度是索引操作的上届, s[i] i<len(s) cap: slice的容量,容量是分割操作的上届, s[i:j] j<=cap(s) slice的使用 slice和数组的区别: 声明数组时,方括号内写明了数组的长度或使用…自动计算长度;而声明slice时,方括号内没有任何字符. var s1 []int //声明切片和声明array一样,只是少了长度,此为空(nil)切片 s2 := []int{} //make([]T, … “Go的slice”

Read More

Golang的channel

Go推荐的并发模型为CSP(Communicating Sequential Process),Channel是CSP的核心。 CSP并发模型不同于传统的多线程并发通过共享内存来通信,CSP是以通信的方式来共享内存。 Go并发的核心哲学是尽量通过消息传递取代共享内存来尽可能的避免显示锁。 在Go中,channel要求操作双方必须明确数据类型,操作的一方并不关心另外一端操作者的数量。 可以把channel理解成一个队列,但有其特殊性,从同步和异步两种模式来理解: 同步模式:要求channel的发送方和接收方成对出现,如果一方没有就绪,则另一方将阻塞。 异步模式:异步模式下将抢夺channel的缓冲区,发送方要求有缓冲区有空位可写入,如果没有则发送方阻塞;接收方要求有缓存数据可读取,如果没有则接收方阻塞。 1.带缓冲区的channel c := make(chan string, 3) c <- “hello” c <- “world” //异步通道缓冲区未满,写入数据不会阻塞 fmt.Println(len(c), cap(c)) // 2 3 len和cap分别为已经缓冲数量和缓冲区大小 fmt.Println(<-c) fmt.Println(<-c) // 缓冲区中还有数据,读取数据不会阻塞 2.从channel中接收数据 第一种直接读取: msg … “Golang的channel”

Read More

Let’s Encrypt使用记录

万维网发展到现在已经有二十多年的时间了,而在我看来HTTPS将会是未来至少二十年内的主流协议,它已经开始飞快的替换掉HTTP这种不安全的协议,但只要HTTPS存在,那HTTP就是不会退出历史舞台的. 废话少说. Let’s Encrypt是去年十二月份开始公测的,可以免费申请SSL证书.其签发的证书已经获得了交叉信任,已经能被所有主流浏览器信任了.交叉签名来自 IdenTrust Root CA. 首先获取acme-tiny,然后建立私钥: #建立let’s encrypt 私钥 openssl genrsa 4096 > account.key #建立域名私钥 openssl genrsa 4096 > domain.key #生成域名请求证书 openssl req -new -sha256 -key domain.key -subj “/” -reqexts SAN -config <(cat … “Let’s Encrypt使用记录”

Read More

程序中的内存布局

上午看了篇管局内存布局的文章,有点收获,特此理一下思路,总结一番. 程序只用在运行的时候才会加载到内存; 程序没有运行前,虽没有加载到内存,但内存布局可以提前规划,当运行加载内存时,即可用规划好的内存加载。 text(代码区):函数,只读,函数入口地址。 data(数据区):初始化的数据,全局变量、static变量、文字常量区。 bss (未初始化数据):未初始化的全局变量。 heap(堆区):由用户手动申请和释放。 stack(栈区):程序自动申请空间自动释放,非static局部变量。启动后分配。 众所周知,如果只是动态分配空间而不释放,必然导致内存泄露。 1. 栈区普通变量 让指针指向栈区变量,生命周期无需手段管理,其只有作用域的限制。 2.指针指向堆区空间 成功分配内存,则返回堆区首地址; 分配失败,则返回NULL。 需要注意的是malloc()函数越界情况,大小设定0也能编译通过,但必定出错。 free()函数释放的不是变量,释放的是指向的内存,但同一块内存不能连续释放。

Read More