python3 flask中SQLAlchemy创建表的简单介绍

在flask的SQLAlchemy中创建表,也是存在 ForeignKey(一对多) 与 ManyToMany(多对多) 的存在,以下是在models中单表、一对多、多对多的创建方式。

models.py代码如下:

import datetime
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column,Integer,String,Text,ForeignKey,DateTime,UniqueConstraint,Index
from sqlalchemy.orm import relationship

Base = declarative_base()

# 【单表创建的示例】
class Users(Base):
    __tablename__ = 'users'
    id = Column(Integer,primary_key=True)
    name = Column(String(32),index=True)
    age = Column(Integer,default=18)
    email = Column(String(32),unique=True)  # unique = True 表示该字段中的值唯一
    ctime = Column(DateTime,default=datetime.datetime.now())
    extra = Column(Text,nullable=True)

    __table_args__ = (
        UniqueConstraint('id','name',name='unique_id_name'),  # 创建表中id和name字段的唯一索引,最后一个参数是索引名,注意前面要写name=
        Index('ix_name_email','name','email')   # 创建表中多个字段的普通索引
    )


# 【一对多示例】
# 表1
class Hobby(Base):
    __tablename__ = 'hobby'
    id = Column(Integer,primary_key=True)
    caption = Column(String(10),nullable=False,default='台球')

# 表2
class Person(Base):
    __tablename__ = 'person'
    nid = Column(Integer,primary_key=True)
    name = Column(String(32),index=True,nullable=True)
    # 创建一对多的关系
    hobby_id = Column(Integer,ForeignKey('hobby.id'))

    #   此字段不在表中生成,只是为了方便调用Hooby表;
    # 正向查找时可以直接用“hobby.”调用“Hobby”表中的字段。
    # 在hobby表中反向查找时可以用“pers”调用“Person”表中的字段。
    hobby = relationship('Hobby',backref='pers')


# 【多对多示例】
# 两表的关系表
class Server2Group(Base):
    __tablename__ = 'server2group'
    id = Column(Integer,primary_key=True,autoincrement=True)
    server_id = Column(Integer,ForeignKey('server.id'))
    group_id = Column(Integer,ForeignKey('group.id'))



# 表1
class Server(Base):
    __tablename__ = 'server'
    id = Column(Integer,primary_key=True,autoincrement=True)
    hostname = Column(String(15),nullable=True,unique=True)

    # 用于方便查找的标识
    groups = relationship('Group',secondary='server2group',backref='servers')

# 表2
class Group(Base):
    __tablename__ = 'group'
    id = Column(Integer,primary_key=True,autoincrement=True)
    name = Column(String(32),nullable=True,unique=True)


def create_all():
    """
        根据类创建数据库表
        :return:
        """
    engine = create_engine(
        "mysql+pymysql://root:[email protected]:3306/test0621?charset=utf8",
        max_overflow=0,  # 超过连接池大小外最多创建的连接
        pool_size=5,  # 连接池大小
        pool_timeout=30,  # 池中没有线程最多等待的时间,否则报错
        pool_recycle=-1  # 多久之后对线程池中的线程进行一次连接的回收(重置)
    )

    Base.metadata.create_all(engine)


def drop_db():
    """
    根据类删除数据库表
    :return:
    """
    engine = create_engine(
        "mysql+pymysql://root:[email protected]:3306/test0621?charset=utf8",
        max_overflow=0,  # 超过连接池大小外最多创建的连接
        pool_size=5,  # 连接池大小
        pool_timeout=30,  # 池中没有线程最多等待的时间,否则报错
        pool_recycle=-1  # 多久之后对线程池中的线程进行一次连接的回收(重置)
    )

    Base.metadata.drop_all(engine)


if __name__ == '__main__':
    drop_db()
    create_all()

记PostgreSQL的连接问题

今天打开psql的时候出现这个错误

psql: could not connect to server: Connection refused (0x0000274D/10061)
Is the server running on host “localhost” (::1) and accepting
TCP/IP connections on port 5432?
could not connect to server: Connection refused (0x0000274D/10061)
Is the server running on host “localhost” (127.0.0.1) and accepting
TCP/IP connections on port 5432?

解决如下

这个问题一般是以下原因造成的:

1.服务器没起来,ps -ef|grep postgres查看是否存在PG进程
2.监听问题,cat postgresql.conf|grep listen 查看监听地址端口是否正确
3.服务端超级用户能进去,其他用户不行,检查是否超出最大连接数限制
4.以上都没问题,服务器端能连进去,但客户端不行,这时需要查看pg_hba.conf文件
5.以上都没问题,检查服务器端的iptables,开启防火墙的访问端口

最后发现端口不是默认的5432,修改即可。

PostgreSQL 主从设置

主库设置

先添加repuser用户

然后设置pg_hba

vi /var/lib/pgsql/10/data/pg_hba.config

未分类

从库设置

把原有数据全删了

rm -rf /var/lib/pgsql/10/data/

然后执行 pg_basebackup -h IP_ADDRESS -R -D /var/lib/pgsql/10/data -U repuser -W

然后运行pgsql

service postgresql-10 start

lnmp环境不重新编译php安装postgresql扩展(pgsql和pdo_pgsql)

新项目的服务器使用的是lnmp环境,已经把mysql换成了postgresql,那么必须让php支持pgsql扩展。

为了不重新编译php,使用phpize工具进行追加。

1.下载php7安装包

访问php官方下载页,找到自己对应的php版本:https://secure.php.net/downloads.php
wget //cn2.php.net/distributions/php-7.0.30.tar.gz

2.解压并进入扩展目录

tar xzf php-7.0.30.tar.gz
cd php-7.0.30/ext/pgsql

3.运行phpize(我的php安装目录为/usr/local/php/)

/usr/local/php/bin/phpize

4.编译安装

./configure --with-php-config=/usr/local/php/bin/php-config
make && make install

5.修改php配置文件php.ini,添加pgsql.so模块

vi /usr/local/php/etc/php.ini
添加
extension=pgsql.so
extension=pdo_pgsql.so

6.重启php后,检查是否有pgsql模块

php -m

注:pdo_pgsql操作同上

解决Ubuntu 16.04更新系统内核出错后的问题

大伟哥的工作电脑使用Ubuntu 16.04系统,已经很久没有更新了,今天正好有空,就运行了sudo apt update, sudo apt upgrade让它在后台自已更新去了。

因为要更新的软件比较多,需要花费挺长时间,大伟哥也没怎么在意,只是在运行结束后看了一下报错,上面显示因为boot分区空间不够,升级linux内核的时候出错了:

在处理时有错误发生:

linux-image-extra-4.4.0-97-generic
linux-image-generic
linux-generic
E: Sub-process /usr/bin/dpkg returned an error code (1)

之前也发生了同样的问题,系统提示可以运行sudo apt-get autoremove清除不需要的依赖的,而多次升级后/boot分区里已经有了多个之前版本的Linux内核,因此大伟哥决定先运行一下这个命令,看能不能自动给/boot分区清理出一部分空间来,这样也省得我再查文档手动清除旧的内核文件了。实验证明这个命令真的有效果,/boot分区清理出了100多M的空间,应该也够安装新的内核了。

再次执行sudo apt update/sudo apt upgrade, 系统并没有接着安装上次没有完成安装的内核,而是报错如下:

davidbro@Workstation:~$ sudo apt upgrade

正在读取软件包列表... 完成
正在分析软件包的依赖关系树       
正在读取状态信息... 完成       
正在计算更新... 完成
有一些软件包无法被安装。如果您用的是 unstable 发行版,这也许是
因为系统无法达到您要求的状态造成的。该版本中可能会有一些您需要的软件
包尚未被创建或是它们已被从新到(Incoming)目录移出。
下列信息可能会对解决问题有所帮助:

下列软件包有未满足的依赖关系:
 linux-image-extra-4.4.0-96-generic : 依赖: linux-image-4.4.0-96-generic 但是它将不会被安装
E: 破损的软件包

试一下sudo apt install命令看看不能能安装:

david@KingChef-Workstation:~$ sudo apt-get install

正在读取软件包列表... 完成
正在分析软件包的依赖关系树       
正在读取状态信息... 完成       
下列软件包将被【卸载】:
  linux-image-extra-4.4.0-96-generic
升级了 0 个软件包,新安装了 0 个软件包,要卸载 1 个软件包,有 0 个软件包未被升级。
有 5 个软件包没有被完全安装或卸载。
解压缩后将会空出 153 MB 的空间。
您希望继续执行吗? [Y/n] Y
(正在读取数据库 ... 系统当前共安装有 356556 个文件和目录。)
正在卸载 linux-image-extra-4.4.0-96-generic (4.4.0-96.119) ...
depmod: FATAL: could not load /boot/System.map-4.4.0-96-generic: No such file or directory
run-parts: executing /etc/kernel/postinst.d/apt-auto-removal 4.4.0-96-generic /boot/vmlinuz-4.4.0-96-generic
run-parts: executing /etc/kernel/postinst.d/dkms 4.4.0-96-generic /boot/vmlinuz-4.4.0-96-generic
Error! Your kernel headers for kernel 4.4.0-96-generic cannot be found.
Please install the linux-headers-4.4.0-96-generic package,
or use the --kernelsourcedir option to tell DKMS where it's located
Error! Your kernel headers for kernel 4.4.0-96-generic cannot be found.
Please install the linux-headers-4.4.0-96-generic package,
or use the --kernelsourcedir option to tell DKMS where it's located
run-parts: executing /etc/kernel/postinst.d/initramfs-tools 4.4.0-96-generic /boot/vmlinuz-4.4.0-96-generic
update-initramfs: Generating /boot/initrd.img-4.4.0-96-generic
WARNING: missing /lib/modules/4.4.0-96-generic
Ensure all necessary drivers are built into the linux image!
depmod: ERROR: could not open directory /lib/modules/4.4.0-96-generic: No such file or directory
depmod: FATAL: could not search modules: No such file or directory
depmod: WARNING: could not open /var/tmp/mkinitramfs_pkdOqR/lib/modules/4.4.0-96-generic/modules.order: No such file or directory
depmod: WARNING: could not open /var/tmp/mkinitramfs_pkdOqR/lib/modules/4.4.0-96-generic/modules.builtin: No such file or directory
run-parts: executing /etc/kernel/postinst.d/pm-utils 4.4.0-96-generic /boot/vmlinuz-4.4.0-96-generic
run-parts: executing /etc/kernel/postinst.d/unattended-upgrades 4.4.0-96-generic /boot/vmlinuz-4.4.0-96-generic
run-parts: executing /etc/kernel/postinst.d/update-notifier 4.4.0-96-generic /boot/vmlinuz-4.4.0-96-generic
run-parts: executing /etc/kernel/postinst.d/zz-update-grub 4.4.0-96-generic /boot/vmlinuz-4.4.0-96-generic
Generating grub configuration file ...
Warning: Setting GRUB_TIMEOUT to a non-zero value when GRUB_HIDDEN_TIMEOUT is set is no longer supported.
Found linux image: /boot/vmlinuz-4.4.0-130-generic
Found initrd image: /boot/initrd.img-4.4.0-130-generic
Found linux image: /boot/vmlinuz-4.4.0-98-generic
Found initrd image: /boot/initrd.img-4.4.0-98-generic
Found linux image: /boot/vmlinuz-3.5.0-54-generic
Found initrd image: /boot/initrd.img-3.5.0-54-generic
Found linux image: /boot/vmlinuz-3.5.0-23-generic
Found initrd image: /boot/initrd.img-3.5.0-23-generic
done
正在设置 initramfs-tools (0.122ubuntu8.11) ...
update-initramfs: deferring update (trigger activated)
正在设置 linux-image-extra-4.4.0-130-generic (4.4.0-130.156) ...
run-parts: executing /etc/kernel/postinst.d/apt-auto-removal 4.4.0-130-generic /boot/vmlinuz-4.4.0-130-generic
run-parts: executing /etc/kernel/postinst.d/dkms 4.4.0-130-generic /boot/vmlinuz-4.4.0-130-generic
ERROR: Cannot create report: [Errno 17] File exists: '/var/crash/i915-4.6.3-4.4.0-dkms.0.crash'
Error! Bad return status for module build on kernel: 4.4.0-130-generic (x86_64)
Consult /var/lib/dkms/i915-4.6.3-4.4.0/1/build/make.log for more information.
run-parts: executing /etc/kernel/postinst.d/initramfs-tools 4.4.0-130-generic /boot/vmlinuz-4.4.0-130-generic
update-initramfs: Generating /boot/initrd.img-4.4.0-130-generic
run-parts: executing /etc/kernel/postinst.d/pm-utils 4.4.0-130-generic /boot/vmlinuz-4.4.0-130-generic
run-parts: executing /etc/kernel/postinst.d/unattended-upgrades 4.4.0-130-generic /boot/vmlinuz-4.4.0-130-generic
run-parts: executing /etc/kernel/postinst.d/update-notifier 4.4.0-130-generic /boot/vmlinuz-4.4.0-130-generic
run-parts: executing /etc/kernel/postinst.d/zz-update-grub 4.4.0-130-generic /boot/vmlinuz-4.4.0-130-generic
Generating grub configuration file ...
Warning: Setting GRUB_TIMEOUT to a non-zero value when GRUB_HIDDEN_TIMEOUT is set is no longer supported.
Found linux image: /boot/vmlinuz-4.4.0-130-generic
Found initrd image: /boot/initrd.img-4.4.0-130-generic
Found linux image: /boot/vmlinuz-4.4.0-98-generic
Found initrd image: /boot/initrd.img-4.4.0-98-generic
Found linux image: /boot/vmlinuz-3.5.0-54-generic
Found initrd image: /boot/initrd.img-3.5.0-54-generic
Found linux image: /boot/vmlinuz-3.5.0-23-generic
Found initrd image: /boot/initrd.img-3.5.0-23-generic
done
正在设置 linux-image-generic (4.4.0.130.136) ...
正在设置 linux-generic (4.4.0.130.136) ...
正在处理用于 initramfs-tools (0.122ubuntu8.11) 的触发器 ...
update-initramfs: Generating /boot/initrd.img-4.4.0-130-generic

这样最新的内核版本4.4.0.130.136就安装好了。其实我觉得这样用autoremove腾出分区空间还是有点风险的,有可能会误删掉其他有用的软件。

git命令-远程仓库拉取、本地仓库更新、工作空间提交等等

未分类

一,新建代码库

1,在当前目录下新建一个git代码库

$ git init 

2,新建一个目录将其初始化为git代码库

$ git init [project-name]

3,git clone 远程代码库

$ git clone [url]

二,配置

1,Git的设置文件为.gitconfig,它可以在用户主目录下(全局配置),也可以在项目目,录(项目配置)。
2, 显示当前的Git配置

$ git config--list

3,编辑git配置文件

$ git config -e[--global]

4,设置提交代码时的用户信息

$ git config[--global] user.name "[name]" 
$ git config[--global] user.email "[email address]"

三、增加/删除文件

1,添加指定文件到暂存区

$ git add [file1][file2] ...

2, 添加指定目录到暂存区,包括子目录,

$ git add [dir]

3, 添加当前目录的所有文件到暂存区

$ git add .

4 添加每个变化前,都会要求确认, 对于同一个文件的多处变化,可以实现分次提交

$ git add -p

5,删除工作区文件,并且将这次删除放入暂存区

$ git rm [file1][file2] ...

6, 停止追踪指定文件,但该文件会保留在工作区

$ git rm --cached[file] 

7, 改名文件,并且将这个改名放入暂存区

$ git mv[file-original] [file-renamed]

四、代码提交

1, 提交暂存区到仓库区,

$ git commit -m[message],

2, 提交暂存区的指定文件到仓库区

$ git commit[file1] [file2] ... -m [message],

3,提交工作区自上次commit之后的变化,直接到仓库区

$ git commit -a,

4, 提交时显示所有diff信息

$ git commit -v

5,使用一次新的commit,替代上一次提交,如果代码没有任何新变化,则用来改写上一次commit的提交信息

$ git commit--amend -m [message]

6, 重做上一次commit,并包括指定文件的新变化

$ git commit--amend [file1] [file2] ...

五、分支

1, 列出所有本地分支

$ git branch

2, 列出所有远程分支

$ git branch -r

3, 列出所有本地分支和远程分支

$ git branch -a

4, 新建一个分支,但依然停留在当前分支

$ git branch[branch-name]

5, 新建一个分支,并切换到该分支

$ git checkout -b[branch]

6, 新建一个分支,指向指定commit

$ git branch[branch] [commit]

7, 新建一个分支,与指定的远程分支建立追踪关系

$ git branch--track [branch] [remote-branch]

8, 切换到指定分支,并更新工作区

$ git checkout[branch-name],

9, 切换到上一个分支

$ git checkout -,

10, 建立追踪关系,在现有分支与指定的远程分支之间

$ git branch--set-upstream [branch] [remote-branch]

11, 合并指定分支到当前分支,

$ git merge[branch]

12, 选择一个commit,合并进当前分支,

$ git cherry-pick[commit]

13, 删除分支,

$ git branch -d[branch-name]

14, 删除远程分支,

$ git push origin--delete [branch-name]
$ git branch -dr[remote/branch]

六、标签,

1, 列出所有tag

$ git tag

2, 新建一个tag在当前commit,

$ git tag [tag]

3, 新建一个tag在指定commit,

$ git tag [tag][commit]

4, 删除本地tag,

$ git tag -d[tag]

5, 删除远程tag,

$ git push origin:refs/tags/[tagName]

6, 查看tag信息,

$ git show [tag]

7, 提交指定tag,

$ git push[remote] [tag]

8, 提交所有tag,

$ git push[remote] --tags

9, 新建一个分支,指向某个tag

$ git checkout -b[branch] [tag]

七、查看信息

1, 显示有变更的文件

$ git status

2, 显示当前分支的版本历史

$ git log

3, 显示commit历史,以及每次commit发生变更的文件

$ git log --stat

4, 搜索提交历史,根据关键词

$ git log -S[keyword]

5, 显示某个commit之后的所有变动,每个commit占据一行

$ git log [tag]HEAD --pretty=format:%s

6, 显示某个commit之后的所有变动,其”提交说明”必须符合搜索条件,

$ git log [tag]HEAD --grep feature

7, 显示某个文件的版本历史,包括文件改名

$ git log --follow[file]
$ git whatchanged[file]

8, 显示指定文件相关的每一次diff

$ git log -p[file]

9, 显示过去5次提交,

$ git log -5--pretty --oneline

10, 显示所有提交过的用户,按提交次数排序

$ git shortlog-sn

11, 显示指定文件是什么人在什么时间修改过,

$ git blame[file]

12, 显示暂存区和工作区的差异

$ git diff

13,显示暂存区和上一个commit的差异

$ git diff--cached [file]

14, 显示工作区与当前分支最新commit之间的差异

$ git diff HEAD

14, 显示两次提交之间的差异,

$ git diff[first-branch]...[second-branch]

15,显示今天你写了多少行代码,

$ git diff--shortstat "@{0 day ago}"

16, 显示某次提交的元数据和内容变化

$ git show[commit]

17, 显示某次提交发生变化的文件,

$ git show--name-only [commit]

18,显示某次提交时,某个文件的内容

$ git show[commit]:[filename]

19, 显示当前分支的最近几次提交

$ git reflog

八、远程同步

1, 下载远程仓库的所有变动

$ git fetch[remote]

2,显示所有远程仓库,

$ git remote -v

3, 显示某个远程仓库的信息,

$ git remote show[remote]

4, 增加一个新的远程仓库,并命名

$ git remote add[shortname] [url]

5,取回远程仓库的变化,并与本地分支合并

$ git pull[remote] [branch]

6, 上传本地指定分支到远程仓库

$ git push[remote] [branch]

7, 强行推送当前分支到远程仓库,即使有冲突

$ git push[remote] --force

8, 推送所有分支到远程仓库

$ git push[remote] --all

九、撤销

1, 恢复暂存区的指定文件到工作区,

$ git checkout[file]

2, 恢复某个commit的指定文件到暂存区和工作区,

$ git checkout[commit] [file]

3,恢复暂存区的所有文件到工作区,

$ git checkout .

4, 重置暂存区的指定文件,与上一次commit保持一致,但工作区不变

$ git reset[file]

5, 重置暂存区与工作区,与上一次commit保持一致

$ git reset--hard

6, 重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变

$ git reset[commit]

7, 重置当前分支的HEAD为指定commit,同时重置暂存区和工作区,与指定commit一致

$ git reset--hard [commit]

8, 重置当前HEAD为指定commit,但保持暂存区和工作区不变

$ git reset--keep [commit]

9, 新建一个commit,用来撤销指定commit, 后者的所有变化都将被前者抵消,并且应用到当前分支

$ git revert[commit]

10, 暂时将未提交的变化移除,稍后再移入

$ git stash
$ git stash pop

十、其他

1, 生成一个可供发布的压缩包

$ git archive

git命令-切换分支

git一般有很多分支,我们clone到本地的时候一般都是master分支,那么如何切换到其他分支呢?主要命令如下:

1. 查看远程分支

$ git branch -a
我在mxnet根目录下运行以上命令:

~/mxnet$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
  remotes/origin/nnvm
  remotes/origin/piiswrong-patch-1
  remotes/origin/v0.9rc1

可以看到,我们现在在master分支下

2. 查看本地分支

~/mxnet$ git branch
* master

3. 切换分支

$ git checkout -b v0.9rc1 origin/v0.9rc1
Branch v0.9rc1 set up to track remote branch v0.9rc1 from origin.
Switched to a new branch 'v0.9rc1'

#已经切换到v0.9rc1分支了
$ git branch
  master
* v0.9rc1

#切换回master分支
$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.

用Zabbix和Docker搭建监控平台

Zabbix 是由 Alexei Vladishev 开发的一种网络监视、管理系统,基于 Server-Client 架构。可用于监视各种网络服务、服务器和网络机器等状态。

1. 架构

Zabbix 作为企业级分布式监控系统,具有很多优点,如:分布式监控,支持 node 和 proxy 分布式模式;自动化注册,根据规则,自动注册主机到监控平台,自动添加监控模板;支持 agentd、snmp、ipmi 和 jmx 等很多通信方式。

同时,Zabbix 官方还发布了 Zabbix Docker 镜像。此次我们以 Zabbix 的官方 Docker 镜像为基础,搭建一个监控平台。 总体架构图如下所示:
未分类
其中,使用 Zabbix 官方的提供的镜像 Zabbix-3.0:3.0.0 作为 Zabbix Web GUI 和 Zabbix Server;Zabbix Server 用来接收来自 Zabbix agent 的数据,并将数据存储到 Zabbix Database,根据配置的监控项和获取到的数据,判断是否达到报警条件,来对主机进行监控;Zabbix Web GUI 提供了 Zabbix Server 的配置和数据展示的可视化界面;

使用 MySQL 作为 Zabbix Database,官方有相应的 MariaDB 的镜像,但是与非容器化的 MySQL 并没有什么区别,因此便于数据的集中管理,我们并不再单独启动一个 MySQL 容器,而是使用已经存在的 MySQL;

使用由 million12 提供的 zabbix-agent:2.4.7 镜像作为 Zabbix agent 部署在各个需要监控的主机上,用来采集 CPU 、内存和进程等监控项的的数据,并发送到 Zabbix Server;

2. 数据库配置

对于数据库无需过多配置,仅需为 Zabbix Server 配置一个用户名密码让其能够访问数据库zabbix 即可。此处配置用户名:zabbix, 密码:zabbix,配置命令如下:

mysql> grant all privileges on zabbix.* to zabbix@'%' identified by 'zabbix';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

3. 启动 Zabbix Server

采用 docker-compose 的方式启动 Zabbix Server,docker-compose.yml 文件内容如下:

version: '2'
services:
  zabbix-server:
    image: zabbix/zabbix-3.0:3.0.0
    container_name: zabbix-server
    network_mode: "bridge"
    restart: always
    ports:
      - "8888:80"
      - "10051:10051"
    volumes:
      - /etc/localtime:/etc/localtime:ro
    environment:
      - ZS_DBHost=192.168.1.100
      - ZS_DBUser=zabbix
      - ZS_DBPassword=zabbix

其中环境变量 ZS_DBHost 是 Zabbix Server 的 IP,我的主机是 192.168.1.100; ZS_DBUser 和ZS_DBPassword 是数据库的用户名和密码,即我们上一步设置的 zabbix;

暴露端口 8888 用于访问页面,10051 用于和 Zabbix-agent 通信;

用 docker-compose up -d 即可启动 Zabbix Server, 启动过程大约需要 1~3 min。用docker logs -f zabbix-server 命令查看容器的日志,日志大致内容如下:

[[email protected] zabbix-server]$ docker logs -f zabbix-server
Creating zabbix-server
Attaching to zabbix-server
zabbix-server | Nginx status page: allowed address set to 127.0.0.1.
zabbix-server | PHP-FPM status page: allowed address set to 127.0.0.1.
zabbix-server | [LOG 13:39:08] Preparing server configuration
zabbix-server | [LOG 13:39:16] Config updated.
zabbix-server | [LOG 13:39:16] Enabling logging and pid management
zabbix-server | [LOG 13:39:17] Done
zabbix-server | [LOG 13:39:17] Waiting for database server
zabbix-server | [LOG 13:39:17] Database server is available
zabbix-server | [LOG 13:39:17] Checking if database exists or SQL import is required
zabbix-server | [WARNING 13:39:17] Zabbix database doesn't exist. Installing and importing default settings
zabbix-server | ERROR 1044 (42000) at line 1: Access denied for user 'zabbix'@'%' to database 'zabbix'
zabbix-server | ERROR 1227 (42000) at line 1: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation
zabbix-server |
zabbix-server | [LOG 13:39:17] Database and user created, importing default SQL
zabbix-server |
zabbix-server | [LOG 13:42:37] Import finished, starting
zabbix-server | [LOG 13:42:37] Starting Zabbix version 3.0.0
zabbix-server | 2016
zabbix-server | 2016-04-07 13:42:37,691 CRIT Supervisor running as root (no user in config file)
zabbix-server | 2016-04-07 13:42:37,691 WARN Included extra file "/etc/supervisor.d/nginx.conf" during parsing
zabbix-server | 2016-04-07 13:42:37,691 WARN Included extra file "/etc/supervisor.d/php-fpm.conf" during parsing

通过日志可以看出,Zabbix Server 启动过程中使用了我们配置的用户名和密码初始化了名为zabbix 的数据库,并导入相应的数据结构及相应的基础数据,所以该容器启动耗时长达 3 min 左右。容器启动后,我们访问 http://192.168.1.100:8888, 出现如下界面,证明 Zabbix Server 启动成功。
未分类
默认账号的用户名、密码是:Admin 和 zabbix, 输入用户名密码登录,即可看到主界面。
未分类
进入到 Configuration 》Hosts 下,点击 disable 按钮,启用 Zabbix Server。
未分类
启用成功后,AVAILABILITY 项中 ZBX 变为绿色,如下图:
未分类

4. 启动 Zabbix agent

同样,Zabbix agent 的启动仍然以 docker-compose 的方式,不同的是 Zabbix agent 添加了一个配置文件,zabbix-agent 目录结构如下:

zabbix-agent
|-- conf
|   -- zabbix-agentd.conf
 -- docker-compose.yml

conf/zabbix-agentd.conf 的内容如下:

LogFile=/tmp/zabbix_agentd.log
EnableRemoteCommands=1
Server=192.168.1.100
ListenPort=10050
ServerActive=192.168.1.100

其中 ListenPort 为容器 zabbix-agent 暴露的端口,用于接收 Zabbix Server 的指令与其交互;Server 和 ServerActive 都指向 Zabbix Server 的 IP;

docker-compose.yml 内容如下:

version: '2'
services:
  zabbix-agent:
    image: million12/zabbix-agent:2.4.7
    container_name: zabbix-agent
    restart: always
    network_mode: "bridge"
    ports:
      - "10050:10050"
    volumes:
      - ./conf/zabbix-agentd.conf:/etc/zabbix_agentd.conf
      - /proc:/data/proc
      - /sys:/data/sys
      - /dev:/data/dev
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - ZABBIX_SERVER=192.168.1.100

其中,ports 暴露了配置文件中需要暴露的接口;挂载 ./conf/zabbix-agentd.conf 自定义配置文件到容器中 /etc/zabbix_agentd.conf 取代默认的配置文件;挂载 /proc、 /sys 和 /dev到容器中 /data 相应文件夹下,用于 zabbix-agent 收集系统进程等监控信息;环境变量中ZABBIX_SERVER 指向 Zabbix Server 的 IP;

运行 docker-compose up -d 即可启动;

5. 结束

数据库已经配置成功,Zabbix Server 正常启动,Zabbix agent 也正常启动,至于如何在 Zabbix Server 中添加需要监控的主机,有很多方式,如主动添加和跟 IP 范围自动发现,但是不在本文讨论范围之内。至此,用Zabbix 和 Docker 搭建监控平台已经完全实现。

(1)报警媒介 Email 配置注意项

未分类
SMTP helo 配置项中,一般是 SMTP server 根域名。如对于腾讯企业邮箱,SMTP server 是smtp.exmail.qq.com,则此处的 SMTP helo 应填写 qq.com。

(2)修改 Zabbix Server 系统语言为简体中文

对于 3.0 版本的 Zabbix Server 系统语言选择下拉框中默认是没有简体中文的,需要改动其源码,改动方式如下:

docker exec -it zabbix-server /bin/bash 进入容器;
vi /usr/local/src/zabbix/frontends/php/include/locales.inc.php,修改文件中的'zh_CN' => ['name' => _('Chinese (zh_CN)'), 'display' => false] 的 false 为 true 即可。

git-bash设置ssh心跳包防超时断开

Windows中使用git-bash作为日常终端工具,在使用ssh命令连接到服务器后,如果较长时间没进行交互时,ssh会断开,导致的现象就是终端卡住,你只能等待它退出,或直接关闭窗口重建连接,很麻烦。

使用ssh命令时,可以增加ServerAliveInterval参数设置心跳时间,比如设置60秒发送一次心跳包

ssh -o ServerAliveInterval=60 [email protected]

想一劳永逸,可以在ssh-config中配置全局参数
在git安装目录下的etc/ssh/ssh_config文件中,增加一行

ServerAliveInterval 60

现在再使用ssh时,就可以一直保存ssh连接在线了。

redis缓存同步小伎俩

redis做缓存分为被动和主动两种,今天要说的是被动+主动结合的一个小伎俩。

主动+被动结合,有2种常见做法:

  • set流派
    • 查询时,先查redis,不命中再查mysql,将结果set到redis里缓存TTL时间
    • 更新时,先更新mysql,再set到redis里缓存TTL时间
  • delete流派
    • 查询流程同上
    • 更新时,先更新mysql,再去redis里做delete删除掉缓存

set流派适合应付读热点的场景,不希望因为delete造成缓存穿透,影响到性能。

delete流派比较平庸,没有太密集的热点读压力,偏向于海量冷数据的被动缓存,删除的性价比更高。

小伎俩

今天的小伎俩与set流派有关,主要指出一个并发竞争的case。

考虑如下的时序:

  • 查询:redis miss,于是查询了mysql得到数据A。
  • 更新:mysql数据修改为B,同时set到Redis中。
  • 查询:通过set 命令将A更新到redis中。

结局:缓存里cache了一份老数据A。

对于缓存一致性要求高的业务是无法接受这种竞争的,即便没有很高的缓存一致性要求,一般业务也不希望这种事情出现。

解决方法,查询时使用setnx命令(set if not exist)取代set,同理可以用hsetnx取代hset,不同数据结构均有对应方法。