• aix5.3操作系统安装:入门(IBM官方文档)aix5.3操作系统安装:入门(IBM官方文档)
  • 阿俊技术论坛成立阿俊技术论坛成立
今日发布0 篇文章 | 本站共发布了122篇文章
  • shell编写复制文件进度条

    !/bin/bash   # Created by Chensj on 2022/03/11. export LC_CTYPE="zh_CN.UTF-8" export LANG="zh_CN.UTF-8" sour=dialog --stdout --title "Coping..." --inputbox "输入原路径" 7 40 dest=dialog --stdout --title "Coping..." --inputbox "输入目标路径" 7 40 LINE=ls -l $sour | wc -l declare -i PERCENT=0 (         for I in $sour;do                 if [ $PERCENT -le 100 ];then                         cp -r $I $dest 2> /dev/null                         echo "XXX"                          echo "复制 $I 中..."                          echo "XXX"                          echo $PERCENT                 fi         LINE=$[$LINE-1]         let PERCENT=`echo "sclae=2; $[100/$LINE]2" | bc`         sleep 0.1         done ) | dialog --title "coping" --gauge "starting to copy files..." 6 50 0...

    2022-03-11 未分类 2629
  • vs code更新到1.53.0之后看板娘无法使用

    1、找到vscode安装目录。 2、按路径找到 workbench.html文件 resources\app\out\vs\code\electron-browser\workbench 3、打开workbench.html文件 文件内容如下: <!-- Copyright (C) Microsoft Corporation. All rights reserved. --> <!DOCTYPE html> <html>  <head>   <meta charset="utf-8" />   <meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' https: data: blob: vscode-remote-resource:; media-src 'none'; frame-src 'self' vscode-webview: https://*.vscode-webview-test.com; object-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; connect-src 'self' https:; font-src 'self' https: vscode-remote-resource:;">  </head>  <body aria-label="">  </body>  <!-- Init Bootstrap Helpers -->  <script src="../../../../bootstrap.js"></script>  <script src="../../../../vs/loader.js"></script>  <script src="../../../../bootstrap-window.js"></script>  <!-- Startup via workbench.js -->  <script src="workbench.js"></script> </html> 4、编辑 workbench.html文件 <!-- Copyright (C) Microsoft Corporation. All rights reserved. --> <!DOCTYPE html> <html>  <head>   <meta charset="utf-8" />   <meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' https: data: blob: vscode-remote-resource:; media-src 'none'; frame-src 'self' vscode-webview: https://*.vscode-webview-test.com; object-src 'self'; script-src * 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; connect-src 'self' https:; font-src 'self' https: vscode-remote-resource:;">  </head>  <style type="text/css">   #live2dcanvas {border: 0 !important;}  </style>  <body aria-label="">   <div id="live2d-widget"><canvas id="live2dcanvas" width="100" height="200" style="position: fixed;width:100px;height:200;opacity: 0.5;right: 0px;bottom: -20px;z-index: 99999;pointer-events: none;border:0;"></canvas></div>  </body>  <!-- Init Bootstrap Helpers -->  <script src="../../../../bootstrap.js"></script>  <script src="../../../../vs/loader.js"></script>  <script src="../../../../bootstrap-window.js"></script>  <!-- Startup via workbench.js -->  <script src="workbench.js"></script>  <script type="text/javascript" charset="utf-8" src="https://cdn.jsdelivr.net/npm/live2d-widget@3.0.4/lib/L2Dwidget.0.min.js"></script>  <script type="text/javascript"  src="https://cdn.jsdelivr.net/npm/live2d-widget@3.0.4/lib/L2Dwidget.min.js?_=1557308476616"></script>  <script type="text/javascript">  // L2Dwidget.init();    L2Dwidget.init({"display": {         "superSample": 2,         "width": 100,         "height": 200,         "position": "right",         "hOffset": 0,         "vOffset": 0         }      });  </script> </html> 直接把上面的代码复制替换掉原来的代码就好,但是为了有一条后路,最好把原来的代码备份下。 5、重启Vscode 重启软件,大功告成! 6、如果出现2个妹子 将配置文件中的以下代码删除,重启VS即可:  <script type="text/javascript">  // L2Dwidget.init();    L2Dwidget.init({"display": {         "superSample": 2,         "width": 100,         "height": 200,         "position": "right",         "hOffset": 0,         "vOffset": 0         }      });  </script> 文章节选自:https://my.oschina.net/u/4161755/blog/4775153 ...

    2021-04-07 未分类 4031
  • 通过Nginx设置HttpOnly Secure SameSite参数解决Cookie跨域丢失

        在前面的文章中“谷歌浏览器Chrome 80版本默认SameSite导致跨域请求Cookie丢失”,我们知道 Chrome 升级到80版本后,默认限制了跨域携带cookie给后端。我们也提到了可以修改Chrome的设置或在服务端添加SameSite设置来解决,但是普通的Web框架需要升级到最新版本才支持SameSite属性,升级Web框架成本太高,因此本文使用Nginx来解决SameSite问题的办法(需要使用Nginx反向代理站点)。     一、Cookie安全相关属性     HttpOnly :         在Cookie中设置了“HttpOnly”属性,通过程序(JS脚本、Applet等)将无法读取到Cookie信息。         将HttpOnly 设置为true 防止程序获取cookie后进行攻击。     Secure :         安全性,指定Cookie是否只能通过https协议访问,一般的Cookie使用HTTP协议既可访问。         设置了Secure (没有值),则只有当使用https协议连接时cookie才可以被页面访问。可用于防止信息在传递的过程中被监听捕获后信息泄漏。     SameSite:         Chrome浏览器在51版本后为 Cookie 新增的属性,用来防止 CSRF 攻击和用户追踪。可以设置三个值:Strict、 Lax、 None         Strict:完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。换言之,只有当前网页的 URL 与请求目标一致,才会带上 Cookie。Set-Cookie: CookieName=CookieValue; SameSite=Strict;         Lax:规则稍稍放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。Set-Cookie: CookieName=CookieValue; SameSite=Lax;设置了Strict或Lax以后,基本就杜绝了 CSRF 攻击。当然,前提是用户浏览器支持 SameSite 属性。         None:Chrome 计划将Lax变为默认设置。这时,网站可以选择显式关闭SameSite属性,将其设为None。不过,前提是必须同时设置Secure属性(Cookie 只能通过 HTTPS 协议发送),否则无效。Set-Cookie: key=value; SameSite=None; Secure     二、配置路径     要通过nginx配置SameSite,可以在 nginx.conf 的 location 节点下进行配置: proxy_cookie_path / "/; httponly; secure; SameSite=Lax; ";     配置示例: server {     listen 443 ssl http2;     server_name www.demo.com;          ssl_certificate /etc/letsencrypt/live/cat73.org/fullchain.pem;     ssl_certificate_key /etc/letsencrypt/live/cat73.org/privkey.pem;     ssl_trusted_certificate /etc/letsencrypt/live/cat73.org/chain.pem;          # add_header X-XSS-Protection "1; mode=block";     # add_header X-Frame-Options SAMEORIGIN;     add_header Strict-Transport-Security "max-age=15768000";          location / {         root /var/www/html;     }          location /api {         proxy_pass http://localhost;         proxy_set_header Host $host;         proxy_set_header X-Real-IP $remote_addr;         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;         # 配置位置如下         proxy_cookie_path / "/; httponly; secure; SameSite=None; ";     } } ———————————————— 版权声明:本文为CSDN博主「ztnhnr」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/ztnhnr/article/details/109447507...

    2021-03-25 未分类 3902
  • docker 安装及启动错误的排除

    docker 安装 这边博文写的很ok: https://www.cnblogs.com/Peter2014/p/7704306.html docker 启动遇到的错误 docker 启动报错,使用 systemctl 或 journalctl 查看错误如下: 其实 systemctl 或 journalctl 并不能很准确的看出问题所在,直接启动 dockerd 能获取更为准确的错误信息 问题1:start request repeated too quickly for docker.service, Failed to start Docker Application Container Engine. 如果依然无法启动可以将 /etc/docker/daemon.json 改为 /etc/docker/daemon.conf 尝试一下。 问题2:Error while creating filesystem xfs on device 这是由于系统 xfsprogs 版本过低造成的,更新一下即可(https://www.cnblogs.com/loopsun/p/9650301.html) 问题3:内核版本过低 新版的 docker 要求系统内核版本在 3.10 以上,可以使用 uname -r 查看自己的系统版本,低于 3.10 的话请升级内核。 以上基本可以解决 docker 启动的错误,推荐个 docker 加速器,傻瓜式安装 docker docker-compose DaoCloud: http://get.daocloud.io/ 转载于:https://my.oschina.net/sallency/blog/3005452 ...

    2020-11-30 未分类 3689
  • pod处于MatchNodeSelector状态故障

    pod处于MatchNodeSelector状态故障 现象描述 节点下电重启后,部分pod处于MatchNodeSelector异常状态。 可能原因 节点重启后,kubelet还未连通kube-api-server。 处理方法 以paas用户登录平台paas-Core01节点。 执行以下命令获取处于MatchNodeSelector状态的pod的名称。 kubectl get pods --all-namespaces | grep MatchNodeSelector 执行如下命令,删除MatchNodeSelector状态的pod。 kubectl delete pod --all-namespaces podname 其中,podname为2中获取pod名称。 ...

    2020-02-01 未分类 9687
  • Docker常见命令

    Docker常见命令 容器相关操作 docker create # 创建一个容器但是不启动它 docker run # 创建并启动一个容器 docker stop # 停止容器运行,发送信号SIGTERM docker start # 启动一个停止状态的容器 docker restart # 重启一个容器 docker rm # 删除一个容器 docker kill # 发送信号给容器,默认SIGKILL docker attach # 连接(进入)到一个正在运行的容器 docker wait # 阻塞到一个容器,直到容器停止运行 获取容器相关信息 docker ps # 显示状态为运行(Up)的容器 docker ps -a # 显示所有容器,包括运行中(Up)的和退出的(Exited) docker inspect # 深入容器内部获取容器所有信息 docker logs # 查看容器的日志(stdout/stderr) docker events # 得到docker服务器的实时的事件 docker port # 显示容器的端口映射 docker top # 显示容器的进程信息 docker diff # 显示容器文件系统的前后变化 导出容器 docker cp # 从容器里向外拷贝文件或目录 docker export # 将容器整个文件系统导出为一个tar包,不带layers、tag等信息 执行 docker exec # 在容器里执行一个命令,可以执行bash进入交互式 镜像操作 docker images # 显示本地所有的镜像列表 docker import # 从一个tar包创建一个镜像,往往和export结合使用 docker build # 使用Dockerfile创建镜像(推荐) docker commit # 从容器创建镜像 docker rmi # 删除一个镜像 docker load # 从一个tar包创建一个镜像,和save配合使用 docker save # 将一个镜像保存为一个tar包,带layers和tag信息 docker history # 显示生成一个镜像的历史命令 docker tag # 为镜像起一个别名 镜像仓库(registry)操作 docker login # 登录到一个registry docker search # 从registry仓库搜索镜像 docker pull # 从仓库下载镜像到本地 docker push # 将一个镜像push到registry仓库中 获取Container IP地址(Container状态必须是Up) docker inspect id | grep IPAddress | cut -d '"' -f 4 获取端口映射 docker inspect -f '{{range $p, $conf := .NetworkSettings.Ports}} {{$p}} -> {{(index $conf 0).HostPort}} {{end}}' id 获取环境变量 docker exec container_id env 杀掉所有正在运行的容器 docker kill $(docker ps -q) 删除老的(一周前创建)容器 docker ps -a | grep 'weeks ago' | awk '{print $1}' | xargs docker rm 删除已经停止的容器 docker rm `docker ps -a -q` 删除所有镜像,小心 docker rmi $(docker images -q) Dockerfile Dockerfile是docker构建镜像的基础,也是docker区别于其他容器的重要特征,正是有了Dockerfile,docker的自动化和可移植性才成为可能。 不论是开发还是运维,学会编写Dockerfile几乎是必备的,这有助于你理解整个容器的运行。 FROM , 从一个基础镜像构建新的镜像 FROM ubuntu MAINTAINER , 维护者信息 MAINTAINER William <wlj@nicescale.com> ENV , 设置环境变量 ENV TEST 1 RUN , 非交互式运行shell命令   RUN apt-get -y update RUN apt-get -y install nginx   ADD , 将外部文件拷贝到镜像里,src可以为url ADD http://nicescale.com/ /data/nicescale.tgz WORKDIR /path/to/workdir, 设置工作目录 WORKDIR /var/www USER , 设置用户ID USER nginx VULUME <#dir>, 设置volume VOLUME [‘/data’] EXPOSE , 暴露哪些端口 EXPOSE 80 443 ENTRYPOINT [‘executable’, ‘param1’,’param2’]执行命令 ENTRYPOINT ["/usr/sbin/nginx"] CMD [“param1”,”param2”] CMD ["start"] docker创建、启动container时执行的命令,如果设置了ENTRYPOINT,则CMD将作为参数 Dockerfile最佳实践 尽量将一些常用不变的指令放到前面 CMD和ENTRYPOINT尽量使用json数组方式 通过Dockerfile构建image docker build csphere/nginx:1.7 . 镜像仓库Registry 镜像从Dockerfile build生成后,需要将镜像推送(push)到镜像仓库。企业内部都需要构建一个私有docker registry,这个registry可以看作二进制的scm,CI/CD也需要围绕registry进行。 部署registry   mkdir /registry docker run  -p 80:5000 -e STORAGE_PATH=/registry  -v /registry:/registry registry:2.0   推送镜像保存到仓库 假设192.168.1.2是registry仓库的地址:   docker tag  csphere/nginx:1.7 192.168.1.2/csphere/nginx:1.7 docker push 192.168.1.2/csphere/nginx:1.7 ...

    2018-07-17 未分类 4268
  • levelDB的安装-Linux

    levelDB是一个快速的key-value (String,String)存储库,由Google编写。 基本操作是:Put(key,value), Get(key), Delete(key).  用户可以创建一个暂时的快照来获得一致的数据视图。  数据支持前向和后向迭代。  数据自动使用Snappy 压缩库进行压缩。  外部活动(文件系统操作等)通过虚拟接口实现,所以用户可以自定义操作系统接口。 限制:  levelDB不是SQL数据库,所以不支持sql查询;  一个时间段只能一个进程(可能是多线程)访问数据库;  在库里没有内置的客户-服务器,若应用需要支持CS就需要把用户自己的服务器包装到库中。 1.下载levelDB文件: git clone https://github.com/google/leveldb.git 1 2.到levelDB目录下,执行make命令:  执行完成后:  leveldb/下多出out-shared和out-static目录,其中out-shared/下有:  db db_bench helpers libleveldb.so libleveldb.so.1 libleveldb.so.1.19 port table util 3.将文件拷贝 sudo cp out-shared/libleveldb.so* /usr/local/lib & sudo cp -R include/* /usr/local/include 1 安装完成!!! git clone https://code.google.com/p/leveldb/  【1】github地址:  https://github.com/google/leveldb  【2】levelDB使用说明:  https://github.com/google/leveldb/blob/master/doc/index.md ...

    2018-07-06 未分类 4377
  • centos 6.5 gcc升级到5.3.0

    1、下载安装包 在这个地址进行下载 http://ftp.gnu.org/gnu/gcc/gcc-5.3.0/ 2、解压 tar -zxvf gcc-5.3.0.tar.gz  3、下载供编译需求的依赖项。据说下面这个神奇的脚本文件会帮我们下载、配置、安装好依赖库,可以节约我们大量的时间和精力。 cd gcc-5.3.0 ./contrib/download_prerequisites 4、建立一个目录供编译出的文件存放 mkdir gcc-build-5.3.0 cd gcc-build-5.3.0 5、生成Makefile文件 ../configure -enable-checking=release -enable-languages=c,c++ -disable-multilib 6、进行编译 此步骤比较费时间,在1核1G内存主机上大约需要2小时左右的编译时间。最好开个screen,可防止万一断线。我在编译时不知道需要这么久,结果等了半天还没结束,跑群里问了一下才知道原来要这么久,好在运气不错,网络坚挺没断开~ make 如果是多核心CPU,那么可以加上参数并行编译,不过有时候会出问题,所以不赶时间的话还是慢慢make吧。 7、安装 make install 8、重启系统 9、验证版本 gcc -v ...

    2018-07-06 未分类 3971
  • 如何在Ubuntu 16.04上增加Swap分区

    如何在Ubuntu 16.04上增加Swap分区 2018年01月31日 16:43:16 阅读数:700 翻译自:How To Add Swap Space on Ubuntu 16.04 前言 提高服务器响应速度和防止应用程序内存不足错误的最简单方法之一是添加一些交换空间。 在本指南中,我们将介绍如何将交换文件添加到Ubuntu 16.04服务器。 但是,请注意: 尽管swap区通常建议用于使用传统旋转硬盘驱动器的系统,但使用与SSD交换可能会导致随着时间的推移硬件退化问题。 由于这个考虑,我们不建议在DigitalOcean或任何其他使用SSD存储的供应商上启用swap分区。 这样做可能会影响到您和您的邻居的底层硬件的可靠性。 本指南仅供可能在其他地方有使用旋转磁盘系统的用户参考。如果您需要改善DigitalOcean服务器的性能,我们建议升级您的Droplet,以致于有更好的体验,并且会降低影响您的服务的硬件问题的可能性。 1.首先来了解一下什么是Swap Swap分区(也称交换分区)是硬盘上的一个区域,被指定为操作系统可以临时存储数据的地方,这些数据不能再保存在RAM中。 基本上,这使您能够增加服务器在工作“内存”中保留的信息量,但有一些注意事项,主要是当RAM中没有足够的空间容纳正在使用的应用程序数据时,将使用硬盘驱动器上的交换空间。 写入磁盘的信息将比保存在RAM中的信息慢得多,但是操作系统更愿意将应用程序数据保存在内存中,并使用交换旧数据。 总的来说,当系统的RAM耗尽时,将交换空间作为回落空间可能是一个很好的安全网,可防止非SSD存储系统出现内存不足的情况。 2.检查系统的交换信息 在开始之前,我们可以检查系统是否已经有一些可用的交换空间,可能有多个交换文件或交换分区,但通常应该是足够的。我们可以通过如下的命令来查看系统是否有交换分区: $ sudo swapon --show 1 如果没有任何结果或者没有任何显示,说明系统当前没有可用的交换空间。也可以使用free工具来验证当前确实没有可用的交换分区。 $ free -h 1 输出结果: total used free shared buff/cache available Mem: 488M 36M 104M 652K 348M 426M Swap: 0B 0B 0B 1 2 3 可以看到这里的”swap”行均为0,也就是说系统上没有交换处于活动状态。 3.检查硬盘驱动器分区上的可用空间 为swap分配空间的最常见方式是使用专门用于具体某个任务的单独分, 但是,改变分区方案并不是一定可行的,我们只是可以轻松地创建驻留在现有分区上的交换文件。 在开始之前,我们应该通过输入以下命令来检查当前磁盘的使用情况: $ df -h 1 输出结果: Filesystem Size Used Avail Use% Mounted on udev 238M 0 238M 0% /dev tmpfs 49M 624K 49M 2% /run /dev/vda1 20G 1.1G 18G 6% / tmpfs 245M 0 245M 0% /dev/shm tmpfs 5.0M 0 5.0M 0% /run/lock tmpfs 245M 0 245M 0% /sys/fs/cgroup tmpfs 49M 0 49M 0% /run/user/1001 1 2 3 4 5 6 7 8 在这种情况下,/dev下的设备是我们的磁盘。在这个例子中我们有足够的空间(只使用了1.1G),当然,您的使用情况可能会有所不同。 尽管对于交换空间的适当大小有许多意见,但这取决于您的个人偏好和应用程序要求。 一般来说,相当于系统内存量的两倍或者两倍是一个很好的起点。 另一个很好的经验是,如果你只是把它用作RAM备用,那么swap分区的大小尽量不要超过4 GB。 4.创建swap文件 现在我们知道了可用的硬盘空间,那我们就可以在文件系统中创建一个交换文件,我们将在我们的根(/)目录下创建一个名为swapfile的文件。创建交换文件最好的方法是使用fallocate命令,这个命令能立即创建一个预分配大小的文件。由于本示例中的服务器RAM的大小为512MB,因此我们将在本教程中创建一个1 GB大小的文件,并适当加以调整,以满足您自己的服务器的需求: $ sudo fallocate -l 1G /swapfile 1 创建完成之后,我们可以通过这个命令来验证是否保留了正确的交换空间: $ ls -lh /swapfile 1 显示结果: $ -rw-r--r-- 1 root root 1.0G Apr 25 11:14 /swapfile 1 这就说明我们的文件已经创建了正确的空间大小。 5.启用交换文件 现在我们有一个1 GB大小的文件,我们需要把它变成交换空间 首先,我们需要锁定文件的权限,以便只有拥有root权限的用户才能读取文件内容,这可以防止普通用户能够访问该文件,以免造成重大的安全隐患。 锁定文件的root权限: $ sudo chmod 600 /swapfile 1 验证权限: $ ls -lh /swapfile 1 显示结果: -rw------- 1 root root 1.0G Apr 25 11:14 /swapfile 1 可以看到,只有root用户启用了读写标志。 接下来,我们可以通过以下命令将文件标记为交换空间 $ sudo mkswap /swapfile 1 显示结果: Setting up swapspace version 1, size = 1024 MiB (1073737728 bytes) no label, UUID=6e965805-2ab9-450f-aed6-577e74089dbf 1 2 标记文件之后,我们可以启用该交换文件,让我们的系统开始使用它: $ sudo swapon /swapfile 1 可以通过以下命令验证交换空间是否可用: $ sudo swapon --show 1 显示结果: NAME TYPE SIZE USED PRIO /swapfile file 1024M 0B -1 1 2 这时,我们可以通过free再次查看我们的设置: $ free -h 1 显示结果: total used free shared buff/cache available Mem: 488M 37M 96M 652K 354M 425M Swap: 1.0G 0B 1.0G 1 2 3 可以看到swap分区已成功创建,大小为1.0 G,操作系统将在必要时使用。 6.永久保留交换文件 我们最近的更改启用了当前会话的swap文件,但是,如果我们重新启动,服务器不会自动保留swap设置,我们可以通过将swap文件添加到/etc/fstab文件中来改变这一点。 备份/etc/fstab文件以防出错: $ sudo cp /etc/fstab /etc/fstab.bak 1 将swap文件信息添加到/etc/fstab文件的末尾: $ echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab 1 这样就保留了swap文件。 7.调整你的交换设置 在处理交换时,可以配置几个选项,这些选项会影响系统的性能 7.1 调整swappiness属性 swappiness参数配置您的系统将数据从RAM交换到交换空间的频率, 值介于0和100之间,表示百分比。如果swappiness值接近0,内核将不会将数据交换到磁盘,除非绝对必要。要记住一点,与swap文件的交互是“昂贵的”,因为与swap交互花费的时间比与RAM的交互更长,并且会导致性能的显著下降。系统更少依赖swap分区通常会使你的系统更快。swappiness接近100的值将尝试将更多的数据放入交换中,以保持更多的RAM空间。根据您的应用程序的内存配置文件或您使用的服务器,这可能会在某些情况下更好。 查看当前的swappiness值: $ cat /proc/sys/vm/swappiness 1 结果显示 60 1 对于桌面系统来说,60的swappiness设置不是一个比较坏的值,但是对于服务器,您可能希望将其设置与0更接近的值。 我们可以使用sysctl命令将swappiness设置为不同的值,例如,要将swappiness设置为10: $ sudo sysctl vm.swappiness=10 1 显示结果: vm.swappiness = 10 1 该设置将保持到系统下次重新启动,如果想要在重启之后也生效,我们可以通过在/etc/sysctl.conf文件中添加一行实现: $ sudo nano /etc/sysctl.conf 1 在文件的最后添加: vm.swappiness=10 1 完成后保存并关闭文件。 7.2 调整缓存压力设置 您可能想要修改的另一个相关值是vfs_cache_pressure,这个设置配置系统将选择多少数据缓存inode和dentry信息。基本上,这是访问有关文件系统的数据,通常是非常耗时的查询和频繁要求,所以这是一个很好的事情,让您的系统缓存,您可以通过再次查询proc文件系统来查看当前值。 $ cat /proc/sys/vm/vfs_cache_pressure 1 输出结果: 100 1 这个配置可能使我们的系统太快地从缓存中删除inode信息。 我们可以设置一个更保守的值,比如50。 $ sudo sysctl vm.vfs_cache_pressure=50 1 显示结果: vm.vfs_cache_pressure = 50 1 和swappiness类似,这只对当前的session有效,我们可以通过将其添加到我们的配置文件来改变它,就像我们使用我们的swappiness设置一样: $ sudo nano /etc/sysctl.conf 1 在末尾添加: vm.vfs_cache_pressure=50 1 完成后保存并关闭文件。 8.总结 遵循本指南的步骤将给您一些喘息的空间,否则会导致内存不足的例外,swap空间对于避免这些常见问题非常有用,如果遇到OOM(内存不足)错误,或者如果发现系统无法使用所需的应用程序,则最佳解决方案是优化应用程序配置或升级服务器。 ...

    2018-07-02 未分类 3794
  • rabbitmq——用户管理

    rabbitmq——用户管理 原文地址: http://my.oschina.net/hncscwc/blog/262246 安装最新版本的rabbitmq(3.3.1),并启用management plugin后,使用默认的账号guest登陆管理控制台,却提示登陆失败。 翻看官方的release文档后,得知由于账号guest具有所有的操作权限,并且又是默认账号,出于安全因素的考虑,guest用户只能通过localhost登陆使用,并建议修改guest用户的密码以及新建其他账号管理使用rabbitmq(该功能是在3.3.0版本引入的)。 虽然可以以比较猥琐的方式:将ebin目录下rabbit.app中loopback_users里的<<"guest">>删除,或者在配置文件rabbitmq.config中对该项进行配置, 并重启rabbitmq,可通过任意IP使用guest账号登陆管理控制台,但始终是违背了设计者的初衷,再加上以前对这一块了解也不多,因此有必要总结一下。 1. 用户管理 用户管理包括增加用户,删除用户,查看用户列表,修改用户密码。 相应的命令 (1) 新增一个用户 rabbitmqctl  add_user  Username  Password (2) 删除一个用户 rabbitmqctl  delete_user  Username (3) 修改用户的密码 rabbitmqctl  change_password  Username  Newpassword (4) 查看当前用户列表 rabbitmqctl  list_users 2. 用户角色 按照个人理解,用户角色可分为五类,超级管理员, 监控者, 策略制定者, 普通管理者以及其他。 (1) 超级管理员(administrator) 可登陆管理控制台(启用management plugin的情况下),可查看所有的信息,并且可以对用户,策略(policy)进行操作。 (2) 监控者(monitoring) 可登陆管理控制台(启用management plugin的情况下),同时可以查看rabbitmq节点的相关信息(进程数,内存使用情况,磁盘使用情况等) (3) 策略制定者(policymaker) 可登陆管理控制台(启用management plugin的情况下), 同时可以对policy进行管理。但无法查看节点的相关信息(上图红框标识的部分)。 与administrator的对比,administrator能看到这些内容 (4) 普通管理者(management) 仅可登陆管理控制台(启用management plugin的情况下),无法看到节点信息,也无法对策略进行管理。 (5) 其他 无法登陆管理控制台,通常就是普通的生产者和消费者。 了解了这些后,就可以根据需要给不同的用户设置不同的角色,以便按需管理。 设置用户角色的命令为: rabbitmqctl  set_user_tags  User  Tag User为用户名, Tag为角色名(对应于上面的administrator,monitoring,policymaker,management,或其他自定义名称)。 也可以给同一用户设置多个角色,例如 rabbitmqctl  set_user_tags  hncscwc  monitoring  policymaker 3. 用户权限 用户权限指的是用户对exchange,queue的操作权限,包括配置权限,读写权限。配置权限会影响到exchange,queue的声明和删除。读写权限影响到从queue里取消息,向exchange发送消息以及queue和exchange的绑定(bind)操作。 例如: 将queue绑定到某exchange上,需要具有queue的可写权限,以及exchange的可读权限;向exchange发送消息需要具有exchange的可写权限;从queue里取数据需要具有queue的可读权限。详细请参考官方文档中"How permissions work"部分。 相关命令为: (1) 设置用户权限 rabbitmqctl  set_permissions  -p  VHostPath  User  ConfP  WriteP  ReadP (2) 查看(指定hostpath)所有用户的权限信息 rabbitmqctl  list_permissions  [-p  VHostPath] (3) 查看指定用户的权限信息 rabbitmqctl  list_user_permissions  User (4)  清除用户的权限信息 rabbitmqctl  clear_permissions  [-p VHostPath]  User =============================== 命令详细参考官方文档:rabbitmqctl ...

    2018-06-29 未分类 4109
  • Centos7手工安装Kubernetes集群

    Centos7手工安装Kubernetes集群 安装Kubernetes集群有多种方式,前面介绍了Kubeadm的方式,本文将介绍手工安装的方法。 安装环境有3台Azure上的VM: Hkube01:10.0.1.4 Hkube02:10.0.1.5 Hbube03:10.0.1.6 其中hkube01是Master节点,将会安装docker, etcd, Kubernetes master, flannel所需要的组件; Hkube02和hkube03是worker节点,将会安装docker, kubernetes node, flannel所需要的组件。 安装过程如下: 一 master节点 1 安装软件 yum install -y docker etcd kubernetes-master 2 配置启动docker 由于docker-hub的站点在国外,下载会非常慢,把docker下载指向国内的镜像站点: vim /etc/docker/daemon.json {"registry-mirrors": ["registry.docker-cn.com"]} systemctl enable docker systemctl start docker 3 配置启动etcd Etcd和zookeeper类似,是存储key/value的工具。 cd /etc/etcd vim etcd.conf ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379" ETCD_NAME="master" ETCD_ADVERTISE_CLIENT_URLS=http://10.0.1.4:2379 systemctl enable etcd systemctl start etcd 4 配置kubernetes 在/etc/kubernetes目录中,有4个配置文件: 需要配置apiserver和config两个配置文件。Controller-manager和scheduler不需要配置。 配置apiserver,需要指定etcd地址、api-server的端口、提供服务的地址和cluster的ip范围: vim /etc/kubernetes/apiserver KUBE_API_PORT="--port=8080" KUBE_API_ADDRESS="--insecure-bind-address=0.0.0.0" KUBE_ETCD_SERVERS="--etcd-servers=http://10.0.1.4:2379" KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.0.0.0/16" KUBE_ADMISSION_CONTROL="--admission_control=NamespaceLifecycle,NamespaceExists,LimitRanger,ResourceQuota" 本文不设计Kubernetes的安全问题,所以在api-server的配置中的admission_control中去掉了和安全相关的内容SecurityContextDeny,ServiceAccount。  配置config,需要指定kubernetes master的地址和端口: vim /etc/kubernetes/config KUBE_MASTER="--master=http://10.0.1.4:8080" 5 启动服务   systemctl enable kube-apiserver kube-controller-manager kube-scheduler systemctl start kube-apiserver kube-controller-manager kube-scheduler systemctl status kube-apiserver kube-controller-manager kube-scheduler   二 node节点 1 安装软件 yum install -y docker kubernetes-node 2 配置启动docker 和master节点相同: vim /etc/docker/daemon.json {"registry-mirrors": ["registry.docker-cn.com"]} systemctl enable docker systemctl start docker 3 配置kubelet 在/etc/kubernetes下有3个配置文件: 需要配置config和kubelet两个配置文件,proxy是kube-proxy的配置文件,保留默认就可以。 配置config,需要指定kubernetes master的地址和端口: vim /etc/kubernetes/config KUBE_MASTER="--master=http://10.0.1.4:8080" 配置kubelet,指定其工作地址、本机注册到master时的名称、master的地址和端口: vim /etc/kubernetes/kubelet KUBELET_ADDRESS="--address=0.0.0.0" KUBELET_HOSTNAME="--hostname-override=hkube02" KUBELET_API_SERVER="--api-servers=http://10.0.1.4:8080" 另外由于centos的yum源指定的pod-infrastructure的docker镜像需要redhat的证书,会导致安装不成功。为避免这个问题,我们把kubelet中的这个镜像更改成docker-hub中的镜像。 先搜索一下: docker search pod-infrastructure 选择一个更改,我选择了最后一个: KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image= docker.io/zengshaoyong/pod-infrastructure:latest " 4 启动服务 systemctl enable kubelet kube-proxy systemctl start kubelet kube-proxy systemctl status kubelet kube-proxy 5 检查 在master节点上查看: 已经看到hkube02和hkube03都注册上来了。 创建一个deployment: kubectl run nginx --image=nginx kubectl scale deployment nginx --replicas=3 但网络层面pod只能和本node的其他pod连通。   三 网络 本文将安装flannel,实现跨节点的容器互通。 1 安装 yum install -y flannel 2 配置 在master节点进行Etcd的配置: etcdctl set /coreos.com/network/config '{"Network":"192.168.0.0/16"}' 在所有node节点上配置flannel配置文件: vim /etc/sysconfig/flanneld systemctl enable flanneld systemctl start flanneld systemctl restart docker 开启转发: iptables -P FORWARD ACCEPT 此时可以看到docker0的地址和flannel的端口地址网段相同: 3 验证 部署pod nginx: kubectl run nginx --image nginx kubectl scale deployment nginx --replicas=3 登录到hkube03,进入到容器: 通过部署flannel,可以实现各个pod间的网络互通。 总结: 在Centos7上,通过yum安装Kubernetes的各个组件,实现Kubernetes的集群部署。 ...

    2018-06-29 未分类 3809
  • prometheus-入门尝试

    prometheus-入门尝试 prometheus-入门 Prometheus 是由 SoundCloud 开源监控告警解决方案2015 年在 github 上开源以来,已经吸引了 很多大公司的使用;2016 年 Prometheus 成为继 k8s 后,第二名 CNCF(Cloud Native Computing Foundation) 成员。 实战 安装prometheus软件 cd /usr/local/src/ wget https://github.com/prometheus/prometheus/releases/download/v1.7.1/prometheus-1.7.1.linux-amd64.tar.gz tar -zxf prometheus-1.7.1.linux-amd64.tar.gz mv prometheus-1.7.1.linux-amd64 /data/app/ ln -s /data/app/prometheus-1.7.1.linux-amd64/ /data/app/prometheus 修改配置文件 global: scrape_interval: 15s evaluation_interval: 15s external_labels: monitor: 'codelab-monitor' rule_files: scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['localhost:9090'] - job_name: 'linux' static_configs: - targets: ['192.168.56.12:9100'] labels: alias: linux-node2 启动prometheus并访问 ./prometheus -config.file=prometheus.yml 安装exporter 端 wget https://github.com/prometheus/mysqld_exporter/releases/download/v0.10.0/mysqld_exporter-0.10.0.linux-amd64.tar.gz wget https://github.com/prometheus/node_exporter/releases/download/v0.14.0/node_exporter-0.14.0.linux-amd64.tar.gz tar -zxf mysqld_exporter-0.10.0.linux-amd64.tar.gz tar -zxf node_exporter-0.14.0.linux-amd64.tar.gz mv node_exporter-0.14.0.linux-amd64 /data/app/ mv mysqld_exporter-0.10.0.linux-amd64 /data/app/ ln -s /data/app/node_exporter-0.14.0.linux-amd64/ /data/app/node_exporter ln -s /data/app/mysqld_exporter-0.10.0.linux-amd64/ /data/app/mysqld_exporter 启动node_exporter screen -R node_exporter cd /data/app/node_exporter ./node_exporter 登录图像页面检查服务是否配置成功 http://localhost:9090/metrics: 监控指标 http://localhost:9090/graph: 图像界面 metrics返回的结果包含多个标签的值。如果想只看延迟是0.99的值可以输入如下参数: prometheus_target_interval_length_seconds{quantile="0.99"} 你也可以对返回结果做个count值: count(prometheus_target_interval_length_seconds) 输入以下表达式来绘制在Prometheus中发生的所有存储块操作的每秒速率: rate(prometheus_local_storage_chunk_ops_total[1m]) 你也可以输出其他参数查看监控后服务器的信息,比如:使用up参数判断linux-node2是否存活。 up{job="linux-node2"} 其他高级的例子 avg(rate(rpc_durations_seconds_count[5m])) by (job, service) 级联同步数据 promtheus 配置文件中增加如下内容: scrape_configs: - job_name: 'federate' scrape_interval: 15s honor_labels: true metrics_path: '/federate' params: 'match[]': ##定义要同步的监控项 - '{job="prometheus"}' - '{__name__=~"job:.*"}' - '{job="node_discovery"}' static_configs: - targets: - 'linux-node1:9090' ## 目标库可以写多行。 参考文档 prometheus-官网 Prometheus 实战 PROMETHEUS 监控系统介绍与实践总结 prometheus-监控mysql prometheus中文文档 官方容器站 Prometheus 监控方案 ...

    2018-06-29 未分类 3790
  • 区块链开发(一)搭建基于以太坊的私有链环境

        李赫 2016.07.08     通过本文所述方法和项目中的脚本,我们可以快速的搭建好自己的私有链进行区块链开发测试,本文基于以太坊技术进行搭建,分两个部分,一个是Ubuntu下搭建方法,另一个是Windwos下搭建方法,关于以太坊相关的基础知识,可以看我原先发表的一些文章,地址如下:    http://blog.csdn.net/sportshark   一、   Ubuntu下安装Geth客户端     之所以采用Ubuntu,是因为以太坊的官方对Ubuntu支持的很好,是在各个linux系统中安装最简单。     Geth官方安装指南:     https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum     进入ubuntu命令行,执行如下命令   sudo apt-get update sudo apt-get installsoftware-properties-common sudo add-apt-repository -yppa:ethereum/ethereum sudo add-apt-repository -yppa:ethereum/ethereum-dev sudo apt-get update sudo apt-get install ethereum       系统联网执行后,即完成了安装以太坊客户端,其中包括geth,bootnode, evm, disasm, rlpdump,ethtest     此时如果输入Geth命令,会出现启动以太坊启动的画面   二、       安装Windows下Geth客户端     Windows必须64位系统,从官方网站下载编译好的win64客户端,解压缩即可运行,下载地址如下:     https://github.com/ethereum/go-ethereum/releases/     下载后,只有一个Geth.exe的文件。     安装图像化客户端Mist,依然是从官方地址下载编译好的客户端即可,下载地址:     https://github.com/ethereum/mist/releases/     下载解压缩后,Ethereum-Wallet即为以太坊图形化界面。   三、       准备创世块文件     配置自己的创世块是为了区分公有链,同一个网络中,创世块必须是一样的,否则无法联通,此方法在windows和Ubuntu下通用。     新建文件piccgenesis.json,输入如下内容并保存 {     "nonce":"0x0000000000000042",     "mixhash":"0x0000000000000000000000000000000000000000000000000000000000000000",     "difficulty": "0x4000",     "alloc": {},     "coinbase":"0x0000000000000000000000000000000000000000",     "timestamp": "0x00",     "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000",     "extraData": "PICC GenesisBlock",     "gasLimit":"0xffffffff" }       解释一下各个参数的作用:   mixhash 与nonce配合用于挖矿,由上一个区块的一部分生成的hash。注意他和nonce的设置需要满足以太坊的Yellow paper, 4.3.4. Block Header Validity, (44)章节所描述的条件。. nonce nonce就是一个64位随机数,用于挖矿,注意他和mixhash的设置需要满足以太坊的Yellow paper, 4.3.4. Block Header Validity, (44)章节所描述的条件。 difficulty 设置当前区块的难度,如果难度过大,cpu挖矿就很难,这里设置较小难度 alloc 用来预置账号以及账号的以太币数量,因为私有链挖矿比较容易,所以我们不需要预置有币的账号,需要的时候自己创建即可以。 coinbase 矿工的账号,随便填 timestamp 设置创世块的时间戳 parentHash 上一个区块的hash值,因为是创世块,所以这个值是0 extraData 附加信息,随便填,可以填你的个性信息 gasLimit 该值设置对GAS的消耗总量限制,用来限制区块能包含的交易信息总和,因为我们是私有链,所以填最大。   四、       启动私有链节点     启动Geth即可以启动以太坊的区块链,为了构建私有链 ,需要在Geth启动时加入一些参数,Geth参数含义如下:  identity 区块链的标示,随便填写,用于标示目前网络的名字 init 指定创世块文件的位置,并创建初始块 datadir 设置当前区块链网络数据存放的位置 port 网络监听端口 rpc 启动rpc通信,可以进行智能合约的部署和调试 rpcapi 设置允许连接的rpc的客户端,一般为db,eth,net,web3 networkid 设置当前区块链的网络ID,用于区分不同的网络,是一个数字 console 启动命令行模式,可以在Geth中执行命令   1、  在Ubuntu启动区块链节点     在Ubuntu下,首先切换到打算运行的目录,目录下应该有配置好的piccgenesis.json文件,执行如下命令 basepath=$(cd `dirname $0`; pwd) 获取当前的目录 geth  --datadir "$basepath/chain" init piccgenesis.json  创建数据存放地址并初始化创世块 geth --identity"PICCetherum"  --rpc  --rpccorsdomain "*" --datadir "$basepath/chain" --port "30303"  --rpcapi "db,eth,net,web3"--networkid 95518 console     启动后界面如下,光标停留在最后的命令行上,可以执行以太坊命令。 I0707 00:45:43.680087 ethdb/database.go:82]Alloted 128MB cache and 1024 file handles to /home/lihe/桌面/chain/chaindata I0707 00:45:43.726008ethdb/database.go:169] closed db:/home/lihe/桌面/chain/chaindata I0707 00:45:43.728913 ethdb/database.go:82]Alloted 128MB cache and 1024 file handles to /home/lihe/桌面/chain/chaindata I0707 00:45:43.908795 ethdb/database.go:82]Alloted 16MB cache and 16 file handles to /home/lihe/桌面/chain/dapp I0707 00:45:43.969506 core/genesis.go:92]Genesis block already in chain. Writing canonical number I0707 00:45:43.980337 eth/backend.go:274]Successfully wrote custom genesis block:6e92f8b23bcdfdf34dc813cfaf1d84b71beac80530506b5d63a2df10fe23a660 I0707 00:45:43.980618 eth/backend.go:184]Protocol Versions: [63 62], Network Id: 95518 I0707 00:45:43.981567core/blockchain.go:204] Last header: #81 [6193c4b0…] TD=10836704 I0707 00:45:43.981645core/blockchain.go:205] Last block: #81 [6193c4b0…] TD=10836704 I0707 00:45:43.981677core/blockchain.go:206] Fast block: #81 [6193c4b0…] TD=10836704 I0707 00:45:43.985253 p2p/server.go:313]Starting Server I0707 00:45:45.834488p2p/discover/udp.go:217] Listening,enode://134881790e54c803955715e3661c27f91caaf499be813e29c9f986e2eac62d47e02b13a8e51776c1caea554655614ed26ce0185d84e626da7ac48a83a60113ff@[::]:30303 I0707 00:45:45.835853 node/node.go:366]HTTP endpoint opened: http://localhost:8545 I0707 00:45:45.848008 p2p/server.go:556]Listening on [::]:30303 I0707 00:45:45.849731 node/node.go:296] IPCendpoint opened: /home/lihe/桌面/chain/geth.ipc Welcome to the Geth JavaScript console!   instance:Geth/v1.5.0-unstable/linux/go1.5.1/PICCetherum coinbase:0x93509a2f4b2b974b07ef0b52e07c3992601f5de1 at block: 81 (Tue, 05 Jul 2016 21:02:25CST)  datadir: /home/lihe/桌面/chain  modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0 >      可以看到Listening on [::]:30303和Welcome to the Geth JavaScript console!的提示,说明已经启动成功     注意:如果想将Ubuntu作为永久区块链节点使用,当使用nohup命令时,Geth启动参数console必须去掉,否则Geth会自动停止。   2、  在windows启动区块链节点     进入Windows下Geth的目录 ,放置配置好的piccgenesis.json文件,执行如下命令: geth  --datadir "%cd%\chain" init piccgenesis.json  创建数据存放地址并初始化创世块 geth--identity "PICCetherum" --rpc--rpccorsdomain "*" --datadir "%cd%\chain" --port"30303"  --rpcapi"db,eth,net,web3" --networkid 95518 console     当看到Listening on [::]:30303和Welcome to the Geth JavaScript console!的提示,说明已经启动成功   五、       使用节点创建账号     启动节点成功后,会进入Geth的命令行模式,输入如下命令 personal.newAccount()     系统会提示你输入账号密码,并确认,最后会显示一个新生成的账号。   六、       启动Windows下私有链图形节点     首先按上面的步骤启动Geth并创建了账号,然后解压缩Ethereum-Wallet,运行Ethereum-Wallet.exe,即启动成功,如果区块链正常的话,会在右上角显示“PRIVATE-NET”,点击“LAUNCH APPLICATION”进入图形界面即可。   七、       连接其他节点     首先要知道自己的节点信息,在Geth命令行界面下输入命令,注意大小写 admin.nodeInfo     系统会显示   enode:"enode://1e3c1727cd3bee9f25edeb5dbb3b880e03e41f8eec99566557f3ee0422734a8fcad17c161aa93d61bdbfb28ed152c143c7eb501db58bc63502a104a84b62d742@0.0.0.0:30303“     其中 enode://1e3c1727cd3bee9f25edeb5dbb3b880e03e41f8eec99566557f3ee0422734a8fcad17c161aa93d61bdbfb28ed152c143c7eb501db58bc63502a104a84b62d742@0.0.0.0:30303     就是自己节点的信息,注意要把“0.0.0.0“换成你自己的IP。将这个信息发送给其他节点,在其他节点的命令行中输入: admin.addPeer(‘enode://1e3c1727cd3bee9f25edeb5dbb3b880e03e41f8eec99566557f3ee0422734a8fcad17c161aa93d61bdbfb28ed152c143c7eb501db58bc63502a104a84b62d742@192.168.1.101:30303’)     如果添加成功,输入admin.peers会显示出新添加的节点。   八、       使用节点进行挖矿     在Geth命令行界面下,输入miner.start()即启动挖矿,挖矿后,会不停刷屏,输入miner.stop()即停止,不用管刷屏导致的命令不全,命令会正常执行。      到这一步,已经组建一个私有链的网络,可以像其他区块链一样不停的扩充这个网络,下一篇文章,我会介绍如何在私有链上编写、调试和部署智能合约。  参考文章: 1. http://tech.lab.carl.pro/kb/ethereum/testnet_setup 2. http://www.ethdocs.org/en/latest/network/test-networks.html#setting-up-a-local-private-testnet 3. https://github.com/ethereum/go-ethereum/wiki/Connecting-to-the-network 4. https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console 5. https://github.com/ethereum/go-ethereum/wiki/Mining 6. https://github.com/ethereum/go-ethereum/wiki/Managing-your-accounts 7. https://github.com/janx/ethereum-bootstrap ...

    2018-06-29 未分类 3838
  • CentOS 6.5 安装GitLab 搭建自己的Github

    前言:        使用Github,免费的公开仓库可以用来开源一些代码,可是写一个项目的时候,并不想开源,在Github创建私有仓库还需要交保护费,所以我就想到了要不要自己搭一个Git服务器。   一开始,我直接yum安装了git,通过简单的配置可以通过git@server:/git/*.git,这样SSH的方式push和pull代码。可是,我还想通过http的方式,于是又通过安装apache实现了通过http的方式进行操作。现在又遇到了问题,就是怎么在线浏览我的代码,然后又是一通搜索,找到了gitweb,然后又是一通安装,失败了,可能是因为太乱了。不过,在我搜索的过程中,搜索引擎自动跳出了GitLab,然后马上展开搜索,就像发现了新大陆一样,顿时感觉,生活在这个开源的时代,学计算机是一件多么幸福的事情。(注:第一次写技术博客,有不好的地方尽管提出来) 登录成功界面 (这个页面是登录之后的页面,因为文章是我安装成功之后才写的,正常首次访问是要求你设置root密码的页面): 安装前准备:   VPS主机商: 腾讯云 (因为我是学生,正好可以用阿里云和腾讯云提供的学生主机,阿里云主机我搭建了我现在的博客,腾讯云一直空着,这次正好用来搭GitLab)   VPS运行内存: 1G   系统版本: Centos 6.5 64位   GitLab版本: 8.9.9 开始安装:   GitLab官网地址:   http://gitlab.com (官方网站全是英文,英文好的可以看下)   国内GitLab镜像地址:  http://gitlab.cc" (该网站还有翻译,以及一些rpm包的国内镜像地址)   查看GitLab硬件需求: https://doc.gitlab.cc/ce/install/requirements.html  (这是翻译版本,看英文原版也可以到官网地址自己找)   GitLab中文文档: https://doc.gitlab.cc/omnibus/"    1.安装配置依赖项 sudo yum install curl openssh-server openssh-clients postfix cronie sudo service postfix start  #GitLab使用postfix发送邮件 sudo chkconfig postfix on   #设置postfix开机自启动 sudo lokkit -s http -s ssh  #配置iptables开放http和ssh端口,这里需要注意,腾讯云安全组选择那里要选择开放所有端口 #这一步可能会显示failed ip6tables start,这个不需要管,直接运行下面查看是否打开端口就可以了 输入命令查看是否打开http和ssh端口 iptables -L 如显示下面的界面则表示已经打开端口 2.下载RPM包,并上传到服务器 (我这里是选择的下载rpm包,也有其他的方式,就是下载他的安装脚本或者镜像等方式,如果不想用rpm安装,可以自行搜索其它方式,官网也都有说明) 国内镜像下载地址: https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el6/ (Centos 6.5 64位) 打开后可以看到各个版本的rpm包,我是选择的8.9.9版本,点击相应rpm包进行下载 3.上传rpm包到服务器root目录,执行以下命令 cd /root rpm -i gitlab-ce-8.9.9-ce.0.el6.x86_64.rpm #rpm替换成自己所选择并下载的版本 安装成功会提示谢谢您的安装什么的。具体的就不截图了,这一步应该不会报错。 4.启动GitLab sudo gitlab-ctl reconfigure 5.使用浏览器访问GitLab (这里访问你的服务器IP地址)   首次访问GitLab,系统会让你重新设置管理员的密码,设置成功后会返回登录界面。   默认的管理员账号是root,如果你想更改默认管理员账号,请输入上面设置的新密码登录系统后修改帐号名。 6.上面的步骤执行完后应该就是可以使用了,可是因为我的服务器只有1G内存,所以浏览器访问的时候,时不时的会报502错误,这里我们需要增加服务器虚拟内存可以解决。 (对于502错误,也有可能是服务器端口占用的原因,不过我的服务器没有安装其他东西,所以不会出现端口占用的情况) 502  GitLab is not responding.  Please contact your GitLab administrator if this problem persists. 下面的操作是增加服务器虚拟内存: dd if=/dev/zero of=/var/swap bs=1024 count=2048000 #增加2G左右SWAP mkswap /var/swap #设置交换文件 swapon /var/swap #激活启用交换分区 下一步编辑fstab文件 vim /etc/fstab 在fstab文件最后一行添加如下内容 /var/swap swap swap defaults 0 0 这样就可以解决浏览器访问出现502的问题。还有就是服务器确实配置不怎么高,不过使用人数少应该没多大问题的。 需要注意的是:   通过这样的安装方式,默认安装的web服务器是Nginx,数据库是PostgreSQL,所以有其它需求的,比如使用Apache和Mysql等,是需要编译安装的。因为我不是学系统运维的,所以就怎么方便怎么来。能满足我的需求就可以了。   还有就是,我发现了一个国人写的类似于GitLab的项目,叫做Gogs,是Go语言开发的,据说比GitLab配置更方便,感兴趣的可以移步到官网看下》Gogs官网 总结:   这篇文章只是实现了GitLab的简单安装,并没有配置域名和https访问等等需要配置的东西。之后的文章,会进行一些简单的配置操作。   第一次写技术博客,很多地方可能我都没有考虑到,有不好的地方可以在下面留言反馈。 参考资料:   GitLab 简明安装配置指南   CentOS增加swap分区大小 ...

    2018-06-29 未分类 3956
  • redis学习笔记---redis的持久化(RDB和AOF方式)

     redis支持两种持久化的方式,可以单独使用或者结合起来使用      第一种:RDB方式(redis默认的持久化方式)  第二种:AOF方式      一、RDB       rdb方式的持久化是通过快照完成的,当符合一定条件时redis会自动将内存中的所有数据执行快照操作并存储到硬盘上。默认存储在redis根目录的dump.rdb文件中。(文件名在配置文件中dbfilename) redis进行快照的时机(在配置文件redis.conf中) save 900 1:表示900秒内至少一个键被更改则进行快照。 save 300 10 save 60 10000 redis自动实现快照的过程     1:redis使用fork函数复制一份当前进程的副本(子进程)  2:父进程继续接收并处理客户端发来的命令,而子进程开始将内存中的数据写入硬盘中的临时文件  3:当子进程写入完所有数据后会用该临时文件替换旧的RDB文件,至此,一次快照操作完成。    注意:redis在进行快照的过程中不会修改RDB文件,只有快照结束后才会将旧的文件替换成新的,也就是说任何时候RDB文件都是完整的。 这就使得我们可以通过定时备份RDB文件来实现redis数据库的备份, RDB文件是经过压缩的二进制文件,占用的空间会小于内存中的数据,更加利于传输。 手动执行save或者bgsave命令让redis执行快照。 两个命令的区别在于,save是由主进程进行快照操作,会阻塞其它请求。bgsave是由redis执行fork函数复制出一个子进程来进行快照操作。 文件修复:redis-check-dump rdb的优缺点 优点:由于存储的有数据快照文件,恢复数据很方便。 缺点:会丢失最后一次快照以后更改的所有数据。 二、AOF      aof方式的持久化是通过日志文件的方式。默认情况下redis没有开启aof,可以通过参数appendonly参数开启。   appendonly yes  aof文件的保存位置和rdb文件的位置相同,都是dir参数设置的,默认的文件名是appendonly.aof,可以通过      appendfilename参数修改    appendfilename appendonly.aof  redis写命令同步的时机  a ppendfsync always 每次都会执行  appendfsync everysec 默认 每秒执行一次同步操作(推荐,默认)  appendfsync no不主动进行同步,由操作系统来做,30秒一次   aof日志文件重写  auto-aof-rewrite-percentage 100(当目前aof文件大小超过上一次重写时的aof文件大小的百分之多少时会再次进行重写,如果之前没有重写,则以启动时的aof文件大小为依据)  auto-aof-rewrite-min-size 64mb   手动执行bgrewriteaof进行重写  重写的过程只和内存中的数据有关,和之前的aof文件无关。 所谓的“重写”其实是一个有歧义的词语, 实际上, AOF 重写并不需要对原有的 AOF 文件进行任何写入和读取, 它针对的是数据库中键的当前值。   文件修复:redis-check-aof      动态切换redis持久方式,从 RDB 切换到 AOF(支持Redis 2.2及以上)     CONFIG SET appendonly yes     CONFIG SET save ""(可选)       注意:当redis启动时,如果rdb持久化和aof持久化都打开了,那么程序会优先使用aof方式来恢复数据集,因为aof方式所保存的数据通常是最完整的。如果aof文件丢失了,则启动之后数据库内容为空。  注意:如果想把正在运行的redis数据库,从RDB切换到AOF,建议先使用动态切换方式,再修改配置文件,重启数据库。(不能直接修改配置文件,重启数据库,否则数据库中数据就为空了。) ...

    2018-06-29 未分类 3573
  • Redis 密码设置和查看密码

    Redis 密码设置和查看密码 redis没有实现访问控制这个功能,但是它提供了一个轻量级的认证方式,可以编辑redis.conf配置来启用认证。    1、初始化Redis密码:    在配置文件中有个参数: requirepass  这个就是配置redis访问密码的参数;    比如 requirepass test123;    (Ps:需重启Redis才能生效)    redis的查询速度是非常快的,外部用户一秒内可以尝试多大150K个密码;所以密码要尽量长(对于DBA 没有必要必须记住密码);    2、不重启Redis设置密码:    在配置文件中配置requirepass的密码(当redis重启时密码依然有效)。    redis 127.0.0.1:6379> config set requirepass test123    查询密码:    redis 127.0.0.1:6379> config get requirepass    (error) ERR operation not permitted    密码验证:    redis 127.0.0.1:6379> auth test123    OK    再次查询:    redis 127.0.0.1:6379> config get requirepass    1) "requirepass"    2) "test123"    PS:如果配置文件中没添加密码 那么redis重启后,密码失效;    3、登陆有密码的Redis:    在登录的时候的时候输入密码:    redis-cli -p 6379 -a test123    先登陆后验证:    redis-cli -p 6379    redis 127.0.0.1:6379> auth test123    OK    AUTH命令跟其他redis命令一样,是没有加密的;阻止不了攻击者在网络上窃取你的密码;    认证层的目标是提供多一层的保护。如果防火墙或者用来保护redis的系统防御外部攻击失败的话,外部用户如果没有通过密码认证还是无法访问redis的。 来自:http://weipengfei.blog.51cto.com/1511707/1217872 分类: redis ...

    2018-06-29 未分类 3457
  • Centos6下搭建ELK

    网上关于ELk的搭建有很多,下面是我搭建的过程,记录下来。   一、概念 ELK由三个部分组成。 logstash: 分析和收集日志,logstash有agent和indexer两个角色. elasticsearch: 搜索功能。 kibana: 提供Web功能。     二、搭建ElasticSearch     2.1  基本环境搭建         关闭防火墙或者放行 # vim /etc/sysconfig/iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 9200 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 9292 -j ACCEPT # service iptables restart     2.2 安装JDK     2.3 安装ElasticSearch     ElasticSearch默认的对外服务的HTTP端口是9200,节点间交互的TCP端口是9300。     1. 下载elasticsearch      wget https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.4.2.tar.gz     2. tar xfz elasticsearch-1.4.2.tar.gz     3. ln -s elasticsearch-2.1.0 elasticsearch     4. 修改配置文件       vi /usr/local/elasticsearch/config/elasticsearch.yml   http.cors.enabled: true #233行     5. 安装elasticsearch-servicewrapper,并启动ElasticSearch服务 wget https://github.com/elasticsearch/elasticsearch-servicewrapper/archive/master.tar.gz mv elasticsearch-servicewrapper-master/service/   /usr/local/elasticsearch/bin/ /usr/local/elasticsearch/bin/service/elasticsearch start           curl -X GET http://localhost:9200 三、搭建logstash 3.1 下载地址:     wget https://download.elasticsearch.org/logstash/logstash/logstash-1.4.2.tar.gz    3.2 tar xfz logstash-1.4.2.tar.gz 3.3 ln -s logstash-1.4.2 logstash   3.4 测试   /usr/local/logstash/bin/logstash -e 'input { stdin { } } output { stdout {} }' 3.5 mkdir /usr/local/logstash/etc 3.6 创建配置文件   vim /usr/local/logstash/etc/logstash_agent.conf   input {    file {    type => "http.access"    path => ["/var/log/httpd/access_log"]    }    file {    type => "http.error"    path => ["/var/log/httpd/error_log"]    }    file {    type => "messages"    path => ["/var/log/messages"]    }   }   output {     elasticsearch {    host => "192.168.241.144"    port => 9300    }   } 3.7 启动服务   nohup /usr/local/logstash/bin/logstash -f /usr/local/logstash/etc/logstash_agent.conf >> logstash.log &   四、安装kibana   4.1 下载地址:     wget https://download.elasticsearch.org/kibana/kibana/kibana-3.1.2.tar.gz   4.2 tar xfz kibana-3.1.2.tar.gz -C /var/www/html   4.3 mv kibana-3.1.2 kibana   4.4 修改config.js      elasticsearch:  "http://192.168.241.144:9200"    4.5 启动服务     /etc/init.d/httpd restart    输入URL http://192.168.241.144kibana       五、监控客户端   5.1 监控方式   我们可以直接监控客户端的配置文件,也可以让客户端把日志发到redis的消息队列里面。   5.2 配置客户端   客户端安装logstash,编写配置文件   vim /usr/local/logstash/etc/logstash_agent.conf   input {           file {                   type => "nginx_access"                   path => ["/usr/local/nginx/log/access.log"]           }   }   output {           redis {                   host => "192.168.241.144"              data_type => "list"                   key => "logstash:redis"                 port => "9400"         }   六、elasticsearch集群搭建实例   集群存放路径:/export/search/elasticsearch-cluster   6.1. 解压tar包,创建集群节点   #进入到集群路径   [root@localhost elasticsearch-cluster]# pwd   /export/search/elasticsearch-cluster   #重命名解压包   [root@localhost elasticsearch-cluster]# ls   elasticsearch-1.4.1   [root@localhost elasticsearch-cluster]# mv elasticsearch-1.4.1 elasticsearch-node1#进入到节点配置路径   [root@localhost elasticsearch-cluster]# cd elasticsearch-node1/config/   [root@localhost config]# ls   elasticsearch.yml logging.yml   6.2.创建集群配置信息:   # elasticsearch-node1配置# 配置集群名称   cluster.name: elasticsearch-cluster-centos   # 配置节点名称   node.name: "es-node1"# 为节点之间的通信设置一个自定义端口(默认为9300)   transport.tcp.port: 9300   # 设置监听HTTP传输的自定义端(默认为9200)   http.port: 9200   elasticsearch配置文件说明见: http://blog.csdn.net/an74520/article/details/10175603  3.安装head插件 #进入到节点bin路径 [root@localhost bin]# pwd /export/search/elasticsearch-cluster/elasticsearch-node1/bin 安装插件 [root@localhost bin]# ./plugin -install mobz/elasticsearch-head 安装完插件之后会在es节点bin路径同级创建一个plugins目录,存放安装的插件  4.复制一份配置好的节点为elasticsearch-node2 [root@localhost elasticsearch-cluster]# ls elasticsearch-node1 elasticsearch-node2  5.修改节点2中的集群配置信息 # elasticsearch-node2配置# 配置集群名称 cluster.name: elasticsearch-cluster-centos # 配置节点名称 node.name: "es-node2"# 为节点之间的通信设置一个自定义端口(默认为9300) transport.tcp.port: 9301 # 设置监听HTTP传输的自定义端(默认为9200) http.port: 9201 说明: 上面配置表示集群中有2个节点,节点名为别为,"es-node1"和  "es-node2",同属于集群"elasticsearch-cluster-centos" 节点二中端口可以不用配置,es在启动时会去检测,如果目标端口被占用,会检测下一个端口.因为两节点部署在同一天虚拟机上为了更好的说明问题,这里手动配置了对应的端口. 我们可以从es对应日志中()查看对应的启动信息,以及端口绑定信息。  6.分别启动节点 [root@localhost bin]# pwd /export/search/elasticsearch-cluster/elasticsearch-node1/bin [root@localhost bin]# ./elasticsearch -d -Xms2048m -Xmx2048m 如上,为启动节点1的命令,es启动配置相关日志查看elasticsearch-cluster- centos.log即可. [root@localhost logs]# pwd /export/search/elasticsearch-cluster/elasticsearch-node2/logs [root@localhost logs]# ls elasticsearch-cluster-centos_index_indexing_slowlog.log elasticsearch-cluster-centos.log elasticsearch-cluster-centos_index_search_slowlog.log  7. 至此我们的简易集群配置完成.查看集群 因为我们安装了head插件,所以可以通过该插件查看,虚拟机ip为192.168.19.56. http://192.168.19.56:9200/_plugin/head/ (对应节点1) http://192.168.19.56:9201/_plugin/head/ (对应节点2)    七、最后的效果图   ...

    2018-06-29 未分类 3807
  • Ubuntu14.04+RabbitMQ3.6.3+Golang的最佳实践

    目录 [TOC] 1、RabbitMQ介绍 1.1、什么是RabbitMQ?   RabbitMQ 是由 LShift 提供的一个 Advanced Message Queuing Protocol (AMQP) 的开源实现,由以高性能、健壮以及可伸缩性出名的 Erlang 写成,因此也是继承了这些优点。 1.2、什么是AMQP?   AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。它从生产者接收消息并递送给消费者,在这个过程中,根据规则进行路由,缓存与持久化。   AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。 RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。   而在AMQP中主要有两个组件:Exchange 和 Queue (在 AMQP 1.0 里还会有变动),如下图所示,绿色的 X 就是 Exchange ,红色的是 Queue ,这两者都在 Server 端,又称作 Broker ,这部分是 RabbitMQ 实现的,而蓝色的则是客户端,通常有 Producer 和 Consumer 两种类型:    1.3、RabbitMQ的基础概念 Broker:简单来说就是消息队列服务器实体 Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列 Queue:消息队列载体,每个消息都会被投入到一个或多个队列 Binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来 Routing Key:路由关键字,exchange根据这个关键字进行消息投递 vhost:虚拟主机,一个broker里可以开设多个vhost,用作不同用户的权限分离 producer:消息生产者,就是投递消息的程序 consumer:消息消费者,就是接受消息的程序 channel:消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务 1.4、RabbitMQ的特性 可靠性:包括消息持久化,消费者和生产者的消息确认 灵活路由:遵循AMQP协议,支持多种Exchange类型实现不同路由策略 分布式:集群的支持,包括本地网络与远程网络 高可用性:支持主从备份与镜像队列 多语言支持:支持多语言的客户端 WEB界面管理:可以管理用户权限,exhange,queue,binding,与实时监控 访问控制:基于vhosts实现访问控制 调试追踪:支持tracing,方便调试 2、RabbitMQ的官网在哪里?   http://www.rabbitmq.com/ 3、RabbitMQ在哪里下载?   http://www.rabbitmq.com/download.html 4、如何安装RabbitMQ 4.1、通过安装RabbitMQ的源来安装   在Ubuntu上安装RabbitMQ非常简单 lion@ubuntu1404:~$ sudo echo 'deb http://www.rabbitmq.com/debian/ testing main' | sudo tee /etc/apt/sources.list.d/rabbitmq.list lion@ubuntu1404:~$ wget -O- https://www.rabbitmq.com/rabbitmq-release-signing-key.asc | sudo apt-key add - lion@ubuntu1404:~$ sudo apt-get update lion@ubuntu1404:~$ sudo apt-get install rabbitmq-server   其他系统安装方法:http://www.rabbitmq.com/download.html 4.2、通过源码安装   本文中的实例,主要通过源码安装来演示。 4.2.1、安装Erlang   相关安装文档:http://erlang.org/erldoc lion@node1:~$ sudo apt-get install -y erlang-nox erlang-dev erlang-src    4.2.2、Rabbitmq 3.6.3安装   相关安装文档:http://www.rabbitmq.com/install-generic-unix.html。   我们先下载源码并解压 lion@node1:~$ mkdir -p _app lion@node1:~/_app$ wget http://www.rabbitmq.com/releases/rabbitmq-server/v3.6.3/rabbitmq-server-generic-unix-3.6.3.tar.xz lion@node1:~/_app$ xz -d rabbitmq-server-generic-unix-3.6.3.tar.xz lion@node1:~/_app$ tar -xvf rabbitmq-server-generic-unix-3.6.3.tar lion@node1:~/_app$ cd rabbitmq_server-3.6.3   设置环境变量$RABBITMQ_HOME lion@node1:~$ vi .bashrc   在.bashrc中添加以下内容 export RABBITMQ_HOME="/home/lion/_app/rabbitmq_server-3.6.3" export PATH="$RABBITMQ_HOME/sbin:$PATH"   让环境变量生效 lion@node1:~$ source .bashrc   启动Rabbitmq lion@node1:~$ rabbitmq-server   安装以后可以通过下面的命令,停止、启动: lion@node1:~$ rabbitmqctl stop lion@node1:~$ rabbitmqctl start 4.3、开启web管理插件   创建一个用户lion,并设置密码123456: lion@node1:~$ rabbitmqctl add_user lion 123456   可以通过下面的命令,查看现有的用户更表 lion@node1:~$ rabbitmqctl list_users Listing users ... guest [administrator] lion []   这个时候lion用户是不能访问web管理插件的,需要配置用户角色,用户角色可分为五类,超级管理员, 监控者, 策略制定者, 普通管理者以及其他。 超级管理员(administrator)   可登陆管理控制台(启用management plugin的情况下),可查看所有的信息,并且可以对用户,策略(policy)进行操作。 监控者(monitoring)   可登陆管理控制台(启用management plugin的情况下),同时可以查看rabbitmq节点的相关信息(进程数,内存使用情况,磁盘使用情况等) 策略制定者(policymaker)   可登陆管理控制台(启用management plugin的情况下), 同时可以对policy进行管理。但无法查看节点的相关信息。 普通管理者(management)   仅可登陆管理控制台(启用management plugin的情况下),无法看到节点信息,也无法对策略进行管理。 其他   无法登陆管理控制台,通常就是普通的生产者和消费者。   通过下面的命令,可以将lion添加到administrator用户组: lion@node1:~$ rabbitmqctl set_user_tags lion administrator   然后可以用下面的命令来启用/信上管理插件: lion@node1:~$ rabbitmq-plugins enable rabbitmq_management (启用插件) lion@node1:~$ rabbitmq-plugins disable rabbitmq_management (禁用插件)   通过浏览访问 http://127.0.0.1:15672/   输入用户名lion,密码123456就可以看到后台了。 rabbitmqctl的更多命令参考:http://www.rabbitmq.com/man/rabbitmqctl.1.man.html 4.4、RabbitMQ 的配置文件介绍   RabbitMQ的配置文件目录默认是$RABBITMQ_HOME/etc/rabbitmq/rabbitmq-env.conf,如果文件不存在,可以自己创建。   配置文件全部说明地址:http://www.rabbitmq.com/configure.html#configuration-file %% -*- mode: erlang -*- %% ---------------------------------------------------------------------------- %% RabbitMQ Sample Configuration File. %% %% See http://www.rabbitmq.com/configure.html for details. %% ---------------------------------------------------------------------------- [ {rabbit, [%% %% Network Connectivity %% ==================== %% %% By default, RabbitMQ will listen on all interfaces, using %% the standard (reserved) AMQP port. %% 默认的监听端口 %% {tcp_listeners, [5672]}, %% To listen on a specific interface, provide a tuple of {IpAddress, Port}. %% For example, to listen only on localhost for both IPv4 and IPv6: %% 也可以使用下面的格式进行指定IP和端口的监听 %% {tcp_listeners, [{"127.0.0.1", 5672}, %% {"::1", 5672}]}, %% SSL listeners are configured in the same fashion as TCP listeners, %% including the option to control the choice of interface. %% SSL连接端口配置 %% {ssl_listeners, [5671]}, %% Number of Erlang processes that will accept connections for the TCP %% and SSL listeners. %% TCP连接的进程数 %% {num_tcp_acceptors, 10}, %% {num_ssl_acceptors, 1}, %% Maximum time for AMQP 0-8/0-9/0-9-1 handshake (after socket connection %% and SSL handshake), in milliseconds. %% 超时时间,单位毫秒 %% {handshake_timeout, 10000}, %% Log levels (currently just used for connection logging). %% One of 'debug', 'info', 'warning', 'error' or 'none', in decreasing %% order of verbosity. Defaults to 'info'. %% 日志的级别,默认是info %% {log_levels, [{connection, info}, {channel, info}]}, %% Set to 'true' to perform reverse DNS lookups when accepting a %% connection. Hostnames will then be shown instead of IP addresses %% in rabbitmqctl and the management plugin. %% %% {reverse_dns_lookups, true}, %% %% Security / AAA %% ============== %% 安全配置 %% The default "guest" user is only permitted to access the server %% via a loopback interface (e.g. localhost). %% {loopback_users, [<<"guest">>]}, %% %% Uncomment the following line if you want to allow access to the %% guest user from anywhere on the network. %% {loopback_users, []}, %% Configuring SSL. %% See http://www.rabbitmq.com/ssl.html for full documentation. %% %% {ssl_options, [{cacertfile, "/path/to/testca/cacert.pem"}, %% {certfile, "/path/to/server/cert.pem"}, %% {keyfile, "/path/to/server/key.pem"}, %% {verify, verify_peer}, %% {fail_if_no_peer_cert, false}]}, %% Choose the available SASL mechanism(s) to expose. %% The two default (built in) mechanisms are 'PLAIN' and %% 'AMQPLAIN'. Additional mechanisms can be added via %% plugins. %% %% See http://www.rabbitmq.com/authentication.html for more details. %% %% {auth_mechanisms, ['PLAIN', 'AMQPLAIN']}, %% Select an authentication database to use. RabbitMQ comes bundled %% with a built-in auth-database, based on mnesia. %% %% {auth_backends, [rabbit_auth_backend_internal]}, %% Configurations supporting the rabbitmq_auth_mechanism_ssl and %% rabbitmq_auth_backend_ldap plugins. %% %% NB: These options require that the relevant plugin is enabled. %% See http://www.rabbitmq.com/plugins.html for further details. %% The RabbitMQ-auth-mechanism-ssl plugin makes it possible to %% authenticate a user based on the client's SSL certificate. %% %% To use auth-mechanism-ssl, add to or replace the auth_mechanisms %% list with the entry 'EXTERNAL'. %% %% {auth_mechanisms, ['EXTERNAL']}, %% The rabbitmq_auth_backend_ldap plugin allows the broker to %% perform authentication and authorisation by deferring to an %% external LDAP server. %% %% For more information about configuring the LDAP backend, see %% http://www.rabbitmq.com/ldap.html. %% %% Enable the LDAP auth backend by adding to or replacing the %% auth_backends entry: %% %% {auth_backends, [rabbit_auth_backend_ldap]}, %% This pertains to both the rabbitmq_auth_mechanism_ssl plugin and %% STOMP ssl_cert_login configurations. See the rabbitmq_stomp %% configuration section later in this file and the README in %% https://github.com/rabbitmq/rabbitmq-auth-mechanism-ssl for further %% details. %% %% To use the SSL cert's CN instead of its DN as the username %% %% {ssl_cert_login_from, common_name}, %% SSL handshake timeout, in milliseconds. %% %% {ssl_handshake_timeout, 5000}, %% Password hashing implementation. Will only affect newly %% created users. To recalculate hash for an existing user %% it's necessary to update her password. %% %% {password_hashing_module, rabbit_password_hashing_sha256}, %% %% Default User / VHost %% ==================== %% 用户访问设置 %% On first start RabbitMQ will create a vhost and a user. These %% config items control what gets created. See %% http://www.rabbitmq.com/access-control.html for further %% information about vhosts and access control. %% %% {default_vhost, <<"/">>}, %% {default_user, <<"guest">>}, %% {default_pass, <<"guest">>}, %% {default_permissions, [<<".*">>, <<".*">>, <<".*">>]}, %% Tags for default user %% %% For more details about tags, see the documentation for the %% Management Plugin at http://www.rabbitmq.com/management.html. %% %% {default_user_tags, [administrator]}, %% %% Additional network and protocol related configuration %% ===================================================== %% %% Set the default AMQP heartbeat delay (in seconds). %% 设置默认AMQP心跳延迟(秒) %% {heartbeat, 600}, %% Set the max permissible size of an AMQP frame (in bytes). %% %% {frame_max, 131072}, %% Set the max frame size the server will accept before connection %% tuning occurs %% %% {initial_frame_max, 4096}, %% Set the max permissible number of channels per connection. %% 0 means "no limit". %% %% {channel_max, 128}, %% Customising Socket Options. %% %% See (http://www.erlang.org/doc/man/inet.html#setopts-2) for %% further documentation. %% %% {tcp_listen_options, [{backlog, 128}, %% {nodelay, true}, %% {exit_on_close, false}]}, %% %% Resource Limits & Flow Control %% ============================== %% %% See http://www.rabbitmq.com/memory.html for full details. %% Memory-based Flow Control threshold. %% %% {vm_memory_high_watermark, 0.4}, %% Alternatively, we can set a limit (in bytes) of RAM used by the node. %% %% {vm_memory_high_watermark, {absolute, 1073741824}}, %% %% Or you can set absolute value using memory units. %% %% {vm_memory_high_watermark, {absolute, "1024M"}}, %% %% Supported units suffixes: %% %% k, kiB: kibibytes (2^10 bytes) %% M, MiB: mebibytes (2^20) %% G, GiB: gibibytes (2^30) %% kB: kilobytes (10^3) %% MB: megabytes (10^6) %% GB: gigabytes (10^9) %% Fraction of the high watermark limit at which queues start to %% page message out to disc in order to free up memory. %% %% Values greater than 0.9 can be dangerous and should be used carefully. %% 内存最大使用比例 %% {vm_memory_high_watermark_paging_ratio, 0.5}, %% Interval (in milliseconds) at which we perform the check of the memory %% levels against the watermarks. %% 检查内存的间隔(毫秒) %% {memory_monitor_interval, 2500}, %% Set disk free limit (in bytes). Once free disk space reaches this %% lower bound, a disk alarm will be set - see the documentation %% listed above for more details. %% %% {disk_free_limit, 50000000}, %% %% Or you can set it using memory units (same as in vm_memory_high_watermark) %% {disk_free_limit, "50MB"}, %% {disk_free_limit, "50000kB"}, %% {disk_free_limit, "2GB"}, %% Alternatively, we can set a limit relative to total available RAM. %% %% Values lower than 1.0 can be dangerous and should be used carefully. %% {disk_free_limit, {mem_relative, 2.0}}, %% %% Misc/Advanced Options %% ===================== %% %% NB: Change these only if you understand what you are doing! %% %% To announce custom properties to clients on connection: %% %% {server_properties, []}, %% How to respond to cluster partitions. %% See http://www.rabbitmq.com/partitions.html for further details. %% %% {cluster_partition_handling, ignore}, %% Make clustering happen *automatically* at startup - only applied %% to nodes that have just been reset or started for the first time. %% See http://www.rabbitmq.com/clustering.html#auto-config for %% further details. %% 设置集群启动的节点 %% {cluster_nodes, {['rabbit@my.host.com'], disc}}, %% Interval (in milliseconds) at which we send keepalive messages %% to other cluster members. Note that this is not the same thing %% as net_ticktime; missed keepalive messages will not cause nodes %% to be considered down. %% 集群消息同步的时间(毫秒) %% {cluster_keepalive_interval, 10000}, %% Set (internal) statistics collection granularity. %% %% {collect_statistics, none}, %% Statistics collection interval (in milliseconds). %% %% {collect_statistics_interval, 5000}, %% Explicitly enable/disable hipe compilation. %% %% {hipe_compile, true}, %% Timeout used when waiting for Mnesia tables in a cluster to %% become available. %% %% {mnesia_table_loading_timeout, 30000}, %% Size in bytes below which to embed messages in the queue index. See %% http://www.rabbitmq.com/persistence-conf.html %% %% {queue_index_embed_msgs_below, 4096} ]}, %% ---------------------------------------------------------------------------- %% Advanced Erlang Networking/Clustering Options. %% %% See http://www.rabbitmq.com/clustering.html for details %% ---------------------------------------------------------------------------- {kernel, [%% Sets the net_kernel tick time. %% Please see http://erlang.org/doc/man/kernel_app.html and %% http://www.rabbitmq.com/nettick.html for further details. %% %% {net_ticktime, 60} ]}, %% ---------------------------------------------------------------------------- %% RabbitMQ Management Plugin %% %% See http://www.rabbitmq.com/management.html for details %% ---------------------------------------------------------------------------- {rabbitmq_management, [%% Pre-Load schema definitions from the following JSON file. See %% http://www.rabbitmq.com/management.html#load-definitions %% %% {load_definitions, "/path/to/schema.json"}, %% Log all requests to the management HTTP API to a file. %% 所有请求的HTTP API文件日志的路径。 %% {http_log_dir, "/path/to/access.log"}, %% Change the port on which the HTTP listener listens, %% specifying an interface for the web server to bind to. %% Also set the listener to use SSL and provide SSL options. %% Web管理的地址和端口 %% {listener, [{port, 12345}, %% {ip, "127.0.0.1"}, %% {ssl, true}, %% {ssl_opts, [{cacertfile, "/path/to/cacert.pem"}, %% {certfile, "/path/to/cert.pem"}, %% {keyfile, "/path/to/key.pem"}]}]}, %% One of 'basic', 'detailed' or 'none'. See %% http://www.rabbitmq.com/management.html#fine-stats for more details. %% {rates_mode, basic}, %% Configure how long aggregated data (such as message rates and queue %% lengths) is retained. Please read the plugin's documentation in %% http://www.rabbitmq.com/management.html#configuration for more %% details. %% %% {sample_retention_policies, %% [{global, [{60, 5}, {3600, 60}, {86400, 1200}]}, %% {basic, [{60, 5}, {3600, 60}]}, %% {detailed, [{10, 5}]}]} ]}, %% ---------------------------------------------------------------------------- %% RabbitMQ Shovel Plugin %% %% See http://www.rabbitmq.com/shovel.html for details %% ---------------------------------------------------------------------------- {rabbitmq_shovel, [{shovels, [%% A named shovel worker. %% {my_first_shovel, %% [ %% List the source broker(s) from which to consume. %% %% {sources, %% [%% URI(s) and pre-declarations for all source broker(s). %% {brokers, ["amqp://user:password@host.domain/my_vhost"]}, %% {declarations, []} %% ]}, %% List the destination broker(s) to publish to. %% {destinations, %% [%% A singular version of the 'brokers' element. %% {broker, "amqp://"}, %% {declarations, []} %% ]}, %% Name of the queue to shovel messages from. %% %% {queue, <<"your-queue-name-goes-here">>}, %% Optional prefetch count. %% %% {prefetch_count, 10}, %% when to acknowledge messages: %% - no_ack: never (auto) %% - on_publish: after each message is republished %% - on_confirm: when the destination broker confirms receipt %% %% {ack_mode, on_confirm}, %% Overwrite fields of the outbound basic.publish. %% %% {publish_fields, [{exchange, <<"my_exchange">>}, %% {routing_key, <<"from_shovel">>}]}, %% Static list of basic.properties to set on re-publication. %% %% {publish_properties, [{delivery_mode, 2}]}, %% The number of seconds to wait before attempting to %% reconnect in the event of a connection failure. %% %% {reconnect_delay, 2.5} %% ]} %% End of my_first_shovel ]} %% Rather than specifying some values per-shovel, you can specify %% them for all shovels here. %% %% {defaults, [{prefetch_count, 0}, %% {ack_mode, on_confirm}, %% {publish_fields, []}, %% {publish_properties, [{delivery_mode, 2}]}, %% {reconnect_delay, 2.5}]} ]}, %% ---------------------------------------------------------------------------- %% RabbitMQ Stomp Adapter %% %% See http://www.rabbitmq.com/stomp.html for details %% ---------------------------------------------------------------------------- {rabbitmq_stomp, [%% Network Configuration - the format is generally the same as for the broker %% Listen only on localhost (ipv4 & ipv6) on a specific port. %% {tcp_listeners, [{"127.0.0.1", 61613}, %% {"::1", 61613}]}, %% Listen for SSL connections on a specific port. %% {ssl_listeners, [61614]}, %% Number of Erlang processes that will accept connections for the TCP %% and SSL listeners. %% %% {num_tcp_acceptors, 10}, %% {num_ssl_acceptors, 1}, %% Additional SSL options %% Extract a name from the client's certificate when using SSL. %% %% {ssl_cert_login, true}, %% Set a default user name and password. This is used as the default login %% whenever a CONNECT frame omits the login and passcode headers. %% %% Please note that setting this will allow clients to connect without %% authenticating! %% %% {default_user, [{login, "guest"}, %% {passcode, "guest"}]}, %% If a default user is configured, or you have configured use SSL client %% certificate based authentication, you can choose to allow clients to %% omit the CONNECT frame entirely. If set to true, the client is %% automatically connected as the default user or user supplied in the %% SSL certificate whenever the first frame sent on a session is not a %% CONNECT frame. %% %% {implicit_connect, true} ]}, %% ---------------------------------------------------------------------------- %% RabbitMQ MQTT Adapter %% %% See https://github.com/rabbitmq/rabbitmq-mqtt/blob/stable/README.md %% for details %% ---------------------------------------------------------------------------- {rabbitmq_mqtt, [%% Set the default user name and password. Will be used as the default login %% if a connecting client provides no other login details. %% %% Please note that setting this will allow clients to connect without %% authenticating! %% %% {default_user, <<"guest">>}, %% {default_pass, <<"guest">>}, %% Enable anonymous access. If this is set to false, clients MUST provide %% login information in order to connect. See the default_user/default_pass %% configuration elements for managing logins without authentication. %% %% {allow_anonymous, true}, %% If you have multiple chosts, specify the one to which the %% adapter connects. %% %% {vhost, <<"/">>}, %% Specify the exchange to which messages from MQTT clients are published. %% %% {exchange, <<"amq.topic">>}, %% Specify TTL (time to live) to control the lifetime of non-clean sessions. %% %% {subscription_ttl, 1800000}, %% Set the prefetch count (governing the maximum number of unacknowledged %% messages that will be delivered). %% %% {prefetch, 10}, %% TCP/SSL Configuration (as per the broker configuration). %% %% {tcp_listeners, [1883]}, %% {ssl_listeners, []}, %% Number of Erlang processes that will accept connections for the TCP %% and SSL listeners. %% %% {num_tcp_acceptors, 10}, %% {num_ssl_acceptors, 1}, %% TCP/Socket options (as per the broker configuration). %% %% {tcp_listen_options, [{backlog, 128}, %% {nodelay, true}]} ]}, %% ---------------------------------------------------------------------------- %% RabbitMQ AMQP 1.0 Support %% %% See https://github.com/rabbitmq/rabbitmq-amqp1.0/blob/stable/README.md %% for details %% ---------------------------------------------------------------------------- {rabbitmq_amqp1_0, [%% Connections that are not authenticated with SASL will connect as this %% account. See the README for more information. %% %% Please note that setting this will allow clients to connect without %% authenticating! %% %% {default_user, "guest"}, %% Enable protocol strict mode. See the README for more information. %% %% {protocol_strict_mode, false} ]}, %% ---------------------------------------------------------------------------- %% RabbitMQ LDAP Plugin %% %% See http://www.rabbitmq.com/ldap.html for details. %% %% ---------------------------------------------------------------------------- {rabbitmq_auth_backend_ldap, [%% %% Connecting to the LDAP server(s) %% ================================ %% %% Specify servers to bind to. You *must* set this in order for the plugin %% to work properly. %% %% {servers, ["your-server-name-goes-here"]}, %% Connect to the LDAP server using SSL %% %% {use_ssl, false}, %% Specify the LDAP port to connect to %% %% {port, 389}, %% LDAP connection timeout, in milliseconds or 'infinity' %% %% {timeout, infinity}, %% Enable logging of LDAP queries. %% One of %% - false (no logging is performed) %% - true (verbose logging of the logic used by the plugin) %% - network (as true, but additionally logs LDAP network traffic) %% %% Defaults to false. %% %% {log, false}, %% %% Authentication %% ============== %% %% Pattern to convert the username given through AMQP to a DN before %% binding %% %% {user_dn_pattern, "cn=${username},ou=People,dc=example,dc=com"}, %% Alternatively, you can convert a username to a Distinguished %% Name via an LDAP lookup after binding. See the documentation for %% full details. %% When converting a username to a dn via a lookup, set these to %% the name of the attribute that represents the user name, and the %% base DN for the lookup query. %% %% {dn_lookup_attribute, "userPrincipalName"}, %% {dn_lookup_base, "DC=gopivotal,DC=com"}, %% Controls how to bind for authorisation queries and also to %% retrieve the details of users logging in without presenting a %% password (e.g., SASL EXTERNAL). %% One of %% - as_user (to bind as the authenticated user - requires a password) %% - anon (to bind anonymously) %% - {UserDN, Password} (to bind with a specified user name and password) %% %% Defaults to 'as_user'. %% %% {other_bind, as_user}, %% %% Authorisation %% ============= %% %% The LDAP plugin can perform a variety of queries against your %% LDAP server to determine questions of authorisation. See %% http://www.rabbitmq.com/ldap.html#authorisation for more %% information. %% Set the query to use when determining vhost access %% %% {vhost_access_query, {in_group, %% "ou=${vhost}-users,ou=vhosts,dc=example,dc=com"}}, %% Set the query to use when determining resource (e.g., queue) access %% %% {resource_access_query, {constant, true}}, %% Set queries to determine which tags a user has %% %% {tag_queries, []} ]} ]. 5、Golang调用RabbitMQ的案例   下载Golgang运行amqp协议的包,在Rabbitmq官网上有提供现在的golang包来使用amqp协议与Rabbitmq交互 。   我们先将包下载到本地,然后就可以直接使用了: lion@node1:~$ go get github.com/streadway/amqp 5.1、使用Golang来发送第一个hello idoall.org   在第一个教程中,我们写程序从一个命名的队列(test-idoall-queues)中发送和接收消息。   producer_hello.go(消息生产者): package main import ( "fmt" "log" "github.com/streadway/amqp" ) const ( //AMQP URI uri = "amqp://guest:guest@localhost:5672/" //Durable AMQP exchange name exchangeName = "" //Durable AMQP queue name queueName = "test-idoall-queues" //Body of message bodyMsg string = "hello idoall.org" ) //如果存在错误,则输出 func failOnError(err error, msg string) { if err != nil { log.Fatalf("%s: %s", msg, err) panic(fmt.Sprintf("%s: %s", msg, err)) } } func main(){ //调用发布消息函数 publish(uri, exchangeName, queueName, bodyMsg) log.Printf("published %dB OK", len(bodyMsg)) } //发布者的方法 // //@amqpURI, amqp的地址 //@exchange, exchange的名称 //@queue, queue的名称 //@body, 主体内容 func publish(amqpURI string, exchange string, queue string, body string){ //建立连接 log.Printf("dialing %q", amqpURI) connection, err := amqp.Dial(amqpURI) failOnError(err, "Failed to connect to RabbitMQ") defer connection.Close() //创建一个Channel log.Printf("got Connection, getting Channel") channel, err := connection.Channel() failOnError(err, "Failed to open a channel") defer channel.Close() log.Printf("got queue, declaring %q", queue) //创建一个queue q, err := channel.QueueDeclare( queueName, // name false, // durable false, // delete when unused false, // exclusive false, // no-wait nil, // arguments ) failOnError(err, "Failed to declare a queue") log.Printf("declared queue, publishing %dB body (%q)", len(body), body) // Producer只能发送到exchange,它是不能直接发送到queue的。 // 现在我们使用默认的exchange(名字是空字符)。这个默认的exchange允许我们发送给指定的queue。 // routing_key就是指定的queue名字。 err = channel.Publish( exchange, // exchange q.Name, // routing key false, // mandatory false, // immediate amqp.Publishing { Headers: amqp.Table{}, ContentType: "text/plain", ContentEncoding: "", Body: []byte(body), }) failOnError(err, "Failed to publish a message") }   consumer_hello(消息消费者).go package main import ( "fmt" "log" "github.com/streadway/amqp" ) const ( //AMQP URI uri = "amqp://guest:guest@localhost:5672/" //Durable AMQP exchange nam exchangeName = "" //Durable AMQP queue name queueName = "test-idoall-queues" ) //如果存在错误,则输出 func failOnError(err error, msg string) { if err != nil { log.Fatalf("%s: %s", msg, err) panic(fmt.Sprintf("%s: %s", msg, err)) } } func main(){ //调用消息接收者 consumer(uri, exchangeName, queueName) } //接收者方法 // //@amqpURI, amqp的地址 //@exchange, exchange的名称 //@queue, queue的名称 func consumer(amqpURI string, exchange string, queue string){ //建立连接 log.Printf("dialing %q", amqpURI) connection, err := amqp.Dial(amqpURI) failOnError(err, "Failed to connect to RabbitMQ") defer connection.Close() //创建一个Channel log.Printf("got Connection, getting Channel") channel, err := connection.Channel() failOnError(err, "Failed to open a channel") defer channel.Close() log.Printf("got queue, declaring %q", queue) //创建一个queue q, err := channel.QueueDeclare( queueName, // name false, // durable false, // delete when unused false, // exclusive false, // no-wait nil, // arguments ) failOnError(err, "Failed to declare a queue") log.Printf("Queue bound to Exchange, starting Consume") //订阅消息 msgs, err := channel.Consume( q.Name, // queue "", // consumer true, // auto-ack false, // exclusive false, // no-local false, // no-wait nil, // args ) failOnError(err, "Failed to register a consumer") //创建一个channel forever := make(chan bool) //调用gorountine go func() { for d := range msgs { log.Printf("Received a message: %s", d.Body) } }() log.Printf(" [*] Waiting for messages. To exit press CTRL+C") //没有写入数据,一直等待读,阻塞当前线程,目的是让线程不退出 <-forever }   Console1(运行producer): lion@node1:~/_code/_rabbitmq/_golang$ go run producer_hello.go 2016/07/23 02:29:51 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 02:29:51 got Connection, getting Channel 2016/07/23 02:29:51 got queue, declaring "test-idoall-queues" 2016/07/23 02:29:51 declared queue, publishing 16B body ("hello idoall.org") 2016/07/23 02:29:51 published 16B OK   然后运行以下命令,可以看到我们刚才创建的queues在列表中 lion@node1:~/_code/_rabbitmq/_golang$ rabbitmqctl list_queues Listing queues ... test-idoall-queues 1   Console2(运行consumer)打印消息到屏幕,可以看到刚才我们通过producer发送的消息hello idoall.org lion@node1:~/_code/_rabbitmq/_golang$ go run consumer_hello.go 2016/07/23 03:33:14 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 03:33:14 got Connection, getting Channel 2016/07/23 03:33:14 got queue, declaring "test-idoall-queues" 2016/07/23 03:33:14 Queue bound to Exchange, starting Consume 2016/07/23 03:33:14 [*] Waiting for messages. To exit press CTRL+C 2016/07/23 03:33:14 Received a message: hello idoall.org 5.2、Rabbitmq的任务分发机制   在5.1章节中,我们写程序从一个命名的队列中发送和接收消息。在这个章节中,我们将创建一个工作队列,将用于分配在多个工人之间的耗时的任务。   RabbitMQ的分发机制非常适合扩展,而且它是专门为并发程序设计的。如果任务队伍过多,那么只需要创建更多的Consumer来进行任务处理即可。   producer_task.go(消息生产者): package main import ( "fmt" "log" "os" "strings" "github.com/streadway/amqp" ) const ( //AMQP URI uri = "amqp://guest:guest@localhost:5672/" //Durable AMQP exchange name exchangeName = "" //Durable AMQP queue name queueName = "test-idoall-queues-task" ) //如果存在错误,则输出 func failOnError(err error, msg string) { if err != nil { log.Fatalf("%s: %s", msg, err) panic(fmt.Sprintf("%s: %s", msg, err)) } } func main(){ bodyMsg := bodyFrom(os.Args) //调用发布消息函数 publish(uri, exchangeName, queueName, bodyMsg) log.Printf("published %dB OK", len(bodyMsg)) } func bodyFrom(args []string) string { var s string if (len(args) < 2) || os.Args[1] == "" { s = "hello idoall.org" } else { s = strings.Join(args[1:], " ") } return s } //发布者的方法 // //@amqpURI, amqp的地址 //@exchange, exchange的名称 //@queue, queue的名称 //@body, 主体内容 func publish(amqpURI string, exchange string, queue string, body string){ //建立连接 log.Printf("dialing %q", amqpURI) connection, err := amqp.Dial(amqpURI) failOnError(err, "Failed to connect to RabbitMQ") defer connection.Close() //创建一个Channel log.Printf("got Connection, getting Channel") channel, err := connection.Channel() failOnError(err, "Failed to open a channel") defer channel.Close() log.Printf("got queue, declaring %q", queue) //创建一个queue q, err := channel.QueueDeclare( queueName, // name false, // durable false, // delete when unused false, // exclusive false, // no-wait nil, // arguments ) failOnError(err, "Failed to declare a queue") log.Printf("declared queue, publishing %dB body (%q)", len(body), body) // Producer只能发送到exchange,它是不能直接发送到queue的。 // 现在我们使用默认的exchange(名字是空字符)。这个默认的exchange允许我们发送给指定的queue。 // routing_key就是指定的queue名字。 err = channel.Publish( exchange, // exchange q.Name, // routing key false, // mandatory false, // immediate amqp.Publishing { Headers: amqp.Table{}, ContentType: "text/plain", ContentEncoding: "", Body: []byte(body), }) failOnError(err, "Failed to publish a message") }   consumer_task(消息消费者).go package main import ( "fmt" "log" "bytes" "time" "github.com/streadway/amqp" ) const ( //AMQP URI uri = "amqp://guest:guest@localhost:5672/" //Durable AMQP exchange nam exchangeName = "" //Durable AMQP queue name queueName = "test-idoall-queues-task" ) //如果存在错误,则输出 func failOnError(err error, msg string) { if err != nil { log.Fatalf("%s: %s", msg, err) panic(fmt.Sprintf("%s: %s", msg, err)) } } func main(){ //调用消息接收者 consumer(uri, exchangeName, queueName) } //接收者方法 // //@amqpURI, amqp的地址 //@exchange, exchange的名称 //@queue, queue的名称 func consumer(amqpURI string, exchange string, queue string){ //建立连接 log.Printf("dialing %q", amqpURI) connection, err := amqp.Dial(amqpURI) failOnError(err, "Failed to connect to RabbitMQ") defer connection.Close() //创建一个Channel log.Printf("got Connection, getting Channel") channel, err := connection.Channel() failOnError(err, "Failed to open a channel") defer channel.Close() log.Printf("got queue, declaring %q", queue) //创建一个queue q, err := channel.QueueDeclare( queueName, // name false, // durable false, // delete when unused false, // exclusive false, // no-wait nil, // arguments ) failOnError(err, "Failed to declare a queue") log.Printf("Queue bound to Exchange, starting Consume") //订阅消息 msgs, err := channel.Consume( q.Name, // queue "", // consumer false, // auto-ack false, // exclusive false, // no-local false, // no-wait nil, // args ) failOnError(err, "Failed to register a consumer") //创建一个channel forever := make(chan bool) //调用gorountine go func() { for d := range msgs { log.Printf("Received a message: %s", d.Body) dot_count := bytes.Count(d.Body, []byte(".")) t := time.Duration(dot_count) time.Sleep(t * time.Second) log.Printf("Done") } }() log.Printf(" [*] Waiting for messages. To exit press CTRL+C") //没有写入数据,一直等待读,阻塞当前线程,目的是让线程不退出 <-forever } 查看结果   Console1(consumer): lion@node1:~/_code/_rabbitmq/_golang$ go run consumer_task.go 2016/07/23 10:11:40 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 10:11:40 got Connection, getting Channel 2016/07/23 10:11:40 got queue, declaring "test-idoall-queues-task" 2016/07/23 10:11:40 Queue bound to Exchange, starting Consume 2016/07/23 10:11:40 [*] Waiting for messages. To exit press CTRL+C   Console2(consumer): lion@node1:~/_code/_rabbitmq/_golang$ go run consumer_task.go 2016/07/23 10:11:40 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 10:11:40 got Connection, getting Channel 2016/07/23 10:11:40 got queue, declaring "test-idoall-queues-task" 2016/07/23 10:11:40 Queue bound to Exchange, starting Consume 2016/07/23 10:11:40 [*] Waiting for messages. To exit press CTRL+C   这个时候我们使用Producer 来 Publish Message: lion@node1:~/_code/_rabbitmq/_golang$ go run producer_task.go First message. && go run producer_task.go Second message.. && go run producer_task.go Third message... && go run producer_task.go Fourth message.... && go run producer_task.go Fifth message..... 2016/07/23 10:17:13 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 10:17:13 got Connection, getting Channel 2016/07/23 10:17:13 got queue, declaring "test-idoall-queues-task" 2016/07/23 10:17:13 declared queue, publishing 14B body ("First message.") 2016/07/23 10:17:13 published 14B OK 2016/07/23 10:17:14 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 10:17:14 got Connection, getting Channel 2016/07/23 10:17:14 got queue, declaring "test-idoall-queues-task" 2016/07/23 10:17:14 declared queue, publishing 16B body ("Second message..") 2016/07/23 10:17:14 published 16B OK 2016/07/23 10:17:15 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 10:17:15 got Connection, getting Channel 2016/07/23 10:17:15 got queue, declaring "test-idoall-queues-task" 2016/07/23 10:17:15 declared queue, publishing 16B body ("Third message...") 2016/07/23 10:17:15 published 16B OK 2016/07/23 10:17:16 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 10:17:16 got Connection, getting Channel 2016/07/23 10:17:16 got queue, declaring "test-idoall-queues-task" 2016/07/23 10:17:16 declared queue, publishing 18B body ("Fourth message....") 2016/07/23 10:17:16 published 18B OK 2016/07/23 10:17:16 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 10:17:16 got Connection, getting Channel 2016/07/23 10:17:16 got queue, declaring "test-idoall-queues-task" 2016/07/23 10:17:16 declared queue, publishing 18B body ("Fifth message.....") 2016/07/23 10:17:16 published 18B OK   这时我们再看刚才打开的两个Consumer的结果:   Console1(consumer): lion@node1:~/_code/_rabbitmq/_golang$ go run consumer_task.go 2016/07/23 10:11:21 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 10:11:21 got Connection, getting Channel 2016/07/23 10:11:21 got queue, declaring "test-idoall-queues-task" 2016/07/23 10:11:21 Queue bound to Exchange, starting Consume 2016/07/23 10:11:21 [*] Waiting for messages. To exit press CTRL+C 2016/07/23 10:17:13 Received a message: First message. 2016/07/23 10:17:14 Done 2016/07/23 10:17:15 Received a message: Third message... 2016/07/23 10:17:18 Done 2016/07/23 10:17:18 Received a message: Fifth message..... 2016/07/23 10:17:23 Done   Console2(consumer): lion@node1:~/_code/_rabbitmq/_golang$ go run consumer_task.go 2016/07/23 10:11:40 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 10:11:40 got Connection, getting Channel 2016/07/23 10:11:40 got queue, declaring "test-idoall-queues-task" 2016/07/23 10:11:40 Queue bound to Exchange, starting Consume 2016/07/23 10:11:40 [*] Waiting for messages. To exit press CTRL+C 2016/07/23 10:17:14 Received a message: Second message.. 2016/07/23 10:17:16 Done 2016/07/23 10:17:16 Received a message: Fourth message.... 2016/07/23 10:17:20 Done   默认情况下,RabbitMQ 会顺序的分发每个Message。当每个收到ack后,会将该Message删除,然后将下一个Message分发到下一个Consumer。这种分发方式叫做round-robin,也叫消息轮询 5.3、Message acknowledgment 消息确认   每个Consumer可能需要一段时间才能处理完收到的数据。如果在这个过程中,Consumer出错了,异常退出了,而数据还没有处理完成,那么非常不幸,这段数据就丢失了。因为我们的代码,一旦RabbitMQ Server发送给Consumer消息后,会立即把这个Message标记为完成,然后从queue中删除。我们将无法再操作这个尚未处理完成的消息。   实际场景中,如果一个Consumer异常退出了,我们希望它处理的数据能够被另外的Consumer处理,这样数据在这种情况下(通道关闭、连接关闭、TCP连接丢失等情况)就不会丢失了。   为了保证数据不被丢失,RabbitMQ支持消息确认机制,ack(nowledgments)是从Consumer消费后发送到一个特定的消息告诉RabbitMQ已经收到、处理结束,RabbitMQ可以去安全的删除它了。   如果Consumer退出了但是没有发送ack,那么RabbitMQ就会把这个Message重新排进队列,发送到下一个Consumer。这样就保证了在Consumer异常退出的情况下数据也不会丢失。   这里并没有用到超时机制。RabbitMQ仅仅通过Consumer的连接中断来确认该Message并没有被正确处理。也就是说,RabbitMQ给了Consumer足够长的时间来做数据处理。   消息确认默认是关闭的,我们需要通过,d.ACK(false)来告诉RabbitMQ我们已经完成任务。   producer_acknowledgments(消息生产者).go: package main import ( "fmt" "log" "os" "strings" "github.com/streadway/amqp" ) const ( //AMQP URI uri = "amqp://guest:guest@localhost:5672/" //Durable AMQP exchange name exchangeName = "" //Durable AMQP queue name queueName = "test-idoall-queues-acknowledgments" ) //如果存在错误,则输出 func failOnError(err error, msg string) { if err != nil { log.Fatalf("%s: %s", msg, err) panic(fmt.Sprintf("%s: %s", msg, err)) } } func main(){ bodyMsg := bodyFrom(os.Args) //调用发布消息函数 publish(uri, exchangeName, queueName, bodyMsg) log.Printf("published %dB OK", len(bodyMsg)) } func bodyFrom(args []string) string { var s string if (len(args) < 2) || os.Args[1] == "" { s = "hello idoall.org" } else { s = strings.Join(args[1:], " ") } return s } //发布者的方法 // //@amqpURI, amqp的地址 //@exchange, exchange的名称 //@queue, queue的名称 //@body, 主体内容 func publish(amqpURI string, exchange string, queue string, body string){ //建立连接 log.Printf("dialing %q", amqpURI) connection, err := amqp.Dial(amqpURI) failOnError(err, "Failed to connect to RabbitMQ") defer connection.Close() //创建一个Channel log.Printf("got Connection, getting Channel") channel, err := connection.Channel() failOnError(err, "Failed to open a channel") defer channel.Close() log.Printf("got queue, declaring %q", queue) //创建一个queue q, err := channel.QueueDeclare( queueName, // name false, // durable false, // delete when unused false, // exclusive false, // no-wait nil, // arguments ) failOnError(err, "Failed to declare a queue") log.Printf("declared queue, publishing %dB body (%q)", len(body), body) // Producer只能发送到exchange,它是不能直接发送到queue的。 // 现在我们使用默认的exchange(名字是空字符)。这个默认的exchange允许我们发送给指定的queue。 // routing_key就是指定的queue名字。 err = channel.Publish( exchange, // exchange q.Name, // routing key false, // mandatory false, // immediate amqp.Publishing { Headers: amqp.Table{}, ContentType: "text/plain", ContentEncoding: "", Body: []byte(body), }) failOnError(err, "Failed to publish a message") }   consumer_acknowledgments(消息消费者).go package main import ( "fmt" "log" "bytes" "time" "github.com/streadway/amqp" ) const ( //AMQP URI uri = "amqp://guest:guest@localhost:5672/" //Durable AMQP exchange nam exchangeName = "" //Durable AMQP queue name queueName = "test-idoall-queues-acknowledgments" ) //如果存在错误,则输出 func failOnError(err error, msg string) { if err != nil { log.Fatalf("%s: %s", msg, err) panic(fmt.Sprintf("%s: %s", msg, err)) } } func main(){ //调用消息接收者 consumer(uri, exchangeName, queueName) } //接收者方法 // //@amqpURI, amqp的地址 //@exchange, exchange的名称 //@queue, queue的名称 func consumer(amqpURI string, exchange string, queue string){ //建立连接 log.Printf("dialing %q", amqpURI) connection, err := amqp.Dial(amqpURI) failOnError(err, "Failed to connect to RabbitMQ") defer connection.Close() //创建一个Channel log.Printf("got Connection, getting Channel") channel, err := connection.Channel() failOnError(err, "Failed to open a channel") defer channel.Close() log.Printf("got queue, declaring %q", queue) //创建一个queue q, err := channel.QueueDeclare( queueName, // name false, // durable false, // delete when unused false, // exclusive false, // no-wait nil, // arguments ) failOnError(err, "Failed to declare a queue") log.Printf("Queue bound to Exchange, starting Consume") //订阅消息 msgs, err := channel.Consume( q.Name, // queue "", // consumer false, // auto-ack false, // exclusive false, // no-local false, // no-wait nil, // args ) failOnError(err, "Failed to register a consumer") //创建一个channel forever := make(chan bool) //调用gorountine go func() { for d := range msgs { log.Printf("Received a message: %s", d.Body) dot_count := bytes.Count(d.Body, []byte(".")) t := time.Duration(dot_count) time.Sleep(t * time.Second) log.Printf("Done") d.Ack(false) } }() log.Printf(" [*] Waiting for messages. To exit press CTRL+C") //没有写入数据,一直等待读,阻塞当前线程,目的是让线程不退出 <-forever }   查看结果   我们先使用Producer来发送一列消息: lion@node1:~/_code/_rabbitmq/_golang$ go run producer_acknowledgments.go First message. && go run producer_acknowledgments.go Second message.. && go run producer_acknowledgments.go Third message... && go run producer_acknowledgments.go Fourth message.... && go run producer_acknowledgments.go Fifth message..... 2016/07/23 21:41:40 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 21:41:40 got Connection, getting Channel 2016/07/23 21:41:40 got queue, declaring "test-idoall-queues-acknowledgments" 2016/07/23 21:41:40 declared queue, publishing 14B body ("First message.") 2016/07/23 21:41:40 published 14B OK 2016/07/23 21:41:41 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 21:41:41 got Connection, getting Channel 2016/07/23 21:41:41 got queue, declaring "test-idoall-queues-acknowledgments" 2016/07/23 21:41:41 declared queue, publishing 16B body ("Second message..") 2016/07/23 21:41:41 published 16B OK 2016/07/23 21:41:41 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 21:41:41 got Connection, getting Channel 2016/07/23 21:41:41 got queue, declaring "test-idoall-queues-acknowledgments" 2016/07/23 21:41:41 declared queue, publishing 16B body ("Third message...") 2016/07/23 21:41:41 published 16B OK 2016/07/23 21:41:42 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 21:41:42 got Connection, getting Channel 2016/07/23 21:41:42 got queue, declaring "test-idoall-queues-acknowledgments" 2016/07/23 21:41:42 declared queue, publishing 18B body ("Fourth message....") 2016/07/23 21:41:42 published 18B OK 2016/07/23 21:41:43 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 21:41:43 got Connection, getting Channel 2016/07/23 21:41:43 got queue, declaring "test-idoall-queues-acknowledgments" 2016/07/23 21:41:43 declared queue, publishing 18B body ("Fifth message.....") 2016/07/23 21:41:43 published 18B OK   通过rabbitmqctl命令,来看下messages_unacknowledged的情况: lion@node1:~/_code/_rabbitmq/_golang$ rabbitmqctl list_queues name messages_ready messages_unacknowledged Listing queues ... test-idoall-queues-task 0 0 test-idoall-queues 0 0 test-idoall-queues-acknowledgments 5 0   使用Consumer来订阅消息操作到第三条的时候,我们按CTRL+C退出,这个时候相当于消息已经被读取,但是未发送d.ACK(false): lion@node1:~/_code/_rabbitmq/_golang$ go run consumer_acknowledgments.go 2016/07/23 21:56:35 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 21:56:35 got Connection, getting Channel 2016/07/23 21:56:35 got queue, declaring "test-idoall-queues-acknowledgments" 2016/07/23 21:56:35 Queue bound to Exchange, starting Consume 2016/07/23 21:56:35 [*] Waiting for messages. To exit press CTRL+C 2016/07/23 21:56:35 Received a message: First message. 2016/07/23 21:56:36 Done 2016/07/23 21:56:36 Received a message: Second message.. 2016/07/23 21:56:38 Done 2016/07/23 21:56:38 Received a message: Third message... ^Csignal: interrupt   再通过rabbitmqctl命令可以看到,还是有3条消息未处理 lion@node1:~/_code/_rabbitmq/_golang$ rabbitmqctl list_queues name messages_ready messages_unacknowledged Listing queues ... test-idoall-queues-task 0 0 test-idoall-queues 0 0 test-idoall-queues-acknowledgments 3 0 5.4、Message durability消息持久化   如果服务器死机或程序 crash了,数据仍然会丢失。为了确保消息不会丢失,我们需要将queue和Message做持久化操作。   将durable设置为true可以做持久化处理(生产者和消息者的代码里都要设置),如果是已经存在的一个queue 没有设置过持久化,再重新设置是不起作用的,我们需要重新为queue设置一个名字。   最后在Producer发布消息的时候,我们需要设置DeliveryMode为amqp.Persistent,持久化的工作就做完了,下面我们来看代码   producer_durability.go(消息生产者): package main import ( "fmt" "log" "os" "strings" "github.com/streadway/amqp" ) const ( //AMQP URI uri = "amqp://guest:guest@localhost:5672/" //Durable AMQP exchange name exchangeName = "" //Durable AMQP queue name queueName = "test-idoall-queues-durability" ) //如果存在错误,则输出 func failOnError(err error, msg string) { if err != nil { log.Fatalf("%s: %s", msg, err) panic(fmt.Sprintf("%s: %s", msg, err)) } } func main(){ bodyMsg := bodyFrom(os.Args) //调用发布消息函数 publish(uri, exchangeName, queueName, bodyMsg) log.Printf("published %dB OK", len(bodyMsg)) } func bodyFrom(args []string) string { var s string if (len(args) < 2) || os.Args[1] == "" { s = "hello idoall.org" } else { s = strings.Join(args[1:], " ") } return s } //发布者的方法 // //@amqpURI, amqp的地址 //@exchange, exchange的名称 //@queue, queue的名称 //@body, 主体内容 func publish(amqpURI string, exchange string, queue string, body string){ //建立连接 log.Printf("dialing %q", amqpURI) connection, err := amqp.Dial(amqpURI) failOnError(err, "Failed to connect to RabbitMQ") defer connection.Close() //创建一个Channel log.Printf("got Connection, getting Channel") channel, err := connection.Channel() failOnError(err, "Failed to open a channel") defer channel.Close() log.Printf("got queue, declaring %q", queue) //创建一个queue q, err := channel.QueueDeclare( queueName, // name true, // durable false, // delete when unused false, // exclusive false, // no-wait nil, // arguments ) failOnError(err, "Failed to declare a queue") log.Printf("declared queue, publishing %dB body (%q)", len(body), body) // Producer只能发送到exchange,它是不能直接发送到queue的。 // 现在我们使用默认的exchange(名字是空字符)。这个默认的exchange允许我们发送给指定的queue。 // routing_key就是指定的queue名字。 err = channel.Publish( exchange, // exchange q.Name, // routing key false, // mandatory false, // immediate amqp.Publishing { Headers: amqp.Table{}, DeliveryMode: amqp.Persistent, ContentType: "text/plain", ContentEncoding: "", Body: []byte(body), }) failOnError(err, "Failed to publish a message") }   consumer_durability.go(消息接收者): package main import ( "fmt" "log" "bytes" "time" "github.com/streadway/amqp" ) const ( //AMQP URI uri = "amqp://guest:guest@localhost:5672/" //Durable AMQP exchange nam exchangeName = "" //Durable AMQP queue name queueName = "test-idoall-queues-durability" ) //如果存在错误,则输出 func failOnError(err error, msg string) { if err != nil { log.Fatalf("%s: %s", msg, err) panic(fmt.Sprintf("%s: %s", msg, err)) } } func main(){ //调用消息接收者 consumer(uri, exchangeName, queueName) } //接收者方法 // //@amqpURI, amqp的地址 //@exchange, exchange的名称 //@queue, queue的名称 func consumer(amqpURI string, exchange string, queue string){ //建立连接 log.Printf("dialing %q", amqpURI) connection, err := amqp.Dial(amqpURI) failOnError(err, "Failed to connect to RabbitMQ") defer connection.Close() //创建一个Channel log.Printf("got Connection, getting Channel") channel, err := connection.Channel() failOnError(err, "Failed to open a channel") defer channel.Close() log.Printf("got queue, declaring %q", queue) //创建一个queue q, err := channel.QueueDeclare( queueName, // name true, // durable false, // delete when unused false, // exclusive false, // no-wait nil, // arguments ) failOnError(err, "Failed to declare a queue") log.Printf("Queue bound to Exchange, starting Consume") //订阅消息 msgs, err := channel.Consume( q.Name, // queue "", // consumer false, // auto-ack false, // exclusive false, // no-local false, // no-wait nil, // args ) failOnError(err, "Failed to register a consumer") //创建一个channel forever := make(chan bool) //调用gorountine go func() { for d := range msgs { log.Printf("Received a message: %s", d.Body) dot_count := bytes.Count(d.Body, []byte(".")) t := time.Duration(dot_count) time.Sleep(t * time.Second) log.Printf("Done") d.Ack(false) } }() log.Printf(" [*] Waiting for messages. To exit press CTRL+C") //没有写入数据,一直等待读,阻塞当前线程,目的是让线程不退出 <-forever }   查看结果   我们先使用Producer来发送一列消息: lion@node1:~/_code/_rabbitmq/_golang$ go run producer_durability.go First message. && go run producer_durability.go Second message.. && go run producer_durability.go Third message... && go run producer_durability.go Fourth message.... && go run producer_durability.go Fifth message..... 2016/07/23 22:35:03 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 22:35:03 got Connection, getting Channel 2016/07/23 22:35:03 got queue, declaring "test-idoall-queues-durability" 2016/07/23 22:35:04 declared queue, publishing 14B body ("First message.") 2016/07/23 22:35:04 published 14B OK 2016/07/23 22:35:04 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 22:35:04 got Connection, getting Channel 2016/07/23 22:35:04 got queue, declaring "test-idoall-queues-durability" 2016/07/23 22:35:04 declared queue, publishing 16B body ("Second message..") 2016/07/23 22:35:04 published 16B OK 2016/07/23 22:35:05 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 22:35:05 got Connection, getting Channel 2016/07/23 22:35:05 got queue, declaring "test-idoall-queues-durability" 2016/07/23 22:35:05 declared queue, publishing 16B body ("Third message...") 2016/07/23 22:35:05 published 16B OK 2016/07/23 22:35:06 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 22:35:06 got Connection, getting Channel 2016/07/23 22:35:06 got queue, declaring "test-idoall-queues-durability" 2016/07/23 22:35:06 declared queue, publishing 18B body ("Fourth message....") 2016/07/23 22:35:06 published 18B OK 2016/07/23 22:35:06 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 22:35:06 got Connection, getting Channel 2016/07/23 22:35:06 got queue, declaring "test-idoall-queues-durability" 2016/07/23 22:35:06 declared queue, publishing 18B body ("Fifth message.....") 2016/07/23 22:35:06 published 18B OK   通过rabbitmqctl list_queues命令,来看下messages_unacknowledged的情况: lion@node1:~/_code/_rabbitmq/_golang$ rabbitmqctl list_queues Listing queues ... test-idoall-queues-task 0 test-idoall-queues 0 test-idoall-queues-durability 5 test-idoall-queues-acknowledgments 0   重启RabbitMQ-Server lion@node1:~/_code/_rabbitmq/_golang$ rabbitmqctl stop lion@node1:~/_code/_rabbitmq/_golang$ rabbitmq-server RabbitMQ 3.6.3. Copyright (C) 2007-2016 Pivotal Software, Inc. ## ## Licensed under the MPL. See http://www.rabbitmq.com/ ## ## ########## Logs: /home/lion/_app/rabbitmq_server-3.6.3/var/log/rabbitmq/rabbit@node1.log ###### ## /home/lion/_app/rabbitmq_server-3.6.3/var/log/rabbitmq/rabbit@node1-sasl.log ########## Starting broker... completed with 6 plugins.   再次通过rabbitmqctl list_queues命令查看,可以看到消息是存在的,说明我们的持久化是成功的 lion@node1:~/_code/_rabbitmq/_golang$ rabbitmqctl list_queues Listing queues ... test-idoall-queues-durability 5 5.5、Fair dispatch 公平分发   上面的,分发机制不是那么优雅。默认状态下,RabbitMQ将第n个Message分发给第n个Consumer。当然n是取余后的。它不管Consumer是否还有unacked Message,只是按照这个默认机制进行分发。   那么如果有个Consumer工作比较重,那么就会导致有的Consumer基本没事可做,有的Consumer却是毫无休息的机会。   通过 ch.Qos 方法设置预读取消息prefetch count=1 。这样RabbitMQ就会使得每个Consumer在同一个时间点最多处理一个Message。换句话说,在接收到该Consumer的ack前,他它不会将新的Message分发给它。   producer_fair_dispatch.go(消息生产者): package main import ( "fmt" "log" "os" "strings" "github.com/streadway/amqp" ) const ( //AMQP URI uri = "amqp://guest:guest@localhost:5672/" //Durable AMQP exchange name exchangeName = "" //Durable AMQP queue name queueName = "test-idoall-queues-fair_dispatch" ) //如果存在错误,则输出 func failOnError(err error, msg string) { if err != nil { log.Fatalf("%s: %s", msg, err) panic(fmt.Sprintf("%s: %s", msg, err)) } } func main(){ bodyMsg := bodyFrom(os.Args) //调用发布消息函数 publish(uri, exchangeName, queueName, bodyMsg) log.Printf("published %dB OK", len(bodyMsg)) } func bodyFrom(args []string) string { var s string if (len(args) < 2) || os.Args[1] == "" { s = "hello idoall.org" } else { s = strings.Join(args[1:], " ") } return s } //发布者的方法 // //@amqpURI, amqp的地址 //@exchange, exchange的名称 //@queue, queue的名称 //@body, 主体内容 func publish(amqpURI string, exchange string, queue string, body string){ //建立连接 log.Printf("dialing %q", amqpURI) connection, err := amqp.Dial(amqpURI) failOnError(err, "Failed to connect to RabbitMQ") defer connection.Close() //创建一个Channel log.Printf("got Connection, getting Channel") channel, err := connection.Channel() failOnError(err, "Failed to open a channel") defer channel.Close() log.Printf("got queue, declaring %q", queue) //创建一个queue q, err := channel.QueueDeclare( queueName, // name true, // durable false, // delete when unused false, // exclusive false, // no-wait nil, // arguments ) failOnError(err, "Failed to declare a queue") log.Printf("declared queue, publishing %dB body (%q)", len(body), body) // Producer只能发送到exchange,它是不能直接发送到queue的。 // 现在我们使用默认的exchange(名字是空字符)。这个默认的exchange允许我们发送给指定的queue。 // routing_key就是指定的queue名字。 err = channel.Publish( exchange, // exchange q.Name, // routing key false, // mandatory false, // immediate amqp.Publishing { Headers: amqp.Table{}, DeliveryMode: amqp.Persistent, ContentType: "text/plain", ContentEncoding: "", Body: []byte(body), }) failOnError(err, "Failed to publish a message") }   consumer_fair_dispatch.go(消息消费者): package main import ( "fmt" "log" "bytes" "time" "github.com/streadway/amqp" ) const ( //AMQP URI uri = "amqp://guest:guest@localhost:5672/" //Durable AMQP exchange nam exchangeName = "" //Durable AMQP queue name queueName = "test-idoall-queues-fair_dispatch" ) //如果存在错误,则输出 func failOnError(err error, msg string) { if err != nil { log.Fatalf("%s: %s", msg, err) panic(fmt.Sprintf("%s: %s", msg, err)) } } func main(){ //调用消息接收者 consumer(uri, exchangeName, queueName) } //接收者方法 // //@amqpURI, amqp的地址 //@exchange, exchange的名称 //@queue, queue的名称 func consumer(amqpURI string, exchange string, queue string){ //建立连接 log.Printf("dialing %q", amqpURI) connection, err := amqp.Dial(amqpURI) failOnError(err, "Failed to connect to RabbitMQ") defer connection.Close() //创建一个Channel log.Printf("got Connection, getting Channel") channel, err := connection.Channel() failOnError(err, "Failed to open a channel") defer channel.Close() log.Printf("got queue, declaring %q", queue) //创建一个queue q, err := channel.QueueDeclare( queueName, // name true, // durable false, // delete when unused false, // exclusive false, // no-wait nil, // arguments ) failOnError(err, "Failed to declare a queue") //每次只取一条消息 err = channel.Qos( 1, // prefetch count 0, // prefetch size false, // global ) failOnError(err, "Failed to set QoS") log.Printf("Queue bound to Exchange, starting Consume") //订阅消息 msgs, err := channel.Consume( q.Name, // queue "", // consumer false, // auto-ack false, // exclusive false, // no-local false, // no-wait nil, // args ) failOnError(err, "Failed to register a consumer") //创建一个channel forever := make(chan bool) //调用gorountine go func() { for d := range msgs { log.Printf("Received a message: %s", d.Body) dot_count := bytes.Count(d.Body, []byte(".")) t := time.Duration(dot_count) time.Sleep(t * time.Second) log.Printf("Done") d.Ack(false) } }() log.Printf(" [*] Waiting for messages. To exit press CTRL+C") //没有写入数据,一直等待读,阻塞当前线程,目的是让线程不退出 <-forever }   查看结果   我们先使用Producer来发送一列消息: lion@node1:~/_code/_rabbitmq/_golang$ go run producer_fair_dispatch.go First message. && go run producer_fair_dispatch.go Second message.. && go run producer_fair_dispatch.go Third message... && go run producer_fair_dispatch.go Fourth message.... && go run producer_fair_dispatch.go Fifth message..... 2016/07/23 23:09:24 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 23:09:24 got Connection, getting Channel 2016/07/23 23:09:24 got queue, declaring "test-idoall-queues-fair_dispatch" 2016/07/23 23:09:24 declared queue, publishing 14B body ("First message.") 2016/07/23 23:09:24 published 14B OK 2016/07/23 23:09:24 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 23:09:24 got Connection, getting Channel 2016/07/23 23:09:24 got queue, declaring "test-idoall-queues-fair_dispatch" 2016/07/23 23:09:24 declared queue, publishing 16B body ("Second message..") 2016/07/23 23:09:24 published 16B OK 2016/07/23 23:09:25 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 23:09:25 got Connection, getting Channel 2016/07/23 23:09:25 got queue, declaring "test-idoall-queues-fair_dispatch" 2016/07/23 23:09:25 declared queue, publishing 16B body ("Third message...") 2016/07/23 23:09:25 published 16B OK 2016/07/23 23:09:26 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 23:09:26 got Connection, getting Channel 2016/07/23 23:09:26 got queue, declaring "test-idoall-queues-fair_dispatch" 2016/07/23 23:09:26 declared queue, publishing 18B body ("Fourth message....") 2016/07/23 23:09:26 published 18B OK 2016/07/23 23:09:27 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 23:09:27 got Connection, getting Channel 2016/07/23 23:09:27 got queue, declaring "test-idoall-queues-fair_dispatch" 2016/07/23 23:09:27 declared queue, publishing 18B body ("Fifth message.....") 2016/07/23 23:09:27 published 18B OK   再依次在两个Console中依次执行下面的命令,可以看到消息被正常的分发了   Console1(consumer): lion@node1:~/_code/_rabbitmq/_golang$ go run consumer_fair_dispatch.go 2016/07/23 23:10:47 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 23:10:47 got Connection, getting Channel 2016/07/23 23:10:47 got queue, declaring "test-idoall-queues-fair_dispatch" 2016/07/23 23:10:47 Queue bound to Exchange, starting Consume 2016/07/23 23:10:47 [*] Waiting for messages. To exit press CTRL+C 2016/07/23 23:10:47 Received a message: First message. 2016/07/23 23:10:48 Done 2016/07/23 23:10:48 Received a message: Second message.. 2016/07/23 23:10:50 Done 2016/07/23 23:10:50 Received a message: Fourth message.... 2016/07/23 23:10:54 Done   Console2(consumer): lion@node1:~/_code/_rabbitmq/_golang$ go run consumer_fair_dispatch.go 2016/07/23 23:10:49 dialing "amqp://guest:guest@localhost:5672/" 2016/07/23 23:10:49 got Connection, getting Channel 2016/07/23 23:10:49 got queue, declaring "test-idoall-queues-fair_dispatch" 2016/07/23 23:10:49 Queue bound to Exchange, starting Consume 2016/07/23 23:10:49 [*] Waiting for messages. To exit press CTRL+C 2016/07/23 23:10:49 Received a message: Third message... 2016/07/23 23:10:52 Done 2016/07/23 23:10:52 Received a message: Fifth message..... 2016/07/23 23:10:57 Done 基于AMQP的更多通道和消息属性,可以浏览AMQP API参考 5.6、Exchanges & Bindings   RabbitMQ 的Messaging Model就是Producer并不会直接发送Message到queue。实际上,Producer并不知道它发送的Message是否已经到达queue。   Producer发送的Message实际上是发到了Exchange中。它的功能也很简单:从Producer接收Message,然后投递到queue中。Exchange需要知道如何处理Message,是把它放到一个queue中,还是放到多个queue中?这个rule是通过Exchange 的类型定义的。   我们知道有三种类型的Exchange:direct,,topic,headers 和fanout。fanout就是广播模式,会将所有的Message都放到它所知道的queue中。   现在我们已经创建了fanout类型的exchange和没有名字的queue(实际上是RabbitMQ帮我们取了名字)。那exchange怎么样知道它的Message发送到哪个queue呢?答案就是通过bindings      通过rabbitmqctl可以列出当前所有的Exchange: lion@node1:~/_code/_rabbitmq/_golang$ rabbitmqctl list_exchanges Listing exchanges ... amq.direct direct amq.fanout fanout amq.match headers amq.headers headers direct amq.rabbitmq.trace topic amq.topic topic amq.rabbitmq.log topic 注意:amq.* 是RabbitMQ默认创建的。 我们假设做一个日志系统,其中一个运行的接收程序Consumer发到消息后写入到磁盘中,同时, 另一个Consumer将收到的日志输出到屏幕上。   producer_exchange_logs.go(消息生产者): package main import ( "fmt" "log" "os" "strings" "github.com/streadway/amqp" ) const ( //AMQP URI uri = "amqp://guest:guest@localhost:5672/" //Durable AMQP exchange name exchangeName = "test-idoall-exchange-logs" //Exchange type - direct|fanout|topic|x-custom exchangeType = "fanout" //AMQP routing key routingKey = "" ) //如果存在错误,则输出 func failOnError(err error, msg string) { if err != nil { log.Fatalf("%s: %s", msg, err) panic(fmt.Sprintf("%s: %s", msg, err)) } } func main(){ bodyMsg := bodyFrom(os.Args) //调用发布消息函数 publish(uri, exchangeName, exchangeType, routingKey, bodyMsg) log.Printf("published %dB OK", len(bodyMsg)) } func bodyFrom(args []string) string { var s string if (len(args) < 2) || os.Args[1] == "" { s = "hello idoall.org" } else { s = strings.Join(args[1:], " ") } return s } //发布者的方法 // //@amqpURI, amqp的地址 //@exchange, exchange的名称 //@exchangeType, exchangeType的类型direct|fanout|topic //@routingKey, routingKey的名称 //@body, 主体内容 func publish(amqpURI string, exchange string, exchangeType string, routingKey string, body string){ //建立连接 log.Printf("dialing %q", amqpURI) connection, err := amqp.Dial(amqpURI) failOnError(err, "Failed to connect to RabbitMQ") defer connection.Close() //创建一个Channel log.Printf("got Connection, getting Channel") channel, err := connection.Channel() failOnError(err, "Failed to open a channel") defer channel.Close() //创建一个queue log.Printf("got Channel, declaring %q Exchange (%q)", exchangeType, exchange) err = channel.ExchangeDeclare( exchange, // name exchangeType, // type true, // durable false, // auto-deleted false, // internal false, // noWait nil, // arguments ) failOnError(err, "Failed to declare a queue") // 发布消息 log.Printf("declared queue, publishing %dB body (%q)", len(body), body) err = channel.Publish( exchange, // exchange routingKey, // routing key false, // mandatory false, // immediate amqp.Publishing { Headers: amqp.Table{}, ContentType: "text/plain", ContentEncoding: "", Body: []byte(body), }) failOnError(err, "Failed to publish a message") }   consumer_exchange_logs.go(消息消费者): package main import ( "fmt" "log" "github.com/streadway/amqp" ) const ( //AMQP URI uri = "amqp://guest:guest@localhost:5672/" //Durable AMQP exchange name exchangeName = "test-idoall-exchange-logs" //Exchange type - direct|fanout|topic|x-custom exchangeType = "fanout" //AMQP binding key bindingKey = "" //Durable AMQP queue name queueName = "" ) //如果存在错误,则输出 func failOnError(err error, msg string) { if err != nil { log.Fatalf("%s: %s", msg, err) panic(fmt.Sprintf("%s: %s", msg, err)) } } func main(){ //调用消息接收者 consumer(uri, exchangeName, exchangeType, queueName, bindingKey) } //接收者方法 // //@amqpURI, amqp的地址 //@exchange, exchange的名称 //@exchangeType, exchangeType的类型direct|fanout|topic //@queue, queue的名称 //@key , 绑定的key名称 func consumer(amqpURI string, exchange string, exchangeType string, queue string, key string){ //建立连接 log.Printf("dialing %q", amqpURI) connection, err := amqp.Dial(amqpURI) failOnError(err, "Failed to connect to RabbitMQ") defer connection.Close() //创建一个Channel log.Printf("got Connection, getting Channel") channel, err := connection.Channel() failOnError(err, "Failed to open a channel") defer channel.Close() //创建一个exchange log.Printf("got Channel, declaring Exchange (%q)", exchange) err = channel.ExchangeDeclare( exchange, // name of the exchange exchangeType, // type true, // durable false, // delete when complete false, // internal false, // noWait nil, // arguments ); failOnError(err, "Exchange Declare:") //创建一个queue q, err := channel.QueueDeclare( queueName, // name false, // durable false, // delete when unused true, // exclusive 当Consumer关闭连接时,这个queue要被deleted false, // no-wait nil, // arguments ) failOnError(err, "Failed to declare a queue") //绑定到exchange err = channel.QueueBind( q.Name, // name of the queue key, // bindingKey exchange, // sourceExchange false, // noWait nil, // arguments ); failOnError(err, "Failed to bind a queue") log.Printf("Queue bound to Exchange, starting Consume") //订阅消息 msgs, err := channel.Consume( q.Name, // queue "", // consumer false, // auto-ack false, // exclusive false, // no-local false, // no-wait nil, // args ) failOnError(err, "Failed to register a consumer") //创建一个channel forever := make(chan bool) //调用gorountine go func() { for d := range msgs { log.Printf(" [x] %s", d.Body) } }() log.Printf(" [*] Waiting for messages. To exit press CTRL+C") //没有写入数据,一直等待读,阻塞当前线程,目的是让线程不退出 <-forever }   在AMQP客户端 ,当routing key为空的时候, 自动创建一个随机的queue,同时设置exclusive为true时,当这个Consumer关闭链接 时,会删除这个queue。   当使用fanout类型的exchange和没有名字的queue,Cusomer并不知道消息发送到了哪个queue,这个时候我们就需要用到QueueBind方法,来绑定到exchange。 过程中可以使用rabbitmqctl list_bindings命令来查看绑定的列表   查看结果   Console1(Consumer),输出到文件: lion@node1:~/_code/_rabbitmq/_golang$ go run consumer_exchange_logs.go &> consumer_exchange_logs.log   Console2(Consumer),打印到控制台: lion@node1:~/_code/_rabbitmq/_golang$ go run consumer_exchange_logs.go   使用Producer来发送消息: lion@node1:~/_code/_rabbitmq/_golang$ go run producer_exchange_logs.go 2016/07/24 02:21:49 dialing "amqp://guest:guest@localhost:5672/" 2016/07/24 02:21:49 got Connection, getting Channel 2016/07/24 02:21:49 got Channel, declaring "fanout" Exchange ("test-idoall-exchange-logs") 2016/07/24 02:21:49 declared queue, publishing 16B body ("hello idoall.org") 2016/07/24 02:21:49 published 16B OK   这时可以使用rabbitmqctl list_bindings来查看我们的绑定信息,可以看到queueu的名字是随机的 lion@node1:~/_code/_rabbitmq/_golang$ rabbitmqctl list_bindings Listing bindings ... exchange amq.gen-D2AnzGsLUMhJCPk7YxgUUw queue amq.gen-D2AnzGsLUMhJCPk7YxgUUw [] exchange amq.gen-GC4VDS3mxsAOTEqii_WsWw queue amq.gen-GC4VDS3mxsAOTEqii_WsWw [] test-idoall-exchange-logs exchange amq.gen-D2AnzGsLUMhJCPk7YxgUUw queue [] test-idoall-exchange-logs exchange amq.gen-GC4VDS3mxsAOTEqii_WsWw queue []   使用cat命令,查看consumer_exchange_logs.log文件,可以看到内容被输入到文件中 lion@node1:~/_code/_rabbitmq/_golang$ cat consumer_exchange_logs.log 2016/07/24 02:25:17 dialing "amqp://guest:guest@localhost:5672/" 2016/07/24 02:25:17 got Connection, getting Channel 2016/07/24 02:25:17 got Channel, declaring Exchange ("test-idoall-exchange-logs") 2016/07/24 02:25:17 Queue bound to Exchange, starting Consume 2016/07/24 02:25:17 [*] Waiting for messages. To exit press CTRL+C signal: interrupt 5.7、Direct exchange   RabbitMQ支持同一个binding key绑定到多个queue中。Direct exchange的算法就是通过binding key来做匹配的。 对于fanout的exchange来说,routing_key这个参数是被忽略的。   producer_exchange_direct_logs.go(消息生产者): package main import ( "fmt" "log" "os" "strings" "github.com/streadway/amqp" ) const ( //AMQP URI uri = "amqp://guest:guest@localhost:5672/" //Durable AMQP exchange name exchangeName = "test-idoall-exchange-direct-logs" //Exchange type - direct|fanout|topic|x-custom exchangeType = "direct" ) //如果存在错误,则输出 func failOnError(err error, msg string) { if err != nil { log.Fatalf("%s: %s", msg, err) panic(fmt.Sprintf("%s: %s", msg, err)) } } func main(){ bodyMsg := bodyFrom(os.Args) //调用发布消息函数 publish(uri, exchangeName, exchangeType, bodyMsg) log.Printf("published %dB OK", len(bodyMsg)) } func bodyFrom(args []string) string { var s string if (len(args) < 3) || os.Args[2] == "" { s = "hello idoall.org" } else { s = strings.Join(args[2:], " ") } return s } func severityFrom(args []string) string { var s string if (len(args) < 2) || os.Args[1] == "" { s = "info" } else { s = os.Args[1] } return s } //发布者的方法 // //@amqpURI, amqp的地址 //@exchange, exchange的名称 //@exchangeType, exchangeType的类型direct|fanout|topic //@body, 主体内容 func publish(amqpURI string, exchange string, exchangeType string, body string){ //建立连接 log.Printf("dialing %q", amqpURI) connection, err := amqp.Dial(amqpURI) failOnError(err, "Failed to connect to RabbitMQ") defer connection.Close() //创建一个Channel log.Printf("got Connection, getting Channel") channel, err := connection.Channel() failOnError(err, "Failed to open a channel") defer channel.Close() //创建一个queue log.Printf("got Channel, declaring %q Exchange (%q)", exchangeType, exchange) err = channel.ExchangeDeclare( exchange, // name exchangeType, // type true, // durable false, // auto-deleted false, // internal false, // noWait nil, // arguments ) failOnError(err, "Failed to declare a queue") // 发布消息 log.Printf("declared queue, publishing %dB body (%q)", len(body), body) err = channel.Publish( exchange, // exchange severityFrom(os.Args), // routing key false, // mandatory false, // immediate amqp.Publishing { Headers: amqp.Table{}, ContentType: "text/plain", ContentEncoding: "", Body: []byte(body), }) failOnError(err, "Failed to publish a message") }   consumer_exchange_direct_logs.go(消息消费者): package main import ( "fmt" "log" "os" "github.com/streadway/amqp" ) const ( //AMQP URI uri = "amqp://guest:guest@localhost:5672/" //Durable AMQP exchange name exchangeName = "test-idoall-exchange-direct-logs" //Exchange type - direct|fanout|topic|x-custom exchangeType = "direct" //AMQP binding key bindingKey = "" //Durable AMQP queue name queueName = "" ) //如果存在错误,则输出 func failOnError(err error, msg string) { if err != nil { log.Fatalf("%s: %s", msg, err) panic(fmt.Sprintf("%s: %s", msg, err)) } } func main(){ //调用消息接收者 consumer(uri, exchangeName, exchangeType, queueName, bindingKey) } //接收者方法 // //@amqpURI, amqp的地址 //@exchange, exchange的名称 //@exchangeType, exchangeType的类型direct|fanout|topic //@queue, queue的名称 //@key , 绑定的key名称 func consumer(amqpURI string, exchange string, exchangeType string, queue string, key string){ //建立连接 log.Printf("dialing %q", amqpURI) connection, err := amqp.Dial(amqpURI) failOnError(err, "Failed to connect to RabbitMQ") defer connection.Close() //创建一个Channel log.Printf("got Connection, getting Channel") channel, err := connection.Channel() failOnError(err, "Failed to open a channel") defer channel.Close() //创建一个exchange log.Printf("got Channel, declaring Exchange (%q)", exchange) err = channel.ExchangeDeclare( exchange, // name of the exchange exchangeType, // type true, // durable false, // delete when complete false, // internal false, // noWait nil, // arguments ); failOnError(err, "Exchange Declare:") //创建一个queue q, err := channel.QueueDeclare( queueName, // name false, // durable false, // delete when unused true, // exclusive 当Consumer关闭连接时,这个queue要被deleted false, // no-wait nil, // arguments ) failOnError(err, "Failed to declare a queue") if len(os.Args) < 2 { log.Printf("Usage: %s [info] [warning] [error]", os.Args[0]) os.Exit(0) } for _, s := range os.Args[1:] { log.Printf("Binding queue %s to exchange %s with routing key %s", q.Name, exchange, s) //绑定到exchange err = channel.QueueBind( q.Name, // name of the queue s, // bindingKey exchange, // sourceExchange false, // noWait nil, // arguments ); failOnError(err, "Failed to bind a queue") } log.Printf("Queue bound to Exchange, starting Consume") //订阅消息 msgs, err := channel.Consume( q.Name, // queue "", // consumer false, // auto-ack false, // exclusive false, // no-local false, // no-wait nil, // args ) failOnError(err, "Failed to register a consumer") //创建一个channel forever := make(chan bool) //调用gorountine go func() { for d := range msgs { log.Printf(" [x] %s", d.Body) } }() log.Printf(" [*] Waiting for messages. To exit press CTRL+C") //没有写入数据,一直等待读,阻塞当前线程,目的是让线程不退出 <-forever }   查看结果   Console1(Consumer),输出到文件: lion@node1:~/_code/_rabbitmq/_golang$ go run consumer_exchange_direct_logs.go warning error &> consumer_exchange_direct_logs.log   Console2(Consumer),打印到控制台: lion@node1:~/_code/_rabbitmq/_golang$ go run consumer_exchange_direct_logs.go info warning error 2016/07/24 08:48:17 dialing "amqp://guest:guest@localhost:5672/" 2016/07/24 08:48:17 got Connection, getting Channel 2016/07/24 08:48:17 got Channel, declaring Exchange ("test-idoall-exchange-direct-logs") 2016/07/24 08:48:17 Binding queue amq.gen-vE-62-Lwt4VQYjlBbMLTjQ to exchange test-idoall-exchange-direct-logs with routing key info 2016/07/24 08:48:17 Binding queue amq.gen-vE-62-Lwt4VQYjlBbMLTjQ to exchange test-idoall-exchange-direct-logs with routing key warning 2016/07/24 08:48:17 Binding queue amq.gen-vE-62-Lwt4VQYjlBbMLTjQ to exchange test-idoall-exchange-direct-logs with routing key error 2016/07/24 08:48:17 Queue bound to Exchange, starting Consume 2016/07/24 08:48:17 [*] Waiting for messages. To exit press CTRL+C   使用Producer来发送消息: lion@node1:~/_code/_rabbitmq/_golang$ go run producer_exchange_direct_logs.go error "Error. Error" && go run producer_exchange_direct_logs.go info "Info. Info" && go run producer_exchange_direct_logs.go warning "warning. warning"   我们可以看到,在Console2控制台上能够看到error、info、waring的所有消息,而在文件中只能看到和error相关的消息。 5.7、Topic exchange   对于Topic的exchange中Message的routing_key是有限制的,不能太随意。格式是以点号“."分割的字符表。比如:"stock.usd.nyse", "nyse.vmw", "quick.orange.rabbit"。你可以放任意的key在routing_key中,不过长度不能超过255 bytes。      对于routing_key,有两个特殊字符(在正则表达式里叫元字符) * (星号) 代表任意 一个单词 # (hash哈希) 0个或者多个单词   Topic exchange和其他exchange的区别,由于有"*"和"#", Topic exchange 非常强大并且可以转化为其他的exchange: 如果binding_key 是 "#" - 它会接收所有的Message,不管routing_key是什么,就像是fanout exchange。 如果 "*"和"#"没有被使用,那么topic exchange就变成了direct exchange。   下面的代码中,我们将演示Topic的exchange使用"#"和"*"来匹配binding key。   producer_exchange_topic_logs.go(消息生产者): package main import ( "fmt" "log" "os" "strings" "github.com/streadway/amqp" ) const ( //AMQP URI uri = "amqp://guest:guest@localhost:5672/" //Durable AMQP exchange name exchangeName = "test-idoall-exchange-direct-logs" //Exchange type - direct|fanout|topic|x-custom exchangeType = "fanout" //AMQP routing key routingKey = "" //Durable AMQP queue name queueName = "test-idoall-queues-direct" ) //如果存在错误,则输出 func failOnError(err error, msg string) { if err != nil { log.Fatalf("%s: %s", msg, err) panic(fmt.Sprintf("%s: %s", msg, err)) } } func main(){ bodyMsg := bodyFrom(os.Args) //调用发布消息函数 publish(uri, exchangeName, exchangeType, routingKey, bodyMsg) log.Printf("published %dB OK", len(bodyMsg)) } func bodyFrom(args []string) string { var s string if (len(args) < 2) || os.Args[1] == "" { s = "hello idoall.org" } else { s = strings.Join(args[1:], " ") } return s } //发布者的方法 // //@amqpURI, amqp的地址 //@exchange, exchange的名称 //@exchangeType, exchangeType的类型direct|fanout|topic //@routingKey, routingKey的名称 //@body, 主体内容 func publish(amqpURI string, exchange string, exchangeType string, routingKey string, body string){ //建立连接 log.Printf("dialing %q", amqpURI) connection, err := amqp.Dial(amqpURI) failOnError(err, "Failed to connect to RabbitMQ") defer connection.Close() //创建一个Channel log.Printf("got Connection, getting Channel") channel, err := connection.Channel() failOnError(err, "Failed to open a channel") defer channel.Close() //创建一个queue log.Printf("got Channel, declaring %q Exchange (%q)", exchangeType, exchange) err = channel.ExchangeDeclare( exchange, // name exchangeType, // type true, // durable false, // auto-deleted false, // internal false, // noWait nil, // arguments ) failOnError(err, "Failed to declare a queue") // 发布消息 log.Printf("declared queue, publishing %dB body (%q)", len(body), body) err = channel.Publish( exchange, // exchange routingKey, // routing key false, // mandatory false, // immediate amqp.Publishing { Headers: amqp.Table{}, ContentType: "text/plain", ContentEncoding: "", Body: []byte(body), }) failOnError(err, "Failed to publish a message") }   consumer_exchange_topic_logs.go(消息消费者): package main import ( "fmt" "log" "github.com/streadway/amqp" ) const ( //AMQP URI uri = "amqp://guest:guest@localhost:5672/" //Durable AMQP exchange name exchangeName = "test-idoall-exchange-topic-logs" //Exchange type - direct|fanout|topic|x-custom exchangeType = "topic" //AMQP binding key bindingKey = "" //Durable AMQP queue name queueName = "" ) //如果存在错误,则输出 func failOnError(err error, msg string) { if err != nil { log.Fatalf("%s: %s", msg, err) panic(fmt.Sprintf("%s: %s", msg, err)) } } func main(){ //调用消息接收者 consumer(uri, exchangeName, exchangeType, queueName, bindingKey) } //接收者方法 // //@amqpURI, amqp的地址 //@exchange, exchange的名称 //@exchangeType, exchangeType的类型direct|fanout|topic //@queue, queue的名称 //@key , 绑定的key名称 func consumer(amqpURI string, exchange string, exchangeType string, queue string, key string){ //建立连接 log.Printf("dialing %q", amqpURI) connection, err := amqp.Dial(amqpURI) failOnError(err, "Failed to connect to RabbitMQ") defer connection.Close() //创建一个Channel log.Printf("got Connection, getting Channel") channel, err := connection.Channel() failOnError(err, "Failed to open a channel") defer channel.Close() //创建一个exchange log.Printf("got Channel, declaring Exchange (%q)", exchange) err = channel.ExchangeDeclare( exchange, // name of the exchange exchangeType, // type true, // durable false, // delete when complete false, // internal false, // noWait nil, // arguments ); failOnError(err, "Exchange Declare:") //创建一个queue q, err := channel.QueueDeclare( queueName, // name false, // durable false, // delete when unused true, // exclusive 当Consumer关闭连接时,这个queue要被deleted false, // no-wait nil, // arguments ) failOnError(err, "Failed to declare a queue") //绑定到exchange err = channel.QueueBind( q.Name, // name of the queue key, // bindingKey exchange, // sourceExchange false, // noWait nil, // arguments ); failOnError(err, "Failed to bind a queue") log.Printf("Queue bound to Exchange, starting Consume") //订阅消息 msgs, err := channel.Consume( q.Name, // queue "", // consumer false, // auto-ack false, // exclusive false, // no-local false, // no-wait nil, // args ) failOnError(err, "Failed to register a consumer") //创建一个channel forever := make(chan bool) //调用gorountine go func() { for d := range msgs { log.Printf(" [x] %s", d.Body) } }() log.Printf(" [*] Waiting for messages. To exit press CTRL+C") //没有写入数据,一直等待读,阻塞当前线程,目的是让线程不退出 <-forever }   查看结果   Console1(Consumer),接收所有的日志: lion@node1:~/_code/_rabbitmq/_golang$ go run consumer_exchange_topic_logs.go "#" 2016/07/24 09:28:29 dialing "amqp://guest:guest@localhost:5672/" 2016/07/24 09:28:29 got Connection, getting Channel 2016/07/24 09:28:29 got Channel, declaring Exchange ("test-idoall-exchange-topic-logs") 2016/07/24 09:28:29 Binding queue amq.gen-jW2-PIBg4izXpt96CynyFw to exchange test-idoall-exchange-topic-logs with routing key # 2016/07/24 09:28:29 Queue bound to Exchange, starting Consume 2016/07/24 09:28:29 [*] Waiting for messages. To exit press CTRL+C   Console2(Consumer),接收以"kern"开头的日志: lion@node1:~/_code/_rabbitmq/_golang$ go run consumer_exchange_topic_logs.go "kern.*" 2016/07/24 09:34:00 dialing "amqp://guest:guest@localhost:5672/" 2016/07/24 09:34:00 got Connection, getting Channel 2016/07/24 09:34:00 got Channel, declaring Exchange ("test-idoall-exchange-topic-logs") 2016/07/24 09:34:00 Binding queue amq.gen-8zYBz2uXYbWXcItJMZ3AQA to exchange test-idoall-exchange-topic-logs with routing key kern.* 2016/07/24 09:34:00 Queue bound to Exchange, starting Consume 2016/07/24 09:34:00 [*] Waiting for messages. To exit press CTRL+C   Console3(Consumer),接收第二个单词以"critical"结尾的日志: lion@node1:~/_code/_rabbitmq/_golang$ go run consumer_exchange_topic_logs.go "*.critical" 2016/07/24 09:37:21 dialing "amqp://guest:guest@localhost:5672/" 2016/07/24 09:37:21 got Connection, getting Channel 2016/07/24 09:37:21 got Channel, declaring Exchange ("test-idoall-exchange-topic-logs") 2016/07/24 09:37:21 Binding queue amq.gen-tq9QsD1i1mCps-jrqDtTTA to exchange test-idoall-exchange-topic-logs with routing key *.critical 2016/07/24 09:37:21 Queue bound to Exchange, starting Consume 2016/07/24 09:37:21 [*] Waiting for messages. To exit press CTRL+C   Console4(Consumer), 可以创建多个绑定关系: lion@node1:~/_code/_rabbitmq/_golang$ go run consumer_exchange_topic_logs.go "kern.critical" "A critical kernel error" 2016/07/24 09:39:35 dialing "amqp://guest:guest@localhost:5672/" 2016/07/24 09:39:35 got Connection, getting Channel 2016/07/24 09:39:35 got Channel, declaring Exchange ("test-idoall-exchange-topic-logs") 2016/07/24 09:39:35 Binding queue amq.gen-vcaHyCor5bbB2NX7YQhmzA to exchange test-idoall-exchange-topic-logs with routing key kern.critical 2016/07/24 09:39:35 Binding queue amq.gen-vcaHyCor5bbB2NX7YQhmzA to exchange test-idoall-exchange-topic-logs with routing key A critical kernel error 2016/07/24 09:39:35 Queue bound to Exchange, starting Consume 2016/07/24 09:39:35 [*] Waiting for messages. To exit press CTRL+C   使用Producer来发送消息: lion@node1:~/_code/_rabbitmq/_golang$ go run producer_exchange_topic_logs.go "kern.critical" "A critical kernel error" 2016/07/24 09:56:33 dialing "amqp://guest:guest@localhost:5672/" 2016/07/24 09:56:33 got Connection, getting Channel 2016/07/24 09:56:33 got Channel, declaring "topic" Exchange ("test-idoall-exchange-topic-logs") 2016/07/24 09:56:33 declared queue, publishing 23B body ("A critical kernel error") 2016/07/24 09:56:33 [x] Sent A critical kernel error 2016/07/24 09:56:33 published 23B OK 5.7、远程调用RPC   之前的实例都是通过一个或多个Consumer来订阅消息,如果我们需要在远程机器上运行一个函数,来等待结果呢?这是一个不同的场景,例如做云计算。   AMQP协议预定义了14个属性,大多数我们都很少用到,以下几个是比较常用的。 persistent:消息持久性 content_type:用来描述编码的MIME类型 reply_to:回调queue的名字 correlation_id:将远程RPC请求,进行关联的唯一标识 correlation_id   如果为每个RPC的请求创建一个queue效率是非常低的,正常发送到queue的一个Message,它不知道是从哪里发过来的,而correlation_id属性的存在就是为每个请求设置一个唯一值,在回调接收消息的时候,也会带回这个属性进行匹配,如果不匹配,这个消息就不会被处理。   接下来我们将使用RabbitMQ搭建一个RPC系统:一个客户端和一个可扩展的RPC服务器,RPC的工作流程如下: 客户端启动时,创建一个匿名的exclusive callback queue 客户端发送请求时,要带两个属性reply_to(设置回调的queue)和correlation_id(唯一标识) 将请求发送到一个RPC queue RPC的server端 ,一直在等待请求,当消息到达时会对过reply_to回复到指定的queue 客户端在等queue从server的回调,检查 correlation_id是否一致,如果和请求时发送的一致,则做其他响应。   rpc_server.go(服务端代码): package main import ( "fmt" "log" "strconv" "github.com/streadway/amqp" ) const ( //AMQP URI uri = "amqp://guest:guest@localhost:5672/" //Durable AMQP queue name queueName = "rpc-queue" ) //如果存在错误,则输出 func failOnError(err error, msg string) { if err != nil { log.Fatalf("%s: %s", msg, err) panic(fmt.Sprintf("%s: %s", msg, err)) } } func main(){ //调用发布消息函数 publish(uri, queueName) } //发布者的方法 // //@amqpURI, amqp的地址 //@queue, queue的名称 func publish(amqpURI string, queue string){ //建立连接 log.Printf("dialing %q", amqpURI) connection, err := amqp.Dial(amqpURI) failOnError(err, "Failed to connect to RabbitMQ") defer connection.Close() //创建一个Channel log.Printf("got Connection, getting Channel") channel, err := connection.Channel() failOnError(err, "Failed to open a channel") defer channel.Close() //创建一个queue log.Printf("got queue, declaring %q", queue) q,err := channel.QueueDeclare( queue, // name false, // durable false, // delete when usused false, // exclusive false, // no-wait nil, // arguments ) failOnError(err, "Failed to declare a queue") //均衡处理,每次处理一条消息 err = channel.Qos( 1, // prefetch count 0, // prefetch size false, // global ) failOnError(err, "Failed to set QoS") //订阅一个消息 //log.Printf("Queue bound to Exchange, starting Consume") msgs, err := channel.Consume( q.Name, // queue "", // consumer false, // auto-ack false, // exclusive false, // no-local false, // no-wait nil, // args ) failOnError(err, "Failed to register a consumer") forever := make(chan bool) // 发布消息 go func() { for d := range msgs { n, err := strconv.Atoi(string(d.Body)) failOnError(err, "Failed to convert body to integer") log.Printf(" [.] server端接收到的数据是 (%d)", n) response := n*2 err = channel.Publish( "", // exchange d.ReplyTo, // routing key false, // mandatory false, // immediate amqp.Publishing{ ContentType: "text/plain", CorrelationId: d.CorrelationId, Body: []byte(strconv.Itoa(response)), }) failOnError(err, "Failed to publish a message") d.Ack(false) } }() log.Printf(" [*] Awaiting RPC requests") //没有写入数据,一直等待读,阻塞当前线程,目的是让线程不退出 <-forever }   consumer_exchange_topic_logs.go(消息消费者): package main import ( "fmt" "log" "math/rand" "os" "strconv" "strings" "time" "github.com/streadway/amqp" ) const ( //AMQP URI uri = "amqp://guest:guest@localhost:5672/" //Durable AMQP exchange name exchangeName = "" //Exchange type - direct|fanout|topic|x-custom queueName = "rpc-queue" ) //如果存在错误,则输出 func failOnError(err error, msg string) { if err != nil { log.Fatalf("%s: %s", msg, err) panic(fmt.Sprintf("%s: %s", msg, err)) } } func randomString(l int) string { bytes := make([]byte, l) for i := 0; i < l; i++ { bytes[i] = byte(randInt(65, 90)) } return string(bytes) } func randInt(min int, max int) int { return min + rand.Intn(max-min) } func bodyFrom(args []string) int { var s string if (len(args) < 2) || os.Args[1] == "" { s = "30" } else { s = strings.Join(args[1:], " ") } n, err := strconv.Atoi(s) failOnError(err, "Failed to convert arg to integer") return n } func main(){ rand.Seed(time.Now().UTC().UnixNano()) n := bodyFrom(os.Args) log.Printf(" [x] 请求的数据是(%d)", n) res, err := fibonacciRPC(n, uri, exchangeName, queueName) failOnError(err, "Failed to handle RPC request") log.Printf(" [.] 计算结果为 %d", res) } //RPC client调用方法 // //@amqpURI, amqp的地址 //@exchange, exchange的名称 //@queue, queue的名称 func fibonacciRPC(n int, amqpURI string, exchange string, queue string) (res int, err error){ //建立连接 log.Printf("dialing %q", amqpURI) connection, err := amqp.Dial(amqpURI) failOnError(err, "Failed to connect to RabbitMQ") defer connection.Close() //创建一个Channel log.Printf("got Connection, getting Channel") channel, err := connection.Channel() failOnError(err, "Failed to open a channel") defer channel.Close() //创建一个queue log.Printf("got queue, declaring %q", queue) q,err := channel.QueueDeclare( "", // name false, // durable false, // delete when usused true, // exclusive false, // no-wait nil, // arguments ) failOnError(err, "Failed to declare a queue") log.Printf("Queue bound to Exchange, starting Consume") //订阅消息 msgs, err := channel.Consume( q.Name, // queue "", // consumer true, // auto-ack false, // exclusive false, // no-local false, // no-wait nil, // args ) failOnError(err, "Failed to register a consumer") corrId := randomString(32) err = channel.Publish( "", // exchange queue, // routing key false, // mandatory false, // immediate amqp.Publishing{ ContentType: "text/plain", CorrelationId: corrId, ReplyTo: q.Name, Body: []byte(strconv.Itoa(n)), }) failOnError(err, "Failed to publish a message") for d := range msgs { if corrId == d.CorrelationId { res, err = strconv.Atoi(string(d.Body)) failOnError(err, "Failed to convert body to integer") break } } return }   查看结果   Console1(rpc server): lion@node1:~/_code/_rabbitmq/_golang$ go run rpc_server.go 2016/07/24 11:20:32 dialing "amqp://guest:guest@localhost:5672/" 2016/07/24 11:20:32 got Connection, getting Channel 2016/07/24 11:20:32 got queue, declaring "rpc-queue" 2016/07/24 11:20:32 [*] Awaiting RPC requests   Console2(rpc client): lion@node1:~/_code/_rabbitmq/_golang$ go run rpc_client.go 69 2016/07/24 11:24:37 [x] 请求的数据是(69) 2016/07/24 11:24:37 dialing "amqp://guest:guest@localhost:5672/" 2016/07/24 11:24:37 got Connection, getting Channel 2016/07/24 11:24:37 got queue, declaring "rpc-queue" 2016/07/24 11:24:37 Queue bound to Exchange, starting Consume 2016/07/24 11:24:37 [.] 计算结果为 138   以上只是简单实现了RPC的功能,如果你有复杂的需求,需要根据需求对Server和Client做调整。 6、写在后面   业界对于消息传输有很多种方案,之前我们也介绍过Kafka,Kafka是Linkedin于2010年12月份开源的消息发布订阅系统,它主要用于处理活跃的流式数据,大数据量的数据处理上。RabbitMQ在吞吐量方面稍逊于kafka,他们的出发点不一样,RabbitMQ支持对消息的可靠的传递,支持事务,不支持批量的操作。   RabbitMQ的消息应当尽可能的小,并且只用来处理实时且要高可靠性的消息。消费者和生产者的能力尽量对等,否则消息堆积会严重影响RabbitMQ的性能。 7、参考资料 http://www.rabbitmq.com/getstarted.html https://github.com/streadway/amqp 8、FAQ 安装Erlang过程中出现提示configure: error: No curses library functions found 因为缺少缺少ncurses安装包,执行以下命令,即可解决: lion@node1:~/$ sudo apt-get install libncurses5-dev...

    2018-06-29 未分类 4414
  • ubuntu系统用pyenv实现python多版本共存

    我们经常会遇到下边这样的情况: 系统自带的 Python 是 2.6,自己需要 Python 2.7 中的某些特性; 系统自带的 Python 是 2.x,自己需要 Python 3.x; 此时需要在系统中安装我们想用的Python,但又不能影响系统自带的 Python,即需要实现 Python 的多版本共存。pyenv 就是这样一个 Python 版本管理器。 安装 pyenv 在ubuntu终端内,输入命令: $ curl -L https://raw.githubusercontent.com/yyuu/pyenv-installer/master/bin/pyenv-installer | bash 即可下载并安装pyenv 安装完成后,根据提示将如下语句加入到 ~/.bashrc 中: export PYENV_ROOT="$HOME/.pyenv" export PATH="$PYENV_ROOT/bin:$PATH" eval "$(pyenv init -)" eval "$(pyenv virtualenv-init -)"   # 这句可以不加 然后重启终端即可。 查看可安装的版本 $ pyenv install --list 该命令会列出可以用 pyenv 安装的 Python 版本。列表很长,其中 2.7.8 和 3.4.1 这种只有版本号的是 Python 官方版本,其他的形如 anaconda2-4.1.0 这种既有名称又有版本后的属于 “衍生版” 或发行版。 安装 Python 的依赖包 在编译 Python 过程中会依赖一些其他库文件,因而需要首先安装这些库文件,已知的一些需要预先安装的库如下。在 Ubuntu下: sudo apt-get update sudo apt-get install make build-essential libssl-dev zlib1g-dev sudo apt-get install libbz2-dev libreadline-dev libsqlite3-dev wget curl sudo apt-get install llvm libncurses5-dev libncursesw5-dev 安装指定版本 用户可以使用 pyenv install 安装指定版本的 python。如果你不知道该用哪一个,推荐你安装 anaconda3 的最新版本,这是一个专为科学计算准备的发行版。 $ pyenv install anaconda3-4.1.0 -v /tmp/python-build.20170108123450.2752 ~ Downloading Anaconda3-4.1.0-Linux-x86_64.sh... -> https://repo.continuum.io/archive/Anaconda3-4.1.0-Linux-x86_64.sh 执行该命令后,会从给定的网址中下载安装文件 Anaconda3-4.1.0-Linux-x86_64.sh。但由于文件很大,通常下载需要很久。建议的做法是,先执行以上命令然后马上中断安装,这样就知道 pyenv 要下载的文件的链接。然后用户自己用其他更快的方式(比如wget、迅雷等等)从该链接中下载安装文件,并将安装文件移动到 ~/.pyenv/cache 目录下(该目录默认不存在,用户要自行新建)。 以本文说的情况为例: 执行 pyenv install anaconda3-4.1.0 -v 获取下载链接 用wget从下载链接中获取文件 Anaconda3-4.1.0-Linux-x86_64.sh 将安装包移动到 ~/.pyenv/cache/Anaconda3-4.1.0-Linux-x86_64.sh 重新执行 pyenv install anaconda3-4.1.0 -v 命令。该命令会检查 cache 目录下已有文件的完整性,若确认无误,则会直接使用该安装文件进行安装。 安装过程中,若出现编译错误,通常是由于依赖包未满足,需要在安装依赖包后重新执行该命令。 更新数据库 在安装 Python 或者其他带有可执行文件的模块之后,需要对数据库进行更新: $ pyenv rehash 查看当前已安装的 python 版本 $ pyenv versions * system (set by /home/seisman/.pyenv/version) anaconda3-4.1.0 其中的星号表示当前正在使用的是系统自带的 python。 设置全局的 python 版本 $ pyenv global anaconda3-4.1.0 $ pyenv versions system * anaconda3-4.1.0 (set by /home/seisman/.pyenv/version) 当前全局的 python 版本已经变成了 anaconda3-4.1.0。也可以使用 pyenv local 或 pyenv shell 临时改变 python 版本。 确认 python 版本 $ python Python 3.5.2 (Anaconda 4.1.0, Sep 10 2014, 17:10:18) [GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> pyenv 其他功能 pyenv uninstall  - 卸载某个版本 pyenv update  - 更新pyenv及其插件...

    2018-06-29 未分类 3873
  • 从0开始教你申请服务器搭建ss服务并开启多账号访问外网

    步骤: 1,你需要购买一台服务器,一个月2.5刀,一年大概199人民币,一个月流量500GB,这里推荐vultr  2,虽然是国外网站,但是支持支付宝扫码支付,直接美刀转人民币实时结算;优先选日本的,然后美国的,我这里选的是New Jersey,购买成功后会有ip地址  3,然后登录你的服务器,我这里用的是xshell客户端来登录的:    4,输入主机地址,然后确定后会弹出让你输入用户名,统一是root,密码输入自己的就ok了,连接好了后再进行安装ss服务: 安装方法如下(一路回车就好): wget --no-check-certificate https://down.upx8.com/shell/shadowsocks-go.sh chmod +x shadowsocks-go.sh ./shadowsocks-go.sh 2>&1 | tee shadowsocks-go.log 1 2 3 <p style="box-sizing:border-box;font-size:16px;font-family:-apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif, SimHei, SimSun;white-space:normal;word-spacing:0px;text-transform:none;word-break:break-all;font-weight:400;color:#4f4f4f;outline-width:0px;padding-bottom:0px;font-style:normal;text-align:justify;padding-top:0px;outline-style:none;padding-left:0px;orphans:2;widows:2;margin:0px 0px 16px;letter-spacing:normal;outline-color:invert;line-height:26px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;text-decoration-style:initial;text-decoration-color:initial;"> 卸载方法: </p> <p style="box-sizing:border-box;font-size:16px;font-family:-apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif, SimHei, SimSun;white-space:normal;word-spacing:0px;text-transform:none;word-break:break-all;font-weight:400;color:#4f4f4f;outline-width:0px;padding-bottom:0px;font-style:normal;text-align:justify;padding-top:0px;outline-style:none;padding-left:0px;orphans:2;widows:2;margin:0px 0px 16px;letter-spacing:normal;outline-color:invert;line-height:26px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;text-decoration-style:initial;text-decoration-color:initial;"> <code style="box-sizing:border-box;font-size:14px;font-family:Consolas, Inconsolata, Courier, monospace;word-break:break-all;color:#c7254e;outline-width:0px;padding-bottom:0px;padding-top:4px;outline-style:none;padding-left:2px;outline-color:invert;line-height:22px;padding-right:2px;background-color:#f9f2f4;border-radius:2px;">./shadowsocks-go.sh uninstall</code> </p> <p style="box-sizing:border-box;font-size:16px;font-family:-apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif, SimHei, SimSun;white-space:normal;word-spacing:0px;text-transform:none;word-break:break-all;font-weight:400;color:#4f4f4f;outline-width:0px;padding-bottom:0px;font-style:normal;text-align:justify;padding-top:0px;outline-style:none;padding-left:0px;orphans:2;widows:2;margin:0px 0px 16px;letter-spacing:normal;outline-color:invert;line-height:26px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;text-decoration-style:initial;text-decoration-color:initial;"> 多端口多用户密码配置 </p> <p style="box-sizing:border-box;font-size:16px;font-family:-apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif, SimHei, SimSun;white-space:normal;word-spacing:0px;text-transform:none;word-break:break-all;font-weight:400;color:#4f4f4f;outline-width:0px;padding-bottom:0px;font-style:normal;text-align:justify;padding-top:0px;outline-style:none;padding-left:0px;orphans:2;widows:2;margin:0px 0px 16px;letter-spacing:normal;outline-color:invert;line-height:26px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;text-decoration-style:initial;text-decoration-color:initial;"> <code style="box-sizing:border-box;font-size:14px;font-family:Consolas, Inconsolata, Courier, monospace;word-break:break-all;color:#c7254e;outline-width:0px;padding-bottom:0px;padding-top:4px;outline-style:none;padding-left:2px;outline-color:invert;line-height:22px;padding-right:2px;background-color:#f9f2f4;border-radius:2px;">vi /etc/shadowsocks/config.json</code> </p> <p style="box-sizing:border-box;font-size:16px;font-family:-apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif, SimHei, SimSun;white-space:normal;word-spacing:0px;text-transform:none;word-break:break-all;font-weight:400;color:#4f4f4f;outline-width:0px;padding-bottom:0px;font-style:normal;text-align:justify;padding-top:0px;outline-style:none;padding-left:0px;orphans:2;widows:2;margin:0px 0px 16px;letter-spacing:normal;outline-color:invert;line-height:26px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;text-decoration-style:initial;text-decoration-color:initial;"> 按i粘贴以下配置,原有内容删除 </p> { "server":"0.0.0.0", "local_address":"127.0.0.1", "local_port":1080, "port_password":{ "8989":"password8989", "7979":"password7979", "6969":"password6969" }, "timeout":300, "method":"aes-256-cfb", "fast_open": false } 1 2 3 4 5 6 7 8 9 10 11 12 13 <p style="box-sizing:border-box;font-size:16px;font-family:-apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif, SimHei, SimSun;white-space:normal;word-spacing:0px;text-transform:none;word-break:break-all;font-weight:400;color:#4f4f4f;outline-width:0px;padding-bottom:0px;font-style:normal;text-align:justify;padding-top:0px;outline-style:none;padding-left:0px;orphans:2;widows:2;margin:0px 0px 16px;letter-spacing:normal;outline-color:invert;line-height:26px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;text-decoration-style:initial;text-decoration-color:initial;"> 按ESC,在输入:x,即保存推出,重启ss使其生效 </p> <p style="box-sizing:border-box;font-size:16px;font-family:-apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif, SimHei, SimSun;white-space:normal;word-spacing:0px;text-transform:none;word-break:break-all;font-weight:400;color:#4f4f4f;outline-width:0px;padding-bottom:0px;font-style:normal;text-align:justify;padding-top:0px;outline-style:none;padding-left:0px;orphans:2;widows:2;margin:0px 0px 16px;letter-spacing:normal;outline-color:invert;line-height:26px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;text-decoration-style:initial;text-decoration-color:initial;"> <code style="box-sizing:border-box;font-size:14px;font-family:Consolas, Inconsolata, Courier, monospace;word-break:break-all;color:#c7254e;outline-width:0px;padding-bottom:0px;padding-top:4px;outline-style:none;padding-left:2px;outline-color:invert;line-height:22px;padding-right:2px;background-color:#f9f2f4;border-radius:2px;">/etc/init.d/shadowsocks restart</code> </p> <p style="box-sizing:border-box;font-size:16px;font-family:-apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif, SimHei, SimSun;white-space:normal;word-spacing:0px;text-transform:none;word-break:break-all;font-weight:400;color:#4f4f4f;outline-width:0px;padding-bottom:0px;font-style:normal;text-align:justify;padding-top:0px;outline-style:none;padding-left:0px;orphans:2;widows:2;margin:0px 0px 16px;letter-spacing:normal;outline-color:invert;line-height:26px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;text-decoration-style:initial;text-decoration-color:initial;"> 常用命令: </p> 启动:/etc/init.d/shadowsocks start 停止:/etc/init.d/shadowsocks stop 重启:/etc/init.d/shadowsocks restart 状态:/etc/init.d/shadowsocks status 1 2 3 4 <p style="box-sizing:border-box;font-size:16px;font-family:-apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif, SimHei, SimSun;white-space:normal;word-spacing:0px;text-transform:none;word-break:break-all;font-weight:400;color:#4f4f4f;outline-width:0px;padding-bottom:0px;font-style:normal;text-align:justify;padding-top:0px;outline-style:none;padding-left:0px;orphans:2;widows:2;margin:0px 0px 16px;letter-spacing:normal;outline-color:invert;line-height:26px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;text-decoration-style:initial;text-decoration-color:initial;"> 如果只能用第一个账号,其他2个账号都不能用,那是防火墙对另外的端口做了限制,此时可以让防火墙不拦截 7979和6969端口 </p> <p style="box-sizing:border-box;font-size:16px;font-family:-apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif, SimHei, SimSun;white-space:normal;word-spacing:0px;text-transform:none;word-break:break-all;font-weight:400;color:#4f4f4f;outline-width:0px;padding-bottom:0px;font-style:normal;text-align:justify;padding-top:0px;outline-style:none;padding-left:0px;orphans:2;widows:2;margin:0px 0px 16px;letter-spacing:normal;outline-color:invert;line-height:26px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;text-decoration-style:initial;text-decoration-color:initial;"> 具体命令: </p> firewall-cmd --zone=public --add-port=7979/tcp --permanent firewall-cmd --reload 1 2 <p style="box-sizing:border-box;font-size:16px;font-family:-apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif, SimHei, SimSun;white-space:normal;word-spacing:0px;text-transform:none;word-break:break-all;font-weight:400;color:#4f4f4f;outline-width:0px;padding-bottom:0px;font-style:normal;text-align:justify;padding-top:0px;outline-style:none;padding-left:0px;orphans:2;widows:2;margin:0px 0px 16px;letter-spacing:normal;outline-color:invert;line-height:26px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;text-decoration-style:initial;text-decoration-color:initial;"> 这时候你可以试试7979的这个账号是不是可以用了 </p> <p style="box-sizing:border-box;font-size:16px;font-family:-apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif, SimHei, SimSun;white-space:normal;word-spacing:0px;text-transform:none;word-break:break-all;font-weight:400;color:#4f4f4f;outline-width:0px;padding-bottom:0px;font-style:normal;text-align:justify;padding-top:0px;outline-style:none;padding-left:0px;orphans:2;widows:2;margin:0px 0px 16px;letter-spacing:normal;outline-color:invert;line-height:26px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;text-decoration-style:initial;text-decoration-color:initial;"> 同样再设置6969 </p> firewall-cmd --zone=public --add-port=6969/tcp --permanent firewall-cmd --reload 1 2 <p style="box-sizing:border-box;font-size:16px;font-family:-apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif, SimHei, SimSun;white-space:normal;word-spacing:0px;text-transform:none;word-break:break-all;font-weight:400;color:#4f4f4f;outline-width:0px;padding-bottom:0px;font-style:normal;text-align:justify;padding-top:0px;outline-style:none;padding-left:0px;orphans:2;widows:2;margin:0px 0px 16px;letter-spacing:normal;outline-color:invert;line-height:26px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;text-decoration-style:initial;text-decoration-color:initial;"> 如果有人问怎么用ss客户端登录,先去下载:<span>&nbsp;</span><br style="box-sizing:border-box;word-break:break-all;outline-width:0px;outline-style:none;outline-color:invert;" /> https://github.com/shadowsocks/shadowsocks-windows/releases 安装后打开,然后设置,服务器地址和端口号记得对应  <p style="box-sizing:border-box;font-size:16px;font-family:-apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif, SimHei, SimSun;white-space:normal;word-spacing:0px;text-transform:none;word-break:break-all;font-weight:400;color:#4f4f4f;outline-width:0px;padding-bottom:0px;font-style:normal;text-align:justify;padding-top:0px;outline-style:none;padding-left:0px;orphans:2;widows:2;margin:0px 0px 16px;letter-spacing:normal;outline-color:invert;line-height:26px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;text-decoration-style:initial;text-decoration-color:initial;"> 然后代理模式选择PAC,这样省流量,你也可以全局,反正500G一个月足够用了:<span>&nbsp;</span><br style="box-sizing:border-box;word-break:break-all;outline-width:0px;outline-style:none;outline-color:invert;" /> </p> <p style="box-sizing:border-box;font-size:16px;font-family:-apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif, SimHei, SimSun;white-space:normal;word-spacing:0px;text-transform:none;word-break:break-all;font-weight:400;color:#4f4f4f;outline-width:0px;padding-bottom:0px;font-style:normal;text-align:justify;padding-top:0px;outline-style:none;padding-left:0px;orphans:2;widows:2;margin:0px 0px 16px;letter-spacing:normal;outline-color:invert;line-height:26px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;text-decoration-style:initial;text-decoration-color:initial;"> 还有Android和iOS请下载各自对应的客户端直接登录使用就可以了! </p>...

    2018-06-29 未分类 4255
  • 使用python fabric写的一个简单的远程部署示例

    python基础教程: http://www.runoob.com/python/python-tutorial.html fabric帮助文档: http://fabric-chs.readthedocs.io/zh_CN/chs/tutorial.html 一、环境 1 安装python python版本2.5 – 2.7 mac上安装方式 brew install python 查看版本 python --version   2 安装fabric mac上安装命令 brew install fabric   二、简单示例程序 这个程序要在多个服务器部署,可以部署多个项目,但是具体部署哪个项目,需要在参数中传入。部署多个服务器时,是依次部署,依次启动的方式,不会导致同时将服务器关闭,到时服务不可用的问题! 该脚本文件名为deploy.py Python代码   #!/usr/bin/env python   # encoding:utf-8      from fabric.api import *   import time      TOMCAT_HOME = "/xxxx/apache-tomcat-8.0.29"   WAR_DIR = "/home/jenkins/.jenkins/xxxx/target/"      #要远程部署的几个服务器   servers = [       'myserver1',       'myserver2'   ]      #这几个服务器有统一的用户名访问   env.user= "server_username "      #服务器用户密码   env.password = "server_password"      def deploy(projectname):       for server in servers:           print("正在部署服务器:" +  server + " 项目名:" + projectname)           with settings(host_string = server):               deploy_one_server(projectname)               print("部署服务器 "+ server +" 项目" + projectname + " 完成!")               print "休息60秒"               time.sleep(60)      #部署一个服务器   def deploy_one_server(projectname):       warfilename = projectname + ".war"       #1,上传文件到tomcat根目录       print("1,上传文件到tomcat根目录")       with lcd(WAR_DIR):           with cd(TOMCAT_HOME):               put(warfilename,warfilename)               run("ls")          #2,关闭服务器       print "2,关闭服务器"       close_tomcat()          #3,删除原有的部署文件       print "3,删除原有的部署文件"       with cd(TOMCAT_HOME + "/webapps/"):           run("rm -rf " + projectname + "/")           run("rm -rfv " + warfilename)          #4,将已上传的文件放到tomcat项目目录       print "4,将已上传的文件放到tomcat项目目录"       with cd(TOMCAT_HOME):           run("mv " + warfilename + " ./webapps/")          #5,启动服务器       print "5,启动服务器"       run(TOMCAT_HOME +"/bin/startup.sh",pty=False)      #关闭tomcat服务器   def close_tomcat():       #kill可能会因为没有tomcat线程,导致关闭命令失败,所以需要在产生异常时继续执行       with settings(           hide('warnings', 'running', 'stdout', 'stderr'),           warn_only=True       ):           run("ps -ef |grep tomcat |grep -v grep   |awk -F \" \" '{print $2}' | xargs kill -9")     注意:最后启动tomcat时,run方法要使用pty=False pty在True的情况下启动tomcat正常,但会在结束后导致tomcat进程也被干掉  参考资料:https://segmentfault.com/q/1010000005131935 脚本调用: fab -f deploy.py deploy:projectname=xxx ...

    2018-06-29 未分类 3653
  • Ubuntu 16.04安装部署Docker指南

    本篇主要翻译一下官方指导Ubuntu下安装Docker指南,方便查阅,官方指导网址 。这篇文章主要指导你去安装使用Docker-managed发布包及其安装机制。使用这些包确保你获得最近的docker官方发布版本。如果你需要安装使用Ubuntu-managed包,查阅Ubuntu文档。 1.docker支持以下Ubuntu操作系统:    Ubuntu Xenial 16.04[LTS]  Ubuntu Trusty 14.04[LTS]  Ubuntu Precise 12.04[LTS] 2.前置需求     不管你是Ubuntu的哪个版本,Docker需要64的操作系统。此外你的kernel内核至少要在3.10版本之上。最近的3.10小版本或者最新的维护版本也是可以接受的。kernel3.10版本之前的系统缺少一些特性来运行docker容器。这些旧版本有些已知的bugs会导致数据丢失并且在一定条件下会频繁的故障。检查你当前的kernel版本,打开终端,输入     uname -r       注意:如果你之前使用APT安装过docker,为了新版本的docker仓库,确保你更新了APT源。 3.更新你的apt源     Docker的APT仓库包含1.7.1以及更高的版本。通过设置APT使用来自docker仓库的包。     1)登陆机器,用户必须使用sudo或者root权限。     2)打开终端     3)更新包信息,确保APT能使用https方式工作,并且CA证书已安装了     sudo apt-get update     sudo apt-get install apt-transport-https ca-certificates     出现这个问题可能是有另一个程序正在运行,导致资源被锁不可用。而导致资源被锁的原因可能是上次运行安装或更新没有正常完成,解决办法就是删掉。     sudo rm /var/cache/apt/archives/lock     sudo rm /var/lib/dpkg/lock     4)添加一个新的GPG密钥       sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D     5)找到合适你的Ubuntu操作系统的键,这个键决定APT将搜索哪个包。可能的键有:     Ubuntu version    Repository     Precise 12.04     deb https://apt.dockerproject.org/repoubuntu-precise main     Trusty 14.04      deb https://apt.dockerproject.org/repoubuntu-trusty main     Xenial 16.04      deb https://apt.dockerproject.org/repoubuntu-xenial main     注意:docker没有为所有的架构提供包,Binary artifacts are built nightly,你可以从https://master.dockerproject.org. 处下载下来。在一个多架构的系统上安装docker,为键添加一个[arch=]条款。更多细节参考Debian Multiarch维基百科。     6)运行下面的命令,用占位符<REPO> 为你的操作系统替换键。     echo "<REPO>" | sudo tee /etc/apt/sources.list.d/docker.list     比如你是16.04将上面命令的<REPO>     替换成deb https://apt.dockerproject.org/repoubuntu-xenial main 执行那条命令,就在那个文件夹下创建了一个docker.list文件,里面的内容就是     deb https://apt.dockerproject.org/repoubuntu-xenial main     7)更新APT包索引     sudo apt-get update     8)校验APT是从一个正确的仓库拉取安装包。     当运行下面命令的时候,这个键会返回你目前可以安装的docker版本,每个键都包括URL:https://apt.dockerproject.org/repo/。下面是截取的部分输出内容。     命令:apt-cache policy docker-engine     现在当你运行apt-get upgrade的时候,APT就会从新的仓库拉安装包。 4.某些Ubuntu版本需要的前置操作     Ubuntu Xenial 16.04[LTS]  Ubuntu Trusty 14.04[LTS]     这两个版本记得安装linux-iamge-extra-*的kernel包。这个包允许你使用aufs存储驱动。     sudo apt-get install linux-image-extra-$(uname -r) linux-image-extra-virtual     Ubuntu Precise 12.04[LTS]     对于这个版本,你需要3.13以上的kernel版本,你必须升级。下面表格指导你需要哪些包:     你可以执行以下命令:     sudo apt-get install linux-image-generic-lts-trusty     sudo reboot 5.安装    1)登陆系统,用你的账号使用sudo全权限    2)更新APT包索引:sudo apt-get update    3)安装docker:sudo apt-get install docker-engine    4)开启docker后天进程:sudo service docker start    5)校验docker是否安装成功:sudo docker run hello-world    这个命令会下载一个测试镜像,并且运行在一个容器中。当容器运行时,他会打印一些信息,并且退出。 6.可选配置 6.1 创建一个docker组   docker后台进程是绑定的Unix的socket而不是TCP端口。默认情况下,Unix的socket属于用户root,其它用户要使用要通过sudo命令。由于这个原因,docker daemon通常使用root用户运行。   为了避免使用sudo当你使用docker命令的时候,创建一个Unix组名为docker并且添加用户。当docker daemon启动,它会分配Unix socket读写权限给所属的docker组。   注意:docker组不等价于用户root,如果想要知道的更多关于安全影响,查看docker daemon attack surface。   sudo groupadd docker   sudo usermod -aG docker $USER   退出再重进,确保该用户有正确的权限。   校验生效,通过运行docker命令不带sudo:docker run hello-world,如果失败会有以下类似的信息:Cannot connect to the Docker daemon. Is 'docker daemon' running on this host?确保DOCKER_HOST环境变量没有设置。如果有取消它。 6.2 调整内存和交换区计算    当用户运行docker时,他们可能在使用一个镜像时看见下面的信息:   WARNING: Your kernel does not support cgroup swap limit. WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.   为了阻止这些信息,在你的系统中启用内存和交换区计算。这个操作会导致即便docker没有使用也有内存开销以及性能下降。内存开销大概是总内存的1%。性能降低了大约10%。   修改/etc/default/grub文件。vi或者vim命令都行,设置GRUB_CMDLINE_LINUX的值,如下:GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"。保存文件并关闭。sudo update-grub更新启动项。reboot重启你的系统。 6.3启动UFW转发   当你运行docker时,在同一台主机上使用UFW(Uncomplicated Firewall) ,你需要额外的配置。docker使用桥接方式来管理容器的网络。默认情况下,UFW废弃所有的转发流量。因此,docker运行时UFW可以使用,你必须设置合适UFW的转发规则。   UFW默认配置规则拒绝了所有传入流量。如果你想要从另一个主机到达你的容器需要允许连接docker的端口。docker的默认端口是2376如果TLS启用,如果没有启动则是2375,会话是不加密的。默认情况,docker运行在没有TLS启动的情况下。   为了配置UFW并且允许进入的连接docker端口:   检查UFW是否安装并启用:sudo ufw status   打开/etc/default/ufw文件并编辑:sudo nano /etc/default/ufw   设置DEFAULT_FORWARD_POLICY:DEFAULT_FORWARD_POLICY="ACCEPT"   保存退出并重启使用新的设置:sudo ufw reload   允许所有的连接到docker端口:sudo ufw allow 2375/tcp 6.4 为使用docker配置DNS服务器   系统运行桌面的Ubuntu或者Ubuntu衍生产品通常使用127.0.0.1作为默认的nameserver文件/etc/resolv.conf文件中。NetworkManager也通常设置dnsmasq nameserver 127.0.0.1在/etc/resolv.conf。   当在桌面机器运行容器,使用这些配置时,docker的使用者会看见这些警告:   WARNING: Local (127.0.0.1) DNS resolver found in resolv.conf and containers can't use it. Using default external servers : [8.8.8.8 8.8.4.4]   这个警告发生是因为docker容器不能使用本地DNS命名服务器。此外docker默认使用一个额外的nameserver。   为了避免这个警告,你可以在使用docker容器的时候指定一个DNS服务器。或者你可以禁用dnsmasq在NetworkManager中。但是,禁用会导致DNS协议在某些网络中变慢。   下面的说明描述了如何在Ubuntu14.0或以下版本配置docker守护进程。Ubuntu15.04及之上的使用systemd用于启动项和服务管理。指导通过使用systemd来配置和控制一个守护进程。   设置指定的DNS服务:   打开/etc/default/docker文件并编辑:sudo nano /etc/default/docker,添加配置项:DOCKER_OPTS="--dns 8.8.8.8"。将8.8.8.8用一个本地的DNS服务例如192.168.1.1替换。你也可以配置多个DNS服务器。用空格隔开它们,如:--dns 8.8.8.8 --dns 192.168.1.1。警告:当你在笔记本连接了不同网络的情况时做这些操作,确保选择一个公用的DNS服务器。保存文件并退出,重启docker守护进程:sudo service docker restart。   或者另一个选择,禁用dnsmasq在网络管理器中,这可能导致你的网速变慢:   打开/etc/NetworkManager/NetworkManager.conf文件,编辑它:sudo nano /etc/NetworkManager/NetworkManager.conf。找到行dns=dnsmasq,注释掉。保存关闭文件,重启网络管理器和docker.sudo restart network-manager  sudo restart docker。 6.5 配置docker引导启动   Ubuntu15.04之后使用systemd作为引导启动和服务管理,14.10及以下版本是upstart。15.04以上,需要配置docker守护进程boot启动,运行命令:sudo systemctl enable docker   14.10及以下版本安装方法会自动配置upstart来启动docke daemon在boot。 7 升级卸载docker   升级:sudo apt-get upgrade docker-engine   卸载:sudo apt-get purge docker-engine   卸载及依赖:sudo apt-get autoremove --purge docker-engine   上述命令不会卸载images,containers,volumes或者用户自己创建的配置文件。你如果想删除这些东西,执行下面的命令:   rm -rf /var/lib/docker   安装最简单的方法是:sudo apt-get update   sudo apt-get install docker ...

    2018-06-29 未分类 3866
  • Docker安装MSSQL-Linux!

    【技术分享】Docker安装MSSQL-Linux! 原创: ntosss NasYun那是云 昨天 微软的Linux版MSSQL出来没多久,赶紧试试。 本文基于威联通container,群晖Docker可借鉴使用。 镜像原地址  https://hub.docker.com/r/microsoft/mssql-server-linux/   有安装MSSQL需求的同学可以使用,这个是测试版,但对于简单的调试,个人数据存储是可以使用的。说是需要4G内存,我的NAS是8G的,没试过小内存是否能运行。数据库装在NAS肯定比装在个人电脑上方便嘛。 搜索microsoft/mssql-server-linux。(这个镜像有点大,1G左右,服务器国外下载比较慢,有时会下载到一半出错,请自行选择合适的时间下载) 直接点高级设置 选择环境,填入两个参数,注意大小写,ACCEPT_EULA=Y,SA_PASSWORD=yourStrong(!)Password,yourStrong(!)Password是sa的密码,后期登录MSSQL的管理器后可以自己修改。 选择网络,将端口号修改为1433,这个是MSSQL的默认端口。 选择共享文件夹, 本机路径是你NAS希望存放数据库的目录,挂载路劲填写:/var/opt/mssql,新建。 这个时候你可以用MSSQL管理器连接微软的Linux版MSSQL了。(管理器估计需要2012以上版本) 这样你就不需要再本机安装一个数据库,装一个管理器就可以了。 微软的管理器你可以下载: SQL Server 2012 Management Studio Express https://www.microsoft.com/zh-CN/download/details.aspx?id=29062(不要选错了,看清要下载的是CHS\x64\SQLManagementStudio_x64_CHS.exe) SQL Server 2014 Management Studio Express https://www.microsoft.com/zh-cn/download/details.aspx?id=42299(不要选错了,看清要下载的是MgmtStudio 64BIT\SQLManagementStudio_x64_CHS.exe) 这两个是单管理器,安装包也不小,不知道微软搞个管理器都这么大。 你也可以下载第三方的管理器,体积小个人存储调试足够: Navicat Premium (收费的,PJ自己搜索) http://www.navicat.com/ HeidiSQL (免费) http://www.heidisql.com/ ...

    2018-06-29 未分类 4731
  • Ubuntu16.04 安装RabbitMQ

    Ubuntu16.04 安装RabbitMQ 安装RabbitMQ 由于rabbitMq需要erlang语言的支持,在安装rabbitMq之前需要安装erlang,执行命令: sudo apt-get install erlang-nox  安装rabbitMq命令: 2.$ sudo apt-get update 3.$ sudo apt-get install rabbitmq-server 启动、停止、重启、状态rabbitMq命令: 启动:sudo rabbitmq-server start 关闭: sudo rabbitmq-server stop 重启: sudo rabbitmq-server restart 查看状态:sudo rabbitmqctl status 安装好了以后可以使用 ps -ef|grep rabbit查看RabbitMQ的情况 hongdada@ubuntu:~$ ps -ef|grep rabbit rabbitmq 7991 1 0 00:12 ? 00:00:00 /bin/sh /usr/sbin/rabbitmq-server rabbitmq 7999 7991 0 00:12 ? 00:00:00 /bin/sh -e /usr/lib/rabbitmq/bin/rabbitmq-server rabbitmq 8077 1 0 00:12 ? 00:00:00 /usr/lib/erlang/erts-7.3/bin/epmd -daemon rabbitmq 8137 7999 0 00:12 ? 00:00:03 /usr/lib/erlang/erts-7.3/bin/beam.smp -W w -A 64 -P 1048576 -K true -B i -- -root /usr/lib/erlang -progname erl -- -home /var/lib/rabbitmq -- -pa /usr/lib/rabbitmq/lib/rabbitmq_server-3.5.7/sbin/../ebin -noshell -noinput -s rabbit boot -sname rabbit@ubuntu -boot start_sasl -kernel inet_default_connect_options [{nodelay,true}] -sasl errlog_type error -sasl sasl_error_logger false -rabbit error_logger {file,"/var/log/rabbitmq/rabbit@ubuntu.log"} -rabbit sasl_error_logger {file,"/var/log/rabbitmq/rabbit@ubuntu-sasl.log"} -rabbit enabled_plugins_file "/etc/rabbitmq/enabled_plugins" -rabbit plugins_dir "/usr/lib/rabbitmq/lib/rabbitmq_server-3.5.7/sbin/../plugins" -rabbit plugins_expand_dir "/var/lib/rabbitmq/mnesia/rabbit@ubuntu-plugins-expand" -os_mon start_cpu_sup false -os_mon start_disksup false -os_mon start_memsup false -mnesia dir "/var/lib/rabbitmq/mnesia/rabbit@ubuntu" -kernel inet_dist_listen_min 25672 -kernel inet_dist_listen_max 25672 rabbitmq 8256 8137 0 00:12 ? 00:00:00 inet_gethost 4 rabbitmq 8257 8256 0 00:12 ? 00:00:00 inet_gethost 4 hongdada 8631 6788 0 00:18 pts/18 00:00:00 grep --color=auto rabbit hongdada@ubuntu:~$ cd /usr/lib/rabbitmq/bin/ 看起来没有问题,现在进入安装文件夹查看Rabbit的状态: hongdada@ubuntu:~$ cd /usr/lib/rabbitmq/bin/ hongdada@ubuntu:/usr/lib/rabbitmq/bin$ sudo ./rabbitmqctl status Status of node rabbit@ubuntu ... Error: unable to connect to node rabbit@ubuntu: nodedown DIAGNOSTICS =========== attempted to contact: [rabbit@ubuntu] rabbit@ubuntu: * connected to epmd (port 4369) on ubuntu * epmd reports node 'rabbit' running on port 25672 * TCP connection succeeded but Erlang distribution failed * suggestion: hostname mismatch? * suggestion: is the cookie set correctly? * suggestion: is the Erlang distribution using TLS? current node details: - node name: 'rabbitmq-cli-8673@ubuntu' - home dir: /home/hongdada - cookie hash: 0PRVafcTz6WKsC1GZlmK7Q== 有错误,要修改配置,先停止服务 hongdada@ubuntu:/usr/lib/rabbitmq/bin$ invoke-rc.d rabbitmq-server stop ==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units === 需要通过认证才能停止“rabbitmq-server.service”。 Authenticating as: hongda,,, (hongdada) Password: ==== AUTHENTICATION COMPLETE === 进入安装文件夹/usr/lib/rabbitmq/bin 修改rabbitmqctl文件 添加一行Home配置:加红色的地方 #!/bin/sh -e ## The contents of this file are subject to the Mozilla Public License ## Version 1.1 (the "License"); you may not use this file except in ## compliance with the License. You may obtain a copy of the License ## at http://www.mozilla.org/MPL/ ## ## Software distributed under the License is distributed on an "AS IS" ## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See ## the License for the specific language governing rights and ## limitations under the License. ## ## The Original Code is RabbitMQ. ## ## The Initial Developer of the Original Code is GoPivotal, Inc. ## Copyright (c) 2007-2015 Pivotal Software, Inc. All rights reserved. ## # Get default settings with user overrides for (RABBITMQ_)<var_name> # Non-empty defaults should be set in rabbitmq-env . `dirname $0`/rabbitmq-env # We specify Mnesia dir and sasl error logger since some actions # (e.g. forget_cluster_node --offline) require us to impersonate the # real node. RABBITMQ_USE_LONGNAME=${RABBITMQ_USE_LONGNAME} \ HOME=/var/lib/rabbitmq \ exec ${ERL_DIR}erl \ -pa "${RABBITMQ_HOME}/ebin" \ -noinput \ -hidden \ ${RABBITMQ_CTL_ERL_ARGS} \ -boot "${CLEAN_BOOT_FILE}" \ -sasl errlog_type error \ -mnesia dir "\"${RABBITMQ_MNESIA_DIR}\"" \ -s rabbit_control_main \ -nodename $RABBITMQ_NODENAME \ -extra "$@"  启用web管理台: hongdada@ubuntu:/usr/lib/rabbitmq/bin$ sudo ./rabbitmq-plugins enable rabbitmq_management The following plugins have been enabled: mochiweb webmachine rabbitmq_web_dispatch amqp_client rabbitmq_management_agent rabbitmq_management Applying plugin configuration to rabbit@ubuntu... failed. * Could not contact node rabbit@ubuntu. Changes will take effect at broker restart. * Options: --online - fail if broker cannot be contacted. --offline - do not try to contact broker. 查看web管理器 127.0.0.1:15672    http://blog.csdn.net/sharetop/article/details/50523081 ...

    2018-06-29 未分类 3984
  • Ubuntu下 rsync同步文件实例

    Rsync(remote synchronize) 是一个远程数据同步工具,可以使用“Rsync算法”同步本地和远程主机之间的文件。 rsync的好处是只同步两个文件不同的部分,相同的部分不在传递。类似于增量备份, 这使的在服务器传递备份文件或者同步文件,比起scp工具要省好多时间。 OS:ubuntu server 10.04 server:192.168.64.128 client:192.168.64.145 server 1.ubuntu  server 10.04默认已安装rsync,rsync服务默认不是启动的,我们要修改下面的文件。 $sudo vi /etc/default/rsync RSYNC_ENABLE=true   #false改true 2.修改配置文件 $sudo cp /usr/share/doc/rsync/examples/rsyncd.conf /etc   #已默认安装的软件,默认不启动的似乎都要这么做 我们先来查看一下这个文件 $sudo cat /etc/rsyncd.conf # sample rsyncd.conf configuration file # GLOBAL OPTIONS #motd file=/etc/motd #登录欢迎信息 #log file=/var/log/rsyncd #日志文件 # for pid file, do not use /var/run/rsync.pid if # you are going to run rsync out of the init.d script. pid file=/var/run/rsyncd.pid #指定rsync发送日志消息给syslog时的消息级别,常见的消息级别是:uth, authpriv, cron, daemon, ftp, kern, lpr, mail, news, security, sys-log, user, uucp, local0, local1, local2, local3,local4, local5, local6和local7。默认值是daemon。 #syslog facility=daemon #自定义tcp选项,默认是关闭的 #socket options= #以下是模块信息,我们可以创建多个模块 # MODULE OPTIONS [ftp]         comment = public archive #模块描述         path = /var/www/pub #需要同步的路径         use chroot = yes #默认是yes|true,如果为true,那么在rsync在传输文件以前首先chroot到path参数指定的目录下。这样做的原因是实现额外的安全防护,但是缺点是需要root权限,并且不能备份指向外部的符号连接指向的目录文件。 #       max connections=10 #最大连接数         lock file = /var/lock/rsyncd #指定支持max connections参数的锁文件。 # the default for read only is yes...         read only = yes #只读选项         list = yes #客户请求时可用模块时是否列出该模块         uid = nobody #设定该模块传输文件时守护进程应该具有的uid         gid = nogroup #设定该模块传输文件时守护进程应具有的gid,此项与uid配合可以确定文件的访问权限 #       exclude = #用来指定多个由空格隔开的多个模式列表,并将其添加到exclude列表中。这等同于在客户端命令中使用--exclude来指定模式,不过配置文件中指定的exlude模式不会传递给客户端,而仅仅应用于服务器。一个模块只能指定一个exlude选项,但是可以在模式前面使用"-"和"+"来指定是exclude还是include    #这个我的理解是排除目录中不需同步的文件 #       exclude from = #可以指定一个包含exclude模式定义的文件名 #       include = #与exclude相似 #       include from = #可以指定一个包含include模式定义的文件名 #       auth users = #该选项指定由空格或逗号分隔的用户名列表,只有这些用户才允许连接该模块。这里的用户和系统用户没有任何关系。如果"auth users"被设置,那么客户端发出对该模块的连接请求以后会被rsync请求challenged进行验证身份这里使用的 challenge/response认证协议。用户的名和密码以明文方式存放在"secrets file"选项指定的文件中。默认情况下无需密码就可以连接模块(也就是匿名方式) #       secrets file = /etc/rsyncd.secrets #该文件每行包含一个username:password对,以明文方式存储,只有在auth users被定义时,此选项才生效。同时我们需要将此文件权限设置为0600         strict modes = yes #该选项指定是否监测密码文件的权限,如果该选项值为true那么密码文件只能被rsync服务器运行身份的用户访问,其他任何用户不可以访问该文件。默认值为true #       hosts allow = #允许的主机 #       hosts deny = #拒绝访问的主机         ignore errors = no #设定rsync服务器在运行delete操作时是否忽略I/O错误         ignore nonreadable = yes #设定rysnc服务器忽略那些没有访问文件权限的用户         transfer logging = no #使rsync服务器使用ftp格式的文件来记录下载和上载操作在自己单独的日志中 #       log format = %t: host %h (%a) %o %f (%l bytes). Total %b bytes. #设定日志格式         timeout = 600 #超时设置(秒)         refuse options = checksum dry-run #定义一些不允许客户对该模块使用的命令选项列表         dont compress = *.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz #告诉rysnc那些文件在传输前不用压缩,默认已设定压缩包不再进行压缩          日志格式选项列表: %h:远程主机名 %a:远程IP地址 %l:文件长度字符数 %p:该次rsync会话的进程id %o:操作类型:"send"或"recv"、”del.” %f:文件名 %P:模块路径 %m:模块名 %t:当前时间 %u:认证的用户名(匿名时是null) %b:实际传输的字节数 %c:当发送文件时,该字段记录该文件的校验码 下面我们来定义自己的conf文件 # sample rsyncd.conf configuration file # GLOBAL OPTIONS #motd file=/etc/motd log file=/var/log/rsyncd # for pid file, do not use /var/run/rsync.pid if # you are going to run rsync out of the init.d script.  pid file=/var/run/rsyncd.pid syslog facility=daemon #socket options= # MODULE OPTIONS [my_rsync_bk] #名字可以任意命名,只要客户端的rsync命令一致         comment = public archive         path = /home/rsync_bk                             #指定路径,如果没有这个目录自己建。         use chroot = no #       max connections=10         lock file = /var/lock/rsyncd # the default for read only is yes...         read only = yes         list = yes         uid = nobody         gid = nogroup #       exclude =  #       exclude from =  #       include = #       include from =         auth users = liu_rsync              #rsync连接时的用户名,要和客户端rsync的命令一致         secrets file = /etc/rsyncd.secrets #这里是保存密码的地方,如果屏蔽掉就不用密码了         strict modes = yes         hosts allow = 192.168.64.145 #运行的客户端ip #       hosts deny =         ignore errors = yes         ignore nonreadable = yes         transfer logging = yes         log format = %t: host %h (%a) %o %f (%l bytes). Total %b bytes.         timeout = 600         refuse options = checksum dry-run         dont compress = *.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz 创建一个密码文件 $sudo vi /etc/rsyncd.secrets  liu_rsync:123 $sudo chmod 0600 /etc/rsyncd.secrets     启动rsync sudo /etc/init.d/rsync start client 我们再来看一下客户端的操作,一般客户端不需要进行特殊的配置,直接同步即可  rsync -vzrtopg --progress  liu_rsync@192.168.64.128::my_rsync_bk .  #.为当前目录,在服务端touch一个文件,同步后就会出现,当然你也可以指定一个位置比如/databk,需注意所建立的权限! 我们把这个同步工作交给crontab去执行。首先我们要创建一个密码文件 $sudo vi /etc/rsync.pwd输入123,保存     #密码要一致 !注意:下面这两步操作是必须的,没有足够权限同步就会不成功,ls -l 你所指向的目录 sudo chmod 0600 /etc/rsync.pwd sudo chown 普通用户:普通用户组 /etc/rsync.pwd 然后我们打开crontab,使它自动同步 $crontab -e * * * * * rsync -a --password-file=/etc/rsync.pwd liu_rsync@192.168.64.128::my_rsync_bk /databk    crontab随机启动  sudo vi /etc/rc.local 参数说明: -v verbose,即详细模式 -z 压缩 -r recursive 递归 -topg 保持文件原有属性,一般不用加  --progress 用来显示详细进度情况 --delete 表示如果服务器删除了一个文件,客户端也应对应删除 --exclude="*.sh" 表明不包括某些文件 --password-file=/etc/rsync.pwd 指定所使用的密码文件 最后一项是需要同步的目录   注意指定使用的密码文件中只需要有密码,不要有用户名。 ------------------------------------------------------------------------ 1.在本地机器上对两个目录同步 $ rsync -zvr filename1 filename2 上述代码是将filename1中的文件与filename2中的文件同步,如果将filename2中的文件同步到filename1中,修改代码为: $ rsync -zvr filename2 filename1 2.使用rsync –a 同步保留时间按标记 $ rsync -azv filename1 filename2 使用上述命令,将filename2中新同步的文件的时间与filename1中的创建的时间相同, 它保留符号链接、权限、时间标记、用户名及组名相同。 3.从本地同步文件到远程服务器 $rsync -avz filename1 ubuntu@192.168.0.1:/home/ubuntu/filename2 上述命令是将本地的filename1同步到远程192.168.0.1的主机上。 注意:如果远程主机的端口不是默认的22端口,假如是3000端口,上述的命令修改为, $ rsync -avz '-e ssh -p 4000' filename1 ubuntu@192.168.0.1:/home/ubuntu/filename2 4.将远程服务器的文件同步到本地 与步骤3类似,只是将filename1与远程服务器的位置对换一下, $rsync -avz ubuntu@192.168.0.1:/home/ubuntu/filename2 filename1 同理如果端口不是22,使用以下命令 $ rsync -avz '-e ssh -p 4000' ubuntu@192.168.0.1:/home/ubuntu/filename2 filename1  参考:http://www.eduicc.com/read-24.html            http://jordy.easymorse.com/?p=273  服务器之间常常要保持些文件或目录的一致,比如一些大的软件下载网站,它们通常使用多台服务器来提供下载服务。当一台服务器上的文件更新后,其它的服务器也需要更新,而且 在更新的时候应该是只对新增或是修改过的文件进行更新,否则会造成网络带宽和时间的浪费。rsync就是能有效的保持文件及目录的一致的优秀软件。   rsync,remote synchronize   顾名思意就知道它是一款实现远程同步功能的软件,它在同步文件的同时,可以保持原来文件的权限、时间、软硬链接等附加信息,而且可以通过ssh方式来传输文件,这样其保密性也非常好,另外它还是免费的软件。rysnc的官方网站:http://rsync.samba.org/,可以从上面得到最新的版本。当然,因为rsync是一款如此有用的软件,所以很多Linux的发行版本都将它收录在内了。你的Linux里并没有安装rsync,你可以按以下的安法自行安装:    一、安装过程   1.下载rsync   目前(2003年9月)最新的rsync版本是2.5.6,从rysnc的官方网站上下载一个回来:   # wget http://ftp.samba.org/ftp/rsync/rsync-2.5.6.tar.gz    2.解压   # tar -xzpvf rsync-2.5.6.tar.gz   3.编译安装   # cd rsync-2.5.6/   # ./configure --prefix=/usr/local/rsync   # make   # make install   以上过程没有出现的话就安装好了,现在就有rsync命令可以用了,rsync命令放在 /usr/local/rsync/bin。用rsync命令可以去运行有rsync服务的服务器上抓取资料。   如果要把当前的机器变成一台rsync服务器的话,就需要继续进行一些配置了。   二、配置rsync服务   配置一个简单的rsync服务并不复杂,你需要修改或建立一些配置文件。   1.rsyncd.conf   # vi /etc/rsyncd.motd   rsyncd.con是rsync服务的主要配置文件,它控制rsync服务的各种属性,下面给出一个 rsyncd.conf文件的例子:   #先定义整体变量   secrets file = /etc/rsyncd.secrets   motd file = /etc/rsyncd.motd   read only = yes   list = yes   uid = nobody   gid = nobody   hosts allow = 192.168.100.90 #哪些电脑可以访问rsync服务   hosts deny = 192.168.100.0/24 #哪些电脑不可以访问rsync服务   max connections = 2   log file = /var/log/rsyncd.log   pid file = /var/run/rsyncd.pid   lock file = /var/run/rsync.lock   #再定义要rsync目录   [terry]   comment = Terry 's directory from 192.168.100.21   path = /home/terry   auth users = terry,rsync   [test]   comment = test rsync   path = /home/test   在上面的配置文件中,限定了192.168.100.0/24这个子网中,只有192.168.100.90的机器可以来访问这台rsync服务器的rsync服务。配置文件的后面部分定义了两个rsync的目录,terry目录是只有知道terry、rsync两个账号的人才能使用的,而text目录是无需账号就可以访问的。rsync在定义目录时还提供了一些其它选项,可以作更严格的控制。   2.rsyncd.secrets   # vi /etc/rsyncd.secrets   rsyncd.secrets是存储rsync服务的用户名和密码的,它是一个明文的文本文件,下面给出一个rsyncd.secrets文件的例子:   terry:12345   rsync:abcde   因为rsyncd.secrets存储了rsync服务的用户名和密码,所以非常重要,因此文件的属性必须 设为600,只有所有者可以读写:   # chmod 600 /etc/rsyncd.secrets   3.rsyncd.motd   # vi /etc/rsyncd.motd   rsyncd.motd记录了rsync服务的欢迎信息,你可以在其中输入任何文本信息,如:   Welcome to use the rsync services!   4.services   # vi /etc/services   services并不是rsync的配置文件,这一步也可以不做。而修改了services文件的好处就在于 系统知道873端口对就的服务名为rsync。修改services的方法就是确保services中有如下两行, 没有的话就自行加入:   rsync  873/tcp  # rsync   rsync  873/udp  # rsync   5./etc/xinetd.d/rsync   # vi /etc/xinetd.d/rsync   建立一个名为/etc/xinetd.d/rsync文件,输入以下内容:   service rsync   {     disable = no     socket_type  = stream     wait      = no     user      = root     server     = /usr/local/rsync/bin/rsync     server_args  = --daemon     log_on_failure += USERID   }   保存后,就可以运行rsync服务了。输入以下命令:   # /etc/rc.d/init.d/xinetd reload   这样rsync服务就在这台机器上(192.168.100.21)运行起来了,接下来就是如何来使用它了。   三、rsync命令的用法   在配置完rsync服务器后,就可以从客户端发出rsync命令来实现各种同步的操作。rsync有很 多功能选项,下面就对介绍一下常用的选项:   rsync的命令格式可以为:   1. rsync [OPTION]... SRC [SRC]... [USER@]HOST : DEST]   2. rsync [OPTION]... [USER@]HOST:SRC DEST]   3. rsync [OPTION]... SRC [SRC]... DEST]   4. rsync [OPTION]... [USER@]HOST::SRC [DEST]   5. rsync [OPTION]... SRC [SRC]... [USER@]HOST :: DEST]   6. rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]   rsync有六种不同的工作模式:   1. 拷贝本地文件;当SRC和DES路径信息都不包含有单个冒号":"分隔符时就启动这种工作模式。   2.使用一个远程shell程序(如rsh、ssh)来实现将本地机器的内容拷贝到远程机器。当DST 路径地址包含单个冒号":"分隔符时启动该模式。   3.使用一个远程shell程序(如rsh、ssh)来实现将远程机器的内容拷贝到本地机器。当SRC 地址路径包含单个冒号":"分隔符时启动该模式。   4. 从远程rsync服务器中拷贝文件到本地机。当SRC路径信息包含"::"分隔符时启动该模式。   5. 从本地机器拷贝文件到远程rsync服务器中。当DST路径信息包含"::"分隔符时启动该模式。   6. 列远程机的文件列表。这类似于rsync传输,不过只要在命令中省略掉本地机信息即可。   下面以实例来说明:   # rsync -vazu -progress terry@192.168.100.21:/terry/ /home   v详细提示   a以archive模式操作,复制目录、符号连接   z压缩   u只进行更新,防止本地新文件被重写,注意两者机器的时钟的同时   -progress指显示   以上命令是保持客户机192.168.100.90上的/home/terry目录和rsync服务器上的terry目录同 步。该命令执行同步之前会要求你输入terry账号的密码,这个账号是我们前面在rsyncd.secrets 文件中定义的。如果想将这条命令写到一个脚本中,然后定时执行它的话,可以使用--password-file 选项,具体命令如下:   # rsync -vazu -progress --password-file=/etc/rsync.secret   terry@192.168.100.21:/terry/ /home   要使用--password-file选项,就得先建立一个存放密码的文件,这里指定为/etc/rsync.secret。 其内容很简单,如下:   terry:12345   同样要修改文件属性如下:   # chmod 600 /etc/rsyncd.secrets   四、利用rsync保持Linux服务器间的文件同步实例   现在假设有两台Linux服务器A(192.168.100.21)和B(192.168.100.90),服务器A中的 /home/terry和服务器B中的/home/terry这两个目录需要保持同步,也就是当服务器A中文件发生 改变后,服务器B中的文件也要对应去改变。   我们按上面的方法,在服务器A上安装rsync,并将其配置为一台rsync服务器,并将/home/terry 目录配置成rsync共享出的目录。然后在服务器B上安装rsync,因为B只做客户端,所以无需配置。 然后在服务器B,建立以下脚本:   #!/bin/bash   /usr/loca/rsync/bin/rsync -vazu -progress --delete   --password-file=/etc/rsync.secret terry@192.168.100.21:/terry/ /home   将这个脚本保存为AtoB.sh,并加上可执行属性:   # chmod 755 /root/AtoB.sh   然后,通过crontab设定,让这个脚本每30分钟运行一次。执行命令:   # crontab -e   输入以下一行:   0,30 * * * * /root/AtoB.sh   保存退出,这样服务器B每个小时的0分和30分时都会自动运行一次AtoB.sh,AtoB.sh是负责 保持服务器B和服务器A同步的。这样就保证了服务器A的所有更新在30钟后,服务器B也一样取 得了和服务器A一样的最新的资料。   五、其它应用   rsync除了同步文件及目录之外,还可以利用它来实现对远程网站的远程备份。如果再结合脚本和Crontab就能实现定时自动远程备份。其可以实现与商业化的备份和镜象产品的类似效果,但完全免费。          附:rsync有六种不同的工作模式:   1. 拷贝本地文件;当SRC和DES路径信息都不包含有单个冒号":"分隔符时就启动这种工作模式。   2.使用一个远程shell程序(如rsh、ssh)来实现将本地机器的内容拷贝到远程机器。当DST 路径地址包含单个冒号":"分隔符时启动该模式。   3.使用一个远程shell程序(如rsh、ssh)来实现将远程机器的内容拷贝到本地机器。当SRC 地址路径包含单个冒号":"分隔符时启动该模式。   4. 从远程rsync服务器中拷贝文件到本地机。当SRC路径信息包含"::"分隔符时启动该模式。   5. 从本地机器拷贝文件到远程rsync服务器中。当DST路径信息包含"::"分隔符时启动该模式。   6. 列远程机的文件列表。这类似于rsync传输,不过只要在命令中省略掉本地机信息即可。   前段日子在网上找rsync daemon的filter等过滤规则的详解,怎么也找不到,哥一怒之下,决定自己动手翻译,于是有了本文…     本文内容翻译自rsync的官方文档:http://rsync.samba.org/ftp/rsync/rsync.html,以及http://rsync.samba.org/ftp/rsync/rsyncd.conf.html,非完整的全文翻译,并且按照我的需要,对原文的相关章节或条目进行了适当的重新编排。官方文档发布日期:26 Mar 2011。     rsync是Unix/Linux系统中一款优秀高效的镜像同步和远程数据备份工具,它可以把本地文件拷贝到远程主机,或从远程主机拷贝文件到本地,也可以在本地的两个目录之间进行拷贝,但不支持两个远程主机之间的互相拷贝。     关于rsync的工作方式:     rsync连接远程主机进行同步或备份时有两种途径:使用远程shell程序(如ssh或rsh)进行连接,或使用TCP直接连接rsync daemon。     当源路径或目的路径的主机名后面包含一个冒号分隔符时,rsync使用远程shell传输;当源路径或目的路径的主机名后面包含两个冒号,或使用rsync://URL时,rsync使用TCP直接连接rsync daemon。     特别的,如果只指定了源路径,而没有指定目的路径,rsync将会显示源路径中的文件列表,类似于使用命令ls -l。  rsync把本地端看作client,把远程端当成server。注意:不要把server与rsync daemon混淆!daemon一定是server,而server却不一定是daemon,也可能是远程shell的衍生进程。     至于什么是daemon,以及远程shell衍生daemon,下文会有说明。     关于rsync的安装:     rsync安装方式是最常规的./configure && make && make install,只是要注意:源机器和目标机器都要安装。     关于rsync的启动:     前面说过rsync在进行同步或备份时,有两种途经连接远程主机:使用远程shell,或使用TCP连接远程daemon,可以把它们分别称之为shell模式和daemon模式。只有daemon模式才有启动rsync一说。     如果使用shell模式,rsync安装完成后就可以直接使用了,无所谓启动,也不需要任何配置文件。远程传输时一般使用ssh作为传输工具,当然,也可以使用参数-e来指定一个远程shell。     如果使用daemon模式,就无需远程shell了,但必须在一台机器上启动rsync daemon,默认端口873.     你可以经由inetd启动daemon,或者作为一个独立进程启动daemon,或者由rsync client通过远程shell启动daemon。      1)如果把它作为一个独立进程来启动,只需要运行命令:rsync --daemon即可;      2)如果通过inetd来运行,要修改两个文件:/etc/services和/etc/inetd.conf:       在/etc/services文件中添加如下行:rsync 873/tcp       在/etc/inetd.conf中添加:rsync stream tcp nowait root /usr/bin/rsync rsyncd --daemon   注意把/usr/bin/rsync换成你的rsync安装目录!然后重启inetd服务,使配置文件生效。     关于由client通过远程shell启动daemon,官方文档中有一个条目:USING RSYNC-DAEMON FEATURES VIA A REMOTE-SHELL CONNECTION。     条目中说,rsync支持这种用法:使用远程shell连接host,然后衍生出一个single-use “daemon”服务器,来读取远程用户家目录下的配置文件。从用户的角度看,通过远程shell连接而启用的daemon传输,它的命令行语法跟正常的rsync daemon传输是一样的,唯一不同的是,你必须在命令中使用--rsh=COMMAND来明确远程shell程序。如下例:     rsync -av --rsh=ssh host::module /dest   译者注:虽然官方文档中说这种用法在某些情况下很有用,但我觉得很别扭。     当rsync作为daemon运行时,它需要一个用户身份。如果你希望启用chroot,则必须以root的身份来运行daemon,监听端口(1024以下,默认873),或设定文件属主;如果不启用chroot,也可以不使用root用户来运行daemon,但该用户必须对相应的模块拥有读写数据、日志和lock file的权限。     当rsync以daemon模式运行时,它还需要一个配置文件:rsyncd.conf。修改这个配置后不必重启rsync daemon,因为每一次的client连接都会去重新读取该文件。     译者注:关于配置文件rsyncd.conf的设定,后面会有详细的参数解释。     关于rsync的两种模式:     该部分额外的内容来自IBM官方网站上的一篇文章。该文章把rsync的运行模式扩展成了四种,但我认为rsync官方文档的两种模式的划分更加合理一些。     所谓rsync daemon,就是在一台机器上永久运行的rsync进程。在任何一台安装rsync的机器上运行rsync --daemon,则这台机器上运行的rsync就是rsync daemon。我们可以把文件发送给daemon,也可以向daemon请求文件。     daemon模式非常适合创建中心备份服务器,或项目存储库。     两种模式的区别前面已经说过,shell模式在源路径和目的路径中使用一个冒号,而daemon模式使用两个冒号。     关于rsync命令的语法: 本地拷贝:     rsync [选项] SRC… DEST,在本地进行复制操作   shell模式:     rsync [选项] [user@]Host:SRC… [DEST],拉动作,从远程主机拉文件到本地     rsync [选项] SRC… [user@]Host:DEST,推动作,把本地文件推送到远程主机   daemon模式:     rsync [选项] [user@]Host::SRC… [DEST],拉动作     rsync [选项] rsync://[user@]Host [:port]/SRC… [DEST],仍然是拉动作     rsync [选项] SRC... [user@]Host::DEST,推动作     rsync [选项] SRC...rsync://[user@]Host [:port]/DEST,仍然是推动作  <div style="box-sizing:border-box;font-size:14px;font-family:宋体, &quot;Arial Narrow&quot;, arial, serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#2c2c2c;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:28px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-family:Arial;font-weight:400;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;">&nbsp; &nbsp; 官方文档的举例:<br style="box-sizing:border-box;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;" data-filtered="filtered" />     1)rsync -t *.c foo:src/         把当前目录中所有以.c结尾的文件传输到机器名为foo的src目录中。如果某些文件已经在远程主机中存在,则跳过该文件。     2)rsync -avz foo:src/bar /data/tmp          从机器名为foo的远程主机上把/src/bar目录及其下所有文件传输到本地机器的/data/tmp目录中。注意:源路径src/bar的最后没有斜杠”/”!         源路径的最后是否有斜杠有不同的含义:有斜杠,只是复制目录中的文件;没有斜杠的话,不但要复制目录中的文件,还要复制目录本身!         目的路径的最后有没有斜杠,对传输没有影响。     3)rsync -av host:file1 :file2 host:file{3,4} /dest/          rsync -av host::mod/file{1,2} host::mod/file3 /dest/          rsync -av host::mod/file1 ::mod/file{3,4}         这个例子是rsync更高级一点的用法,使用rsync同时传输多个指定文件。     rsync可以一次传输多个指定的文件,方法是添加多个远程主机参数,或忽略主机名。如上例。     关于rsync命令中的选项:     上面例子中提到了一些选项,rsync的选项有很多,请参考官方文档。常用的选项如下: -a:归档模式,保持文件的所有属性,相当于-rlptgoD  -r:递归模式  -e:指定一个远程shell  -z:文件传输时进行压缩处理  --delete:镜像中常用,删除DEST中那些SRC中不存在的文件  <div style="box-sizing:border-box;font-size:14px;font-family:宋体, &quot;Arial Narrow&quot;, arial, serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#2c2c2c;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:28px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-family:Arial;font-weight:400;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;"> daemon也有一些常用选项,下面会有介绍。<br style="box-sizing:border-box;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;" data-filtered="filtered" />     client如何连接rsync daemon:     上面第3个例子已经给出了client连接daemon的语法示例。但是官方文档又把本条目单独列了出来,提醒我们在连接rsync daemon时要注意的几点:     1) daemon模式中的源路径,即SRC,实际上是模块的名称     2) 如果未在双冒号::后面指定源路径,则rsync会列出daemon上所有可能的模块     3) 不要使用--rsh(-e)参数     4) 有些模块可能需要密码认证,你可以使用--password-file选项,来指定密码文件     启用一个rsync daemon来接受client的连接:     除--daemon外,rsync daemon启动时还有其它一些常用选项:     --daemon:       使rsync作为一个daemon运行。daemon有两种启动方式,前面已经说过。对client发出的每一次连接请求,daemon会读取配置文件rsyncd.conf,然后做出相应的回应。     --bwlimit=KBPS:       指定daemon每秒传输的最大千字节。client在请求连接时也可以指定一个--bwlimit值,但该值不能大于daemon端的设置。     --config=FILE:       指定daemon的配置文件。只有当rsync以daemon模式运行的时候,该选项才有效。默认的配置文件为/etc/rsyncd.conf,除非daemon是通过远程shell运行,并且远程user非超级用户,这种情况下,配置文件rsyncd.conf默认存在于当前目录(在$HOME目录中比较典型)。关于通过远程shell启用daemon,见上文。     --port=PORT:       指定daemon监听的端口。     --log-file=FILE:       该选项告诉daemon不要使用rsyncd.conf中指定的log文件,而要使用此处指定的文件。此选项很少用到 <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;text-align:center;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-size:12px;font-family:&quot;courier new&quot;, courier;font-weight:400;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;"><strong style="box-sizing:border-box;font-weight:bold;">rsync 远程数据同步工具详解</strong></span> </p> <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-size:12px;font-family:&quot;courier new&quot;, courier;font-weight:400;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;"><span style="box-sizing:border-box;font-weight:400;color:#888888;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;"><br style="box-sizing:border-box;" data-filtered="filtered" /> rysnc(remote synchronize)在CentOS系统默认安装在/usr/bin,此外rysnc在windows平台下也有相应版本。主页地址为: http://rsync.samba.org/ <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-size:12px;font-family:&quot;courier new&quot;, courier;font-weight:400;color:#888888;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;">rsync(remote synchronize)是一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间的文件。rsync使用所谓的“rsync算法”来使本地和远 程两个主机之间的文件达到同步,这个算法只传送两个文件的不同部分,而不是每次都整份传送,因此速度相当快。</span> </p> <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-weight:400;color:#888888;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;" data-filtered="filtered"></span> </p> <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-size:12px;font-family:&quot;courier new&quot;, courier;font-weight:400;color:#888888;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;"><br style="box-sizing:border-box;" data-filtered="filtered" /> rsync本来是用于替代rcp的一个工具,目前由rsync.samba.org维护,所以rsync.conf文件的格式类似于samba的主配 置文件。rsync可以通过rsh或ssh使用,也能以daemon模式去运行,在以daemon方式运行时rsync server会打开一个873端口,等待客户端去连接。连接时,rsync server会检查口令是否相符,若通过口令查核,则可以开始进行文件传输。第一次连通完成时,会把整份文件传输一次,以后则就只需进行增量备份。   <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-weight:400;color:#0000ff;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;"><strong style="box-sizing:border-box;font-weight:bold;">------------------------------------------------------------------------------------------------------------------------------------------------------------</strong></span> </p> <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;text-align:center;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-size:12px;font-family:&quot;courier new&quot;, courier;font-weight:400;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;">&nbsp;</span> </p> <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-size:12px;font-family:&quot;courier new&quot;, courier;font-weight:400;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;" data-filtered="filtered"></span> </p> <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-size:12px;font-family:&quot;courier new&quot;, courier;font-weight:400;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;"><strong style="box-sizing:border-box;font-weight:bold;">rsync的命令格式可以为以下六种:</strong>&nbsp;<br style="box-sizing:border-box;" data-filtered="filtered" />   rsync [OPTION]... SRC DEST   rsync [OPTION]... SRC [USER@]HOST:DEST   rsync [OPTION]... [USER@]HOST:SRC DEST   rsync [OPTION]... [USER@]HOST::SRC DEST   rsync [OPTION]... SRC [USER@]HOST::DEST   rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]    对应于以上六种命令格式,rsync有六种不同的工作模式:   1、拷贝本地文件。当SRC和DES路径信息都不包含有单个冒号":"分隔符时就启动这种工作模式。如:rsync -a /data /backup   2、使用一个远程shell程序(如rsh、ssh)来实现将本地机器的内容拷贝到远程机器。当DST路径地址包含单个冒号":"分隔符时启动该模式。如:rsync -avz *.c foo:src   3、使用一个远程shell程序(如rsh、ssh)来实现将远程机器的内容拷贝到本地机器。当SRC地址路径包含单个冒号":"分隔符时启动该模式。如:rsync -avz foo:src/bar /data   4、从远程rsync服务器中拷贝文件到本地机。当SRC路径信息包含"::"分隔符时启动该模式。如:rsync -av root@172.16.78.192::www /databack   5、从本地机器拷贝文件到远程rsync服务器中。当DST路径信息包含"::"分隔符时启动该模式。如:rsync -av /databack root@172.16.78.192::www   6、列远程机的文件列表。这类似于rsync传输,不过只要在命令中省略掉本地机信息即可。如:rsync -v rsync://172.16.78.192/www <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-size:12px;font-family:&quot;courier new&quot;, courier;font-weight:400;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;"><strong style="box-sizing:border-box;font-weight:bold;">rsync 命令常用参数</strong>&nbsp;<br style="box-sizing:border-box;" data-filtered="filtered" /> -a 递归方式传输文件,并保持文件属性,等价-rlptgoD不包含-H  -r 子目录以递归模式处理 -l 保持符号链接文件 -H 保持硬链接文件 -p 保持文件权限 -t 保持文件时间信息 -g 保持文件归属组信息 -o 保持文件归属用户信息 -D 保持设备文件和特殊文件 -z 在传输文件时进行压缩处理 --exclude=PATTERN 指定排除一个不需要传输文件匹配模式 --exclude-from=FILE 从FILE中读取排除规则 --include=PATTERN 指定需要传输的文件匹配模式 --include-from=FILE 从FILE中读取匹配规则 --copy-unsafe-links 复制指向复制源路径目录以外的链接文件 --safe-links 忽略指向复制源路径目录以外的链接文件(默认) --existing 仅更新那些已经存在于接收端的文件,而不复制新创建文件 --ignore-existing 忽略那些已经存在于接收端的文件,只复制新创建文件 -b 当有变化时,对目标目录中的旧文件进行备份 --backup-dir=DIR 与-b结合使用,指定备份路径 --link-dest=DIR 当文件未改变时在指定路径创建硬链接文件 --delete 删除接收端还存在而保存端不存在的文件 --delete-before 接收端在传输之前进行删除操作(默认) --delete-during 接收端在传输过程中进行删除操作 --delete-after 接收端在传输之后进行删除操作 --delete-excluded 接收端在传输同时进行删除操作 --e,--rsh=COMMAND 指定代替rsh的shell程序,例如可以指定为ssh --ignore-erros 即使出现I/O错误也要进行删除 --partial 保留因故没有完全传输的文件,以加快随后的再次传输 --progress 在传输时显示传输过程 -p 等价于—partial—progress --delay-updates 将正在更新的文件先保存到.~tmp~临时目录,待传输完毕再更新目标文件 -v,--verbose 详细输出模式 -q,--quiet 精简输出模式 -h,--human-readable 输出文件大小 -n,--dry-run 显示那些文件将要被传输 --list-only 仅列出文件而不进行复制 --rsync-path=PROGRAM 指定远程服务器上的rsync命令所在路径 --password-file=FILE 指定从FILE中读取口令,避免在终端中输入口令 -4,-6 使用IPv4或者IPv6 --version 打印版本信息 --help 显示帮组信息 <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-size:12px;font-family:&quot;courier new&quot;, courier;font-weight:400;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;"><br style="box-sizing:border-box;" data-filtered="filtered" /> 注意: 若用普通用户身份运行rsync命令,同步后的文件的属主将改变为这个普通用户身份;若用超级用户身份运行rsync命令同步后文件属性保持原来用户身份不变。若指定-tg但目标计算机没有指定用户和组,则复制的文件归入501用户 501组 <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> &nbsp; </p> <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-weight:400;color:#0000ff;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;"><strong style="box-sizing:border-box;font-weight:bold;">------------------------------------------------------------------------------------------------------------------------------------------------------------</strong></span> </p> <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-size:12px;font-family:&quot;courier new&quot;, courier;font-weight:400;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;"><br style="box-sizing:border-box;" data-filtered="filtered" /> 启动 rsync 服务  启动 rsync 服务  <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-size:12px;font-family:&quot;courier new&quot;, courier;font-weight:400;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;">vi /etc/xinetd.d/rsync&nbsp; 把disable = YES改成NO<br style="box-sizing:border-box;" data-filtered="filtered" /> service rsync {         disable = no         socket_type     = stream         wait            = no         user            = root         server          = /usr/bin/rsync         server_args     = --daemon         log_on_failure  += USERID } <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> &nbsp; </p> <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-size:12px;font-family:&quot;courier new&quot;, courier;font-weight:400;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;"><br style="box-sizing:border-box;" data-filtered="filtered" /> <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> &nbsp; </p> <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-size:12px;font-family:&quot;courier new&quot;, courier;font-weight:400;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;"><strong style="box-sizing:border-box;font-weight:bold;">配置服务端&nbsp;</strong></span><span style="box-sizing:border-box;font-size:12px;font-family:&quot;courier new&quot;, courier;font-weight:400;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;"><strong style="box-sizing:border-box;font-weight:bold;">rsync</strong>&nbsp;<br style="box-sizing:border-box;" data-filtered="filtered" /> rsync 服务器可以独立运行也可以由xinetd运行,CentOS默认以xinetd运行,同时默认监听873端口。需要创建rsync配置文件 vi /etc/rsyncd.conf 在文件中[module]之外的所有配置行都是全局参数,也可以在全局参数部分定义模块参数,模块参数主要功能定义哪个目录要被同步,可以根据需要来定义多个模块 uid = root  gid = root  max connections = 10 use chroot = no  log file = /var/log/rsyncd.log  pid file = /var/run/rsyncd.pid  lock file = /var/run/rsyncd.lock  [tongbu]  path = /opt/tongbu  comment = hello world  ignore errors = yes  read only = no  hosts allow = 192.168.1.125  hosts deny = * (可以匿名连接,不安全,详细参考以下) <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-size:12px;font-family:&quot;courier new&quot;, courier;font-weight:400;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;">启动并设置随系统启动 rsync,要求</span>&nbsp;<span style="box-sizing:border-box;font-size:12px;font-family:&quot;courier new&quot;, courier;font-weight:400;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;">服务端和客户端都启动</span>&nbsp;<span style="box-sizing:border-box;font-size:12px;font-family:&quot;courier new&quot;, courier;font-weight:400;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;">,否则使用的时候报错Connection refused</span> </p> <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> &nbsp; </p> <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-size:12px;font-family:&quot;courier new&quot;, courier;font-weight:400;color:#800000;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;"><br style="box-sizing:border-box;" data-filtered="filtered" /> rsync --daemon –-config=/etc/rsyncd.conf  chkconfig rsync on <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> &nbsp; </p> <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-size:12px;font-family:&quot;courier new&quot;, courier;font-weight:400;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;" data-filtered="filtered"><span style="box-sizing:border-box;font-weight:400;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;background-color:#cfe2f3;" data-filtered="filtered"><span style="box-sizing:border-box;font-weight:400;color:#993300;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;" data-filtered="filtered"></span></span></span> </p> <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> &nbsp; </p> <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-weight:400;color:#0000ff;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;"><strong style="box-sizing:border-box;font-weight:bold;">------------------------------------------------------------------------------------------------------------------------------------------------------------</strong></span> </p> <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-size:12px;font-family:&quot;courier new&quot;, courier;font-weight:400;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;"><br style="box-sizing:border-box;" data-filtered="filtered" /> 全局参数  address 指定的服务器运行的IP地址。由xinetd运行时将忽略此参数 port 指定rsync守护进程监听端口号(默认873)。由xinetd运行时将忽略此参数 motd file 指定一个消息文件,当客户连接服务器时该文件内容将显示给客户 pid file rsync的守护进程将其PID写入指定的文件 log file 指定守护进程的日志文件,而不将日志发给syslog syslog facility 指定发送日志消息给syslog时的消息级别 socket options 自定义tcp选项   <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-size:12px;font-family:&quot;courier new&quot;, courier;font-weight:400;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;"><strong style="box-sizing:border-box;font-weight:bold;">基本模块参数</strong>&nbsp;<br style="box-sizing:border-box;" data-filtered="filtered" /> path 指定当前模块在rsync服务器上的同步路径,必须指定 comment 给模块指定一个描述 控制模块参数 use 默认为true,传输文件之前先chroot到path参数所指定的目录下,这样做实现额外的安全防护,但缺点需要root权限,并且不能备份指向path外部的符号链接所指向的目录文件 uid 制定该模块已指定的UID传输文件 gid 指定该模块已指定的GID文件 max connections 限制最大连接并发数以保护服务器,超过限制则提示稍后操作 lock file 指定支持max connections参数的锁文件,默认/etc/run/rsyncd.lock list 指定当客户请求列出可以使用的模块列表时(默认ture),该模块是否被列出。如果false,可以创建隐藏的模块 read only 是否也许客户上传文件,默认ture则不也许上传。为false并且服务器目录具有读写权限则允许上传 write only 是否也许客户上传文件,默认ture则不也许下载。为false并且服务器目录具有读写权限则允许下载 ignore errors 指定rsync服务器在运行delete操作时是否忽略I/O错误 ignore nonreadable 指定rysnc服务器忽略那些没有访问文件权限的用户 timeout 设定连接超时时间,单位为秒 dont compress 告诉rysnc那些文件在传输前不用压缩,默认已设定压缩包不再进行压缩 refuse options 定义一些不允许客户对该模块使用的命令选项列表 <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-size:12px;font-family:&quot;courier new&quot;, courier;font-weight:400;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;"><strong style="box-sizing:border-box;font-weight:bold;">文件筛选模块参数</strong>&nbsp;<br style="box-sizing:border-box;" data-filtered="filtered" /> exclude 指定排除的多个文件或目录,由空格隔开 exclude from 从指定文件中读取排除规则 include 指定包含复制多个文件或者目录,由空格隔开 include from 从指定文件中读取包含规则 用户认证模块参数  auth users 指定用户才允许连接该模块 secrets file 指定一个口令认证文件,格式是 用户:密码,即指定用户和密码连接匹配才行,不匹配的话会提示ERROR: auth failed on module,不设置该参数则可以匿名连接。  strict modes 指定是否检测口令文件权限。rsync认证口令文件权限一定是600 <p style="box-sizing:border-box;font-size:14px;font-family:Helvetica, Tahoma, Arial, sans-serif;white-space:normal;word-spacing:0px;text-transform:none;font-weight:normal;color:#333333;padding-bottom:0px;font-style:normal;padding-top:0px;padding-left:0px;orphans:2;widows:2;margin:0px;letter-spacing:normal;line-height:25px;padding-right:0px;background-color:#ffffff;text-indent:0px;font-variant-ligatures:normal;font-variant-caps:normal;-webkit-text-stroke-width:0px;"> <span style="box-sizing:border-box;font-size:12px;font-family:&quot;courier new&quot;, courier;font-weight:400;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;padding-right:0px;"><strong style="box-sizing:border-box;font-weight:bold;">访问控制参数</strong>&nbsp;<br style="box-sizing:border-box;" data-filtered="filtered" /> hosts allow 指定哪些IP可以访问该模块 hosts deny 指定哪些IP不可以访问该模块,*表示全部 ...

    2018-01-25 未分类 3996
  • CentOS命令行下安装VMware tools

    首先,在ESXI客户端管理工具vSphere Client选择 清单->虚拟机->客户机->安装升级VMware Tools,看下面提示信息已经挂载后再用mount虚拟光驱: mkdir /mnt/cdrom mount -t iso9660 /dev/cdrom /mnt/cdrom 然后拷贝VMWarexxx.tar.gz到/tmp: cp /mnt/cdrom/VMWarexxx.tar.gz /tmp 然后解开压缩包: cd /tmp tar zxf VMWarexxx.tar.gz 然后进入vmware-tools-distribute cd vmware-tools-disxx 然后执行: ./vmware-install.pl 如下不去请执行下面的步骤 yum install perl yum install gcc yum install kernel 一路回车 注:如果你的机器没有安装相应版本的linux kernel和c编译器,这个过程中可能会失败,解决办法是在问你是否编译相关模块的地方输入no即可。 安装完成后重启一下机器即完成安装: shutdown -r now 貌似确实要先把压缩包拷贝到其他的文件夹,不然的话,貌似tar命令没有生效~~~O(∩_∩)O~ ...

    2018-01-25 未分类 3684
  • CentOS关闭SELinux

        查看 [root@dev-server ~]# getenforce Disabled [root@dev-server ~]# /usr/sbin/sestatus -v SELinux status: disabled 临时关闭 ##设置SELinux 成为permissive模式 ##setenforce 1 设置SELinux 成为enforcing模式 setenforce 0 永久关闭 vi /etc/selinux/config 将SELINUX=enforcing改为SELINUX=disabled  设置后需要重启才能生效     ...

    2018-01-25 未分类 3549
  • Centos6版本升级

    1.查看当前版本 2 3 4 [root@IDC-D-1699 docker]# cat /etc/issue CentOS release 6.8 (Final) Kernel \r on an \m 2.升级Centos [root@IDC-D-1699 docker]# yum update –y 3.内核升级至3.10 前往http://www.elrepo.org/   3.1下载升级包 [root@localhost ~]# rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org  [root@localhost ~]# cd /etc/yum.repos.d/  [root@localhost yum.repos.d]# rpm -ivh http://www.elrepo.org/elrepo-release-6-6.el6.elrepo.noarch.rpm  [root@localhost yum.repos.d]# yum --enablerepo=elrepo-kernel install kernel-lt -y 3.2 修改grub.conf文件的default=0 2 3 4 5 6 7 8 9 10 11 12 13 [root@localhost yum.repos.d]# vim /etc/grub.conf # grub.conf generated by anaconda # # Note that you do not have to rerun grub after making changes to this file # NOTICE:  You have a /boot partition.  This means that #          all kernel and initrd paths are relative to /boot/, eg. #          root (hd0,0) #          kernel /vmlinuz-version ro root=/dev/mapper/VolGroup-lv_root #          initrd /initrd-[generic-]version.img #boot=/dev/sda default=0 timeout=5 3.3 重启并查看内核 [root@localhost yum.repos.d]# reboot 2 3 4 5 6 [root@localhost ~]# uname -r 3.10.94-1.el6.elrepo.x86_64 [root@localhost ~]# more /etc/issue CentOS release 6.7 (Final) Kernel \r on an \m ...

    2018-01-25 未分类 3835
  • chmod用数字来表示权限的方法

    前提:  mode权限设定字串,格式:[ugoa...][[+-=][rwxX]...][,...]     其中u表示拥有者(user),g表示与拥有者属于同一个群体(group),o表示其他以外的人(other),a表  示这三者皆是;    +表示增加权限,-表示取消权限,=表示唯一设定权限; r:表示可读取,w表示可写入,x表示可执行。 语法:chmod abc file 其中a,b,c各为一个数字,a表示User,b表示Group,c表示Other的权限。 r=4,w=2,x=1 若要rwx(可读、可写、可执行)属性,则4+2+1=7 若要rw-(可读、可写、不可执行)属性,则4+2=6 若要r-w(可读、不可写、可执行)属性,则4+1=5 范例: chmod a=rwx file 和 chmod 777 file 效果相同 chmod ug=rwx,o=x file 和 chmod 771 file 效果相同 若用chmod 4755 filename可使此程式具有root的权限 ...

    2018-01-23 未分类 3986
  • Zabbix 图像中文乱码

    如将zabbix改为中文界面,可直接更改。 但是打开监控图像时,出现了中文乱码: 解决方法:将windows中的字体,替换zabbix php 中的字体。 1. 打开 windows 控制面板——》字体——》如选择 “黑体”——》上传到linux中 2. 将名字改为小写 “simhei.ttf” 3. 原字体文件备份 [plain] view plain copy mv /var/www/html/zabbix/fonts/DejaVuSans.ttf /var/www/html/zabbix/fonts/DejaVuSans.ttf.bak   mv /home/centos/simhei.ttf /var/www/html/zabbix/fonts/   4. 编辑文件defines.inc.php,将原来的 DejaVuSans 更改为 simhei (有两个地方更改) [plain] view plain copy # find / -name defines.inc.php   /home/zdtest/zabbix-2.4.8/frontends/php/include/defines.inc.php   /var/www/html/zabbix/include/defines.inc.php      # vi /var/www/html/zabbix/include/defines.inc.php   define('ZBX_FONT_NAME', 'simhei');   define('ZBX_GRAPH_FONT_NAME', 'simhei');    完成!刷新正常了! ...

    2017-09-22 未分类 3990

友情链接 百度收录正常的正规站可申请友情链接! 申请友链

联系我们

在线咨询:点击这里给我发消息

微信号:chensj923

工作日:9:00-23:00,节假日休息

扫码关注