还没想好用什么标题

0%

网络是服务器连接外面世界的通道, 即使是内网, 也需要配置好网络
遇到一台服务器好像dns被污染了, 解析的movie.douban.com的ip地址不正确, 而其他都没有问题

以下记录排查网络问题的几个方面

是否可以联网

首先需要查看网络是否连通
可以通过ping网关的形式判断网络是否可以连通外界
如果无法ping通, 通过ip addr 查看ip地址是否配置
ip addr add 192.168.86.111/24 dev eth0 #给eth0网卡配置ip
同时可能需要指定网关地址

启动网卡

有种可能是网卡现在已经配置ip 但是没有启动
ip link set eth0 up #启动网卡

添加dns

可以ping通网关, 无法ping通域名
ping www.baidu.com
这是由于没有配置dns的问题
编辑/etc/resolv.conf文件
添加 servername 114.114.114.114 #附录列出常用dns

添加路由

可能的情况还有没有配置路由信息
ip route add default gw 192.168.86.1

持久化配置

以上都是临时使用时配置的, 如想开机自动配置, 最简单的是查看局域网有没有dhcp服务器,直接使用dhcp可以方便的上网了
手动设置需要更改配置文件, 一般是在/etc/network/interface, 需要的信息由网络管理员之前提供

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
address 192.168.86.111
netmask 255.255.255.0
network 192.168.86.0
broadcast 192.168.86.255
gateway 192.168.86.1
# dns-* options are implemented by the resolvconf package, if installed
dns-nameservers 114.114.114.114

up route add-net 10.10.10.10 netmask 255.255.255.255 gw 192.168.86.110 eth0

查询dns可以使用以下两个命令

nslookup

其中server可以指定需要的dns服务器, 默认是本机的dns服务器

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
nslookup
> www.baidu.com
Server: 192.168.75.14
Address: 192.168.75.14#53

Non-authoritative answer:
www.baidu.com canonical name = www.a.shifen.com.
Name: www.a.shifen.com
Address: 115.239.210.27
Name: www.a.shifen.com
Address: 115.239.211.112
>
> server 114.114.114.114
Default server: 114.114.114.114
Address: 114.114.114.114#53
> www.baidu.com
Server: 114.114.114.114
Address: 114.114.114.114#53

Non-authoritative answer:
www.baidu.com canonical name = www.a.shifen.com.
Name: www.a.shifen.com
Address: 115.239.211.112
Name: www.a.shifen.com
Address: 115.239.210.27
>
> server 223.5.5.5
Default server: 223.5.5.5
Address: 223.5.5.5#53
> www.baidu.com
Server: 223.5.5.5
Address: 223.5.5.5#53

Non-authoritative answer:
www.baidu.com canonical name = www.a.shifen.com.
Name: www.a.shifen.com
Address: 115.239.210.27
Name: www.a.shifen.com
Address: 115.239.211.112
>

dig

dig命令功能更加强大
可以通过 +trace 来追踪路由解析
示例使用www.baidu.com, 百度应该是使用了cdn, 解析的结果可能比较难理解

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
dig www.baidu.com @114.114.114.114 A +trace

; <<>> DiG 9.8.1-P1 <<>> www.baidu.com @114.114.114.114 A +trace
;; global options: +cmd
. 302116 IN NS k.root-servers.net.
. 302116 IN NS h.root-servers.net.
. 302116 IN NS f.root-servers.net.
. 302116 IN NS m.root-servers.net.
. 302116 IN NS c.root-servers.net.
. 302116 IN NS e.root-servers.net.
. 302116 IN NS j.root-servers.net.
. 302116 IN NS a.root-servers.net.
. 302116 IN NS l.root-servers.net.
. 302116 IN NS g.root-servers.net.
. 302116 IN NS i.root-servers.net.
. 302116 IN NS b.root-servers.net.
. 302116 IN NS d.root-servers.net.
;; Received 228 bytes from 114.114.114.114#53(114.114.114.114) in 36 ms

com. 172800 IN NS a.gtld-servers.net.
com. 172800 IN NS b.gtld-servers.net.
com. 172800 IN NS c.gtld-servers.net.
com. 172800 IN NS d.gtld-servers.net.
com. 172800 IN NS e.gtld-servers.net.
com. 172800 IN NS f.gtld-servers.net.
com. 172800 IN NS g.gtld-servers.net.
com. 172800 IN NS h.gtld-servers.net.
com. 172800 IN NS i.gtld-servers.net.
com. 172800 IN NS j.gtld-servers.net.
com. 172800 IN NS k.gtld-servers.net.
com. 172800 IN NS l.gtld-servers.net.
com. 172800 IN NS m.gtld-servers.net.
;; Received 491 bytes from 199.7.83.42#53(199.7.83.42) in 320 ms

baidu.com. 172800 IN NS dns.baidu.com.
baidu.com. 172800 IN NS ns2.baidu.com.
baidu.com. 172800 IN NS ns3.baidu.com.
baidu.com. 172800 IN NS ns4.baidu.com.
baidu.com. 172800 IN NS ns7.baidu.com.
;; Received 201 bytes from 192.54.112.30#53(192.54.112.30) in 200 ms

www.baidu.com. 1200 IN CNAME www.a.shifen.com.
a.shifen.com. 1200 IN NS ns5.a.shifen.com.
a.shifen.com. 1200 IN NS ns1.a.shifen.com.
a.shifen.com. 1200 IN NS ns3.a.shifen.com.
a.shifen.com. 1200 IN NS ns4.a.shifen.com.
a.shifen.com. 1200 IN NS ns2.a.shifen.com.
;; Received 228 bytes from 220.181.38.10#53(220.181.38.10) in 23 ms

附录: dns列表

数据来源: http://www.ip.cn/dns.html

公共 DNS 服务器 IP 地址

名称 DNS 服务器 IP 地址
114 DNS 114.114.114.114 114.114.115.115
阿里 AliDNS 223.5.5.5 223.6.6.6
百度 BaiduDNS 180.76.76.76
DNSPod DNS+ 119.29.29.29 182.254.116.116
CNNIC SDNS 1.2.4.8 210.2.4.8
oneDNS 112.124.47.27 114.215.126.16
DNS 派
电信/移动/铁通
101.226.4.6 218.30.118.6
DNS 派 联通 123.125.81.6 140.207.198.6
Google DNS 8.8.8.8 8.8.4.4
OpenDNS 208.67.222.222 208.67.220.220
V2EX DNS 199.91.73.222 178.79.131.110

全国各地电信 DNS 服务器 IP 地址

名称 DNS 服务器 IP 地址
安徽电信 DNS 61.132.163.68 202.102.213.68
北京电信 DNS 219.141.136.10 219.141.140.10
重庆电信 DNS 61.128.192.68 61.128.128.68
福建电信 DNS 218.85.152.99 218.85.157.99
甘肃电信 DNS 202.100.64.68 61.178.0.93
广东电信 DNS 202.96.128.86 202.96.128.166
202.96.134.33 202.96.128.68
广西电信 DNS 202.103.225.68 202.103.224.68
贵州电信 DNS 202.98.192.67 202.98.198.167
河南电信 DNS 222.88.88.88 222.85.85.85
黑龙江电信 219.147.198.230 219.147.198.242
湖北电信 DNS 202.103.24.68 202.103.0.68
湖南电信 DNS 222.246.129.80 59.51.78.211
江苏电信 DNS 218.2.2.2 218.4.4.4
61.147.37.1 218.2.135.1
江西电信 DNS 202.101.224.69 202.101.226.68
内蒙古电信 219.148.162.31 222.74.39.50
山东电信 DNS 219.146.1.66 219.147.1.66
陕西电信 DNS 218.30.19.40 61.134.1.4
上海电信 DNS 202.96.209.133 116.228.111.118
202.96.209.5 108.168.255.118
四川电信 DNS 61.139.2.69 218.6.200.139
天津电信 DNS 219.150.32.132 219.146.0.132
云南电信 DNS 222.172.200.68 61.166.150.123
浙江电信 DNS 202.101.172.35 61.153.177.196
61.153.81.75 60.191.244.5

全国各地联通 DNS 服务器 IP 地址

名称 DNS 服务器 IP 地址
北京联通 DNS 202.106.196.115 202.106.46.151
202.106.0.20 202.106.195.68
重庆联通 DNS 221.5.203.98 221.7.92.98
广东联通 DNS 210.21.196.6 221.5.88.88
河北联通 DNS 202.99.160.68 202.99.166.4
河南联通 DNS 202.102.224.68 202.102.227.68
黑龙江联通 202.97.224.69 202.97.224.68
吉林联通 DNS 202.98.0.68 202.98.5.68
江苏联通 DNS 221.6.4.66 221.6.4.67
内蒙古联通 202.99.224.68 202.99.224.8
山东联通 DNS 202.102.128.68 202.102.152.3
202.102.134.68 202.102.154.3
山西联通 DNS 202.99.192.66 202.99.192.68
陕西联通 DNS 221.11.1.67 221.11.1.68
上海联通 DNS 210.22.70.3 210.22.84.3
四川联通 DNS 119.6.6.6 124.161.87.155
天津联通 DNS 202.99.104.68 202.99.96.68
浙江联通 DNS 221.12.1.227 221.12.33.227
辽宁联通 DNS 202.96.69.38 202.96.64.68

全国各地移动 DNS 服务器 IP 地址

名称 DNS 服务器 IP 地址
江苏移动 DNS 221.131.143.69 112.4.0.55
安徽移动 DNS 211.138.180.2 211.138.180.3
山东移动 DNS 218.201.96.130 211.137.191.26

Apple TV DNS 服务器 IP 地址

名称 DNS 服务器 IP 地址
上海电信 180.153.225.136
杭州电信 115.29.189.118
广东电信 203.195.182.150
北方联通 118.244.224.124

logstash收集日志时,日志部分是由google的protobuf工具打印的,直接利用json解析会造成部分无法解析的问题
搜索后发现有个logstash的protobuf插件

在logstash中添加protobuf

首先需要下载一个用于解码protobuf的插件,

安装插件

从rubygems下载gemfile。在Logstash目录中,执行以下命令:

1
bin/plugin install PATH_TO_DOWNLOADED FILE

创建protobuf定义的Ruby脚本

示例下面的unicorn.pb是您要解码消息的现有protobuf定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package Animal;

message Unicorn {

// colour of unicorn
optional string colour = 1;

// horn length
optional int32 horn_length = 2;

// unix timestamp for last observation
optional int64 last_seen = 3;

}

需要下载uby-protocol编译器。然后运行

1
ruby-protoc unicorn.pb

编译器将创建一个扩展名为.rb的新文件,如unicorn.rb.pb。它包含一个Ruby版本的定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/env ruby
# Generated by the protocol buffer compiler. DO NOT EDIT!

require 'protocol_buffers'

module Animal
# forward declarations
class Unicorn < ::ProtocolBuffers::Message; end

class Unicorn < ::ProtocolBuffers::Message
set_fully_qualified_name "animal.Unicorn"

optional :string, :colour, 1
optional :int32, :horn_length, 2
optional :int64, :last_seen, 3
end

end

现在,需要通过在配置中提供其位置来使该文件已知到Logstash。

Logstash配置

可以在Logstash的任何输入源中使用编解码器。在这个例子中,我们将使用Kafka作为数据源。用于读取protobuf类Unicorn消息的配置如下所示:

1
2
3
4
5
6
7
8
9
10
kafka 
{
zk_connect => "127.0.0.1"
topic_id => "unicorns_protobuffed"
codec => protobuf
{
class_name => "Animal::Unicorn"
include_path => ['/path/to/compiled/protobuf/definitions/unicorn.pb.rb']
}
}

在GitHub的文档中可以找到一个更复杂的例子。

这是一个官方给出的实例文件, 将这个配置直接应用到我处理的日志还是有点问题,还需要更改

# 对于系统里面设置的开机启动程序

先来看一个例子nginx启动脚本

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
#!/bin/sh

### BEGIN INIT INFO
# Provides: nginx
# Required-Start: $local_fs $remote_fs $network $syslog
# Required-Stop: $local_fs $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts the nginx web server
# Description: starts nginx using start-stop-daemon
### END INIT INFO

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/sbin/nginx
NAME=nginx
DESC=nginx

# Include nginx defaults if available
if [ -f /etc/default/nginx ]; then
. /etc/default/nginx
fi

test -x $DAEMON || exit 0

set -e

. /lib/lsb/init-functions

test_nginx_config() {
if $DAEMON -t $DAEMON_OPTS >/dev/null 2>&1; then
return 0
else
$DAEMON -t $DAEMON_OPTS
return $?
fi
}

case "$1" in
start)
echo -n "Starting $DESC: "
test_nginx_config
# Check if the ULIMIT is set in /etc/default/nginx
if [ -n "$ULIMIT" ]; then
# Set the ulimits
ulimit $ULIMIT
fi
start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \
--exec $DAEMON -- $DAEMON_OPTS || true
echo "$NAME."
;;

stop)
echo -n "Stopping $DESC: "
start-stop-daemon --stop --quiet --pidfile /var/run/$NAME.pid \
--exec $DAEMON || true
echo "$NAME."
;;

restart|force-reload)
echo -n "Restarting $DESC: "
start-stop-daemon --stop --quiet --pidfile \
/var/run/$NAME.pid --exec $DAEMON || true
sleep 1
test_nginx_config
start-stop-daemon --start --quiet --pidfile \
/var/run/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS || true
echo "$NAME."
;;

reload)
echo -n "Reloading $DESC configuration: "
test_nginx_config
start-stop-daemon --stop --signal HUP --quiet --pidfile /var/run/$NAME.pid \
--exec $DAEMON || true
echo "$NAME."
;;

configtest|testconfig)
echo -n "Testing $DESC configuration: "
if test_nginx_config; then
echo "$NAME."
else
exit $?
fi
;;

status)
status_of_proc -p /var/run/$NAME.pid "$DAEMON" nginx && exit 0 || exit $?
;;
*)
echo "Usage: $NAME {start|stop|restart|reload|force-reload|status|configtest}" >&2
exit 1
;;
esac

exit 0

如果我们需要按照系统里面的格式创建文件我们可以使用sudo update-rc.d minidlna defaults来将程序加到默认的启动程序里面, 在/etc/rcx.d里面将创建软连接
如果遇到如下提示System start/stop links for /etc/init.d/minidlna already exist.说明这个文件已经存在,我们可以直接使用这个命令更新下sudo update-rc.d minidlna enable

使用rc.local 实现开机启动

查看/etc/rcx.d文件夹里面的文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
root@Test1:/tmp/nginx# ls -l /etc/rc3.d/
total 4
-rw-r--r-- 1 root root 677 Jul 27 2012 README
lrwxrwxrwx 1 root root 17 Sep 23 2016 S10vboxadd -> ../init.d/vboxadd
lrwxrwxrwx 1 root root 27 Sep 23 2016 S20nfs-kernel-server -> ../init.d/nfs-kernel-server
lrwxrwxrwx 1 root root 21 Sep 23 2016 S30vboxadd-x11 -> ../init.d/vboxadd-x11
lrwxrwxrwx 1 root root 25 Sep 23 2016 S35vboxadd-service -> ../init.d/vboxadd-service
lrwxrwxrwx 1 root root 15 Sep 23 2016 S50rsync -> ../init.d/rsync
lrwxrwxrwx 1 root root 19 Sep 23 2016 S70dns-clean -> ../init.d/dns-clean
lrwxrwxrwx 1 root root 18 Sep 23 2016 S70pppd-dns -> ../init.d/pppd-dns
lrwxrwxrwx 1 root root 14 Sep 23 2016 S75sudo -> ../init.d/sudo
lrwxrwxrwx 1 root root 21 Sep 23 2016 S99grub-common -> ../init.d/grub-common
lrwxrwxrwx 1 root root 18 Sep 23 2016 S99ondemand -> ../init.d/ondemand
lrwxrwxrwx 1 root root 18 Sep 23 2016 S99rc.local -> ../init.d/rc.local

可以看到这些都是链接文件,指向/etc/init.d文件夹
这里的S开头的文件代表开机启动,后两位数字越小越先执行, 还有一个是K开头的文件代表进入改运行级别时关闭程序,后两位数字越小越先执行
注意最后一个文件S99rc.local,在各个运行基本都有,这是开机过程中最后运行的程序,可以将需要开机运行的程序写到这里面vim /etc/rc.local

示例:开机时添加一条iptables规则

1
2
sh /home/ivan/iptables.sh 
echo 'Iptable Configured!'

同时注意需要确保你需要执行的程序写在 exit 0的前面, 写在之后将不起作用

使用定时任务crontab来曲线实现开机启动

这里以crontab重启时执行命令为例,通过crontab -e编辑自己的cron @reboot /path/to/script这将在重启时运行.

使用upstart的开机启动

upstart开机将会运行所有/etc/init目录下的脚本(以.conf结尾的文件),这些程序将以root身份运行
同时upstart提供了~/.config/upstart文件,当用户登陆时运行

一些桌面环境提供的自动运行

gnome和kde这些桌面程序也提供自动启动程序,可以直接使用图形化设置,也可以直接编辑配置文件

上次hadoop集群一块数据盘报警, 提交工单后维修人员更换硬盘
服务器是dell r720的, 8盘位, 蛋疼的是这些硬盘都是做的单盘raid1,维修人员说必须关机导入硬盘才能正常使用 (服务器就这样因为一块硬盘而经常关机???)
没办法关机吧, 重启动时候, 好像系统盘出现问题,无法开机. 我去机房查看了下 感觉是没有识别到系统盘, 直接启用了网络启动程序
对服务器raid配置不熟,没法搞定,只能按照维修人员的建议先更换系统盘,再重装系统了 -_-!!!
重装系统… 累得是我们啊,所有环境需要重新配置,搞不好以后还会出现各种奇怪的问题, 还是原装的好啊

一下记录新增hadoop节点的步骤, 以防万一

查看了下 我们的hadoop集群基本只需要复制家目录下所有文件就可以了

1
rsync -av hadoop 192.168.86.51:/home/

好的差不多搞定一半了, 主要找个小点的节点复制文件, 我选的是需要复制40多G的节点, 当然太大的话也可以通过–exclude剔除不需要复制的文件

复制完成后需要注意文件的属主问题, 可以直接复制原系统的/etc/passwd /etc/group /etc/shadow 文件, 这样就保持了文件属主一致了

hadoop集群需要通过hosts访问到各个节点, 所以需要复制/etc/hosts文件

因为我们的hadoop环境变量是通过/etc/profile文件设置的, 还需要更改/etc/profile文件,设置好环境变量, 当然home家目录也是有环境变量设置的,不过我们直接rsync过来了
基本不需要另行更改

更改/etc/fatab文件, 并建立好数据盘的挂载点, mount -a 看是否正常挂载, 操作之前需要将新加的硬盘分区并格式化文件系统, 并在新加的硬盘创建目录 mkdir -p /disk2/hadoop-data/data注意保持好目录的权限, 属主属组是运行hadoop的用户. 另外这是3T的硬盘, 分区需要使用parted, 当然新版的fdisk也可以(ubuntu12.04傻笑中…)

更改hostname, 这一步应该不是必须的, 我这里需要替换之前的节点, 所以换成之前节点的名字了hostname xxxx 这个临时起作用, 还需要编辑/etc/hostname文件,保持永久生效

因为更新了系统,需要更新ssh的key文件, 这里先更新hadoop主节点的ssh密钥, 最好在其他的节点同样进行操作

做完这些就可以尝试启动hadoop节点了
运气好的话,应该是可以启动了

其他需要注意的地方

为了减少以后导致的各种问题, 最好把/etc目录下的配置文件都看下, 以免忘记配置某些重要文件
可以参考的文件有 /etc/security/limit.conf /etc/sysctl.conf

遇到的一些坑

  1. 他们给我安装了一个图形话的系统, 黑人问号… 而且locale设置的还是zh_TW.UTF-8, 果断换成我大美帝啊, en_US.UTF-8
  2. 现在默认的系统没有vim 倒是有个vim.tiny 这是什么鬼东西? 好像连vi的功能都不如, 果断换源,安装vim
  3. 这里忘记说数据了, 数据这东西才是最重要的, 按照各自需求进行吧

最后的忠告
换啥系统, 要啥自行车, DELL能不能愉快玩耍啊

上个系统很乱,基本系统是lfs7.7,上面应用都是基于lfs7.9,基本系统是才接触lfs时搭建的,打包保存后一直没怎么使用过,到lfs7.10快出来的时候有段时间有空就拿出来跑了一下,安装了一些软件,
所以这个系统没有任何规划总体就是拼凑出来的(比如尝试了从ext4转换到btrfs,甚至中间误删除过系统重要文件),现在还是换下系统吧,顺便将一些以前没有完成的事做掉
PS:误删的是pkg-config目录下的所有文件(按照查看的教程应该是删除临时目录下pkg-config里面的所有文件?!为什么要删这个目录???,最后删错目录了),这对编译来说完全就是灾难性的,
后来通过btrfs的快照恢复过一些,重新安装了一些软件恢复过一些,其他的是等到编译软件报错时再处理的
首先是分区, 由于采用btrfs,分区格式化操作就十分简单了

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
#之前挂了三个子卷,安装系统前将两个子卷及快照都删了
[root@myOS 23:49:08 sources]# btrfs subvolume list /
ID 262 gen 95727 top level 5 path lfs

#好久没玩btrfs了,错误创建子卷
[root@myOS 23:49:10 sources]# mkdir /lfs
[root@myOS 23:49:40 sources]# btrfs subvolume create /lfs_8
Create subvolume '//lfs_8'
[root@myOS 23:50:33 sources]# btrfs subvolume list /
ID 262 gen 95730 top level 5 path lfs
ID 324 gen 95730 top level 262 path lfs_8

#删除刚才误创建的子卷
[root@myOS 23:50:38 sources]# btrfs subvolume delete /lfs_8
Delete subvolume (no-commit): '//lfs_8'
[root@myOS 23:51:04 sources]#
[root@myOS 23:51:07 sources]# btrfs subvolume delete -C /lfs_8
ERROR: cannot access subvolume /lfs_8: No such file or directory

#上面第一步已经删除子卷了,第二步错误用法
[root@myOS 23:51:11 sources]# btrfs subvolume list /
ID 262 gen 95730 top level 5 path lfs
[root@myOS 23:51:13 sources]#

#创建新的子卷用来安装新系统
[root@myOS 23:51:14 sources]# mount -t btrfs /dev/sda2 /lfs
[root@myOS 23:51:33 sources]# ls -l /lfs/
total 0
drwxr-xr-x 1 root root 172 Apr 2 23:51 lfs
[root@myOS 23:51:38 sources]#

#这里的挂载看着文件名很揪心,我创建挂载点时没考虑太多
[root@myOS 23:51:38 sources]# btrfs subvolume create /lfs/lfs_8
Create subvolume '/lfs/lfs_8'
[root@myOS 23:52:01 sources]# btrfs subvolume list /
ID 262 gen 95732 top level 5 path lfs
ID 325 gen 95732 top level 5 path lfs_8
[root@myOS 23:54:47 sources]# mount -v -t btrfs -o subvol=/lfs_8 /dev/sda2 /mnt/lfs
mount: /dev/sda2 mounted on /mnt/lfs.

好了, 系统分区及挂载完成,下面就可以正式安装系统了
2017年2月底lfs8.0就出来了,虽然是大版本号更新,但是具体内容没有太大变化,至少安装过程还是一样地
基础系统的安装花费四个小时的时间,这其中我已经尽量避免做软件安装时的测试了,如果加上测试时间,另算

基础系统安装,完全按照手册进行即可, 这里需要主要的是宿主机的环境一定要在手册规定的范围内,否则可能出现各种奇怪问题
主要考虑 binutils和glibc两个版本对不对就差不错了

1
2
ld --version
ldd --version

由于我已经有可以启动的系统了,采用的引导器是grub, 原则上来说我现在不需要安装grub了
这里再说一下grub的安装, 我安装时一般选择 i386 pc模式(传统bios) + x86_64 efi模式(新的uefi),而这两个如果需要同时安装 configure的时候好像有问题, 我是采用先安装一个之后清空编译环境重新安装另一个,达到安装两个模式

安装基本到第六步走完就结束了, 第七步的配置适当进行就可以了 第八步的内核配置及引导按照往常进行

基本系统安装结束可以考虑继续blfs了
首先的问题是需要网络连接
我的有线网卡内核自带驱动,比较好解决(之前安装系统都是先插上网线安装的)
这次我打算直接使用无线网卡 (bcm43228), 我的这个无线网卡内核其实也是自带驱动b43驱动可以使用,但是b43驱动经常无缘无故掉线,很烦,不如直接wl驱动
所以在有网络环境的时候先下载好 wpa_supplicant 及 broadcom 的驱动程序 dhcp程序可以考虑之后安装也行
安装好无线网卡驱动 利用ip配置好ip地址, 写好dns地址, 设置好路由 就可以ping百度看下能不能正常上网了, 网络环境依个人情况而定,大伙的和我并不一样,不详讲

我所安装的组件

  1. wayland 想尽快进入图像界面可以考虑先不安装xwayland支持,那样就少很多依赖可以快速进入图形化系统 就可以愉快的复制粘贴了
  2. awesome 这是我使用的windos manager, 4.x版本和之前的3.x版本改动很大, 感觉现在就是一个完整的图形环境了
  3. mpfc 音乐播放器
  4. mpv 视频播放器
  5. fcitx 输入法程序这个blfs里面好像没有, blfs里面有ibus,所以简单的话可以直接考虑使用ibus
  6. google-chrome chrome57版本的flash挺坑的,可以参考chromium的启动脚本添加 –paapo-path 等参数启动(启用flash后cpu占用轻松达到25%), blfs8里面其实自带了chromium, 看到SBU达到90我就放弃了,渣本估计需要接近5个小时才能编译完成
  7. wps 金山的软件,不喜欢,人品都被败光了,只是为了测试安装试下
  8. 其他的一些必须的软件, 比如解压就可直接使用的Telegram等

遇到的坑

  1. 因为我打算完全禁用nvidia显卡(鸡肋,甚至鸡肋都算不算的东西,如果不是焊死在主板上,早就拿下来了),安装软件的时候无脑进行,导致安装了 libvdpau这个库文件,最后导致ffmpeg及mplayer默认使用vdpau的模块,在我电脑上播放视频犹如
    幻灯片,最后去掉这个库文件,重新编译ffmpeg mplayer mpv gst等软件才完全剔除这个影响
  2. fcitx,安装时无脑,就安装了个fcitx就认为可以输入汉字了,调了好久发现没装输入法啊,我只装了一个输入法框架而已,安装libgooglepinyin后可以正常调用输入法(怕libpinyin依赖太多,就没装, sunpinyin依赖不是很多可以考虑)
  3. google-chrome 之前讲了启动脚本的问题,现在还有一个问题是google-chrome好像调用某个系统调用经常失败,导致系统日志里面都是 audit chrome。。。。, 无奈,没搜到好的解决办法,把内核的audit功能关了,眼不见心不烦,顺便还能减小100K的内核大小
  4. 还是显卡的问题,之前禁用不完整,导致nvidia一直是全功率运行的,发热量巨大,笔记本放在哪不动风扇都呼呼的转,参考这个解决Hybrid graphics
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
Fully Power Down Discrete GPU
You may want to turn off the high-performance graphics processor to save battery power, this can be done by installing the acpi_call package.
Tip: For kernels not in the Official repositories, the acpi_call-git-dkmsAUR is an alternative. See also DKMS.
Once installed load the kernel module:
# modprobe acpi_call
With the kernel module loaded run the following:
# /usr/share/acpi_call/examples/turn_off_gpu.sh
This script will go through all the known data buses and attempt to turn them off. You will get an output similar to the following:
Trying \_SB.PCI0.P0P1.VGA._OFF: failed
Trying \_SB.PCI0.P0P2.VGA._OFF: failed
Trying \_SB_.PCI0.OVGA.ATPX: failed
Trying \_SB_.PCI0.OVGA.XTPX: failed
Trying \_SB.PCI0.P0P3.PEGP._OFF: failed
Trying \_SB.PCI0.P0P2.PEGP._OFF: failed
Trying \_SB.PCI0.P0P1.PEGP._OFF: failed
Trying \_SB.PCI0.MXR0.MXM0._OFF: failed
Trying \_SB.PCI0.PEG1.GFX0._OFF: failed
Trying \_SB.PCI0.PEG0.GFX0.DOFF: failed
Trying \_SB.PCI0.PEG1.GFX0.DOFF: failed
Trying \_SB.PCI0.PEG0.PEGP._OFF: works!
Trying \_SB.PCI0.XVR0.Z01I.DGOF: failed
Trying \_SB.PCI0.PEGR.GFX0._OFF: failed
Trying \_SB.PCI0.PEG.VID._OFF: failed
Trying \_SB.PCI0.PEG0.VID._OFF: failed
Trying \_SB.PCI0.P0P2.DGPU._OFF: failed
Trying \_SB.PCI0.P0P4.DGPU.DOFF: failed
Trying \_SB.PCI0.IXVE.IGPU.DGOF: failed
Trying \_SB.PCI0.RP00.VGA._PS3: failed
Trying \_SB.PCI0.RP00.VGA.P3MO: failed
Trying \_SB.PCI0.GFX0.DSM._T_0: failed
Trying \_SB.PCI0.LPC.EC.PUBS._OFF: failed
Trying \_SB.PCI0.P0P2.NVID._OFF: failed
Trying \_SB.PCI0.P0P2.VGA.PX02: failed
Trying \_SB_.PCI0.PEGP.DGFX._OFF: failed
Trying \_SB_.PCI0.VGA.PX02: failed
See the "works"? This means the script found a bus which your GPU sits on and it has now turned off the chip. To confirm this, your battery time remaining should have increased. Currently, the chip will turn back on with the next reboot to get around this we do the following:
Note: To turn the GPU back on just reboot.
Add the kernel module to the array of modules to load at boot:
/etc/modules-load.d/acpi_call.conf
#Load 'acpi_call.ko' at boot.

acpi_call
To turn off the GPU at boot we could just run the above script but honestly that is not very elegant so instead lets make use of systemd's tmpfiles.
/etc/tmpfiles.d/acpi_call.conf

w /proc/acpi/call - - - - \\_SB.PCI0.PEG0.PEGP._OFF
The above config will be loaded at boot by systemd. What it does is write the specific OFF signal to the /proc/acpi/call file. Obviously, replace the \_SB.PCI0.PEG0.PEGP._OFF with the one which works on your system (please note that you need to escape the backslash).

待完善的地方

  1. 打算安装teamviewer的,这样我就基本可以实现迁移到linux上工作了(qq用手机版就行,本来也是不常用的东西,聊天有telegram及irc),可是teamviewer依赖wine才能跑,需要安装很多32位库,暂时没有解决这个问题,留待之后进行
    [通过复制arch的32位库, teamviewer已经基本可以使用]
  2. awesome及weston个性化定制,由于不是经常使用这个linux,所以个性化的定制没有进行,期待以后有时间完善这个
  3. 内核编译时间越来越久了,大小已经达到5.4M了,需要优化下, 其他需要使用的软件,可能因为各种原因没有安装,期待之后有时间多使用这个Linux系统吧,不要一直吃灰了

最近需要将sqlserver数据导入到mongodb中,在github上搜了一圈,发现两个项目有点适合

  1. mongify
  2. sql2mongodb

先试了下sql2mongodb(有个好名字果然有好处啊), 可是,but,但是,这东西好像并不没有名字取得好,试了下感觉不靠谱,弃坑,逃~
说点题外话,sql2server以来nodejs, mongify依赖ruby, 这两个库都是我最讨厌的,暂时没有理由。

好了,现在咱专注mongify吧
先看官网介绍:
Mongify是一个将数据从sql数据库转换到mongoDB的ruby工具。支持MySQL,PostgreSQL,SQLite,Oracle,SQLServer和DB2(基本上ActiveRecord内置的内容),支持任何版本的MongoDB。
但是,缺点是作者声称只在MySql和SQLite测试过,对于我现在需要的sqlserver,心中一群在奔腾。。。

安装

使用的环境是ubuntu12.04,该版本软件仓库中的ruby是1.8版本的,需要ruby2.1版本以上才行

  1. 省懒,直接加ppa吧, 这里可以随便安装到2.3版本
    From the travis-cli installation instructions for Ubuntu, the Brightbox Ruby NG(NextGeneration) ppa:
1
2
3
4
5
$ sudo apt-get install python-software-properties
$ sudo apt-add-repository ppa:brightbox/ruby-ng
$ sudo apt-get update
$ sudo apt-get install ruby2.1 ruby-switch
$ sudo ruby-switch --set ruby2.1

顺便注明下gem的使用吧

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
ubuntu@aws:~$ gem --help
RubyGems is a sophisticated package manager for Ruby. This is a
basic help message containing pointers to more information.

Usage:
gem -h/--help
gem -v/--version
gem command [arguments...] [options...]

Examples:
gem install rake
gem list --local
gem build package.gemspec
gem help install

Further help:
gem help commands list all 'gem' commands
gem help examples show some examples of usage
gem help gem_dependencies gem dependencies file guide
gem help platforms gem platforms guide
gem help <COMMAND> show help on COMMAND
(e.g. 'gem help install')
gem server present a web page at
http://localhost:8808/
with info about installed gems
Further information:
http://guides.rubygems.org

好,那我们安装mongify吧gem install mongify

经过一轮踩坑,还是关注下mongify目录结构吧 其中有一个文件mongify.gemspec

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
$:.push File.expand_path("../lib", __FILE__)
require "mongify/version"

Gem::Specification.new do |s|
s.name = "mongify"
s.version = Mongify::VERSION
s.platform = Gem::Platform::RUBY
s.authors = ["Andrew Kalek"]
s.email = ["[email protected]"]
s.homepage = "http://mongify.com"
s.summary = %q{Translate your SQL data to MongoDB with ease}
s.description = %q{Mongify allows you to map your sql data into a mongodb document database with a simple DSL.}
s.required_ruby_version = ">= 1.8.7"

s.add_runtime_dependency('activerecord', ">= 4.2", "< 5.0")
s.add_runtime_dependency('activesupport', ">= 4.2", "< 5.0")
s.add_runtime_dependency('mongo', "= 1.12.5")
s.add_runtime_dependency('bson', "= 1.12.5")
s.add_runtime_dependency('bson_ext', "= 1.12.5") unless RUBY_PLATFORM == 'java'
s.add_runtime_dependency('highline', '= 1.7.8')


s.add_development_dependency('rspec', '~> 2.0')
s.add_development_dependency('rspec-collection_matchers', '~> 1.0')
s.add_development_dependency('cucumber', '>= 0.10')
s.add_development_dependency('mocha', '>= 0.9.8')
s.add_development_dependency('yard', '>= 0.8')
s.add_development_dependency('sqlite3', '>= 1.3')
s.add_development_dependency('pg', '>= 0.17')
s.add_development_dependency('mysql2', '>= 0.4')
s.add_development_dependency('watchr', '>= 0.6')
s.add_development_dependency('rake')
s.add_development_dependency('jazz_fingers')

s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
s.require_paths = ["lib"]

s.extra_rdoc_files = [
"CHANGELOG.md",
"README.rdoc"
]
s.rdoc_options = ["--title", "Mongify -- SQL db to Mongo db converter", "--main", "README", "--line-numbers", "--inline-source"]
end

可以看到这里指定了依赖,对版本也有要求。

如果已经安装过mongify1.3.1版本的话,导出sqlserver数据库时将会发现如果要支持sqlserver数据库还需要安装activerecord-sqlserver-adapter

而在activerecord-sqlserver-adapter官网有这样的描述

1
2
3
The SQL Server adapter for ActiveRecord v5.0 using SQL Server 2012 or higher.

Interested in older versions? We follow a rational versioning policy that tracks Rails. That means that our 5.0.x version of the adapter is only for the latest 5.0 version of Rails. If you need the adapter for SQL Server 2008 or 2005, you are still in the right spot. Just install the latest 3.2.x to 4.1.x version of the adapter that matches your Rails version. We also have stable branches for each major/minor release of ActiveRecord.

由于我的sqlserver是2008版本的,也就是说我最高可以使用4.1.x版本,并且最好有配套的ActiveRecord

所以我选择了1.2.4版本的Mongify,可以看下这个版本的依赖

1
2
3
4
5
6
s.add_dependency('activerecord', "~> 3.2")
s.add_dependency('activesupport', "~> 3.2")
s.add_dependency('mongo', "~> 1.10.2")
s.add_dependency('bson', "~> 1.10.2")
s.add_dependency('bson_ext', "~> 1.10.2") unless RUBY_PLATFORM == 'java'
s.add_dependency('highline', '>= 1.6.1')

对应的可以满足3.2.x-4.1.x这个要求,那么就是他了

重新安装Mongify

1
gem install mongify -v 1.2.4

根据上面的依赖,会安装对应版本软件再安装activerecord-sqlserver-adapter

1
gem install activerecord-sqlserver-adapter -v 3.2.17

创建配置文件

为了让Mongify正常工作,它需要知道数据库的位置及连接信息。
构建配置文件就像这样简单: (对于我们,adapter需要改成sqlserver)

1
2
3
4
5
6
7
8
9
10
11
12
13
sql_connection do
adapter "mysql"
host "localhost"
username "root"
password "passw0rd"
database "my_database"
batch_size 10000 # This is defaulted to 10000 but in case you want to make that smaller (on lower RAM machines)
end

mongodb_connection do
host "localhost"
database "my_database"
end

检查配置文件

1
mongify check database.config

生成转换文件

如果您的数据库庞大而复杂,手工编写转换文件可能会有太多的工作。 Mongify的可以直接使用命令生成:

1
mongify translation database.config

可以使用重定向将配置输出到文件

1
mongify translation database.config > translation_file.rb

最后将sql数据导入到mongodb中

1
mongify process database.config translation_file.rb

导出时每次读取10000条数据,以进度条显示进度

1
2
3
4
5
6
7
8
9
10
11
Copying playsrc (261/607):            (10000/10000) 100% |ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:03
Copying playsrc (262/607): (10000/10000) 100% |ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:03
Copying playsrc (263/607): (10000/10000) 100% |ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:02
Copying playsrc (264/607): (10000/10000) 100% |ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:02
Copying playsrc (265/607): (10000/10000) 100% |ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:03
Copying playsrc (266/607): (10000/10000) 100% |ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:03
Copying playsrc (267/607): (10000/10000) 100% |ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:02
Copying playsrc (268/607): (10000/10000) 100% |ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:02
Copying playsrc (269/607): (10000/10000) 100% |ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:03
Copying playsrc (270/607): (10000/10000) 100% |ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:03
Copying playsrc (271/607): (10000/10000) 100% |ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:02

附录Mongify的命令,总共就四个主要命令,以上用过了三个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Usage: mongify command database_config [database_translation.rb]

Commands:
"check" or "ck" >> Checks connection for sql and no_sql databases [configuration_file]
"process" or "pr" >> Takes a translation and process it to mongodb [configuration_file, translation_file]
"sync" or "sy" >> Takes a translation and process it to mongodb, only syncs (insert/update) new or updated records based on the updated_at column [configuration_file, translation_file]
"translation" or "tr" >> Outputs a translation file from a sql connection [configuration_file]

Examples:

mongify translation datbase.config
mongify tr database.config
mongify check database.config
mongify process database.config database_translation.rb
mongify sync database.config database_translation.rb

Common options:
-h, --help Show this message
-v, --version Show version

(待完善,想到哪就写到哪,目前内容大幅度参考中文man手册)

最重要的命令(man)

在 Linux 下遇到问题,最重要的是要自己寻求帮助, google是个好东西
man 是 Linux 的帮助手册,即 manual 。因为大多数程序都会自带手册,所以可以通过 man 命令获取帮助。执行以后,man页面默认采用less命令变体进行输出,less的快捷键在man中一般都可用,在 man page 页面中按 q 退出。

基础管理命令

基础操作

ls(list) 及文件权限 引申 stat touch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-C     多列输出,纵向排序。 
-F 每个目录名加“ / ”后缀,每个 FIFO 名加“ | ”后缀, 每个可运行名加“ * ”后缀。
-R 递归列出遇到的子目录。
-a 列出所有文件,包括以 "." 开头的隐含文件。
-c 使用“状态改变时间”代替“文件修改时间”为依据来排序 (使用“ -t ”选项时)或列出(使用“ -l ”选项时)。
-d 将目录名象其它文件一样列出,而不是列出它们的内容。
-i 输出文件前先输出文件系列号(即 i 节点号: i-node number)。 -l 列出(以单列格式)文件模式( file mode ),文件的链
接数,所有者名,组名,文件大小(以字节为单位),时间信 息,及文件名。缺省时,时间信息显示最近修改时间;可以以 选项“
-c ”和“ -u ”选择显示其它两种时间信息。对于设 备文件,原先显示文件大小的区域通常显示的是主要和次要的 号(majorand
minor device numbers)。
-q 将文件名中的非打印字符输出为问号。(对于到终端的输出这是缺省的。)
-r 逆序排列。
-t 按时间信息排序。
-u 使用最近访问时间代替最近修改时间为依据来排序(使用 “ -t ”选项时)或列出(使用“ -l ”选项时)。
-1 单列输出。

cd(change directory) pwd test kill type echo alias unalias set unset job fg bg ulimit umask trap hash等bash内建命令

cd 命令是bash的内建命令,没有单独的man页面展示,查看是否是bash内建命令使用type command

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
root@Test1:~# type cd
cd is a shell builtin
root@Test1:~# type ls
ls is aliased to `ls --color=auto'
root@Test1:~# unalias ls
root@Test1:~# type ls
ls is hashed (/bin/ls)
root@Test1:~# ls -l /usr/bin/ls
ls: cannot access /usr/bin/ls: No such file or directory
root@Test1:~# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
root@Test1:~# mv /bin/ls /usr/bin/
root@Test1:~# ls
-bash: /bin/ls: No such file or directory
root@Test1:~# hash -r
root@Test1:~# ls -d /mnt
/mnt
root@Test1:~#

top uptime free

top是最经常用来查看系统的负载情况
另外top的选项比较多,以及各列的意义需要明确

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
top - 13:24:58 up 47 min,  2 users,  load average: 0.00, 0.01, 0.05
Tasks: 95 total, 2 running, 93 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.4%us, 0.4%sy, 0.0%ni, 97.2%id, 1.9%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 2049632k total, 431916k used, 1617716k free, 20040k buffers
Swap: 2093052k total, 0k used, 2093052k free, 246056k cached

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 24448 2368 1340 S 0.0 0.1 0:00.97 init
2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 0:00.05 ksoftirqd/0
4 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0
5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H
6 root 20 0 0 0 0 S 0.0 0.0 0:00.52 kworker/u2:0
7 root 20 0 0 0 0 S 0.0 0.0 0:00.37 rcu_sched
8 root 20 0 0 0 0 S 0.0 0.0 0:00.56 rcuos/0
9 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_bh
10 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcuob/0
11 root RT 0 0 0 0 S 0.0 0.0 0:00.00 migration/0
12 root RT 0 0 0 0 S 0.0 0.0 0:00.02 watchdog/0
13 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 khelper
14 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kdevtmpfs
15 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 netns
16 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 writeback

id w who last lastlog pkill

id - 显示真实和有效的 UID 和 GID
w - 显示已经登录的用户以及他们在做什么
who - 显示已经登录的用户
last, lastb - 显示最近登录的用户列表
lastlog - reports the most recent login of all users or of a given user

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
root@Test1:~# id
uid=0(root) gid=0(root) groups=0(root)
root@Test1:~# w
13:33:06 up 56 min, 2 users, load average: 0.00, 0.01, 0.05
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root tty1 12:37 55:12 0.22s 0.21s -bash
root pts/0 192.168.1.102 12:38 0.00s 0.50s 0.00s w
kill is a shell builtin
root@Test1:~# who
root tty1 2017-03-26 12:37
root pts/0 2017-03-26 12:38 (192.168.1.102)

# 踢出登陆的用户
root@Test1:~# pkill -kill -t tty1
root@Test1:~# w
03:38:09 up 1:01, 2 users, load average: 0.00, 0.01, 0.05
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 192.168.1.102 02:38 3.00s 0.51s 0.00s w

useradd passwd userdel usermod change

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
新帐号建立
-c comment 新帐号password档的说明栏。
-d home_dir 新帐号每次登入时所使用的home_dir。预设值为default_home内login名称,并当成登入时目录名称。
-e expire_date 帐号终止日期。日期的指定格式为MM/DD/YY。
-f inactive_days 帐号过期几日后永久停权。当值为0时帐号则立刻被停权。而当值为-1时则关闭此功能,预设值为-1
-g initial_group group名称或以数字来做为使用者登入起始群组(group)。群组名须为现有存在的名称。群组数字也须为现有存在的群组。预设的群组
数字为1。
-G group,[...] 定义此使用者为此一堆groups的成员。每个群组使用","区格开来,不可以夹杂空白字元。群组名同-g选项的限制。定义值为使用者的>起始群组。
-m 使用者目录如不存在则自动建立。如使用-k选项skeleton_dir内的档案将复制至使用者目录下。然而在/etc/skel目录下的档案也会复制过去取代。>任何在skeleton_diror/etc/skel的目录也相同会在使用者目录下一一建立。The-k同-m不建立目录以及不复制任何档案为预设值。
-M 不建立使用者目录,即使/etc/login.defs系统档设定要建立使用者目录。
-n 预设值使用者群组与使用者名称会相同。此选项将取消此预设值。-r 此参数是用来建立系统帐号。系统帐号的UID会比定义在系统档上/etc/login.defs.的UID_MIN来的小。注意useradd此用法所建立的帐号不会建立使>用者目录,也不会在乎纪录在/etc/login.defs.的定义值。如果你想要有使用者目录须额外指定-m参数来建立系统帐号。这是REDHAT额外增设的选项。
-s shell 使用者登入后使用的shell名称。预设为不填写,这样系统会帮你指定预设的登入shell。
-u uid 使用者的ID值。必须为唯一的ID值,除非用-o选项。数字不可为负值。预设为最小不得小于999而逐次增加。0~999传统上是保留给系统帐号使用

改变预设值当-D选项出现时,useradd秀出现在的预设值,或是藉由命令列的方式更新预设值。可用选项为∶-bdefault_home定义使用者所属目录的前一个目录。使>用者名称会附加在default_home后面用来建立新使用者的目录。当然使用-d后则此选项无效。
-e default_expire_date 使用者帐号停止日期。
-f default_inactive 帐号过期几日后停权。
-g default_group 新帐号起始群组名或ID。群组名须为现有存在的名称。群组ID也须为现有存在的群组。
-s default_shell 使用者登入后使用的shell名称。往后新加入的帐号都将使用此shell. 如不指定任何参数,useradd显示目前预设的值。

passwd 需改密码或者可以设置账号过期时间等

1
2
3
4
5
6
7
8
9
10
11
12
13
# 第一次登陆需要修改密码
WARNING: Your password has expired.
You must change your password now and login again!
Changing password for mike.
(current) UNIX password:
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
# 修改密码
root@Test1:~# passwd mike
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully

head tail nl tr less more

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
在标准输出上显示每个FILE的最后10行.          如果多于一个FILE,会一个接一个地显示,        并在每个文件显示的首部给出文件名.
如果没有FILE,或者FILE是-,那么就从标准输入上读取.
--retry
即使tail开始时就不能访问 或者在tail运行后不能访问,也仍然不停地尝试打开文件. -- 只与-f合用时有用.
-c, --bytes=N
输出最后N个字节
-f, --follow[={name|descriptor}]
当文件增长时,输出后续添加的数据; -f, --follow以及 --follow=descriptor 都是相同的意思
-n, --lines=N
输出最后N行,而非默认的最后10行
--max-unchanged-stats=N
参看texinfo文档(默认为5)
--max-consecutive-size-changes=N
参看texinfo文档(默认为200)
--pid=PID
与-f合用,表示在进程ID,PID死掉之后结束.
-q, --quiet, --silent
从不输出给出文件名的首部
-s, --sleep-interval=S
与-f合用,表示在每次反复的间隔休眠S秒
-v, --verbose
总是输出给出文件名的首部
--help 显示帮助信息后退出
--version
输出版本信息后退出 如果N(字节或者行数)的第一个字符为`+', 那么从每个文件的开头算起的第N项开始显示, 否则, 显示该文件的最后N项. N可以有一个倍数前缀: b表示512,k表示1024,m表示1048576(1兆). 第一个选项 -VALUE 或+VALUE 以-n VALUE或-n +VALUE方式看待,除非VALUE含有[bkm]后缀倍数中的一个,在这种情>况下,它被看作 -c VALUE 或者-c +VALUE
使用--follow (-f)时,tail默认后接文件描述符, 这意味着即使tail显示的文件改名了,tail仍然可以追踪到其末尾部分. 如果你确实希望查询文件的实
际名而非文件描述符 (例如,日志轮转时), 这种默认的操作就不是你所期望的了. 在这种情况下应使用--follow=name. 这将导致tail通过周期性地重>新打开所指定的文件来 追踪其是否被删除了,或者被其他程序重新创建了.

cut split cat tac

有时候文件太大不适合查看,可以将文件切割,或者有时需要合并文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
把 输入文件 INPUT 按 固定大小 的 文件片 PREFIXaa, PREFIXab, ... 输出; 缺省的 PREFIX 是 `x'. 如果 没有 指定 INPUT, 或 INPUT  
是 -, 就从 标准输入 读取 数据.
-b, --bytes=SIZE
输出文件 大小 定为 SIZE 字节
-C, --line-bytes=SIZE
输出文件 大小 定为 最多 SIZE 字节 的 行
-l, --lines=NUMBER
输出文件 大小 定为 NUMBER 行
-NUMBER
同 -l NUMBER
--verbose
在 打开 每一个 输出文件 之前, 把 诊断信息 送往 标准错误
--help 显示 帮助信息, 然后 结束
--version
显示 版本信息, 然后 结束
指定 SIZE 时 可以 使用 倍乘后缀: b 是 512, k 是 1K, m 是 1 Meg.

mkdir mkfs mknod mktemp

mkdir -建立目录
mkfs - 创建一个 Linux 文件系统
mknod - 建立块专用或字符专用文件
mktemp — 产生唯一的临时文件名

1
2
3
4
5
6
7
8
9
10
下列的 sh 片断 展示了 mktemp 的 简单用法, 如果无法获得可靠的临时文件, 程序就退出.
TMPFILE=`mktemp /tmp/$0.XXXXXX` || exit 1
echo "program output" >> $TMPFILE

照上例, 我们打算让脚本程序自己捕获这个错误.
TMPFILE=`mktemp -q /tmp/$0.XXXXXX`
if [ $? -ne 0 ]; then
echo "$0: Can't create temp file, exiting..."
exit 1
fi

du df mount unmount lsblk blkid

du - 报告磁盘空间使用情况
df - 报告文件系统磁盘空间的使用情况

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
-a, --all
显示对所有文件的统计,而不只是包含子目录。
-b, --bytes
输出以字节为单位的大小,替代缺省时1024字节的计数单位。
--block-size=size
输出以块为单位的大小,块的大小为 size 字节。( file- utils-4.0 的新选项)
-c, --total
在处理完所有参数后给出所有这些参数的总计。这个选项被 用给出指定的一组文件或目录使用的空间的总和。
-D, --dereference-args
引用命令行参数的符号连接。但不影响其他的符号连接。 这对找出象 /usr/tmp 这样的目录的磁盘使用量有用, /usr/tmp 等通常是符
号连接。 译住:例如在 /var/tmp 下建立一个目录test, 而/usr/tmp 是指向 /var/tmp 的符号连接。du /usr/tmp 返回一项 /usr/tmp , 而 du - D /usr/tmp 返回两项 /usr/tmp,/usr/tmp/test。
--exclude=pattern
在递归时,忽略与指定模式相匹配的文件或子目录。模式 可以是任何 Bourne shell 的文件 glob 模式。( file- utils-4.0 的新选项)
-h, --human-readable
为每个数附加一个表示大小单位的字母,象用M表示二进制 的兆字节。
-H, --si
与 -h 参数起同样的作用,只是使用法定的 SI 单位( 用 1000的幂而不是 1024 的幂,这样 M 代表的就是1000000 而不是 1048576)。
(fileutils-4.0 的新选项)
-k, --kilobytes
输出以1024字节为计数单位的大小。
-l, --count-links
统计所有文件的大小,包括已经被统计过的(作为一个硬连接)。
-L, --dereference
引用符号连接(不是显示连接点本身而是连接指向的文件或 目录所使用的磁盘空间)。
-m, --megabytes
输出以兆字节的块为计数单位的大小(就是 1,048,576 字节)。
--max-depth=n
只输出命令行参数的小于等于第 n 层的目录的总计。 --max-depth=0的作用同于-s选项。(fileutils-4.0的新选项)
-s, --summarize
对每个参数只显示总和。
-S, --separate-dirs
单独报告每一个目录的大小,不包括子目录的大小。
-x, --one-file-system
忽略与被处理的参数不在同一个文件系统的目录。
-X file, --exclude-from=file
除了从指定的文件中得到模式之外与 --exclude 一样。 模式以行的形式列出。如果指定的文件是'-',那么从标准输入中读出模>
式。(fileutils-4.0 的新选项) GNU 标准选项

tar gzip bzip2 zip xz 及相应的解压,查看压缩文件命令

tar - tar 档案文件管理程序的 GNU 版本。
gzip, gunzip, zcat - 压缩或展开文件
bzip2, bunzip2 - 一种块排序文件压缩软件,v0.9.5
bzcat - 将文件解压缩至标准输出
bzip2recover - 恢复损坏的 bzip2 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
参数说明
运行tar时必须要有下列参数中的至少一个才可运行
-A, --catenate, --concatenate
将一存档与已有的存档合并
-c, --create
建立新的存档
-d, --diff, --compare
比较存档与当前文件的不同之处
--delete
从存档中删除
-r, --append
附加到存档结尾
-t, --list
列出存档中文件的目录
-u, --update
仅将较新的文件附加到存档中
-x, --extract, --get
从存档展开文件

bzip2,gzip及xz压缩文件基本都是在linux环境产生,编码基本没有太大问题, zip是比较通用的快平台压缩工具,容易产生乱码
可以使用-O 选项,一般windows的压缩式gbk2312编码,可以采用unzip -O CP936 filename

chmod chown chgrp chattr lsattr facl

chmod - 改变文件的访问权限
chown - 修改文件所有者和组别
chgrp - 改变文件的组所有权
chattr - 修改文件在Linux第二扩展文件系统(E2fs)上的特有属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
使用chmod命令改变指定文件访问权限有两种方式:一种是用符号标记所进行更改,另一种方式是采用8进制数指定新的访问权限。使用下面的语法格式来>使用符号改变方式 `[ugoa...][[+-=][rwxXstugo...]...][,...]'.

在这种格式下,所带参数是一个用逗号分隔的字符列表.每个符号方式的 改变命令以零或者字'ugoa'开始;'ugoa'控制哪些用户对该文件访问权
操作符'+'使得用户选择的权限被追加到每个指定文件,(操作给指定文件添加所选权限);操作符'-'使得这些权限被撤消;'='使得指定文件只具有这些
权限。

字符串'rwxXstugo' 给用户选择新的属性:(r)读权限、(w)写权限、(x)执行权(或对目录的访问权),(X)只有目标文件对某些用户是可执行的或该目标
文件是目录时才追加x属性,(s)同时设定用户或组ID,(t)粘滞位(保存程序的文本到交换设备上),(u)目标文件属主,(g)目标文件属主所在的组,
(o)其他用户。(因此,'chmod g-s file' 撤消sgid位,'chmod ug+s file'同时设置了suid和sgid位,'chmod o+s file' 则没有进行任何设置)

POSIX并没有粘滞位的描述。它最初是指在交换设备上保留程序文本。现在,如果设置了目录的粘滞位,那么只有文件和目录的所有者可以删除该目录下
的文件。 (一般使用于类似于/tmp这样有基本写权限的目录)

数字模式是一到4个八进制数,每个数由位权为4,2,1的3位叠加而得. 被省略掉的数字缺省设置为零. 第一位为4时为suid,2时为sgid,1时为粘滞位,.第二
位设置文件所有者的权限:可读(4),可写(2),可执行(1); 第三位设置了文件所在组其他用户的权限,值如上;第四位设置了其他组的用户的权限,值同上.

由于chmod的系统调用不支持,chomd命令不能改变符号链接的权限. 由于符号链接的权限从不使用,所以这也不成问题.无论如何,由于每个符号连接都可>
在命令行中列出,chmod改变了所指文件的属性. 相反,chmod在递归目录遍历时忽略所碰到的符号连接.

date cal hwclock locale localedef locale-gen locate

一些其他常用命令集合

安装及卸载软件 主要对比deb和rpm

Task apt (deb)
Debian, Ubuntu
zypp (rpm)
openSUSE
yum/dnf (rpm)
Fedora, CentOS
urpmi (rpm)
Mandriva, Mageia
Managing software        
Install new software from package repository apt-get install pkg zypper install pkg yum install pkg urpmi pkg
Install new software from package file dpkg -i pkg zypper install pkg yum localinstall pkg urpmi pkg
Update existing software apt-get install pkg zypper update -t package pkg yum update pkg urpmi pkg
Remove unwanted software apt-get remove pkg zypper remove pkg yum erase pkg urpme pkg
Updating the system        
Update package list apt-get update
aptitude update
zypper refresh yum check-update urpmi.update -a
Update system apt-get upgrade
aptitude safe-upgrade
zypper update yum update urpmi --auto-select
Searching for packages        
Search by package name apt-cache search pkg zypper search pkg yum list pkg urpmq pkg
Search by pattern apt-cache search pattern zypper search -t pattern pattern yum search pattern urpmq --fuzzy pkg
Search by file name apt-file search path zypper wp file yum provides file urpmf file
List installed packages dpkg -l zypper search -is rpm -qa rpm -qa
Configuring access to software repositories        
List repositories cat /etc/apt/sources.list zypper repos yum repolist urpmq --list-media
Add repository (edit /etc/apt/sources.list) zypper addrepo path name (add repo to /etc/yum.repos.d/) urpmi.addmedia name path
Remove repository (edit /etc/apt/sources.list) zypper removerepo name (remove repo from /etc/yum.repos.d/) urpmi.removemedia media

用户及权限管理

文件及系统管理

文本编辑命令

文本编辑三剑客 sed(stream editor) gerp(Global Regular Expression Print) awk(三位创始人)

神之编辑器(emacs)及编辑器之神(vim)

其他有趣的终端命令

cmatrix (还是直接图片展示吧)

ETCD etcd

架设etcd集群

静态启动etcd集群需要每个成员在集群中知道另一个成员。在许多情况下,集群成员的IP可能提前未知。在这种情况下,可以使用etcd集群的自动发现服务。一旦etcd集群启动并运行,可以通过运行时重新配置完成添加或删除成员。

下面是三种典型的启动配置 具体参照官方介绍 etcd clustering

下面将在以下三台主机上搭建etcd集群:

Name Address Hostname
infra0 10.0.1.10 infra0.example.com
infra1 10.0.1.11 infra1.example.com
infra2 10.0.1.12 infra2.example.com

静态配置

因为我们知道集群成员,它们的地址和集群在启动之前的大小,我们可以使用离线引导配置,通过设置初始集群标志。每台机器将获得以下环境变量或命令行:

1
2
ETCD_INITIAL_CLUSTER="infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380"
ETCD_INITIAL_CLUSTER_STATE=new
1
2
--initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
--initial-cluster-state new

在每台机器上,使用以下标志启动etcd:

1
2
3
4
5
6
7
$ etcd --name infra0 --initial-advertise-peer-urls http://10.0.1.10:2380 \
--listen-peer-urls http://10.0.1.10:2380 \
--listen-client-urls http://10.0.1.10:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://10.0.1.10:2379 \
--initial-cluster-token etcd-cluster-1 \
--initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
--initial-cluster-state new
1
2
3
4
5
6
7
$ etcd --name infra1 --initial-advertise-peer-urls http://10.0.1.11:2380 \
--listen-peer-urls http://10.0.1.11:2380 \
--listen-client-urls http://10.0.1.11:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://10.0.1.11:2379 \
--initial-cluster-token etcd-cluster-1 \
--initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
--initial-cluster-state new
1
2
3
4
5
6
7
$ etcd --name infra2 --initial-advertise-peer-urls http://10.0.1.12:2380 \
--listen-peer-urls http://10.0.1.12:2380 \
--listen-client-urls http://10.0.1.12:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://10.0.1.12:2379 \
--initial-cluster-token etcd-cluster-1 \
--initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
--initial-cluster-state new

以–initial-cluster开头的命令行参数在etcd的后续运行时将被忽略。在初始引导过程之后,可以随意删除环境变量或命令行标志。

CONFD confd

直接在Github上下载解压到对应目录就实现了安装

下面主要是confd搭配etcd进行nginx的自动配置

添加一些键值对

1
2
etcdctl set /myapp/database/url db.example.com
etcdctl set /myapp/database/user rob

创建配置文件目录

这个配置文件目录是用来存放配置文件和模板文件

1
sudo mkdir -p /etc/confd/{conf.d,templates}

创建资源配置文件

模板资源配置文件使用TOML配置文件格式来定义定义。

/etc/confd/conf.d/myconfig.toml

1
2
3
4
5
6
7
[template]
src = "myconfig.conf.tmpl"
dest = "/tmp/myconfig.conf"
keys = [
"/myapp/database/url",
"/myapp/database/user",
]

创建资源模板文件

资源模板文件采用Golang text templates格式定义

/etc/confd/templates/myconfig.conf.tmpl

1
2
3
[myconfig]
database_url = {{getv "/myapp/database/url"}}
database_user = {{getv "/myapp/database/user"}}

生成模板

confd支持守护程序和一次性操作两种操作模式。在守护程序模式下,confd轮询后端以进行更改,并在必要时更新目标配置文件。

1
confd -onetime -backend etcd -node http://127.0.0.1:4001

Note: The metadata api prefix can be defined on the cli, or as part of your keys in the template toml file.

输出:

1
2
2014-07-08T20:38:36-07:00 confd[16252]: INFO Target config /tmp/myconfig.conf out of sync
2014-07-08T20:38:36-07:00 confd[16252]: INFO Target config /tmp/myconfig.conf has been updated

目标配置文件已经生成

1
cat /tmp/myconfig.conf

输出:

1
2
3
4
# This a comment
[myconfig]
database_url = db.example.com
database_user = rob

配置使用使用生成nginx配置文件

这个例子将使用一个confd模板生成两个nginx配置文件

添加键值对

1
2
3
4
5
6
etcdctl set /myapp/subdomain myapp
etcdctl set /myapp/upstream/app2 "10.0.1.100:80"
etcdctl set /myapp/upstream/app1 "10.0.1.101:80"
etcdctl set /yourapp/subdomain yourapp
etcdctl set /yourapp/upstream/app2 "10.0.1.102:80"
etcdctl set /yourapp/upstream/app1 "10.0.1.103:80"

创建资源模板

/etc/confd/conf.d/myapp-nginx.toml

1
2
3
4
5
6
7
8
9
10
11
12
[template]
prefix = "/myapp"
src = "nginx.tmpl"
dest = "/tmp/myapp.conf"
owner = "nginx"
mode = "0644"
keys = [
"/subdomain",
"/upstream",
]
check_cmd = "/usr/sbin/nginx -t -c {{.src}}"
reload_cmd = "/usr/sbin/service nginx reload"

/etc/confd/conf.d/yourapp-nginx.toml

1
2
3
4
5
6
7
8
9
10
11
12
[template]
prefix = "/yourapp"
src = "nginx.tmpl"
dest = "/tmp/yourapp.conf"
owner = "nginx"
mode = "0644"
keys = [
"/subdomain",
"/upstream",
]
check_cmd = "/usr/sbin/nginx -t -c {{.src}}"
reload_cmd = "/usr/sbin/service nginx reload"

创建模板

/etc/confd/templates/nginx.tmpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
upstream {{getv "/subdomain"}} {
{{range getvs "/upstream/*"}}
server {{.}};
{{end}}
}

server {
server_name {{getv "/subdomain"}}.example.com;
location / {
proxy_pass http://{{getv "/subdomain"}};
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

数据库关系到业务的核心,备份数据库进行容灾是必不可少的操作

mysql

使用mysqldump命令备份

mysqldump基本语法:

mysqldump -u username -p dbname table1 table2 …-> BackupName.sql

其中:

dbname参数表示数据库的名称;
table1和table2参数表示需要备份的表的名称,为空则整个数据库备份;
BackupName.sql参数表设计备份文件的名称,文件名前面可以加上一个绝对路径. 通常将数据库被分成一个后缀名为sql的文件;

直接复制整个数据库目录

简单粗暴, 操作时最好保持数据库服务是停止的,以免影响数据,导致最终无法还原

另外这种方法不适用于InnoDB存储引擎的表,而对于MyISAM存储引擎的表很方便。同时,还原时MySQL的版本最好相同。

和这种方法类似,利用LVM或者btrfs这些文件系统层面的快照可以将硬盘当前状态保存,速度更快,但是需要文件系统支持

mysql的备份脚本

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

. /etc/profile
. ~/.bashrc

. common.sh

# general variable define
bk_date=`date +'%Y%m%d'`
bk_dir=/data/backup/mysql/
bk_path=/data/backup/mysql/$bk_date
bk_log=/data/backup/log/$bk_date.log
de_date=`date -d"-7 day" +"%Y%m%d"`
dbs=(agreement cqa_test healthy hive hive_dfs hive_gas hive_kcloud hive_new hive_rec kcloud_chat kcloud_data kcloud_operation kcloud_operation_test kcloud_system kcloud_tool lingxi_yunwei mysql oppo public test xiaomi yunwei)

# alias define
shopt -s expand_aliases
alias now="date +'%Y-%m-%d %H:%M:%S'"
alias nowmin="date +'%H%M'"

# logging level
l1=INFO
l2=WARN
l3=CRIT
l4=UNKNOWN

logging(){
echo "[`now`] $1 $2" >> $bk_log
}

check_bkpath(){
if [ ! -d $bk_path ]
then
logging "$l1" "Backup path $bk_path not exist, make it"
mkdir -p $bk_path
[ $? -eq 0 ] && logging "$l1" "Backup path $bk_path make ok" || logging "l3" "Backup path $bk_path make exception"
fi
}

backup_dbs(){
cd $bk_path
for d in ${dbs[@]}
do
db=$d.`nowmin`
logging "$l1" "DB $db backup starting"
res=`mysqldump -uroot -piflytek! $d > $db.sql 2>&1`
if [ $? -eq 0 ]; then logging "$l1" "DB $db backup finish"; else logging "$l3" "DB $db backup exception: $res"; return 1; fi
logging "$l1" "DB $db compress starting"
res=`tar czf $db.sql.tgz $db.sql 2>&1`
if [ $? -eq 0 ]; then logging "$l1" "DB $db compress finish"; else logging "$l2" "DB $db compress exception: $res"; return 1; fi
res=`rm $db.sql 2>&1`
if [ $? -eq 0 ]; then logging "$l1" "DB $db rm finish"; else logging "$l2" "DB $db rm exception: $res"; return 1; fi
done
}

rm_history(){
cd $bk_dir
ls -l .|awk '{print $NF}'|sort -n|uniq|while read line
do
if [[ ${#line} -eq 8 ]] && [[ $line =~ ^[0-9]*.?[0-9]*$ ]]
then
r=`echo $line|awk '{if($1<="'"$de_date"'")print}'`
if [ ! -z $r ]
then
logging "$l1" "$line is expire, will be removed"
res=`rm -rf $line 2>&1`
[ $? -eq 0 ] && logging "$l1" "$line removed finish" || logging "$l2" "$line removed exception: $res"
fi
fi
done
}

check_bkpath
mdb "BACKING"
[ $? -eq 0 ] && logging "$l1" "Write BACKING to db" || logging "$l2" "Write BACKING to db Failed"
backup_dbs
[ $? -ne 0 ] && mdb "BACKERR" || mdb "BACKOK"
[ $? -eq 0 ] && logging "$l1" "Write BACKOK/BACKERR to db" || logging "$l2" "Write BACKOK/BACKERR to db Failed"
rm_history

mongodb

备份前的检查

1
2
3
4
5
6
7
8
9
10
11
12
> show dbs
MyDB 0.0625GB
admin (empty)
bruce 0.0625GB
local (empty)
test 0.0625GB
> use MyDB
switched to db MyDB
> db.users.find()
{ "_id" : ObjectId("4e290aa39a1945747b28f1ee"), "a" : 1, "b" : 1 }
{ "_id" : ObjectId("4e2cd2182a65c81f21566318"), "a" : 3, "b" : 5 }
>

整库备份

1
mongodump -h dbhost -d dbname -o dbdirectory

-h:MongDB所在服务器地址,例如:127.0.0.1,当然也可以指定端口号:127.0.0.1:27017
-d:需要备份的数据库实例,例如:test
-o:备份的数据存放位置,例如:c:\data\dump,当然该目录需要提前建立,在备份完成后,系统自动在dump目录下建立一个test目录,这个目录里面存放该数据库实例的备份数据。

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
mongodump的官方说明(可通过mongodump --help查看):
options:
--help produce help message
-v [ --verbose ] be more verbose (include multiple times for more
verbosity e.g. -vvvvv)
--version print the program's version and exit
-h [ --host ] arg mongo host to connect to ( /s1,s2 for
sets)
--port arg server port. Can also use --host hostname:port
--ipv6 enable IPv6 support (disabled by default)
-u [ --username ] arg username
-p [ --password ] arg password
--dbpath arg directly access mongod database files in the given
path, instead of connecting to a mongod server -
needs to lock the data directory, so cannot be used
if a mongod is currently accessing the same path
--directoryperdb if dbpath specified, each db is in a separate
directory
--journal enable journaling
-d [ --db ] arg database to use
-c [ --collection ] arg collection to use (some commands)
-o [ --out ] arg (=dump) output directory or "-" for stdout
-q [ --query ] arg json query
--oplog Use oplog for point-in-time snapshotting
--repair try to recover a crashed database
--forceTableScan force a table scan (do not use $snapshot)

备注:
--forceTableScan 在内存比较空闲时可以显著加快对冷数据的备份, 备份速度提升接近100倍

整库恢复

1
mongorestore -h dbhost -d dbname –directoryperdb dbdirectory

-h:MongoDB所在服务器地址
-d:需要恢复的数据库实例,例如:test,当然这个名称也可以和备份时候的不一样,比如test2
–directoryperdb:备份数据所在位置
–drop:恢复的时候,先删除当前数据,然后恢复备份的数据。就是说,恢复后,备份后添加修改的数据都会被删除

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
mongorestore的官方说明(可通过mongorestore --help查看):
options:
--help produce help message
-v [ --verbose ] be more verbose (include multiple times for more
verbosity e.g. -vvvvv)
--version print the program's version and exit
-h [ --host ] arg mongo host to connect to ( /s1,s2 for sets)
--port arg server port. Can also use --host hostname:port
--ipv6 enable IPv6 support (disabled by default)
-u [ --username ] arg username
-p [ --password ] arg password
--dbpath arg directly access mongod database files in the given
path, instead of connecting to a mongod server -
needs to lock the data directory, so cannot be used
if a mongod is currently accessing the same path
--directoryperdb if dbpath specified, each db is in a separate
directory
--journal enable journaling
-d [ --db ] arg database to use
-c [ --collection ] arg collection to use (some commands)
--objcheck validate object before inserting
--filter arg filter to apply before inserting
--drop drop each collection before import
--oplogReplay replay oplog for point-in-time restore
--oplogLimit arg exclude oplog entries newer than provided timestamp
(epoch[:ordinal])
--keepIndexVersion don't upgrade indexes to newest version
--noOptionsRestore don't restore collection options
--noIndexRestore don't restore indexes
--w arg (=1) minimum number of replicas per write

单个collection备份

1
mongoexport -h dbhost -d dbname -c collectionname -f collectionKey -o dbdirectory

-h: MongoDB所在服务器地址
-d: 需要恢复的数据库实例
-c: 需要恢复的集合
-f: 需要导出的字段(省略为所有字段)
-o: 表示导出的文件名

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
mongoexport的官方说明(可通过mongoexport --help查看):
--help produce help message
-v [ --verbose ] be more verbose (include multiple times for more
verbosity e.g. -vvvvv)
--version print the program's version and exit
-h [ --host ] arg mongo host to connect to ( /s1,s2 for
sets)
--port arg server port. Can also use --host hostname:port
--ipv6 enable IPv6 support (disabled by default)
-u [ --username ] arg username
-p [ --password ] arg password
--dbpath arg directly access mongod database files in the given
path, instead of connecting to a mongod server -
needs to lock the data directory, so cannot be used
if a mongod is currently accessing the same path
--directoryperdb if dbpath specified, each db is in a separate
directory
--journal enable journaling
-d [ --db ] arg database to use
-c [ --collection ] arg collection to use (some commands)
-f [ --fields ] arg comma separated list of field names e.g. -f
name,age
--fieldFile arg file with fields names - 1 per line
-q [ --query ] arg query filter, as a JSON string
--csv export to csv instead of json
-o [ --out ] arg output file; if not specified, stdout is used
--jsonArray output to a json array rather than one object per
line
-k [ --slaveOk ] arg (=1) use secondaries for export if available, default
true
--forceTableScan force a table scan (do not use $snapshot)

单个collection恢复

1
mongoimport -d dbhost -c collectionname –type csv –headerline –file

-type: 指明要导入的文件格式
-headerline: 批明不导入第一行,因为第一行是列名
-file: 指明要导入的文件路径

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
mongoimport的官方说明(可通过mongoimport --help查看):
--help produce help message
-v [ --verbose ] be more verbose (include multiple times for more
verbosity e.g. -vvvvv)
--version print the program's version and exit
-h [ --host ] arg mongo host to connect to ( /s1,s2 for sets)
--port arg server port. Can also use --host hostname:port
--ipv6 enable IPv6 support (disabled by default)
-u [ --username ] arg username
-p [ --password ] arg password
--dbpath arg directly access mongod database files in the given
path, instead of connecting to a mongod server -
needs to lock the data directory, so cannot be used
if a mongod is currently accessing the same path
--directoryperdb if dbpath specified, each db is in a separate
directory
--journal enable journaling
-d [ --db ] arg database to use
-c [ --collection ] arg collection to use (some commands)
-f [ --fields ] arg comma separated list of field names e.g. -f name,age
--fieldFile arg file with fields names - 1 per line
--ignoreBlanks if given, empty fields in csv and tsv will be ignored
--type arg type of file to import. default: json (json,csv,tsv)
--file arg file to import from; if not specified stdin is used
--drop drop collection first
--headerline CSV,TSV only - use first line as headers
--upsert insert or update objects that already exist
--upsertFields arg comma-separated fields for the query part of the
upsert. You should make sure this is indexed
--stopOnError stop importing at first error rather than continuing
--jsonArray load a json array, not one item per line. Currently
limited to 16MB.

其他导入与导出操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1. mongoimport -d my_mongodb -c user user.dat

参数说明:

-d 指明使用的库, 本例中为” my_mongodb”

-c 指明要导出的表, 本例中为”user”

可以看到导入数据的时候会隐式创建表结构
2. mongoexport -d my_mongodb -c user -o user.dat

参数说明:

-d 指明使用的库, 本例中为” my_mongodb”

-c 指明要导出的表, 本例中为”user”

-o 指明要导出的文件名, 本例中为”user.dat”

从上面可以看到导出的方式使用的是JSON 的样式.

redis

持久化设置

1
2
3
save 900 1    # 900秒内有至少1个键被更改则进行快照
save 300 10 # 300秒内有至少10个键被更改则进行快照
save 60 10000 # 60秒内有至少10000个键被更改则进行快照

redis 可以直接复制持久化的文件进行备份

1
2
3
4
5
6
7
8
9
#! /bin/bash

PATH=/usr/local/bin:$PATH
redis-cli SAVE

date=$(date +"%Y%m%d")
cp /var/lib/redis/6379/dump.rdb /data01/cache_backup/$date.rdb

echo "done!"

若没有进行持久化可以通过SAVE命令进行持久化

1
redis 127.0.0.1:6379> SAVE

另外可以后台进行操作

1
2
3
127.0.0.1:6379> BGSAVE

Background saving started

一、简介

Keepalived是一个免费开源的,用C编写的类似于layer3, 4 & 7交换机制软件,具备我们平时说的第3层、第4层和第7层交换机的功能。主要提供loadbalancing(负载均衡)和 high-availability(高可用)功能,负载均衡实现需要依赖Linux的虚拟服务内核模块(ipvs),而高可用是通过VRRP协议实现多台机器之间的故障转移服务。
Keepalived体系结构
上图是Keepalived的功能体系结构,大致分两层:用户空间(user space)和内核空间(kernel space)。

内核空间:主要包括IPVS(IP虚拟服务器,用于实现网络服务的负载均衡)和NETLINK(提供高级路由及其他相关的网络功能)两个部份。
用户空间:
WatchDog:负载监控checkers和VRRP进程的状况
VRRP Stack:负载负载均衡器之间的失败切换FailOver,如果只用一个负载均稀器,则VRRP不是必须的。
Checkers:负责真实服务器的健康检查healthchecking,是keepalived最主要的功能。换言之,可以没有VRRP Stack,但健康检查healthchecking是一定要有的。
IPVS wrapper:用户发送设定的规则到内核ipvs代码
Netlink Reflector:用来设定vrrp的vip地址等。
Keepalived的所有功能是配置keepalived.conf文件来实现的。

二、安装与配置

从官网下载keepalived的最新版本,本文以当前最新版本1.2.24为例。

2.1 安装

1
2
3
4
5
6
shell> cd /usr/local/src
shell> wget http://www.keepalived.org/software/keepalived-1.2.24.tar.gz
shell> tar -zxvf keepalived-1.2.24.tar.gz
shell> cd keepalived-1.2.24
shell> ./configure --prefix=/usr/local/keepalived
shell> make && make install

2.2 配置

安装完成后,进入安装目录的etc目录下,将keepalived相应的配置文件拷贝到系统相应的目录当中。keepalived启动时会从/etc/keepalived目录下查找keepalived.conf配置文件,如果没有找到则使用默认的配置。/etc/keepalived目录安装时默认是没有安装的,需要手动创建。配置文件目录结构如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
shell> tree -l /usr/local/keepalived/etc
-- keepalived
| |-- keepalived.conf
| `-- samples
| |-- keepalived.conf.status_code
| |-- keepalived.conf.track_interface
| |-- keepalived.conf.vrrp
| |-- 。。。
|-- rc.d
| `-- init.d
| `-- keepalived
`-- sysconfig
`-- keepalived

分别对应系统目录(忽略samples目录):

1
2
3
/etc/keepalived/keepalived.conf
/etc/rc.d/init.d/keepalived
/etc/sysconfig/keepalived

将配置文件拷贝到系统对应的目录下:

1
2
3
4
shell> mkdir /etc/keepalived
shell> cp /usr/local/keepalived/etc/keepalived.conf /etc/keepalived/keepalived.conf
shell> cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/rc.d/init.d/keepalived
shell> cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/keepalived

设置keepalived服务开机启动:

1
2
3
4
shell> chkconfig keepalived on
shell> service keepalived start #启动服务
shell> service keepalived stop #停止服务
shell> service keepalived restart #重启服务

另外需要注意的一点是,keepalived启动时不会检查配置文件的语法是否正确,所以我们在编写配置文件时要特别小心,别写错了,否则会出现一些意想不到的现象。

使用service keepalived start命令启动服务时,默认会将/etc/sysconfig/keepalived文件中KEEPALIVED_OPTIONS参数作为keepalived服务启动时的参数,并从/etc/keepalived/目录下加载keepalived.conf配置文件,或用-f参数指定配置文件的位置。

1
2
3
4
5
6
7
8
9
10
11
12
13
# Options for keepalived. See `keepalived --help' output and keepalived(8) and
# keepalived.conf(5) man pages for a list of all options. Here are the most
# common ones :
#
# --vrrp -P Only run with VRRP subsystem.
# --check -C Only run with Health-checker subsystem.
# --dont-release-vrrp -V Dont remove VRRP VIPs & VROUTEs on daemon stop.
# --dont-release-ipvs -I Dont remove IPVS topology on daemon stop.
# --dump-conf -d Dump the configuration data.
# --log-detail -D Detailed log messages.日志默认输出在/var/log/message文件中
# --log-facility -S 0-7 Set local syslog facility (default=LOG_DAEMON)
#
KEEPALIVED_OPTIONS="-D"

运行keepalived –help可以查看启动时的可选参数,这些可选参数都可以配置在/etc/sysconfig/keepalived文件中的KEEPALIVED_OPTIONS选项中,作为服务启动时的参数。

keepalived正常运行后,会启动3个进程,其中一个是父进程,负责监控其子进程。一个是vrrp子进程,另外一个是checkers子进程。

1
2
3
4
shell> ps -ef | grep keepalived
root 831 1 0 11:22 ? 00:00:00 keepalived -D
root 840 831 0 11:22 ? 00:00:00 keepalived -D
root 841 831 0 11:22 ? 00:00:00 keepalived -D

到此keepalived就安装完成了。

三、keepalived.conf配置文件说明

keepalived服务安装完成之后,后面的主要工作就是在keepalived.conf文件中配置HA和负载均衡。一个功能比较完整的常用的keepalived配置文件,主要包含三块:全局定义块、VRRP实例定义块和虚拟服务器定义块。全局定义块是必须的,如果keepalived只用来做ha,虚拟服务器是可选的。下面是一个功能比较完整的配置文件模板:

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
#全局定义块
global_defs {
# 邮件通知配置
notification_email {
email1
email2
}
notification_email_from email
smtp_server host
smtp_connect_timeout num

lvs_id string
router_id string ## 标识本节点的字条串,通常为hostname
}

#VRRP 实例定义块
vrrp_sync_group string {
group {
string
string
}
}

vrrp_instance string {
state MASTER|BACKUP
virtual_router_id num
interface string
mcast_src_ip @IP
priority num
advert_int num
nopreempt
smtp_alert
lvs_sync_daemon_interface string
authentication {
auth_type PASS|AH
auth_pass string
}

virtual_ipaddress { # Block limited to 20 IP addresses @IP
@IP
@IP
}
}

#虚拟服务器定义块
virtual_server (@IP PORT)|(fwmark num) {
delay_loop num
lb_algo rr|wrr|lc|wlc|sh|dh|lblc
lb_kind NAT|DR|TUN
persistence_timeout num
protocol TCP|UDP
real_server @IP PORT {
weight num
notify_down /path/script.sh
TCP_CHECK {
connect_port num
connect_timeout num
}
}

real_server @IP PORT {
weight num
MISC_CHECK {
misc_path /path_to_script/script.sh(or misc_path “/path_to_script/script.sh <arg_list>”)
}
}

real_server @IP PORT {
weight num
HTTP_GET|SSL_GET {
url {
# You can add multiple url block path alphanum
digest alphanum
}
connect_port num
connect_timeout num
nb_get_retry num
delay_before_retry num
}
}
}

全局定义块

  1. email通知(notification_email、smtp_server、smtp_connect_timeout):用于服务有故障时发送邮件报警,可选项,不建议用。需要系统开启sendmail服务,建议用第三独立监控服务,如用nagios全面监控代替。
  2. lvs_id:lvs负载均衡器标识,在一个网络内,它的值应该是唯一的。
  3. router_id:用户标识本节点的名称,通常为hostname
  4. 花括号{}:用来分隔定义块,必须成对出现。如果写漏了,keepalived运行时不会得到预期的结果。由于定义块存在嵌套关系,因此很容易遗漏结尾处的花括号,这点需要特别注意。

VRRP实例定义块

vrrp_sync_group:同步vrrp级,用于确定失败切换(FailOver)包含的路由实例个数。即在有2个负载均衡器的场景,一旦某个负载均衡器失效,需要自动切换到另外一个负载均衡器的实例是哪
group:至少要包含一个vrrp实例,vrrp实例名称必须和vrrp_instance定义的一致
vrrp_instance:vrrp实例名

  1. state:实例状态,只有MASTER 和 BACKUP两种状态,并且需要全部大写。抢占模式下,其中MASTER为工作状态,BACKUP为备用状态。当MASTER所在的服务器失效时,BACKUP所在的服务会自动把它的状态由BACKUP切换到MASTER状态。当失效的MASTER所在的服务恢复时,BACKUP从MASTER恢复到BACKUP状态。
  2. interface:对外提供服务的网卡接口,即VIP绑定的网卡接口。如:eth0,eth1。当前主流的服务器都有2个或2个以上的接口(分别对应外网和内网),在选择网卡接口时,一定要核实清楚。
  3. mcast_src_ip:本机IP地址
  4. virtual_router_id:虚拟路由的ID号,每个节点设置必须一样,可选择IP最后一段使用,相同的 VRID 为一个组,他将决定多播的 MAC 地址。
  5. priority:节点优先级,取值范围0~254,MASTER要比BACKUP高
  6. advert_int:MASTER与BACKUP节点间同步检查的时间间隔,单位为秒
  7. lvs_sync_daemon_inteface:负载均衡器之间的监控接口,类似于 HA HeartBeat 的心跳线。但它的机制优于 Heartbeat,因为它没有“裂脑”这个问题,它是以优先级这个机制来规避这个麻烦的。在 DR 模式中,lvs_sync_daemon_inteface与服务接口interface使用同一个网络接口
  8. authentication:验证类型和验证密码。类型主要有 PASS、AH 两种,通常使用PASS类型,据说AH使用时有问题。验证密码为明文,同一vrrp 实例MASTER与BACKUP使用相同的密码才能正常通信。
  9. smtp_alert:有故障时是否激活邮件通知
  10. nopreempt:禁止抢占服务。默认情况,当MASTER服务挂掉之后,BACKUP自动升级为MASTER并接替它的任务,当MASTER服务恢复后,升级为MASTER的BACKUP服务又自动降为BACKUP,把工作权交给原MASTER。当配置了nopreempt,MASTER从挂掉到恢复,不再将服务抢占过来。
  11. virtual_ipaddress:虚拟IP地址池,可以有多个IP,每个IP占一行,不需要指定子网掩码。注意:这个IP必须与我们的设定的vip保持一致。
    虚拟服务器virtual_server定义块

virtual_server:定义一个虚拟服务器,这个ip是virtual_ipaddress中定义的其中一个,后面一个空格,然后加上虚拟服务的端口号。

  1. delay_loop:健康检查时间间隔,单位:秒
  2. lb_algo:负载均衡调度算法,互联网应用常用方式为wlc或rr
  3. lb_kind:负载均衡转发规则。包括DR、NAT、TUN 3种,一般使用路由(DR)转发规则。
  4. persistence_timeout:http服务会话保持时间,单位:秒
  5. protocol:转发协议,分为TCP和UDP两种
    real_server:真实服务器IP和端口,可以定义多个
  6. weight:负载权重,值越大,转发的优先级越高
  7. notify_down:服务停止后执行的脚本
  8. TCP_CHECK:服务有效性检测
  • connect_port:服务连接端口
  • connect_timeout:服务连接超时时长,单位:秒
  • nb_get_retry:服务连接失败重试次数
  • delay_before_retry:重试连接间隔,单位:秒