0%

安装

安装Gitlab 社区版本。选择操作系统,并选择安装源。

安装源及安装方法参考https://mirror.tuna.tsinghua.edu.cn/help/gitlab-ce/

如迁移,需要相同版本的Gitlab。故在选择安时指定版本。

Ubuntu 列举出安装的软件版本,

1
2
3
4
apt-cache policy <<package name>>
apt-get install package=version
# 例如
apt-get install autoconf=2.50

CentOS 安装软件版本,

1
2
yum list | grep mariadb
yum install mariadb-5.5.56-2.el7.x86_64

迁移

备份原GIT服务器数据

1
gitlab-rake gitlab:backup:create RAILS_ENV=production 

默认备份后文件一般位于/var/opt/gitlab/backups/,文件名:1513578325_2017_12_18_gitlab_backup.tar

新服务器上安装与原服务器一样版本的Gitlab

将步骤1生成的tar文件拷贝到新服务器上相应的backups目录下

新GitLab服务数据恢复

1
2
3
4
# This command will overwrite the contents of your GitLab database!
gitlab-rake gitlab:backup:restore RAILS_ENV=production BACKUP=1513578325_2017_12_18
sudo gitlab-ctl restart
sudo gitlab-rake gitlab:check SANITIZE=true

设置

可以指定仓库及备份的位置,防止磁盘占用过大。

打开/etc/gitlab/gitlab.rb 打开 git_data_dir选项。

注意

gitlab 会占用80端口,如果本机有80端口占用,会无法访问服务。需调整。旗下有很多服务,要注意。

支持多文件形式

https://play.golang.org/p/KLZR7NlVZNX

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import (
"play.ground/foo"
)

func main() {
foo.Bar()
}

-- go.mod --
module play.ground

-- foo/foo.go --
package foo

import "fmt"

func Bar() {
fmt.Println("The Go playground now has support for multiple files!")
}

// Output:

1
The Go playground now has support for multiple files!

支持远程库导入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
"fmt"
"github.com/alphaqiu/EventEmitter/event" //我是远程库
)

const (
fireEvent event.EventType = "fire"
)

func main() {
fmt.Println("Hello, playground")
emitter := event.NewEmitter(2)
emitter.On(fireEvent, doEvent())
}

func doEvent() event.Callback {
return func(event event.Event) {}
}

支持测试用例

1
2
3
4
5
6
7
8
9
package main

import (
"testing"
)

func TestUnit(t *testing.T) {
t.Log("hello")
}

Playground 源码

https://github.com/golang/playground

阅读全文 »

搜索软件

brew search [TEXT|/REGEX/]用于搜索软件,支持使用正则表达式进行复杂的搜索。

例如,查询静态博客生成工具 hugo:

1
2
3
4
5
6
$ brew search hugo

==> Searching local taps...
hugo ✔
==> Searching taps on GitHub...
==> Searching blacklisted, migrated and deleted formulae...

查看安装的包

查看已经安装的包

1
brew list

查看包相关信息

brew info 可以查看包的相关信息,最有用的应该是包依赖和相应的命令。比如 Nginx 会提醒你怎么加 launchctl ,PostgreSQL 会告诉你如何迁移数据库。这些信息会在包安装完成后自动显示,如果忘了的话可以用这个命令很方便地查看。

1
2
3
4
5
brew info $FORMULA    # 显示某个包的信息
brew info # 显示安装了包数量,文件数量,和总占用空间
brew deps 可以显示包的依赖关系,我常用它来查看已安装的包的依赖,然后判断哪些包是可以安全删除的。

brew deps --installed --tree # 查看已安装的包的依赖,树形显示

更新 Homebrew

要获取最新的包的列表,首先得更新 Homebrew 自己。这可以用 brew update 办到。

brew update
完后会显示可以更新的包列表,其中打钩的是已经安装的包。

更新包 (formula)

更新之前,我会用 brew outdated 查看哪些包可以更新。

brew outdated
然后就可以用 brew upgrade 去更新了。Homebrew 会安装新版本的包,但旧版本仍然会保留

brew upgrade # 更新所有的包

brew upgrade $FORMULA # 更新指定的包

阅读全文 »

在 $HOME/.cargo/config 中添加如下内容

1
2
[registry]
index = "git://mirrors.ustc.edu.cn/crates.io-index"

如果所处的环境中不允许使用 git 协议, 可以把上述地址改为

1
index = "http://mirrors.ustc.edu.cn/crates.io-index"

同步频率为每两个小时更新一次.

如果 cargo 版本为 0.13.0 或以上, 需要更改 $HOME/.cargo/config 为以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
[source.crates-io]
registry = "https://github.com/rust-lang/crates.io-index"
replace-with = 'ustc'
[source.ustc]
registry = "git://mirrors.ustc.edu.cn/crates.io-index"

# 以下是字节跳动新的Rust镜像,2021年6月25日创建。
# 用于备选代理
#[source.crates-io]
#replace-with = 'rsproxy'
#[source.rsproxy]
#registry = "https://rsproxy.cn/crates.io-index"

相关链接

https://lug.ustc.edu.cn/wiki/mirrors/help/rust-crates

官方主页: https://crates.io/

Swagger

一个一键生成API文档的工具。GoSwagger,Golang版本的Swagger,支持在代码中编写注释,通过Swagger编译后生成API文档。

Swagger是一个简单但功能强大的API表达工具。它具有地球上最大的API工具生态系统,数以千计的开发人员,使用几乎所有的现代编程语言,都在支持和使用Swagger。使用Swagger生成API,我们可以得到交互式文档,自动生成代码的SDK以及API的发现特性等。

——《使用go-swagger为golang API自动生成swagger文档

安装方式

通过brew安装

1
2
brew tap go-swagger/go-swagger
brew install go-swagger

其余的安装方式请移步:Install goswagger

阅读全文 »

1
find . -type f -size +10M

查找大于10M的文件。

1
find . -size +10M -print0|xargs -0 ls -l

查看大于10M的文件的信息。

1
find . -size +10M -print0|xargs -0 du -h

只列举大于10M的文件的具体尺寸。

1
find . -size +10M -print0|xargs -0 du -h|sort -nr

再逆序排个序。

1
du -h --max-depth=1

查找大目录。

VuePress

https://vuepress.vuejs.org/zh/

Vue驱动静态网站生成器,非常不错哟,支持Markdown

ReadTheDocs

readthedocs是一个文档托管网站。它可以连接GitHub帮助你编译项目文档。编译好的文档会自动的发布在http://项目名称.readthedocs.io上。

Sphinx

Sphinxreadthedocs 网站首推的文档生成工具。它的作用是把rst或者markdown文件编译成html或者pdf。这边使用它的原因是需要用它生成文档脚手架,在本地查看编译后的效果。

安装

Sphinx支持python2.73.7。我在本机使用了python3.7的版本。因此使用pip3作为下载器。由于需要用到sphinx_rtd_theme这样的插件,macOS下不建议使用brew install sphinx

1
pip3 install sphinx sphinx_rtd_theme recommonmark sphinx-markdown-tables
阅读全文 »

远程的镜像库往往非常慢,此时需要有一个快速的镜像库会加速下载效率。下面讲讲创建镜像库的步骤:

创建一个本地的克隆

1
git clone --mirror https://github.com/cocoapods/Specs.git

然后设定镜像仓库的地址

1
2
cd Specs.git
git remote set-url --push origin <your-mirror-localtion>

设定一个脚本

1
2
git fetch -p origin
git push --mirror

设定一个cronjob定时脚本

1
* 2 * * * /path/your/script.sh > /var/log/specssync.log 2>&1

遇到推送失败?

阅读全文 »

程序中的所有数在计算机内存中都是以二进制的形式储存的。而位运算,就是直接对在内存中的二进制位进行操作,跳过了 程序转义成二进制的这一步骤,对编译时间有所提高,但带来的缺点也很明显,程序的可读性变低了。

掌握位运算 是一位程序员的基本素养,位运算在计算机领域的作用可谓举足轻重。下面我将讲解 位运算的大体方法以及一些基本的应用。

and 运算

只有对应的两个 二进制数,均为 1,结果才为 1,否则为 0

& 1

判断 n 的第 m 位数

介绍两个重要应用,来证明其含义:

  1. (n >>m ) & 1 判断 整数 n 的二进制 第 m 位 是否 为 1 或者 为 0 n 的第 m 位数,如果为 1 ,1&1 就返回 1 ,如果为 0,0&1 就返回 0
  2. 判断 奇偶性 如果 n 为奇数,辗转相除 2,最后的余数 必定为 1,如果 n 为偶数,辗转相除 余数必定为 0 也就是说,n 为奇数,n&1 等价于 1&1 ,返回 1,n 为偶数,n&1 等价于 0&1,返回 0

& 0

将 n 的第 m 位数,重置为 0 基本应用:n & ~(1 << m)

  1. 1 << m 定位到 n 的第 m 位数
  2. ~(1 << m) 将 1 进行非运算,变为 0,其他剩下的 m 位,变成 1,而 &1,是无实际作用的
  3. n & 0 :& 按位与运算 只有对应的两个数 全部为 1 时,结果才为 1,而&0,返回值一定为 0

or 运算

只有对应的两个 二进制数,均为 0,结果才为 0,否则为 1

| 1

将 n 的第 m 位数,重置为 1

基本应用:n | (1 << m):

  1. 1 << m
    定位到 n 的第 m 位数
  2. n | 1
    n 的第 m 位数 进行 |1 操作 其返回值必定为 1! 因为|只有,两个数都为 0 时,结果才为 0

| 0

无实际作用

一定要清楚, 是 n 的第 m 位数 在进行操作,其他 位数操作,根本无 影响

因为,其他位数,是 在进行 “| 0” 操作,而所谓的 |0 操作,与 &1 操作,毫无差别。

假设 k=n 的第 m 位数,k = 1 ,k|0 = 1|0 = 1,k = 0,k|0 = 0|0 = 0,所谓 无实际作用。

但是要注意一点,我说的 0 是在二进制数中的 0,有实际含义的 0,不是补 0 的 0

所以,可以感性的认识到,| 0 与 & 1 以及 下文的 ^ 0,都是无实际作用的

xor 运算

只有对应的两个 二进制数相等时,结果才为 0,否则为 1

^ 1

将 n 的第 m 位数,取反

基本应用:n ^ (1 << m)

  1. 1 << m : 定位到 n 的第 m 位数
  2. n ^ 1,我们要知道,^ (异或):不相等为 1,相等为 0

而 ^1:如果 n 的第 m 位数 为 1,1^1 返回值为 0,如果 n 的第 m 位数 为 0,0^1 返回值 为 1

所以,^1 的重要作用,就是 与之相反的作用

^ 0

无实际作用

假定 整数 k 为 0,k^0 = 0^0 = 0 ; 假定整数 k 为 1,k^0 = 1^0 = 1

所以说,无论怎么变化,^0 都是无实际作用的

shl & shr 运算

  1. 左移运算符 “<<”

表达式:a << b a<<b 的值是:将 a 各二进位全部左移 b 位后得到的值。左移时,高位丢弃,低位补 0。 实际上,左移 1 位,就等于是乘以 2,左移 n 位,就等于是乘以 2n。 而左移操作比乘法操作快得多。

1
2
3
4
5
COPY例如:9 << 4
9的二进制形式:0000 0000 0000 0000 0000 0000 0000 1001
因此,表达式“9<<4”的值,就是将上面的二进制数左移4位,得:
0000 0000 0000 0000 0000 0000 1001 0000
即为十进制的144 , 9*2的4次幂 = 9*16 = 144.
  1. 右移运算符 “>>”

表达式:a >> b a>>b 的值是:将 a 各二进位全部右移 b 位后得到的值。右移时,移出最右边的位就被丢弃。 对于有符号数,如 long,int,short,char 类型变量,在右移时,符号位(即最高位)将一起移动,并且大多数 C/C++编译器规定,如果原符号位为 1,则右移时高位就补充 1,原符号位为 0,则右移时高位就补充 0。

1
2
COPY实际上,右移 n 位,就相当于左操作数除以2n,并且将结果往小里取整。
例如:-25 >> 4 = -2 -2 >> 4 = -1 18 >> 4 = 1

应用

对 2 的整数幂进行模运算

1
2
3
4
5
6
7
8
9
10
11
12
COPY#include <stdio.h>
int main(){
int n,k;
while(~scanf("%d %d",&n,&k)){
n<<=k;//相当于 n 乘以 2 的 k 次幂,并将结果赋给 n

n>>=k;//相当于 n 除以 2 的 k 次幂,并将结果赋给 n

printf("%d\n",n);
}
return 0;
}

两数交换

1
2
3
4
5
6
7
8
9
10
11
COPY#include <stdio.h> 
int main(){
int n,m;
while(~scanf("%d %d",&n,&m)){
n^=m;
m^=n;
n^=m;
printf("%d %d\n",n,m);
}
return 0;
}

按位异或 ^ : 不相同 为:1 ; 相同 为 :0 将参与运算的两操作数各对应的二进制位进行异或操作, 即只有对应的两个二进位不相同时,结果的对应二进制位才是 1,否则为 0。

异或运算的特点是:如果 a^b=c,那么就有 c^b = a 以及 c^a=b

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
COPY例如:表达式“21 ^ 18 ”的值是7(即二进制数111)。
21: 10101
18: 10010
21^18: 00111

假设 n = 5,m = 6
5的二进制为:101
6的二进制为:110

n^=m = 5^=6 = 101 ^ 110 = 011 ,
此时 n 的二进制为:011

m^=n = 6^=011 = 110 ^ 011 = 101 ,
此时 m 的二进制为:101,也正是 5的二进制数,也就是说 m ==开始的 n

n^=m = 011^=5 = 011 ^ 101 = 110 ,
此时 n 的二进制位:110,也正是 6的二进制数,也就是说 n ==开始的 m

层次结构:A->B B->A A->B 正 反 正

判断 2 的正整数幂

1
2
3
4
5
6
7
8
9
10
11
COPY#include <stdio.h>
int main(){
int n;
while(~scanf("%d",&n)){
if(!(n & (n-1)) && n)
printf("%d 为 2 的正整数幂\n",n);
else
printf("%d 不是 2 的正整数幂\n",n);
}
return 0;
}

给定整数 n 判断 n 是否为 2 的正整数幂 表达式:(! (n & (n-1)) && n

1
2
3
4
COPY举个例子: n = 16 = 10000,n-1 = 15 = 1111
那么 :10000 & 01111 = 00000 = 0
再举个例子: n = 256 = 10000000 ,n-1 = 255 = 11111111
那么:100000000 & 011111111 = 000000000 = 0

是的,如果一个数 n 是 2 的正整数幂,那么 n 的二进制必定为 1000…. n-1 的二进制必定为 1111…. 即: n & n-1 = 0 所以 (! (n & (n-1)) 为 1 ; && n :判断 n 为正数

判断奇偶性

1
2
3
4
5
6
7
8
9
10
11
COPY#include <stdio.h>
int main(){
int n;
while(~scanf("%d",&n)){
if(n&1)
printf("%d 是奇数\n",n);
else
printf("%d 是偶数\n",n);
}
return 0;
}

记住:在做位运算时,位数不够的数,自动在 前面补 0 比如:21 & 1 :10101 & 00001 = 00001 = 1 16 & 1 :10000 & 00001 = 00000 = 0 事实证明:偶数的二进制的末尾 为 0,奇数的二进制的末尾 为 1

十进制 m 转换 n 进制方法: m 一直除 n,每相除一次,m 就等于商,直到商为 0,然后余数反排 即可。

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
COPY1的二进制:1/2 =01
余数反排 即是 1的二进制:1

6的二进制:6/2 =30
3/2 =11
1/2 =01
余数反排 即是 6的二进制:110

15的二进制:15/2=71
7/2=31
3/2=11
1/2=01
余数反排 即是 15的二进制:1111

5的二进制:5/2 =21
2/2 =10
1/2 =01
余数反排 即是 5的二进制:101

21的二进制:21/2 =101
10/2 =50
5/2 =21
2/2 =10
1/2 =01
余数反排 即是 21的二进制:10101

其他方面

(n >> m) & 1 == (n >> m) | 0 == (n >> m) ^ 0

n & ~(1 << m) : 将 n 的第 m 位数,重置为 0

n | (1 << m) : 将 n 的第 m 位数,重置为 1

n ^ (1 << m) : 将 n 的第 m 位数,取其相反

使用位移运算来避免乘法运算是一种技巧,乘数必须都是正整数,而且必须至少有一个是2的n次方,例如:2,4,6,8,16,32……移位运算的特点是速度快,而乘法运算速度较慢,把乘法运算转化为移位运算可以提高程序运算效率。

1
2
3
4
5
6
7
8
9
12*2 = 12 << 1
12*3 = 12*(2+1) = 12*2 + 12 = 12 << 1 + 12
12*4 = 12 << 2
12*5 = 12*(4+1) = 12 << 2 + 12
12*6 = 12*(4+2) = 12*4 + 12*2 = 12 << 2 + 12 << 1
12*7 = 12*(4+2+1) = 12 << 2 + 12 << 1 + 12
12*8 = 12 << 3
12*9 = 12*(8+1) = 12 << 3 + 12
12*10 = 12*(8+2) = 12 << 3 + 12 << 1

位移也可以做除法

1
2
3
12/2 = 12 >> 1
12/4 = 12 >> 2
12/8 = 12 >> 3

服务器双向认证,原理上就是相互交换公钥,双方通过公钥认证对方。不同的是服务器双向认证,有一方作为主导方,另一方作为连接方。所以网上讲的自签发证书需要生成CA证书,通过CA证书再分别分发服务器证书和客户端证书这件事情不是必须的

生成证书的脚本

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
#!/usr/bin/env bash 

# call this script with an email address (valid or not).
# must install openssl before run this script.
# like:
# ./makecert.sh [email protected]

FULLPATH=$1

rm -f ${FULLPATH}/client.pem ${FULLPATH}/client.key

SUBJECT_SERVER="/C=CN/ST=Shanghai/L=Earth/O=BOX/OU=DC/CN=192.168.10.189/emailAddress"
SUBJECT_CLIENT="/C=CN/ST=Shanghai/L=Earth/O=BOX/OU=DC/CN=192.168.10.190/emailAddress"

EMAIL=${2:[email protected]}
DAYS=${3:-3650}

# 生成服务器证书对,pem和key

openssl req -new -nodes -x509 -days ${DAYS} -out ${FULLPATH}/server.pem -keyout ${FULLPATH}/server.key -extensions v3_req -config openssl.cnf -subj "${SUBJECT_SERVER}=${EMAIL}"

# 生成客户端证书对,pem和key

openssl req -new -nodes -x509 -days ${DAYS} -out ${FULLPATH}/client.pem -keyout ${FULLPATH}/client.key -extensions v3_req -config openssl.cnf -subj "${SUBJECT_CLIENT}=${EMAIL}"

阅读全文 »