0%

物理备库是可以以只读模式打开的,然后就可以exp数据出来了,注意备库readonly模式打开时,是没有在apply日志的,所有exp出来的数据会少了主库在这段时间更新的数据。

备库端:

1
2
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
SQL> alter database open read only;

然后exp数据库:

1
$ exp ...

最后备库重新开始apply日志就好了:

1
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT FROM SESSION; 

分为两个步骤,首先用新的节点替换宕机的节点,其次把新节点提升为种子节点。

替换故障节点

1、nodetool status命令找到DN节点的ip地址比如192.168.0.82,后面会用到这个ip地址。

2、新节点安装与集群其他节点一样版本的cassandra,然后停止cassandra服务,并清除节点全部数据

1
2
3
4
$ sudo systemctl stop cassandra
//$ sudo kill -sigterm <pid_of_cassandra>
//$ sudo kill -15 <pid_of_cassandra>
$ sudo rm -rf /var/lib/cassandra/*

3、设置参数文件cassandra.yaml和cassandra-rackdc.properties或者 cassandra-topology.properties

auto_bootstrap要设置为true,因为新节点要从种子节点获取数据。
cluster_name设置为要加入的集群的名字
linsten_address和rpc_address设置为本机ip
endpoint_snitch 要与集群其他节点一致,然后修改对应的属性文件
seed_provider只要要提供一个集群中现有的种子节点,但不要将新添加节点的地址加入,因为种子节点并不会bootstrap,等新节点bootstrap完成后再将新节点提升为种子节点。

可以提取集群中其他节点的配置文件,只对应修改新节点独有的参数即可。

4、使用 replace_address 选项启动新节点

修改/etc/cassandra/cassandra-env.sh 文件,添加选项:

1
JVM_OPTS="$JVM_OPTS -Dcassandra.replace_address=192.168.0.82"

这里的ip地址就是上面找到的要被替换的节点ip地址

5、启动新节点

等新节点bootstrap完成后再执行以下步骤,并且需要去掉replace_address选项

6、cassandra-rackdc.properties或cassandra-topology.properties文件中去掉被替换的节点

7、从集群中移除当掉的节点

1
$ nodetool removenode <hostid>

nodetool status命令可以获取到节点的hostid

提升为种子节点

新添加节点bootstrap完成之后,可以提升为种子节点。

1、因为种子节点不能bootstrap,所以需要将其cassandra.yaml文件中的auto_bootstrap参数设置为false
2、在集群所有节点执行以下操作:
将cassandra.yaml配置文件中的种子列表中去掉被替换的节点,将新添加节点的地址加入种子列表,然后重启节点。
注意不要并行操作,最好一个节点接一个节点的逐一操作。

References:
[1]Replacing a dead node or dead seed node
[2]Replace a Dead Node in a Scylla Cluster
[3]Replacing a dead seed node
[4]nodetool removenode

v3700从服务界面新建系统时,提示:

CMMVC8020E: 存在存储集群标识时尝试创建集群

无法创建新系统,是因为以前的集群信息尚未完全清除干净,在机柜配置界面重置集群标识,再次尝试新建系统成功。

如果还是不行,可以尝试[1]里面讲的方法,ssh登录进存储,执行以下命令:

1
satask chenclosurevpd -resetclusterid

没有尝试,或许可以。

References:
[1][SOLVED] Storwize v3700: CMMVC8020E

已经创建的容器可以通过一定的方法更改为使用其他的存储池/存储后端

本机

本机有两个存储池,分别使用btrfs和zfs

1
2
3
4
5
6
7
8
$ lxc storage list
+---------+-------------+--------+--------------------------------------------+---------+
NAME DESCRIPTION DRIVER SOURCE USED BY
+---------+-------------+--------+--------------------------------------------+---------+
default btrfs /var/snap/lxd/common/lxd/disks/default.img 1
+---------+-------------+--------+--------------------------------------------+---------+
lxd_zfs zfs /var/snap/lxd/common/lxd/disks/lxd_zfs.img 2
+---------+-------------+--------+--------------------------------------------+---------+

使用btrfs存储池新建一个alpine容器

1
2
$ lxc init images:alpine/3.10/amd64 alp -s default
$ lxc storage show default

可以看到alp容器使用default存储池,也就是btrfs后端。

然后通过将容器发布为image,使用image创建新容器的方式使新的alp容器使用lxd_zfs存储后端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ lxc publish -f alp --alias alp_img
$ lxc delete alp
$ lxc init alp_img alp -s lxd_zfs
$ lxc image delete alp_img
$ lxc storage show lxd_zfs
config:
size: 15GB
source: /var/snap/lxd/common/lxd/disks/lxd_zfs.img
zfs.pool_name: lxd_zfs
description: ""
name: lxd_zfs
driver: zfs
used_by:
- /1.0/containers/alp
- /1.0/profiles/default
status: Created
locations:
- none

可以看到容器alp使用zfs后端存储,其实这是一个全新的容器,不过使用image做了一下中转。

异机

在目标服务器上新建zfs存储池和profile

1
2
3
4
5
6
7
8
9
10
11
12
13
$ lxc storage create lxd_zfs zfs
$ lxc profile create storage_zfs
$ lxc profile device add storage_zfs root disk path=/ pool=lxd_zfs
$ lxc profile show storage_zfs
config: {}
description: ""
devices:
root:
path: /
pool: lxd_zfs
type: disk
name: storage_zfs
used_by: \[\]

这样在向目标服务器上copy/move容器时,指定storage_zfs profile就可以了。

1
$ lxc copy container1 remotesvr1: -p storage_zfs

lxd支持btrfs,zfs,lvm和ceph存储后端,默认使用btrfs,但在线迁移容器的时候btrfs总是不成功,可以尝试更换到zfs存储后端,zfsonlinux项目已经十分成熟。

安装

buster发布后,debian-backports已经启用了,为了安装更新版本的zfs,最好添加这个源:
/etc/apt/source.list

1
2
# backports
deb http://ftp.cn.debian.org/debian buster-backports main contrib non-free

/etc/apt/preferences.d/90_zfs

1
2
3
Package: libnvpair1linux libuutil1linux libzfs2linux libzpool2linux spl-dkms zfs-dkms zfs-test zfsutils-linux zfsutils-linux-dev zfs-zed
Pin: release n=buster-backports
Pin-Priority: 990

因为需要编译内核模块,先安装内核头文件

1
2
# apt update
# apt install linux-headers-$(uname -r) linux-image-amd64

安装zfsonlinux

1
# apt install zfs-dkms zfsutils-linux

安装到最后会有一些错误提示,不要害怕,那是因为还没有加载zfs内核模块

加载内核模块

1
# modprobe zfs

然后重新执行上一个安装命令,zfs就会配置成功了。

系统自动加载内核模块

1
# echo "zfs" >> /etc/modules

如果安装zfs之前已经安装了lxd,那么需要将lxd daemon重启一下,否则lxd会报错:

1
Error: The "zfs" tool is not enabled

重启lxd daemon

1
$ sudo systemctl reload snap.lxd.daemon

存储池

lxd init的时候就可以选择ZFS作为存储后端来新建default storage pool了,默认会使用当前文件系统内的文件来虚拟一个zfs文件系统,也可以使用真实的zfs文件系统来建立存储池。

也可以使用lxc storage create命令来创建新的使用zfs作为存储后端的存储池。
创建zfs存储池lxd_zfs

1
$ lxc storage create lxd_zfs zfs size=100GB

将默认配置的存储池设置为lxd_zfs,前提是没有容器在使用default profile的root disk设备。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ lxc profile device remove default root
$ lxc profile device add default root disk path=/ pool=lxd_zfs
$ lxc profile show default
config: {}
description: Default LXD profile
devices:
eth0:
name: eth0
nictype: bridged
parent: lxdbr0
type: nic
root:
path: /
pool: lxd_zfs
type: disk
name: default
used_by: \[\]

后面再新建容器就会自动使用zfs存储池lxd_zfs了。
也可以将default存储池删除掉,重现创建一个default存储池,只要default存储池没有被镜像、容器或profile使用即可。
其实default就是一个名字而已,与其他存储池并无任何不同。

References:
[1]Setup a ZFS pool for your LXC containers with LXD
[2]zfsonlinux
[3]debian

wine会将大部分的linux环境变量直接传递给windows程序,但是PATH, SYSTEM和TEMP这几个变量除外,主要还是因为冲突,这些变量需要在windows registry中设置。

js$ wine regedit

打开注册表编辑器,然后在HKEY_CURRENT_USER/Environment下添加或修改PATH等变量就可以了,比如设置PATH为以下值:

jsc:\\windows;c:\\windows\\system32;c:\\Program Files (x86)\\Mozilla Firefox

然后运行程序时就无需指定繁琐的全路径了,比如

js$ wine firefox

就可以运行firefox了。

另外,macosx下每次运行wine都需要打开app,其实只要在.bashrc中添加几个环境变量就可以在terminal下直接使用wine了

1
2
3
4
export PATH="/Applications/Wine Devel.app/Contents/Resources/wine/bin:$PATH"
#export PATH="/Applications/Wine Stable.app/Contents/Resources/wine/bin:$PATH"
export FREETYPE_PROPERTIES="truetype:interpreter-version=35"
export DYLD_FALLBACK_LIBRARY_PATH="/usr/lib:/opt/X11/lib:$DYLD_FALLBACK_LIBRARY_PATH"

References:
[1]3.6.6 Setting Windows/DOS environment variables

因为使用默认的compaction策略SizeTieredCompactionStrategy,导致产生了几个巨大的sstable,虽然已经更改为了LeveledCompactionStrategy策略,但是cassadra自动进行major compaction的时候因为需要巨大的空闲存储空间出错了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
WARN \[CompactionExecutor:6\] 2019-07-31 16:32:15,726 CompactionTask.java:298 - Not enough space for compaction, estimated sstables = 8643, expected write size = 2320284556243
ERROR \[CompactionExecutor:6\] 2019-07-31 16:32:15,727 CassandraDaemon.java:195 - Exception in thread Thread\[CompactionExecutor:6,1,main\]
java.lang.RuntimeException: Not enough space for compaction, estimated sstables = 8643, expected write size = 2320284556243
at org.apache.cassandra.db.compaction.CompactionTask.checkAvailableDiskSpace(CompactionTask.java:299) ~\[apache-cassandra-2.2.14.jar:2.2.14\]
at org.apache.cassandra.db.compaction.CompactionTask.runMayThrow(CompactionTask.java:119) ~\[apache-cassandra-2.2.14.jar:2.2.14\]
at org.apache.cassandra.utils.WrappedRunnable.run(WrappedRunnable.java:28) ~\[apache-cassandra-2.2.14.jar:2.2.14\]
at org.apache.cassandra.db.compaction.CompactionTask.executeInternal(CompactionTask.java:74) ~\[apache-cassandra-2.2.14.jar:2.2.14\]
at org.apache.cassandra.db.compaction.AbstractCompactionTask.execute(AbstractCompactionTask.java:59) ~\[apache-cassandra-2.2.14.jar:2.2.14\]
at org.apache.cassandra.db.compaction.CompactionManager$BackgroundCompactionCandidate.run(CompactionManager.java:257) ~\[apache-cassandra-2.2.14.jar:2.2.14\]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~\[na:1.8.0_211\]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~\[na:1.8.0_211\]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~\[na:1.8.0_211\]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) \[na:1.8.0_211\]
at java.lang.Thread.run(Thread.java:748) \[na:1.8.0_211\]

所有可以借助离线工具sstablesplit拆分大的sstables,拆分后使用LCS策略进行compaction就不需要那么多的空闲磁盘空间了。

安装

1
$ sudo apt install cassandra-tools

cassandra-tools包中包含sstablesplit和sstablemeta等工具

停止cassandra

要注意,拆分sstable一定要在离线状态下进行

1
$ sudo systemctl stop cassandra

或者

1
$ sudo kill -sigterm <pid_of_cassandra>

拆分

sstablesplit帮助信息

1
2
3
4
5
6
7
8
9
10
11
$ sstablesplit -h
usage: sstablesplit \[options\] <filename> \[<filename>\]*
--
Split the provided sstables files in sstables of maximum provided filesize (see option --size).
--
Options are:
--debug display stack traces
-h,--help display this help message
--no-snapshot don't snapshot the sstables before splitting
-s,--size <size> maximum size in MB for the output sstables (default:
50)

sstablesplit按给定的文件尺寸拆分指定的sstables,可以一次指定多个。注意文件权限的问题,使用cassandra用户来执行操作,下面是一个例子,:

1
$ sudo -u cassandra sstablesplit -s 256 /var/lib/cassandra/data/keyspace/table-xxxx/la-xxxx-big-Data.db

拆分完成后cassandra可以重新上线。

sstablesplit设定的默认堆内存只有256M,拆分过程中出现了OOM错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
at java.nio.Bits.reserveMemory(Bits.java:694)
at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123)
at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)
at org.apache.cassandra.io.compress.BufferType$2.allocate(BufferType.java:35)
at org.apache.cassandra.io.compress.CompressedSequentialWriter.<init>(CompressedSequentialWriter.java:70)
at org.apache.cassandra.io.util.SequentialWriter.open(SequentialWriter.java:168)
at org.apache.cassandra.io.sstable.format.big.BigTableWriter.<init>(BigTableWriter.java:75)
at org.apache.cassandra.io.sstable.format.big.BigFormat$WriterFactory.open(BigFormat.java:107)
at org.apache.cassandra.io.sstable.format.SSTableWriter.create(SSTableWriter.java:84)
at org.apache.cassandra.db.compaction.writers.MaxSSTableSizeWriter.append(MaxSSTableSizeWriter.java:83)
at org.apache.cassandra.db.compaction.CompactionTask.runMayThrow(CompactionTask.java:186)
at org.apache.cassandra.utils.WrappedRunnable.run(WrappedRunnable.java:28)
at org.apache.cassandra.db.compaction.CompactionTask.executeInternal(CompactionTask.java:74)
at org.apache.cassandra.db.compaction.AbstractCompactionTask.execute(AbstractCompactionTask.java:59)
at org.apache.cassandra.db.compaction.SSTableSplitter.split(SSTableSplitter.java:44)
at org.apache.cassandra.tools.StandaloneSplitter.main(StandaloneSplitter.java:156)

修改/usr/bin/sstablesplit脚本中的MAX_HEAP_SIZE="256M"MAX_HEAP_SIZE="8192M",重启一下cassandra会自动清除掉临时的sstables,nodetool clearsnapshot清除掉sstablesplit自动生成的快照,最后停止cassandra再重新拆分。

删除再repair

拆分大sstable需要离线操作,重新上线后应该需要repair,其实还有一种最小离线时间的方法,那就是”停止节点->删除大sstable->启动节点->repair节点”,这也是一种可行的方法。

References:
[1]sstablesplit
[2]FAQ - How to split large SSTables on another server
[3]do sstablesplit on the side

使用git和ssh搭建一个私有的小型git服务器

安装

1
# apt install git openssh-server

创建用户

使用git用户来运行git服务

1
# adduser git

添加用户公钥

把所有用户的公钥导入到/home/git/.ssh/authorized_keys文件里,一个公钥独占一行。

初始化仓库

1
2
# su - git
$ git init --bare test.git

克隆仓库

1
$ git clone git@server:test

禁止git用户登录

将git用户的shell修改为/usr/bin/git-shell

1
# usermod --shell=/usr/bin/git-shell git

或者直接修改/etc/passwd文件

nginx社区版仅支持十分有限的upstream健康检查,其他高级特性需要商业订阅。
github上有个开源的upstream检查模块nginx_upstream_check_module

安装

安装必要的编译环境

1
$ sudo apt install build-essential patch libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl1.1 libssl-dev

下载最新的nginx stable 1.16 1.22版本,clone nginx_upstream_check_module master分支

1
2
3
//$ wget http://nginx.org/download/nginx-1.16.1.tar.gz
$ wget https://nginx.org/download/nginx-1.22.0.tar.gz
$ git clone https://github.com/yaoweibin/nginx_upstream_check_module

为源码打补丁

1
2
3
4
5
6
//$ tar zxvf nginx-1.16.1.tar.gz
//$ cd nginx-1.16.1/
//$ patch -p1 < ../nginx_upstream_check_module/check_1.14.0+.patch
$ tar zxvf nginx-1.22.0.tar.gz
$ cd nginx-1.22.0/
$ patch -p1 < ../nginx_upstream_check_module/check_1.20.1+.patch

配置、编译、安装nginx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ ./configure --add-module=../nginx_upstream_check_module --with-http_ssl_module --with-stream_ssl_preread_module --with-http_v2_module --with-stream
...
Configuration summary
+ using system PCRE library
+ using system OpenSSL library
+ using system zlib library

nginx path prefix: "/usr/local/nginx"
nginx binary file: "/usr/local/nginx/sbin/nginx"
nginx modules path: "/usr/local/nginx/modules"
nginx configuration prefix: "/usr/local/nginx/conf"
nginx configuration file: "/usr/local/nginx/conf/nginx.conf"
nginx pid file: "/usr/local/nginx/logs/nginx.pid"
nginx error log file: "/usr/local/nginx/logs/error.log"
nginx http access log file: "/usr/local/nginx/logs/access.log"
nginx http client request body temporary files: "client_body_temp"
nginx http proxy temporary files: "proxy_temp"
nginx http fastcgi temporary files: "fastcgi_temp"
nginx http uwsgi temporary files: "uwsgi_temp"
nginx http scgi temporary files: "scgi_temp"
$ make
$ sudo make install

安装目录位于/usr/local/nginx

添加systemd服务nginx.service
将以下内容的文件nginx.service添加到/lib/systemd/system/nginx.service

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
# Stop dance for nginx
# =======================
#
# ExecStop sends SIGSTOP (graceful stop) to the nginx process.
# If, after 5s (--retry QUIT/5) nginx is still running, systemd takes control
# and sends SIGTERM (fast shutdown) to the main process.
# After another 5s (TimeoutStopSec=5), and if nginx is alive, systemd sends
# SIGKILL to all the remaining processes in the process group (KillMode=mixed).
#
# nginx signals reference doc:
# http://nginx.org/en/docs/control.html
#
[Unit]
Description=A high performance web server and a reverse proxy server
Documentation=man:nginx(8)
After=network.target nss-lookup.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/local/nginx/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/local/nginx/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
TimeoutStopSec=5
KillMode=mixed

[Install]
WantedBy=multi-user.target

enable服务并启动

1
2
3
$ sudo systemctl enable nginx.service 
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /lib/systemd/system/nginx.service.
$ sudo systemctl start nginx.service

健康检查配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
http {
upstream cluser {
server 192.168.0.17:8080;
server 192.168.0.18:8080;
server 192.168.0.19:8080;

check interval=1000 fall=1 rise=2 timeout=1000 default_down=true type=http;
check_http_send "HEAD /aurl/ HTTP/1.0\\r\\n\\r\\n";
}

server {
listen 80;
server_name localhost;

location /aurl/ {
proxy_pass http://cluser/aurl/;
}

location /status {
check_status;
}
}
}

设置的检查间隔为1000毫秒,一次没有响应就标记节点down(fall)了,接连两次检查有响应节点才算up(rise),没有检查之前节点的默认状态为down,使用http方式检查,检查的超时时间为1000毫秒,总之1000毫秒没有应答就是无响应。

使用_http方式_检查upstream服务的_业务入口/aurl/_是否已经就绪

upstream状态

访问http://your_ip/status查看检查结果
Nginx http upstream check status
Check upstream server number: 3, generation: 1

Index Upstream Name Status Rise counts Fall counts Check type Check port
0 cluser 192.168.0.17:8080 up 30 0 http 0
1 cluser 192.168.0.18:8080 up 19 0 http 0
2 cluser 192.168.0.19:8080 up 15 0 http 0

References:

[1]Health checks upstreams for nginx

[2]HTTP Health Checks

拿到配置文件就可以破译管理员密码了,只是base64编码了一下下,秒解码。
有两种方法可以拿到配置文件

telnet方法

用光猫后面提供的user密码登录,然后访问http://192.168.1.1/servmngr.html,界面几乎是全白的,选择一下就可以看到大部分内容了,启用telnet并设置为在LAN网络监听,默认账号密码是admin/admin,可以修改,然后

1
2
3
$ telnet 192.168.1.1
> help
> dumpcfg

找到

1
2
3
4
<Web>
<UserPassword>NXB1c2RmbTQA</UserPassword>
<AdminPassword>Y3VhZG1pbxxxxxxNTgwAA==</AdminPassword>
</Web>

这一段,UserPassword就是光猫后面印刷的user账户的密码,AdminPassword就是管理员的密码了,都是base64编码的,随便找个在线服务解码一下好了。

telnet模式还可以执行sh获的shell,可以慢慢研究一下,跑的就是个linux系统

1
2
3
4
5
6
> sh
BusyBox v1.17.2 (2018-09-04 20:22:42 CST) built-in shell (ash)
Enter 'help' for a list of built-in commands.

# uname -a
Linux (none) 3.4.11-rt19 #1 SMP PREEMPT Tue Sep 4 18:24:42 CST 2018 mips GNU/Linux

获得是特权shell,切记不要乱删东西。

工程账号方法

访问http://192.168.1.1/logoffaccount.html,隐藏账户选择“启用”,"保存/应用"之后,跳转到http://192.168.1.1/logoffaccount.cmd?enableFactoryAccount=1,在此界面下输入工厂账号的密码“hg2x0”进入工厂模式

然后访问http://192.168.1.1/backupsettings.html页面,点击“保存/应用”下载当前配置文件到本地电脑,后面就和第一个方法一样了。

桥接模式

访问http://192.168.1.1/cu.html页面,使用管理员账户登录光猫,"基本配置"->"宽带配置"界面选择“*_INTERNET_R_VID_*”这个连接名称,改为桥接就好了,比修改配置文件上传的方式简单不易出错。

据说user用户登录后,直接访问http://192.168.1.1/fbctwanconfig.html也可以修改桥接模式,能看到配置界面,没有尝试。

References:
[1]上海联通光猫烽火HG2201U改桥接,路由拨号上网并做解析
[2]烽火HG2201U 5.0/5.01 版本 光猫改桥接 设置IPV6 超级管理员获取