just a joke

且说有一天,一群物理学家在天堂里闲极无聊,便玩起了抓人游戏。这回轮到爱因斯坦抓人了。待他数到100,便睁开眼睛。只见所有人都藏起来了,只有伏特还趴在不远处。
爱因斯坦走过去,说:“伏特,我抓住你了。”
伏特说:“不,你没有抓到我。”
爱因斯坦说:“你若不是伏特,那你又是谁?”
伏特说:“你且看看我身下是谁?”
爱因斯坦低头一看,趴在伏特身下的,竟是安培!
伏特说:“我身下是安培,我俩就是伏特/安培,所以你抓住的不是我,你抓住的是欧姆!”
爱因斯坦反应何其敏捷,迅速改口道:“欧姆,我抓住你了!” 可是呢,伏特和安培毕竟是欧姆的好哥们。于是,伏特和安培一个鱼跃站了起来,但是仍然紧紧抱在一起,爱因斯坦感到大惑不解。
他俩不紧不慢地说,现在,我们不再是欧姆,而是伏特×安培, 变成瓦特了!
爱因斯坦觉得很有道理,于是喊,那我终于抓到你了,瓦特!
这时,瓦特躲在角落里,慢慢悠悠地开口说:“你看,他俩这样抱着已经有好几秒了,所以,你抓到的不是瓦特,而是瓦特×秒,是焦耳啦!”
这时,爱因斯坦看到牛顿站在不远处。于是他跑过去说:“牛顿,我抓住你了。”
牛顿说:“不,你没有抓到牛顿。”
爱因斯坦说:“你如果不是牛顿,那你是谁?”
牛顿说:“你看,我脚下踩的是什么?”
爱因斯坦低头一看,只见牛顿站在一块长宽都是一米的正方形地砖上。
牛顿说:“我脚下是一块一平方米的方块,我站在上面,就是牛顿/平方米。所以说,你抓住的并不是牛顿,而是帕斯卡呀!”
爱因斯坦屡受挫折,终于忍无可忍,爆发了。于是,他飞起一脚,踹在了牛顿身上,把牛顿踹出了那块一平米的地板砖。
然后他吼道:“说!你还敢说你是帕斯卡吗!”
牛顿慢吞吞地从地上爬起来,说:“不,我已经不是帕斯卡了。你刚刚让我牛顿移动了一米的距离,所以,我现在也是焦耳了!”
焦耳这次学聪明了,一把将阿伏伽德罗扑倒在自己身下,说:“你看,我现在是J/mol啦!”
正当爱因斯坦思考J/mol是什么东西的时候,亥姆霍兹和吉布斯这两个自由能吵了起来,都说是对方。为了不至于两败俱伤,他们一脚把开尔文踹到了焦耳下面,将阿伏伽德罗顶了出来。
“看!”他俩说,“现在是J/K,是熵啦,要抓就抓克劳修斯吧!” 游戏继续。
这次是安培最先被爱因斯坦发现。眼看安培就要被抓了,他顺势往地上一躺,伸直身体对站在身边不远处的爱因斯坦说:“等等,我在你站的地方产生了磁场。”
正当爱因斯坦在考虑该抓高斯还是特斯拉的时候,发现他俩一人找了一块地板砖抱着,说:“不麻烦您老了,我们现在是磁通量B·S,您还是去找韦伯吧!”
等到爱因斯坦要抓住韦伯的时候,却发现韦伯正在做深蹲。
爱因斯坦问:“你干嘛呢?”
韦伯回答说:“你没看到我一会儿变大,一会儿变小吗?我在产生感应电动势呢。”
伏特一下子慌了,他一把抓住密立根的衣领,说:“你成天拿个油壶乱喷什么!”
“测定元电荷。”密立根回答道。
“太好了!”伏特一把抱住密立根说,“从现在起,我们就是eV,也就是焦耳。”
“靠,今天真是邪了门啦!”焦耳嘀咕道。
他一把将赫兹压在胯下,说:“看,我现在是E/v,是普朗克啦!”
普朗克也不是好惹的。他突然发现,远处有个来自东方的长者在地上写下了22/7和355/113,心里很是得意。一打听,此人姓祖,更是心里大喜。
他急忙跑过去,把这两个分数照抄了一遍,然后趴在这四个分数上面,对气喘嘘嘘赶来的爱因斯坦说:“看,我现在是h/4pi啦!”
“那又怎样?”爱因斯坦问。
“这是我的好哥们海森堡教我的,他说这样我就不是我了,有什么事尽管找他。”
“好,那他在哪里?”
“这个,还真说不准。”
爱因斯坦恼羞成怒,正准备对普朗克大打出手。
普朗克说:“等等,海森堡有个姓薛的好哥们,就躲在前面的那个箱子里。”
“这箱子连个通风口都没有,难道他不会被憋死吗?” 爱因斯坦问。
“这个嘛,就得你亲自去打开看看了。”“(??ω??)??”

ubuntu能够ping通ip但是无法ping通域名

故障描述

今天在克隆一个github仓库的时候,突然发现克隆失败了,于是检查了一下,发现域名都ping不通了
开始以为是网络挂掉了,但是使用代理的网络并没有挂掉,于是猜想是dns的问题
接着ping一下ip地址,发现可以ping通,确信是dns的问题无疑

解决方案

找到了问题要解决就很简单了,使用命令

sudo  gedit /etc/resolv.conf

把nameserver改成可用的dns服务器即可,如8.8.8.8

nameserver 8.8.8.8

验证

然后再次ping github.com,成功的收到了数据包,故障排除

dokcer快速入门

docker是什么

对于docker究竟是什么,有很多种的说法.不但不管是什么说法,总没有办法避开一个概念

docker仅仅就是一个工具而已、

听起来或许好像和没有解释是一样的,但是我觉得这就是最好的解释
但是正因为docker是一种工具,只要明白dokcer能做什么,不能做什么,我们就能很好的使用docker这个工具了。
因为对于工具而言,只有在特定的场景才有存在的意义,无脑的跟风和吹捧都是没有意义的。

docker能做什么

  1. 跨环境无缝迁移
  2. 项目水平扩展,轻松实现分布式架构
  3. 自动化运维
  4. CI/CD 持续集成,持续交付

任何一种工具的使用方法,都是没有办法用穷举法来完成的,但是只需要这几种优点,已经足以成为我学习并学会使用这种工具的推动力了。

docker核心概念

学会一种工具并不需要你完全的吧这种工具发明出来(当然能够发明出来,那说明你不仅仅是学会使用了),只需要工具的每个组成部分就可以了,想要更好的使用docker,有三个核心概念是必要要深刻了解的
- repository 仓库
- image 镜像
- container 容器

什么是镜像?什么是容器?什么又是仓库?

用面向对象的方法来理解,我觉得会更容易一点
镜像和容器之间的关系,就好像面向对象编程中类与实例的关系
仓库和镜像之间的关系,就好像包和类之间的关系

一个镜像可以创建出很多的容器,多个镜像可以组成以的镜像仓库

docker基础命令

docker的基本概念就好比心法口诀,但是想要运用自如,只有通过不断的练习才有可能
但是有组织的练习可以让你事半功倍,docker的操作主要分为两种

  • 对镜像的操作
  • 对容器的操作

docker镜像操作命令

docker pull  #从docker云拉取一个镜像
docker push  #把本地镜像推送到docker云上
docker build  #根据Dockerfile创建一个docker镜像
docker images  #列出当前系统上所有的镜像
docker image  #镜像操作命令的集合

docker容器操作命令

docker run # 运行某个容器的镜像
docker ps #显示正在运行的容器
docker rm # 删除一个或者多个容器
docker rename # 对容器进行重命名
docker port # 查看容器运行的端口
docker cp  # 拷贝文件到容器

docker快速上手

背诵命令是非常枯燥又低下的,通过一个完整的过程来练习docker才能使你的印象更加深刻,那么亲自运行一个容器就显得的非常有必要了。
容器的运行需要依赖镜像,首先要做的事情就是从docker云上获取一个可用的镜像,因为我的操作系统就是ubuntu,所以我对ubuntu比较熟悉,那么我就使用ubuntu镜像了

docker pull ubuntu # docker pull ubuntu:14.0.4 带上tag的话,可以获取到指定版本的系统
docker images  # pull之后 查看当前的iamges 查看自己的镜像是不是拉取成功

接下来使用run来练习了

docker run ubuntu ls -al #ls -al 就是在容器中运行的命令,只要ubuntu下运行的命令,都可以使用这种方法来运行,包括使用bash来登录
docker run -it ubuntu /bin/bash # 注意这里的-it参数,如果没有这个参数,将不能进入bahs终端

因为这是ubuntu默认环境,几乎是没有什么工具的,为了打造自己的环境,那么我们可以稍微配置一下,在这里安装个vim

apt update
apt install vim

安装成功以后,可以把容器重新打包成镜像,制作成属于自己的镜像,重新打开一个终端

使用Dockerfile 来构建自己的镜像会有更好的体验,这里粗暴一点解决,成就感会来的快一点

docker ps # 查看正在运行的ubuntu镜像的容器  找到第一行的contain ID
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                    NAMES
4ad0ebaa1cd1        ubuntu              "/bin/bash"              About a minute ago   Up About a minute 

接着使用commit 对容器重新打包成镜像

docker commit 4ad0ebaa1cd1 crisen/ubuntu  # 4ad0ebaa1cd1是容器的id,这是一个随机字符串,不同的电脑上得到的随机字符串是不一样的
docker images # 接着验证自己的镜像是否成功创建

最后验证自己的镜像是不是成功安装上了vim

docker run crisen/ubuntu which vim  #这里运行crisen/ubuntu 表示自己创建的镜像的名称

最后得到结果/usr/bin/vim,说明成功个性化了自己的镜像。

ubuntu16.0.4 安装NVIDIA显卡驱动

查看显卡驱动型号

lspci | grep -i vga
01:00.0 VGA compatible controller: NVIDIA Corporation GF108 [GeForce GT 630] (rev a1)

GeForce GT630就是我当前的电脑的显卡型号了(一块比较古老的显卡,基本够用吧)

找到官方提供的驱动程序

NVIDIA的显卡,不是所有的类型都提供了linux版本的,所以要去英伟达官网去搜索一下
很幸运的是,GT630提供了linux64位版本的驱动下载,
那么接下来复制下载地址,用wget获取了

cd ~
wget http://cn.download.nvidia.com/XFree86/Linux-x86_64/390.77/NVIDIA-Linux-x86_64-390.77.run

安装驱动需要的依赖

sudo apt-get update
sudo apt-get install dkms build-essential linux-headers-generic

禁用nouveau驱动

编辑blacklist-nouveau.conf配置文件

sudo vim  /etc/modprobe.d/blacklist-nouveau.conf

添加下面的内容

 blacklist nouveau
 blacklist lbm-nouveau
 options nouveau modeset=0
 alias nouveau off
 alias lbm-nouveau off

使用命令让禁用生效

sudo update-initramfs -u

重启

接着重启操作系统

sudo reboot

进入纯终端环境安装驱动

使用组合快捷键登录ctrl+alt+F1 进入纯终端环境
接着关闭图形界面服务

sudo service lightdm stop

赋予驱动安装程序可执行权限,然后运行驱动安装程序

cd ~
sudo chmod a+x NVIDIA-Linux-x86_64-390.77.run
./NVIDIA-Linux-x86_64-390.77.run

中途有几次选择过程,按需选择即可,安装完毕之后重启操作系统,最后使用命令验证,出现了显卡信息则驱动安装成功

sudo nvidia-smi

拥有原生体验版的本地局域网gitlab服务器

场景描述

  • gitlab服务器(ubuntu16.0.4),运行在内网,提供git服务
  • 云服务器(centos7),提供端口转发功能,为git服务器提供外网连通环境

遇到的问题

我开始使用了ssh远程端口转发功能,把云服务器的8080端口和2222端口分别转发到了git服务器的80和22端口,这样我就能通过121.40.150.93:8080的方式来访问我的git网页了,但是这里出现了一个问题

没有办法使用ssh协议来克隆仓库

虽然我之前找到了解决方案,可以通过一些配置来克隆仓库,但是这对不熟悉ssh或者新手来说太不友好了,这不是我想要的git服务器。

目标

我的目标只有一个,希望我在本地配置的git服务器,能达到gitlab官方服务器一样的使用感觉。
所以我现在需要解决的一个问题就是,使用云服务器的22端口来访问我的本地服务器,从而提供gitlab原声般的体验。

解决过程

因为我现在需要用到云服务器的22端口,那么云服务器原来的ssh服务器就不能走22端口了,所以接下来的任务,隐藏原服务器的22端口,修改成其他任意端口,我这里就用9468好了

阿里云服务器有安全组规则,所以要先在阿里云开启9468端口,要不然云服务器就无法登录了

修改ssh-server默认端口(云服务器)

vim /etc/ssh/sshd_config

在17行代码左右的配置,把Post修改为9468

Port 9468

重启sshd服务

/bin/systemctl restart sshd.service

使用autossh进行转发22端口(git服务器)

因为22端口是特权端口,只能以root运行,而且云服务器已经修改了ssh服务的端口了,为了建立这条隧道,首先要做的事情是添加一个配置配置

vim ~/.ssh/config

添加下面的内容

Host  server
        hostname 121.40.150.93
        user root
        port 9468

接着使用ssh远程端口转发功能,把云服务器22端口转发到本地22端口

ssh -NR 22:localhost:22 server

验证

接下来只要验证就可以了,点击我的git服务器进行体验

docker in ubuntu—-安装

系统环境

  • 操作系统: ubuntu Xenial 16.04 (LTS)
  • 操作系统架构:x86_64
  • 目标工具:docker-ce(docker社区版)

移除旧版本(可选)

sudo apt-get remove docker docker-engine docker.io

安装docker-ce依赖

  • apt-transport-https:开启https支持
  • ca-certificates:CA证书
  • curl: curl工具
  • software-properties-common:软件源管理工具
sudo apt-get update
sudo  apt-get install  apt-transport-https ca-certificates  curl  software-properties-common

添加 docker官方GPG秘钥

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

验证秘钥(可选)

sudo apt-key fingerprint 0EBFCD88
pub   4096R/0EBFCD88 2017-02-22
      Key fingerprint = 9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
uid                  Docker Release (CE deb) <docker@docker.com>
sub   4096R/F273FCD8 2017-02-22

设置稳定版repository

sudo add-apt-repository    "deb [arch=amd64] https://download.docker.com/linux/ubuntu  $(lsb_release -cs)   stable"

安装docker-ce(核心步骤)

sudo apt-get update
sudo apt-get install docker-ce

需要安装指定版本的docker,可以使用命令sudo apt-get install docker-ce=

验证安装结果

sudo docker hello-world

卸载

# 移除docker二进制包
 sudo apt-get purge docker-ce
 # 删除已安装的镜像和 容器等数据(可选)
 sudo rm -rf /var/lib/docker

配置本地DNS服务器

引言

因为在本地环境搭建了一个git服务器,有很多同事一起使用,每次通过地址访问实在是感觉很不好,通过域名访问,又需要修改hosts,为了一劳永逸解决这个纠结的问题, 配置一个本地dns服务器是最好的选择

系统环境

  • dns服务器操作系统: ubutnu16.0.4
  • dns服务器地址: 10.0.0.10
  • git服务器地址. 10.0.0.11
  • dns工具: bind9

目标

通过配置dns地址为10.0.0.10之后
把域名git.crisen.org解析到10.0.0.11的服务器上

安装

安装bind工具,在当前时间节点bind的版本是bind9.使用下列命令安装

sudo apt update
sudo apt install bind9 -y
# centos请使用 sudo yum install bind

配置

打开/etc/bind/named.conf.local 文件

sudo vim /etc/bind/named.conf.local  

输入如下内容

zone "crisen.org"{
    type master;
file "db.crisen.org";
};

zone 指定域名, file指定域名解析文件

配置域名解析文件

sudo cp /etc/bind/db.local /var/cache/bind/db.crisen.org
sudo vim /var/cache/bind/db.crisen.org

打开看到如下内容

;
; BIND data file for local loopback interface
;
$TTL    604800
@       IN      SOA     localhost. root.localhost. (
                              2         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;
@       IN      NS      localhost.
@       IN      A       127.0.0.1
@       IN      AAAA    ::1

最后一行加上

@       IN      A      10.0.0.11

细心一点 这里就能发现 @表示泛解析 A表示A记录 10.0.0.11就是解析的ip地址 使用过其他域名服务商的朋友们应该比较熟悉这个配置了,也就是说如果我想添加git.crisen.org的解析到10.0.0.11,那么配置应该是git IN A 10.0.0.11

配置dns服务器访问外网

sudo vim /etc/bind/named.conf.options

在13行左右的位置,修改forwarders配置,这里配置为114.114.114.114,可以替换成任意dns地址

forwarders {
        114.114.114.114;
};

重启bind服务并清除缓存

sudo service bind9 restart
sudo rndc flush

测试

将10.0.0.10地址作为首选dns服务器,使用ping命令测试

ping git.crisen.org
# 
PING git.crisen.org (10.0.0.11) 56(84) bytes of data.
64 bytes from gitlab.crisen.org (10.0.0.11): icmp_seq=1 ttl=64 time=0.405 ms
...

最后域名成功解析到了10.0.0.11服务器上,DNS服务器配置完毕

统计大文件中IP出现的次数

相关工具与文件

  • 操作系统CentOS7
  • GNU Awk 4.0.2
  • GNU sed 4.2.2
  • ss-server 日志文件ss.log

任务目标

统计ss.log中出现的不重复的ip的访问次数

分析过程

首先查看ss.log文件的大小

wc -l ss.log
# 69149 ss.log
...

接着取出其中的5行进行人工分析

tail -n 5 ss.log
# 2018-07-16 14:04:44 INFO     connecting sync-624-us-west-2.sync.services.mozilla.com:443 from 105.150.63.146:29776
......

由此可见IP地址出现的位置在第7列,那么接下来使用awk命令把记录中的第7列取出

tail -n 5 ss.log | awk '{pring $7}'
# 105.150.63.146:29776
...

于是得到了带有ip:port 的列表数据,但是我需要的仅仅是ip地址,那么接下来是取出ip地址部分,使用强大的流编辑器sed直接取出ip地址部分

ps:sed使用的是基础正则表达式,不是perl正则表达式, 语法有些差异

tail -n 5 ss.log | awk '{pring $7}' | sed  's/:[0-9]\+//g '
# 105.150.63.146
...

's/:[0-9]+//g' 正则的作用是把:符号以及:符号后面所有的数字全部替换为空

接下来使用awk命令 对ip进行统计
awk '{IP[$1]++}END {for(a in IP) print a"-----"IP[a]}'

tail -n 5 ss.log  |  awk '{pring $7}'  |  sed  's/:[0-9]\+//g ' |  awk '{IP[$1]++}END {for(a in IP) print a"-----"IP[a]}'
#  105.150.63.146-----3
...

统计末尾的5行文件,得出IP为105.150.63.146的地址请求了3次请求,接下来吧tail命令换成cat命令,对整个文件进行统计

cat  ss.log  |  awk '{pring $7}'  |  sed  's/:[0-9]\+//g ' |  awk '{IP[$1]++}END {for(a in IP) print a"-----"IP[a]}'

# 105.150.63.146-----13503
...

最后把这一串命令写成脚本保存,方便下次继续使用

#! /bin/bash 
cat  ss.log  |  awk '{pring $7}'  |  sed  's/:[0-9]\+//g ' |  awk '{IP[$1]++}END {for(a in IP) print a"-----"IP[a]}'

Docker初探(centos7)

系统环境

  • Centos7 64位

docker安装

centos下安装docker非常简单
首先移除可能的旧版本(可选)

sudo yum remove docker docker-client  docker-client-latest  docker-common  docker-latest docker-latest-logrotate   docker-logrotate   docker-selinux   docker-engine-selinux  docker-engine

接着安装安装docker-ce依赖环境

 sudo yum install -y yum-utils   device-mapper-persistent-data   lvm2

添加docker-ce官方安装包

 sudo yum-config-manager   --add-repo   https://download.docker.com/linux/centos/docker-ce.repo

然后安装docker-ce

sudo yum install docker-ce

其他环境的安装请参考官方文档

配置DNS

在/etc/docker/daemon.json 文件中添加下列内容

{
     "dns": ["114.114.114.114", "8.8.8.8"]
}

定义一个测试用的容器

mkdir app && cd app

创建一个app目录,接着创建三个文件名称如下
- requirements.txt
- app.py
- Dockerfile

requirement.txt

Flask
Redis

app.py

python 代码要注意缩进


from flask import Flask from redis import Redis, RedisError import os import socket # Connect to Redis redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2) app = Flask(__name__) @app.route("/") def hello(): try: visits = redis.incr("counter") except RedisError: visits = "<i>cannot connect to Redis, counter disabled</i>" html = "<h3>Hello {name}!</h3>" \ "<b>Hostname:</b> {hostname}<br/>" \ "<b>Visits:</b> {visits}" return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits) if __name__ == "__main__": app.run(host='0.0.0.0', port=80)

Dockerfile

Dockerfile是docker的核心文件,必不可少

# Use an official Python runtime as a parent image
FROM python:2.7-slim

# Set the working directory to /app
WORKDIR /app

# Copy the current directory contents into the container at /app
ADD . /app

# Install any needed packages specified in requirements.txt
RUN pip install --trusted-host pypi.python.org -r requirements.txt

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World

# Run app.py when the container launches
CMD ["python", "app.py"]

创建docker容器

如果上面的一切配置正常,那么使用ls命令,应该在app目录下出现三个文件

Dockerfile      app.py          requirements.txt

接着使用docker build 命令创建一个python容器(ps: 注意命令最后面的符号.)

sudo docker build -t  hello-docker  .

验证容器是否创建成功

sudo docker image ls

出现了下面的字样,则创建成功

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-docker                latest              a74bf93b68c9        26 minutes ago      132 MB

如果遇到error creating overlay mount to /var/lib/docker/overlay2 错误,请参考这里

运行

首先重启docker服务

sudo /bin/systemctl restart docker.server

接着运行docker,把宿主机环境的4000端口转发到hello-docker环境中的80端口

sudo  docker run -p 4000:80 hello-docker

验证

curl localhost:4000

出现结果如下,则说明docker运行成功

<h3>Hello World!</h3><b>Hostname:</b> 79b3ed825e21<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>