Vcancy's Home

电影|阅读|记录


  • 首页

  • 标签

  • 分类

  • 归档

Mariadb on k8s

发表于 2021-07-08 | 分类于 服务器技术

在k8s上部署单实例mariadb

前提

  1. k8s 集群
  2. 持久化存储(NFS, Longhorn等)

构建自定义docker镜像

这里设置容器语言以及时区为上海东八区

1
2
3
4
5
6
7
8
9
FROM mariadb:10.1

ENV LANG="en_US.UTF-8" \
LANGUAGE="en_US:en" \
LC_ALL="en_US.UTF-8"

RUN \
echo "Asia/shanghai" > /etc/timezone && \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

docker build -f mysql.Dockerfile -t vcancy/mariadb:10.1 .

1
2


服务编排

1
kubectl -n default apply -f mysql.yaml
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
## config map
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-config
data:
cust.cnf: |
[mysqld]
max_connections=1000

---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: mysql
name: mysql
spec:
replicas: 1
selector:
matchLabels:
name: mysql
template:
metadata:
labels:
name: mysql
spec:
containers:
- name: mysql
image: vcancy/mariadb:10.1
volumeMounts:
- name: mysql-data
mountPath: "/var/lib/mysql"
- name: mariadb-config
mountPath: "/etc/mysql/conf.d"
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
volumes:
- name: mysql-data
persistentVolumeClaim:
claimName: mysql-data
- name: mariadb-config
configMap:
name: mysql-config

##创建Service
---
apiVersion: v1
kind: Service
metadata:
name: mysql
labels:
name: mysql
spec:
type: ClusterIP
ports:
- port: 3306
protocol: TCP
targetPort: 3306
name: tcp-3306-3306
selector:
name: mysql

遇到的问题

1、自定义conf。使用官方docker镜像对于自定义的配置文件有要求,需要挂载到/etc/mysql/conf.d下以.cnf结尾同时 [mysqld]开头,不然会启动报错,配置重复等问题

Mac配置zsh

发表于 2018-08-23

安装zsh

brew install zsh

配置zsh

nano ~/.zshrc

复制以下内容到.zshrc

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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# 配置kubectl添加补全
source <(kubectl completion zsh)

# Antigen: https://github.com/zsh-users/antigen
ANTIGEN="$HOME/.local/bin/antigen.zsh"

# Install antigen.zsh if not exist
if [ ! -f "$ANTIGEN" ]; then
echo "Installing antigen ..."
[ ! -d "$HOME/.local" ] && mkdir -p "$HOME/.local" 2> /dev/null
[ ! -d "$HOME/.local/bin" ] && mkdir -p "$HOME/.local/bin" 2> /dev/null
[ ! -f "$HOME/.z" ] && touch "$HOME/.z"
URL="http://git.io/antigen"
TMPFILE="/tmp/antigen.zsh"
if [ -x "$(which curl)" ]; then
curl -L "$URL" -o "$TMPFILE"
elif [ -x "$(which wget)" ]; then
wget "$URL" -O "$TMPFILE"
else
echo "ERROR: please install curl or wget before installation !!"
exit
fi
if [ ! $? -eq 0 ]; then
echo ""
echo "ERROR: downloading antigen.zsh ($URL) failed !!"
exit
fi;
echo "move $TMPFILE to $ANTIGEN"
mv "$TMPFILE" "$ANTIGEN"
fi


# Initialize command prompt
export PS1="%n@%m:%~%# "

# Enable 256 color to make auto-suggestions look nice
export TERM="xterm-256color"


# Load local bash/zsh compatible settings
_INIT_SH_NOFUN=1
[ -f "$HOME/.local/etc/init.sh" ] && source "$HOME/.local/etc/init.sh"

# exit for non-interactive shell
[[ $- != *i* ]] && return

# WSL (aka Bash for Windows) doesn't work well with BG_NICE
[ -d "/mnt/c" ] && [[ "$(uname -a)" == *Microsoft* ]] && unsetopt BG_NICE


# Initialize antigen
source "$ANTIGEN"


# Initialize oh-my-zsh
antigen use oh-my-zsh

# default bundles
# visit https://github.com/unixorn/awesome-zsh-plugins
# antigen bundle git
# antigen bundle heroku
antigen bundle pip
antigen bundle svn-fast-info
# antigen bundle command-not-find

antigen bundle colorize
antigen bundle github
antigen bundle python
antigen bundle rupa/z z.sh
# antigen bundle z

antigen bundle zsh-users/zsh-autosuggestions
antigen bundle zsh-users/zsh-completions
# antigen bundle supercrabtree/k
antigen bundle Vifon/deer

antigen bundle willghatch/zsh-cdr
# antigen bundle zsh-users/zaw

# uncomment the line below to enable theme
# antigen theme fishy


# check login shell
if [[ -o login ]]; then
[ -f "$HOME/.local/etc/login.sh" ] && source "$HOME/.local/etc/login.sh"
[ -f "$HOME/.local/etc/login.zsh" ] && source "$HOME/.local/etc/login.zsh"
fi

# syntax color definition
ZSH_HIGHLIGHT_HIGHLIGHTERS=(main brackets pattern)

typeset -A ZSH_HIGHLIGHT_STYLES

# ZSH_HIGHLIGHT_STYLES[command]=fg=white,bold
# ZSH_HIGHLIGHT_STYLES[alias]='fg=magenta,bold'

ZSH_HIGHLIGHT_STYLES[default]=none
ZSH_HIGHLIGHT_STYLES[unknown-token]=fg=009
ZSH_HIGHLIGHT_STYLES[reserved-word]=fg=009,standout
ZSH_HIGHLIGHT_STYLES[alias]=fg=cyan,bold
ZSH_HIGHLIGHT_STYLES[builtin]=fg=cyan,bold
ZSH_HIGHLIGHT_STYLES[function]=fg=cyan,bold
ZSH_HIGHLIGHT_STYLES[command]=fg=white,bold
ZSH_HIGHLIGHT_STYLES[precommand]=fg=white,underline
ZSH_HIGHLIGHT_STYLES[commandseparator]=none
ZSH_HIGHLIGHT_STYLES[hashed-command]=fg=009
ZSH_HIGHLIGHT_STYLES[path]=fg=214,underline
ZSH_HIGHLIGHT_STYLES[globbing]=fg=063
ZSH_HIGHLIGHT_STYLES[history-expansion]=fg=white,underline
ZSH_HIGHLIGHT_STYLES[single-hyphen-option]=none
ZSH_HIGHLIGHT_STYLES[double-hyphen-option]=none
ZSH_HIGHLIGHT_STYLES[back-quoted-argument]=none
ZSH_HIGHLIGHT_STYLES[single-quoted-argument]=fg=063
ZSH_HIGHLIGHT_STYLES[double-quoted-argument]=fg=063
ZSH_HIGHLIGHT_STYLES[dollar-double-quoted-argument]=fg=009
ZSH_HIGHLIGHT_STYLES[back-double-quoted-argument]=fg=009
ZSH_HIGHLIGHT_STYLES[assign]=none

# load local config
[ -f "$HOME/.local/etc/config.zsh" ] && source "$HOME/.local/etc/config.zsh"
[ -f "$HOME/.local/etc/local.zsh" ] && source "$HOME/.local/etc/local.zsh"

# enable syntax highlighting
antigen bundle zsh-users/zsh-syntax-highlighting

antigen apply

# setup for deer
autoload -U deer
zle -N deer

# default keymap
bindkey -s '\ee' 'vim\n'
bindkey '\eh' backward-char
bindkey '\el' forward-char
bindkey '\ej' down-line-or-history
bindkey '\ek' up-line-or-history
# bindkey '\eu' undo
bindkey '\eH' backward-word
bindkey '\eL' forward-word
bindkey '\eJ' beginning-of-line
bindkey '\eK' end-of-line

bindkey -s '\eo' 'cd ..\n'
bindkey -s '\e;' 'll\n'

bindkey '\e[1;3D' backward-word
bindkey '\e[1;3C' forward-word
bindkey '\e[1;3A' beginning-of-line
bindkey '\e[1;3B' end-of-line

bindkey '\ev' deer

alias ll='ls -l'


# options
unsetopt correct_all

setopt BANG_HIST # Treat the '!' character specially during expansion.
setopt INC_APPEND_HISTORY # Write to the history file immediately, not when the shell exits.
setopt SHARE_HISTORY # Share history between all sessions.
setopt HIST_EXPIRE_DUPS_FIRST # Expire duplicate entries first when trimming history.
setopt HIST_IGNORE_DUPS # Don't record an entry that was just recorded again.
setopt HIST_IGNORE_ALL_DUPS # Delete old recorded entry if new entry is a duplicate.
setopt HIST_FIND_NO_DUPS # Do not display a line previously found.
setopt HIST_IGNORE_SPACE # Don't record an entry starting with a space.
setopt HIST_SAVE_NO_DUPS # Don't write duplicate entries in the history file.
setopt HIST_REDUCE_BLANKS # Remove superfluous blanks before recording entry.
setopt HIST_VERIFY # Don't execute immediately upon history expansion.


# source function.sh if it exists
[ -f "$HOME/.local/etc/function.sh" ] && . "$HOME/.local/etc/function.sh"


# ignore complition
zstyle ':completion:*:complete:-command-:*:*' ignored-patterns '*.pdf|*.exe|*.dll'
zstyle ':completion:*:*sh:*:' tag-order files

为root用户修改默认shell为zsh

chsh -s /bin/zsh root
为当前用户修改默认shell为zsh
chsh -s /bin/zsh
or
chsh -s `which zsh`
恢复命令

chsh -s /bin/bash

Drone + gogs CI

发表于 2018-06-29 | 分类于 服务器技术

Drone是一个CI/CD平台,支持通过docker来分发和使用。Gogs使用介绍Gogs是一款类似Github(国内有码市)的开源文件/代码管理系统。
相比使用rancher+gitlabCI的解决方案使用Drone + gogs更轻量级,服务器资源有限的中小型团队和个人开发者使用是比较好的。

前提条件:

安装 Docker、Docker-Compose,参考本博客之前的文章

创建文件夹

1
2
3
4
5
6
mkdir -p/data/program/drone-ci/gogs-data
mkdir -p /data/program/drone-ci/drone

cd /data/program/drone-ci/

nano docker-compose.yml

docker-compose.yml

1
2
3
4
5
6
mkdir -p/data/program/drone-ci/gogs-data
mkdir -p /data/program/drone-ci/drone

cd /data/program/drone-ci/

nano docker-compose.yml

docker-compose.yml

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
version: '2'

services:
gogs:
image: gogs/gogs:0.11.53
ports:
- "10081:22” # 这里是有双引号的,gogs ssh端口映射到宿主机10081
- 10082:3000 # gogs web端口映射到宿主机10082
volumes:
- /data/program/drone-ci/gogs-data:/data
restart: always
drone-server:
image: drone/drone:0.8.1
ports:
- 10083:8000 # drone web 端口映射到宿主机10082
- 10084:9000 # drone 服务端口
volumes:
- /data/program/drone-ci/drone:/var/lib/drone # drone存储文件映射到宿主机上
restart: always
environment:
# 开启注册,此配置允许任何人自注册和登录系统
- DRONE_OPEN=true
# 设置管理员用户
- DRONE_ADMIN=admin
# 开启Gogs驱动
- DRONE_GOGS=true
# Gogs服务器地址
- DRONE_GOGS_URL=http://宿主机IP或者域名:10082
# 此SECRET为任意值
- DRONE_SECRET=handhand
- DRONE_HOST=http://宿主机IP或者域名
# - DRONE_GOGS_SKIP_VERIFY=true
- DRONE_GOGS_PRIVATE_MODE=true
drone-agent:
image: drone/agent:0.8.1
command: agent
restart: always
depends_on: [ drone-server ]
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
# Drone Server 地址
- DRONE_SERVER=drone-server:9000
# 与Drone Server一致即可
- DRONE_SECRET=handhand

启动docker-compose

1
docker-compose up -d

gogs初始化

创建数据库

gogs可以使用mysql存储,需要提前创建数据库,在mysql中创建名为gogs到数据库,字符集为utf8,排序规则为utf8_general_ci.

首次运行安装向导:http://IP地址:10082

注:

域名:宿主机IP或者域名

ssh端口号:10081

http端口号:3000(这个为docker容器内监听的端口)

应用url: http://宿主机IP或者域名:10082

可选设置:
禁用用户自注册:内部使用,所有账号由管理员创建

创建管理员:填写管理员账号密码

参考 http://readme.drone.io/

docker私服仓库搭建

发表于 2018-06-29 | 分类于 服务器技术

docker官方提供私服镜像,我们可以很方便的启动一个docker私服仓库

1
2
mkdir -p /data/program/docker-registry
docker run -d -p 5000:5000 -v /data/program/docker-registry:/var/lib/registry --name docker-registry --restart=always registry

注意:这样启动的私服只能通过http访问,客户端使用需要做一定的配置

Ubuntu

1
2
3
4
5
nano /etc/docker/daemon.json
添加"insecure-registries"
{
"insecure-registries": ["x.x.x.x:5000"]
}

这样的私服镜像是公开可访问的,我们可以在docker-registry前加上nginx做https的代理转发同时配置用户登录

注:替换xx.com为你自己申请的域名

acme.sh域名证书配置

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
apt install socat

curl https://get.acme.sh | sh

cd ~/.acme.sh/

申请签发 SSL 证书
sh acme.sh --issue -d xx.com --standalone

# 证书安装目录
mkdir -p /opt/certs

cd ~/.acme.sh/

安装证书

sh acme.sh --installcert -d xx.com --keypath /opt/certs/xx.com.key --fullchainpath /opt/certs/xx.com.pem --reloadcmd "/data/release/nginx-1.15.0/sbin/nginx -s reload"

# /opt/certs/ 是证书安装目录
# /data/release/nginx-1.15.0/sbin/nginx为nginx安装路径
# reloadcmd 是nginx 的reload 命令 acme.sh 记住重启 Nginx 的命令,以后自动更新证书的动作需要重启 Nginx,然后你会看到结果

生成 dhparam.pem 文件
openssl dhparam -out /opt/certs/dhparam.pem 2048

配置docker 私服 与nginx

mkdir -p /data/program/docker-registry

cd /data/program/docker-registry

# 安装apache 工具箱
apt install apache2-utils
# 生成私服访问账号密码
htpasswd -bc nginx.htpasswd admin 123456

nginx 配置:/data/release/nginx-1.15.0/conf/conf.d/docker-registry.conf
测试访问:https://xx.com:10090/v2/
返回{}

docker-registry.conf

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
upstream docker-registry {
server 127.0.0.1:5000;
}

## Set a variable to help us decide if we need to add the
## 'Docker-Distribution-Api-Version' header.
## The registry always sets this header.
## In the case of nginx performing auth, the header is unset
## since nginx is auth-ing before proxying.
map $upstream_http_docker_distribution_api_version $docker_distribution_api_version {
'' 'registry/2.0';
}

server {
listen 10090 ssl;
server_name xx.com;

# SSL
ssl_certificate /opt/certs/xx.com.pem;
ssl_certificate_key /opt/certs/xx.com.key;

# Recommendations from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
ssl_protocols TLSv1.1 TLSv1.2;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;

# disable any limits to avoid HTTP 413 for large image uploads
client_max_body_size 0;

# required to avoid HTTP 411: see Issue #1486 (https://github.com/moby/moby/issues/1486)
chunked_transfer_encoding on;

location /v2/ {
# Do not allow connections from docker 1.5 and earlier
# docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents
if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
return 404;
}

# To add basic authentication to v2 use auth_basic setting.
auth_basic "Registry realm";
auth_basic_user_file /data/program/docker-registry/nginx.htpasswd;

## If $docker_distribution_api_version is empty, the header is not added.
## See the map directive above where this variable is defined.
add_header 'Docker-Distribution-Api-Version' $docker_distribution_api_version always;

proxy_pass http://docker-registry;
proxy_set_header Host $http_host; # required for docker client's sake
proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 900;
}
}

使用docker搭建kafka集群

发表于 2018-06-29 | 分类于 服务器技术

通过docker可以很方便的搭建kafka集群作为本地测试环境使用
使用docker-compose进行搭建,包含zookpper服务、kafka broker、kafka-manager。

创建目录

1
2
3
mkdir -p /data/program/kafka
cd /data/program/kafka
nano docker-compose.yml

docker-compose.yml文件内容:

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
version: '2'

services:
zoo1:
image: wurstmeister/zookeeper
restart: unless-stopped
hostname: zoo1
ports:
- "12181:2181"
container_name: zookeeper

# kafka version: 1.1.0
# scala version: 2.12
kafka1:
image: wurstmeister/kafka
ports:
- "9092:9092"
environment:
KAFKA_ADVERTISED_HOST_NAME: xxx # 这里为宿主机host name
KAFKA_ZOOKEEPER_CONNECT: "zoo1:2181"
KAFKA_BROKER_ID: 1
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
depends_on:
- zoo1
container_name: kafka
kafka-manager:
image: hlebalbau/kafka-manager
restart: unless-stopped
ports:
- "10085:9000"
environment:
ZK_HOSTS: "zoo1:2181"
APPLICATION_SECRET: "random-secret"
KAFKA_MANAGER_AUTH_ENABLED: "true"
KAFKA_MANAGER_USERNAME: "admin"
KAFKA_MANAGER_PASSWORD: "TL2oo8tl2oo8"
depends_on:
- zoo1
container_name: kafka-manager
command: -Dpidfile.path=/dev/null

启动kakfa集群

1
docker-compose up -d

Ubuntu 快速搭建docker环境

发表于 2018-06-29 | 分类于 服务器技术

目前使用Ubuntu16.04 作为服务器系统,下面介绍docker环境的安装和配置

安装docker :访问官网资源速度慢,这里使用daocloud提供的脚本

curl -sSL https://get.daocloud.io/docker | sh

修改docker路径:由于/var目录在服务器的系统分区上,只有20G,这里需要将/var/lib/docker软链接到数据磁盘

1
2
3
4
5
6
7
8
9
10
11
新建docker存储目录
mkdir -p /data/program/docker

查询默认的存储路径
sudo docker info | grep "Docker Root Dir"

sudo service docker stop

sudo ln -s /data/program/docker /var/lib/docker

sudo service docker start

安装 docker compose:这里依然使用daocloud提供的脚本安装docker compose

1
2
3
curl -L https://get.daocloud.io/docker/compose/releases/download/1.21.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

chmod +x /usr/local/bin/docker-compose

阿里云ECS挂载数据磁盘

发表于 2018-06-29

当我们购买阿里云的ECS服务器后,默认的系统磁盘20G,数据磁盘根据我们的选择挂载到ECS上。
需要做以下操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
分区
> fdisk /dev/vdb

> fdisk -l

创建分区表
> mkfs.ext3 /dev/vdb

fstab配置
> cp /etc/fstab /etc/fstab.bak

> echo /dev/vdb1 /mnt ext3 defaults 0 0 >> /etc/fstab

创建挂载目录
> mkdir /data

挂载磁盘到目录
> mount /dev/vdb1 /mnt

> df -h

参考:https://help.aliyun.com/document_detail/25426.html?spm=a2c4g.11186623.2.9.5jvUla

python redis操作

发表于 2018-06-08

String操作

方法 作用 示例 示例结果
set(name, value) 给name赋值为value redis.set(‘name’, ‘Bob’) True
get(name) 返回数据库中key为name的string的value redis.get(‘name’) b’Bob’
getset(name, value) 给数据库中key为name的string赋予值value并返回上次的value redis.getset(‘name’, ‘Mike’) b’Bob’
mget(keys, *args) 返回多个key对应的value redis.mget([‘name’, ‘nickname’]) [b’Mike’, b’Miker’]
setnx(name, value) 如果key不存在才设置value redis.setnx(‘newname’, ‘James’) 第一次运行True,第二次False
setex(name, time, value) 设置可以对应的值为string类型的value,并指定此键值对应的有效期 redis.setex(‘name’, 1, ‘James’) True
setrange(name, offset, value) 设置指定key的value值的子字符串 redis.set(‘name’, ‘Hello’) redis.setrange(‘name’, 6, ‘World’) 11,修改后的字符串长度
mset(mapping) 批量赋值 redis.mset({‘name1’: ‘Durant’, ‘name2’: ‘James’}) True
msetnx(mapping) key均不存在时才批量赋值 redis.msetnx({‘name3’: ‘Smith’, ‘name4’: ‘Curry’}) True
incr(name, amount=1) key为name的value增值操作,默认1,key不存在则被创建并设为amount redis.incr(‘age’, 1) 1,即修改后的值
decr(name, amount=1) key为name的value减值操作,默认1,key不存在则被创建并设置为-amount redis.decr(‘age’, 1) -1,即修改后的值
append(key, value) key为name的string的值附加value redis.append(‘nickname’, ‘OK’) 13,即修改后的字符串长度
substr(name, start, end=-1) 返回key为name的string的value的子串 redis.substr(‘name’, 1, 4) b’ello’
getrange(key, start, end) 获取key的value值从start到end的子字符串 redis.getrange(‘name’, 1, 4) b’ello’

Key操作

方法 作用 示例 示例结果
exists(name) 判断一个key是否存在 redis.exists(‘name’) True
delete(name) 删除一个key redis.delete(‘name’) 1
type(name) 判断key类型 redis.type(‘name’) b’string’
keys(pattern) 获取所有符合规则的key redis.keys(‘n*’) [b’name’]
randomkey() 获取随机的一个key randomkey() b’name’
rename(src, dst) 将key重命名 redis.rename(‘name’, ‘nickname’) True
dbsize() 获取当前数据库中key的数目 dbsize() 100
expire(name, time) 设定key的过期时间,单位秒 redis.expire(‘name’, 2) True
ttl(name) 获取key的过期时间,单位秒,-1为永久不过期 redis.ttl(‘name’) -1
move(name, db) 将key移动到其他数据库 move(‘name’, 2) True
flushdb() 删除当前选择数据库中的所有key flushdb() True
flushall() 删除所有数据库中的所有key flushall() True

List操作

方法 作用 示例 示例结果
rpush(name, *values) 在key为name的list尾添加值为value的元素,可以传多个 redis.rpush(‘list’, 1, 2, 3) 3,list大小
lpush(name, *values) 在key为name的list头添加值为value的元素,可以传多个 redis.lpush(‘list’, 0) 4,list大小
llen(name) 返回key为name的list的长度 redis.llen(‘list’) 4
lrange(name, start, end) 返回key为name的list中start至end之间的元素 redis.lrange(‘list’, 1, 3) [b’3’, b’2’, b’1’]
ltrim(name, start, end) 截取key为name的list,保留索引为start到end的内容 ltrim(‘list’, 1, 3) True
lindex(name, index) 返回key为name的list中index位置的元素 redis.lindex(‘list’, 1) b’2’
lset(name, index, value) 给key为name的list中index位置的元素赋值,越界则报错 redis.lset(‘list’, 1, 5) True
lrem(name, count, value) 删除count个key的list中值为value的元素 redis.lrem(‘list’, 2, 3) 1,即删除的个数
lpop(name) 返回并删除key为name的list中的首元素 redis.lpop(‘list’) b’5’
rpop(name) 返回并删除key为name的list中的尾元素 redis.rpop(‘list’) b’2’
blpop(keys, timeout=0) 返回并删除名称为在keys中的list中的首元素,如果list为空,则会一直阻塞等待 redis.blpop(‘list’) [b’5’]
brpop(keys, timeout=0) 返回并删除key为name的list中的尾元素,如果list为空,则会一直阻塞等待 redis.brpop(‘list’) [b’2’]
rpoplpush(src, dst) 返回并删除名称为src的list的尾元素,并将该元素添加到名称为dst的list的头部 redis.rpoplpush(‘list’, ‘list2’) b’2’

Set操作

方法 作用 示例 示例结果
sadd(name, *values) 向key为name的set中添加元素 redis.sadd(‘tags’, ‘Book’, ‘Tea’, ‘Coffee’) 3,即插入的数据个数
srem(name, *values) 从key为name的set中删除元素 redis.srem(‘tags’, ‘Book’) 1,即删除的数据个数
spop(name) 随机返回并删除key为name的set中一个元素 redis.spop(‘tags’) b’Tea’
smove(src, dst, value) 从src对应的set中移除元素并添加到dst对应的set中 redis.smove(‘tags’, ‘tags2’, ‘Coffee’) True
scard(name) 返回key为name的set的元素个数 redis.scard(‘tags’) 3
sismember(name, value) 测试member是否是key为name的set的元素 redis.sismember(‘tags’, ‘Book’) True
sinter(keys, *args) 返回所有给定key的set的交集 redis.sinter([‘tags’, ‘tags2’]) {b’Coffee’}
sinterstore(dest, keys, *args) 求交集并将交集保存到dest的集合 redis.sinterstore(‘inttag’, [‘tags’, ‘tags2’]) 1
sunion(keys, *args) 返回所有给定key的set的并集 redis.sunion([‘tags’, ‘tags2’]) {b’Coffee’, b’Book’, b’Pen’}
sunionstore(dest, keys, *args) 求并集并将并集保存到dest的集合 redis.sunionstore(‘inttag’, [‘tags’, ‘tags2’]) 3
sdiff(keys, *args) 返回所有给定key的set的差集 redis.sdiff([‘tags’, ‘tags2’]) {b’Book’, b’Pen’}
sdiffstore(dest, keys, *args) 求差集并将差集保存到dest的集合 redis.sdiffstore(‘inttag’, [‘tags’, ‘tags2’]) 3
smembers(name) 返回key为name的set的所有元素 redis.smembers(‘tags’) {b’Pen’, b’Book’, b’Coffee’}
srandmember(name) 随机返回key为name的set的一个元素,但不删除元素 redis.srandmember(‘tags’)

Sorted Set操作

方法 作用 示例 示例结果
zadd(name, args, *kwargs) 向key为name的zset中添加元素member,score用于排序。如果该元素存在,则更新其顺序 redis.zadd(‘grade’, 100, ‘Bob’, 98, ‘Mike’) 2,即添加的元素个数
zrem(name, *values) 删除key为name的zset中的元素 redis.zrem(‘grade’, ‘Mike’) 1,即删除的元素个数
zincrby(name, value, amount=1) 如果在key为name的zset中已经存在元素value,则该元素的score增加amount,否则向该集合中添加该元素,其score的值为amount redis.zincrby(‘grade’, ‘Bob’, -2) 98.0,即修改后的值
zrank(name, value) 返回key为name的zset中元素的排名(按score从小到大排序)即下标 redis.zrank(‘grade’, ‘Amy’) 1
zrevrank(name, value) 返回key为name的zset中元素的倒数排名(按score从大到小排序)即下标 redis.zrevrank(‘grade’, ‘Amy’) 2
zrevrange(name, start, end, withscores=False) 返回key为name的zset(按score从大到小排序)中的index从start到end的所有元素 redis.zrevrange(‘grade’, 0, 3) [b’Bob’, b’Mike’, b’Amy’, b’James’]
zrangebyscore(name, min, max, start=None, num=None, withscores=False) 返回key为name的zset中score在给定区间的元素 redis.zrangebyscore(‘grade’, 80, 95) [b’Amy’, b’James’]
zcount(name, min, max) 返回key为name的zset中score在给定区间的数量 redis.zcount(‘grade’, 80, 95) 2
zcard(name) 返回key为name的zset的元素个数 redis.zcard(‘grade’) 3
zremrangebyrank(name, min, max) 删除key为name的zset中排名在给定区间的元素 redis.zremrangebyrank(‘grade’, 0, 0) 1,即删除的元素个数
zremrangebyscore(name, min, max) 删除key为name的zset中score在给定区间的元素 redis.zremrangebyscore(‘grade’, 80, 90) 1,即删除的元素个数

Hash操作

方法 作用 示例 示例结果
hset(name, key, value) 向key为name的hash中添加映射 hset(‘price’, ‘cake’, 5) 1,即添加的映射个数
hsetnx(name, key, value) 向key为name的hash中添加映射,如果映射键名不存在 hsetnx(‘price’, ‘book’, 6) 1,即添加的映射个数
hget(name, key) 返回key为name的hash中field对应的value redis.hget(‘price’, ‘cake’) 5
hmget(name, keys, *args) 返回key为name的hash中各个键对应的value redis.hmget(‘price’, [‘apple’, ‘orange’]) [b’3’, b’7’]
hmset(name, mapping) 向key为name的hash中批量添加映射 redis.hmset(‘price’, {‘banana’: 2, ‘pear’: 6}) True
hincrby(name, key, amount=1) 将key为name的hash中映射的value增加amount redis.hincrby(‘price’, ‘apple’, 3) 6,修改后的值
hexists(name, key) key为namehash中是否存在键名为key的映射 redis.hexists(‘price’, ‘banana’) True
hdel(name, *keys) key为namehash中删除键名为key的映射 redis.hdel(‘price’, ‘banana’) True
hlen(name) 从key为name的hash中获取映射个数 redis.hlen(‘price’) 6
hkeys(name) 从key为name的hash中获取所有映射键名 redis.hkeys(‘price’) [b’cake’, b’book’, b’banana’, b’pear’]
hvals(name) 从key为name的hash中获取所有映射键值 redis.hvals(‘price’) [b’5’, b’6’, b’2’, b’6’]
hgetall(name) 从key为name的hash中获取所有映射键值对 redis.hgetall(‘price’) {b’cake’: b’5’, b’book’: b’6’, b’orange’: b’7’, b’pear’: b’6’}

openmediavault omv3升级omv4

发表于 2018-06-01 | 分类于 问题解决

在升级openmediavault的omv3到omv4的时候出现升级后无法进入界面。

先说一下omv3升级到omv4的流程

1
2
3
4
apt-get update
apt-get upgrade
omv-update
omv-initsystem

注意:在root下

错误1: apt-get update 错误

weakref.py ‘NoneType’ object is not callable

apt-get update升级中遇到升级错误:

1
2
3
4
5
6
7
8
9
10

Traceback (most recent call last):

  File "/usr/lib/python3.5/weakref.py", line 117, in remove

TypeError: 'NoneType' object is not callable

E: Sub-process /usr/bin/dpkg returned an error code (1)

`

在论坛上找到是由于python3.5的bug导致的错误https://forum.openmediavault.org/index.php/Thread/22370-Errors-when-Upgrading-from-OMV-3-0-99-to-OMV-4/

手动修复

1
2
3
4
5
6
7
8

cd /usr/lib/python3.5

nano weakref.py

第109行 def remove(wr, selfref=ref(self)):替换成def remove(wr, selfref=ref(self), _atomic_removal=_remove_dead_weakref):

第117行_remove_dead_weakref(d, wr.key)替换成_atomic_removal(d, wr.key)

错误2:登录界面输入账号密码后无法登录:Failed to connect to socket: No such file or directory

1
错误 #0: OMV\Rpc\Exception: Failed to connect to socket: No such file or directory in /usr/share/php/openmediavault/rpc/rpc.inc:140 Stack trace: #0 /var/www/openmediavault/rpc/session.inc(56): OMV\Rpc\Rpc::call('UserMgmt', 'authUser', Array, Array, 2, true) #1 [internal function]: OMVRpcServiceSession->login(Array, Array) #2 /usr/share/php/openmediavault/rpc/serviceabstract.inc(123): call_user_func_array(Array, Array) #3 /usr/share/php/openmediavault/rpc/rpc.inc(86): OMV\Rpc\ServiceAbstract->callMethod('login', Array, Array) #4 /usr/share/php/openmediavault/rpc/proxy/json.inc(95): OMV\Rpc\Rpc::call('Session', 'login', Array, Array, 3) #5 /var/www/openmediavault/rpc.php(45): OMV\Rpc\Proxy\Json->handle() #6 {main}

查看/var/log/syslog发现有

1
'omv-engined'failedtostart(exitstatus1)--'/bin/systemctl start openmediavault-engined':Failedtostartopenmediavault-engined.service:Unitopenmediavault-engined.serviceismasked.

参考[http://www.mobibrw.com/2017/8741]
(http://www.mobibrw.com/2017/8741)

修复

1
2
3
4
5
6
7
8
9
$ omv-mkconf collectd

$ omv-mkconf rrdcached

$ omv-mkconf monit

$ sudo systemctl unmask openmediavault-engined.service

$ sudo reboot

错误3:登录界面输入账号密码后无法进入后台,又返回登录界面,账号密码是正确的,输入错误密码会报密码错误

查看日志发现有一个明显的错误信息

tail -f /var/log/nginx/openmediavault-webgui_error.log

image.png

/var/lib/php/sessions/ Permission denied

omv4使用的php版本从php5升级到了php7,可能是导致这个问题的原因,给/var/lib/php/sessions/授权即可

1
chmod 777 /var/lib/php/session

终于omv3升级omv4成功,在论坛https://forum.openmediavault.org/发现升级出现问题的还是很多啊。

Linux误操作移动根目录/lib 的血泪恢复

发表于 2018-05-31 | 分类于 linux

Linux 发行版:Debian 9

一不小心执行了一条语句,直接把根目录下的lib目录移动到了/var下面,导致除了cd,pwd的bash外其他ls,cp,mv都不可用,记录一下血泪恢复历程。

mv /lib lib2

执行所有命令

bash: ./ls: No such file or directory

通过参考帖子发现可以通过ld-linux.so.2来执行命令,现在只能通过tab提示查看目录下的文件,找到在/var/lib2/x86_64-linux-gnu下面有ld-linux-x86-64.so.2文件

看名称差不多,执行后感觉有戏,但是按照参考帖子上的说明发现不行

/bin/ls: error while loading shared libraries: libselinux.so.1: cannot open shared object file: No such file or directory

然后注意错误提示说找不到libselinux.so,然后继续查询发现就在/var/lib2/x86_64-linux-gnu/下面有libc.so.6文件,估计就是这个家伙。

终于在执行下面的命令成功了

/var/lib2/x86_64-linux-gnu/ld-linux-x86-64.so.2  --library-path /var/lib2/x86_64-linux-gnu/ /bin/ls

赶紧恢复

/var/lib2/x86_64-linux-gnu/ld-linux-x86-64.so.2  --library-path /var/lib2/x86_64-linux-gnu/ /bin/cp -rfp /var/lib2 /lib

熟悉的ls命令又回来了

linux下命令操作需谨慎啊

参考

https://www.haiwaidao.com/2012/03/06/1603.html

http://blog.51cto.com/sharkyan/771966

https://blog.csdn.net/jiazhen/article/details/3962994

https://wenku.baidu.com/view/a1e72be9b8f67c1cfad6b808.html

12…7
Vcancy

Vcancy

TO BE OR NOT TO BE.

67 日志
15 分类
36 标签
GitHub E-Mail
© 2021 Vcancy
由 Hexo 强力驱动
|
主题 — NexT.Mist v6.0.6