作者:aming


MySQL延迟主从复制


世界上没有卖后悔药的,一旦做错了,后悔莫及。我们作为运维,尤其是不小心误删除数据库里的数据时,那更是损失巨大。对于MySQL来说,这里有一种方法,可以避免这种悲剧的发生。

这儿所谓的延迟,并不是经常说的网络延迟,而是我们故意把从库复制的步伐放慢,比如让从库比主库慢30分钟。这样,如果在半小时内发现数据有问题,还能补救。

MySQL 5.6 已经支持延迟复制, 可设置备节点的延迟时间, 延迟复制是有意义的,例如防止主节点数据误删,查看数据库历史状态等。

配置也不难,做完主从后,再加上这句:

CHANGE MASTER TO MASTER_DELAY = N;

这里的N单位是秒,这样从库则会比主库延时N秒。做完之后,在show slave status的时候,就可以看到SQL_Delay的值。

SQL_Delay: xxx

三年出纳工作经验的医学生是怎么做运维的


导读:

2016年12月25号,报名
2017年5月24号,收到 offer
多么完美的半年!!哦不,是 5 个月。

背景介绍:

91年,14年毕业,大学专业是 康复治疗学,主要针对各种功能障碍进行功能恢复训练。

毕业之后,在贸易公司工作,做过网站、google SEO、google Adwords。也做过司机、出纳、财务、跟单,全是跟外贸有关的行当,和计算机没半毛钱关系。

至于为什么学Linux,原因和你一样,问问你自己为什么选择这条路,应该八九不离十。

学习方法:

http://ask.apelearn.com/question/16773 ,这个帖子是当时应铭哥要求给大家分享的我的学习方法,我就不多说了,视频里面特别详细,可以去看看。

视频中没有提及的东西:

1 如果你决定了要换工作,如果条件不算太苛刻,那就辞职,专心看课程,给自己压力,家人也会给你压力,破釜沉舟不是没有道理的。

之前看过一个师兄的帖子,辞职专心学习,老婆和长辈都不理解(有没有孩子不记得了),当然你能想象那时候他的压力,但是工作找到之后,老婆和长辈的那些刁难的话,也就无所谓了,老婆和长辈也都理解了。

2 分享你的笔记,不管有没有人看。未必天天都分享笔记,因为理解程度低,可能两天三天才整理一个笔记,但是一旦整理好,还是要分享的。
我分享笔记的初衷很简单,我要盖楼,我要刷屏,整个页面都是你的帖子,不是很爽的事情吗??说白了就是嘚瑟!

3 回复专帖,无论有没有学习!最长记录是连续 71 天,再嘚瑟一下

复习方法:

1 学完之后,自己回顾整理一下每个知识点自己掌握的情况,跟铭哥沟通一下,计划下一步怎么复习,哪些是重点,哪些不是重点。

2 结合笔记再操作一下,听大师兄的建议,有必要可以把笔记重新整理归档一下。

3 扩展部分,不要死磕,特别是你本身没有计算机基础,大牛除外。

4 结合面试宝典复习,里面都是面试官出的题目,同学们一点一滴整理来的。

5 有必要,能画图就画图,一图剩千言

找工作经过

简历写好之后,我的计划是一天投三份简历,不多投,看看招聘要求里面的东西,是不是你都知道(招聘内容里面设计的知识点大部分是你知道的或者见过就可以,无需全部精通)。

如果合适,就把简历投过去,发完三份,就继续去做面试宝典,继续按照你的复习计划去复习。

可能是我比较幸运,5.22 号投的简历,中午接到面试通知,约我下去去面试,我推到了明天去,给自己时间针对公司招聘要求里面的内容复习巩固一下。

另外两家,一家直接拒绝了我的简历(app上拒绝的),还一家过了两天都没回复我。

23 号去面试,整理发型,衣服,喷喷香水( six god ),约的10:30面试,我担心迟到,提取45分钟到了,在楼底下继续复习,继续背资料,还剩10分钟的时候上去的。

说真的,我是真的比较幸运,没有笔试,直接面试(估计是看了我的博客,因为之前有同学说过,看了他的博客直接约面试,免笔试),面试官也没问我特别专业的问题,主要针对个人的职业发展方向聊了聊。

还有就是问我对目前行业的看法,我哪有什么看法,门外汉一个,问我对 php 了解多少,,内心OS:玩我呢!!实际回答:“这个真不了解,您也清楚我没计算机基础,不能骗您,咱实事求是”

后来人事过来聊,那就轻松了,没啥技术性的东西,聊的轻松。临走的时候告诉我第二天回通知结果,我问了一句如果没通过是不是也会通知,人事很爽快,说也会通知。

24号,也就是今天,其实我今天一天没有投简历,也没有复习任何资料,心里惦记着昨天的公司是不是能入职,一点复习的心思都没有,玩了一天的游戏,真的,一点都不想复习,不思进取,就想玩一天游戏,啥也不干!!!

计划是今天颓废一天,让自己有罪恶感,第二天继续努力奋斗。午觉睡醒,两点60分,我有点憋不住了,编辑了短信,想咨询一下有没有通过,因为说好的第二天给回复,为啥都快下班了,还不回复我!!!

短信已经编辑好,每个字都斟酌了一遍,不能没礼貌,不能显得自己特别着急,不能这么没耐性!!!ok,就这样了,发送 ……. 就是这么巧,还没点发送,就来电话了!!!O(∩_∩)O~,。

通话内容简单点,后天入职,底薪7k,试用期3个月,试用期工资6k…………,我没工作经验,没计算机基础,给我这个机会,为何不去!!!说来也巧,五点左右,收到另一家的 hr 的面试邀请,我拒绝了,拒绝的好有底气的,哈哈哈哈哈哈哈

1 包装简历,有工作经验的自然不用说,没工作经验的,又不是计算机专业的,写好之后发给铭哥看看,会给你指导性的意见。多改几遍。

2 简历模板可以去搜五百丁,9 块钱买几个模板,看上去舒服点。PS:别来找我要模板,我也是花钱买的。

3 多下载一些app,搜索 招聘即可

困惑

其实复习的时候真的特别郁闷,心里没底,我一个什么基础都没的,学了半年不到能不能找到工作啊,知识点都不牢靠,IDC 机房都没见过,万一搞砸了咋办,万一被同事鄙视咋办,万一搞了一两个月就被辞退了咋办,辞退了就没工资了,养不活自己,没办法娶媳妇,没孩子,不能让孩子上清华北大,不能不能走向人生巅峰赢取白富美咋办???

咋办,凉拌,硬着头皮走下去!!!没人能开导你,除了你自己。这点困难都克服不了,怎么做隔壁老王,哦不,是热心市民王先生。

做一年运维后


从去年的3月份进入现在的公司,我已经干了一年多了,在这一年多里,我学习到了许多的东西,不过最珍贵还是宝贵的线上运维的经验,我现在也是一名有着实操经验的运维了。

不过慢慢也遇到一些瓶颈,想着换一个工作环境。而且也有一个原因,就是过了一年了,涨薪的事情好像被他们遗忘了一样,都没有提及。这个就更加促使我换工作了。

今年过来,一直都有筹划找工作,断断续续在苏州面试了几家,都不太好,不是我看不上他,就是他无法达到我要求的薪资,总是一对矛盾。

后来,我找铭哥聊了聊,铭哥的建议是直接去上海吧,苏州毕竟是二线城市,上海不同,机会多,待遇也高。考虑再三,决定去上海。

经过一轮又一轮的投简历,等面试。终于有两次面试的邀请,准备了下,去上海面试去。

第一家是蚁城,是一家提供商城解决方案的公司。环境还不错。一面是技术组长,总体来说我表现还不错。

其中一个问题是,有三台web机器,开发只部署了其中一台机器,如何把将代码同步到剩余的web机器上。我的回答是使用rsync 的后台方式,或者ssh 密钥建立三台web机器的信任关系。

接着问我说,还有其他的方式么,我想了下,又给出一个方案,将开发部署的web机器的代码目录通过NFS共享出来,其他的两台机器来挂载。但是,技术组长对这两种方案,好像都不是太满意。

ps:其实,咱们课程里面的有很多解决方案,比如你可以讲铭哥讲过的shell项目《分发系统》,也可以说通过自动化运维工具(salt或者ansible),当然还可以说第三阶段的课程jenkins。

快要结束一面的时候,我问了他一个问题,如果有三台tomcat机器,用户的session如何共享?

他给我的答案是使用阿里云的load balance的session 会话粘连,我又接着问,如果是自己搭建呢,他回答说,可以使用nginx的IP-hash功能,固定的IP会链接到固定的tomcat机器上。

我说这个方案有一个缺点,会导致其中一台tomcat机器负载比较高,因为现有网络的公网IP大都是公用的。

最后,我提了一个方案是,可以使用memcached搭建一个session共享存储层,将三台tomcat机器的session都存储在这个共享层中,而且memcached是nosql,容易横向扩展。

接着就是二面了,是cto来面试的,cto比较nice,先问了对LNMP的架构熟悉么,我心里就在偷笑了,在铭哥的课程里,讲的非常细,我自己在面试前也复习过,所以根本不是问题。这家公司的offer我拿到了,但是因为有更好的选择,我没有选择这家公司。

第二家公司主要是做云计算以及大数据的解决方案的。我面试的部门主要是做大数据,负责给咪咕视频提供大数据的解决方案。但是这家公司会比较特别,三面都是电话面试。

一面是一位来自总部的资深工程师给我面试的,电话聊了1个小时左右,就是聊一些技术,mysql的高可用,redis的高可用,nginx, openresty, django 聊了许多,因为时间比较久了,我也不记得问了我什么问题。但是聊完之后,让我做了一个线下题,以下是线下题:

1. 编写shell程序,实现自动删除50个账号的功能。账号名为stud1至stud50。

2. 给定一个正整数数组,前半段非递减、后半段非递增,要求从小到大不重复打印数字。给定时间复杂度O(n),空间复杂度O(1)

input: Array={1,2,2,3,5,4,2} output: 1 2 3 4 5
input: Array={1,2,2,2} output: 1 2
input: Array={5,3,2,2,2,1} output: 1 2 3 5
input: Array={1,1,1,1,1} output: 1
input: Array={1,2,1} output: 1 2

第一题,我很快就解决了,不过,这第二题,可是把我难坏了。在网上找了许多资料,终于是搞定了。

之后是第二面,第二面也是一位总部的一位资深的工程师。我们主要聊了发布方面的事情,了解什么是灰度发布么?

我的答案是灰度发布就是正式发布生产前,新建一个生产环境,把新的代码部署到新的生产环境,然后通过前面的负载均衡把现有生产环境的一部分流量倒入到新的生产环境,防止新版本的代码出现大的bug导致用户都无法正常使用。

最后是第三面,第三面的面试官是上海的技术总监。他和我说,因为前面已经有两位工程师和你聊过了,那我们就聊聊一些技术上面的细节。

1 生产服务器的磁盘快要满了,你上线查看磁盘使用量,发现了有一个大的log文件,你将这个文件删除了,之后发现文件系统并没有释放这部分空间,是什么原因?

我的答案是,使用这个文件的进程并没有结束,基于Linux系统的特性,被进程占用的文件是不会被释放的,可以使用lsof | grep deleted 来查看有那些文件已经被删除,但是没有被释放的。

解决这个问题的方法有 (1) 结束掉该进程,(2) 如果这个进程不能被结束的话,可以给这个进程发送一个日志轮转的信号。

2 现在有一复杂的分布式系统,他们之间通过api调用去相互联系,A -> B , B->C and D , 这样的系统,让你来选型监控系统,你会选择什么?

我的答案是可以选择prometheus来监控这样的复杂分布式系统。

3 现在研发说线上的服务器卡,你会通过什么方式去排查这种问题?

(1). 我会使用w, top , free,vmstat 查看Linux系统的负载,CPU, 内存,是否存在瓶颈。

(2). 我会使用iostat , iotop 查看磁盘的IO 是否存在瓶颈。

(3). 我会使用sar -n DEV 来分析网络带宽方面是不是存在瓶颈,带宽是不是不够了等原因。

三面结束了,我也顺利拿到offer , 我最终选择去后面这家,不仅仅是因为他们给我13k的薪资,同时也是因为如果我去这里,在技术领域会有更好的发展。

好了,说了这么多,这次的求职分享到这里就该结束了。谢谢!

正则表达式非贪婪匹配


我们学习正则时,用到过贪婪匹配.*
其实,还有一个相对的概念,叫做非贪婪匹配。

如:str=”abcaxc”
  p=”a.*c”
  
贪婪匹配:正则表达式一般趋向于最大长度匹配,也就是所谓的贪婪匹配。如上面使用模式p匹配字符串str,结果就是匹配到:abcaxc。
  
非贪婪匹配:就是匹配到结果就好,最少的匹配字符。如上面使用模式p匹配字符串str,结果就是匹配到:abc(a.*c)。

shell中如何区分两种模式?

默认是贪婪模式;
在量词后面直接加上一个问号?就是非贪婪模式。

常用的量词有:

{m,n}: m到n个
*: 任意多个
+: 一个到多个
?: 0或一个

示例:

str=”123abc0axc456″
echo $str|grep ‘a.*c’
结果: 123abc0axc456

echo $str|grep -P ‘a.*?c’
结果: 123abc0axc456


elastic stack 使用redis作为日志缓冲


直接上步骤:

1、首先建立一个配置文件,将output的数据写到redis中,而不是ES了。配置文件示例:

input {
    stdin { }
}
output {
    redis {
        host => "192.168.1.100"  #redis服务器地址
        port => "6379"  #redis服务端口
        db => "5"  #使用redis第五个库,用其他库也可以
        data_type => "list"  #用list类型
        key => "demo"  #存储的key名,可自定义自己喜欢的
    }
}

 

2、指定配置文件然后运行Logstash,然后我们在标准输入中随便写点什么东西,这个时候输入的数据都会提交到redis中。登录redis后使用info命令可以查看keyspace相关信息,可以看到db5的keys数量有了变化,我们切换到db5再来看看

select 5
keys *

 

3、通过keys *命令可以看到有了一个key叫做demo,这个就是配置文件里设置的key名,使用LLEN demo可以看到该key的长度,input如果输入了100行,那么这个key就应该有100行

4、再次建立一个配置文件,这次input是从第一步里的redis里读取数据,然后output到ES中

input {
    redis {
        host => "192.168.1.100"  
        port => "6379"  
        db => "5"  
        data_type => "list"
        key => "demo" 
    }
}
output {
    elasticsearch {
        hosts => ["192.168.0.100:9200"]
        index => "redis-demo-%{+YYYY.MM.dd}"
    }
}

 

5、运行该配置文件后去redis看看,之前的队列因为被output到了ES中,所以队列会消失掉或者是迅速减少长度

下面是一个改造后的配置文件,更符合实际需求

input {
    file {
        path => "/var/log/messages"
        type => "system"
}
output {
    if [type] == "system" {
        redis {
          host => "192.168.1.100"
          port => "6379"
          db => "5" 
          data_type => "list" 
          key => "system"
    }
}

shell习题-自定义rm


linux系统的rm命令太危险,一不小心就会删除掉系统文件。 写一个shell脚本来替换系统的rm命令,要求当删除一个文件或者目录时,都要做一个备份,然后再删除。下面分两种情况,做练习:

1. 简单

假设有一个大的分区/data/,每次删除文件或者目录之前,都要先在/data/下面创建一个隐藏目录,以日期/时间命名,比如/data/.201703271012/,然后把所有删除的文件同步到该目录下面,可以使用rsync -R 把文件路径一同同步

2. 复杂

不知道哪个分区有剩余空间,在删除之前先计算要删除的文件或者目录大小,然后对比系统的磁盘空间,如果够则按照上面的规则创建隐藏目录,并备份,如果没有足够空间,要提醒用户没有足够的空间备份并提示是否放弃备份,如果用户选择y,则直接删除文件或者目录,如果选择n,则提示未删除,然后退出脚本。

 

参考答案:

1.  简单
#!/bin/bash
filename=$1
d=`date +%Y%m%d%H%M`
read -p “Are U sure delete the file or directory $1? y|n: ” c
if [ $c == “y” ] || [ $c == “Y” ]
then
    mkdir /data/.$d
    rsync -aR $1/ /data/.$d/$1/
    /bin/rm -rf $1
elif [ $c == “n” ] || [ $c == “N” ]
then
    exit 0
else
    echo “Please input ‘y’ or ‘n’.”
fi
2.  复杂
#!/bin/bash
filename=$1
d=`date +%Y%m%d%H%M`
f_size=`du -sk $1|awk ‘{print $1}’`
disk_size=`LANG=en; df -k |grep -vi filesystem|awk ‘{print $4}’ |sort -n |tail -n1`
big_filesystem=`LANG=en; df -k |grep -vi filesystem |sort -n -k4 |tail -n1 |awk ‘{print $NF}’`
if [ $f_size -lt $disk_size ]
then
    read -p “Are U sure delete the file or directory: $1? y|n: ” c
    if [ $c == “y” ] || [ $c == “Y” ]
    then
        mkdir -p $big_filesystem/.$d && rsync -aR $1 $big_filesystem/.$d/ && /bin/rm -rf $1
    elif [ $c == “n” ] || [ $c == “N” ]
    then
        exit 0
    else
        echo “Please input ‘y’ or ‘n’.”
    fi
else
    echo “The disk size is not enough to backup the files $1.”
    read -p “Do you want to delete “$1″? y|n: ” c
    if [ $c == “y” ] || [ $c == “Y” ]
    then
        echo “It will delete “$1″ after 5 seconds whitout backup.”
        for i in `seq 1 5`; do echo -ne “.”; sleep 1;done
    echo
        /bin/rm -rf $1
    elif [ $c == “n” ] || [ $c == “N” ]
    then
        echo “It will not delete $1.”
        exit 0
    else
        echo “Please input ‘y’ or ‘n’.”
    fi
fi

shell习题-转换字符串


请把下面的字符串:

zhangsan

y97JbzPru

lisi

5JhvCls6q

xiaowang

Nnr8qt2Ma

laoma

iqMtvC02y

zhaosi

9fxrb4sJD

改为如下:

zhangsan:y97JbzPru

lisi:5JhvCls6q

xiaowang:Nnr8qt2Ma

laoma:iqMtvC02y

zhaosi:9fxrb4sJD

 

参考答案:

sed 'N;s/\n/:/g'  filename

java程序员学习linux的感受


作者:23期陈旭

“哇 Linux系统操作起来怎么这么麻烦的!”,这是我第一次成功安装最小化CentOS7系统,初体验后的感叹(手动滑稽)。那时候我还没有报名猿课,仅仅是看着鸟哥的书和百度到的教程安装的。

因为我是学Java的,所以自然安装好后第一件事情就是安装JDK,那时候还不知道有远程终端这么个神器。所以下载JDK安装包的时候,只能在虚拟机里一点点地把那一长串的下载地址给敲进去。

两小时过后终于折腾完毕,于是开头的第一句话,就是这时候说出来的。在这之后就想着需要系统地从基础开始学习一下Linux,于是乎就抱着广为流传的“鸟哥的Linux私房菜”吃了起来,真的很厚很多字而且还是从最基本的硬件开始讲起,个人感受啃这一段跟啃砖头一样难啃和无趣(并没有黑这本书的意思,后面章节写的还是很不错的)。

由于啃书进度太慢,而且书上都是CentOS5的版本,也算是有点老旧了,所以就去网络上找一些视频教程看。在腾讯课堂上看到阿铭老师的课程视频,试听了两节后感觉还不错,然后就去咨询报名事宜,接着我就成为了23期2班的一员。

刚开始感觉阿铭老师挺严格的,学习安排也很有计划性,像笔记、专贴的格式、规则也挺多,后来习惯之后就好了很多,而且这样有严格的要求也让我养成了一些好习惯,学习上也不敢怠惰,如果不是听阿铭老师介绍,我还不知道那么多辅助工具的使用和拥有一个自己的技术博客。

到现在学到第二阶段,终于没有之前那么菜了,学到现在的感受就是阿铭老师的授课方式适合初学者,每个视频都不超过二十分钟,把每个知识点都分作一个个模块去讲解,而且讲解的过程中还能屏蔽一些暂时没必要深入的知识点,因为对于初学者来说附带这些知识点只会增加压力。

在扩展方面也为我们收集了很多资料,每天公众号上面都有shell的练习题,并且还有个考试平台,让我们能去测试自己的水平分数。

相信每一期的同学都有经常听到阿铭老师强调笔记的重要性,在这里我也要喊一下:笔记真的要记得详细!笔记真的要记得详细!笔记真的要记得详细!重要的事情说三遍。当你认真并把笔记做详细了,把出现的错误总结、记录起来了,有时候真的比练习还重要。

当学完一个阶段去复习时效率上要高很多,出错的时候也能从笔记中找到解决的办法。除此之外搜索引擎也很重要,我学习过程中遇到的许多错误都是在网络上找到解决办法的,出现问题后先自己尝试着去解决,相信这一点也不需要多说了。

除以上两点外就是练习,但是练习不要死记硬背命令,而是去理解命令的用法和技巧,记住技巧和理解命令最重要,死记硬背就像只懂得吃,不懂得消化一样。命令单词在日常中使用多了就自然而然的记下了,即便是一些冷僻的命令,你已经理解了它的用法的话,你只需要瞄一遍就又掌握了。

以上就是我学习过程中的一些心得和感受,在下是没读过书的人文笔不好辞藻不华丽,希望大家多多指教不要打脸。

0基础3个月找到工作


作者:23期小明

先自我介绍一下,我是23期学员,在大学学的是数控技术,我在工厂实习的时候,不喜欢用劳动力时间换来的金钱,所以我就决定辞职报名阿铭linux,在我报名之前从未听过linux,我相信绝大数人的基础比我要好,所以大家都要对自己有信心,天下无难事,只怕你坚持不下。

在我们报名的时候,我相信大家都是激情澎湃,但是学习入门是无趣的。每天面对一些基础的命令专业知识。但是大家一定一定不要放弃。

经过两个半月的学习我就开始找工作了,因为在找工作的过程中,很清晰明了的知道自己哪里不足,在面试中出现的问题,和自己回答不出甚至是从未听到过的专有名词,回家后一定要多学习。

由于我在长沙找工作,招聘运维岗位不是多,所以我面试了很多技术支持的工作,面试技术支持的岗位对技能要求很低,所以对我们以后面试运维工程师在技术方面没有太多用,但是可以增加你的面试经历。

我的面试总结

1、在面试的时候无论如何,一定要有一个非常积极的心态去面试,一定要把自己一颗学习的心态体现出来,特别是像我这种非科班转行的,这一点尤为重要。

 

2、在面试过程中,有90%的面试官会问:你对以后的职业生涯有什么规划。在说自己的规划时,我觉得最好是回答:在工作中中不断的学习进步,能成为公司的技术骨干,我自己认定我**岗位是我一生的追求。千万不能体现自己有跳槽的想法。

 

3、在面试过程中,只要有了解过的专业技能知识,面试官问你会不会,你就回答会,反正不要你具体操作,笔试的时候有机会就把题目发到群里,我相信只要大家有时间一定会帮你的,但是不能说着说着不能把自己带到坑里去了。

 

4、最重要的就是总结前面面试遇到的问题,回家总结形成文档,只要你每次把前面面试中遇到的问题,和回答不出的问题在下次面试中不再出现,我相信你一定会找到工作。

 

关于专业知识的回答阿铭论坛中有非常多,自己耐心寻找总结。

linux shell命名管道FIFO


在shell脚本中,我们想要实现多进程高并发,最简单的方法是把命令丢到后台去,如果量不大的话,没问题。 但是如果有几百个进程同一时间丢到后台去就很恐怖了,对于服务器资源的消耗非常大,甚至导致宕机。

那有没有好的解决方案呢? 当然有!

我们先来学习下面的常识。

1 文件描述符

文件描述符(缩写fd)在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。每一个unix进程,都会拥有三个标准的文件描述符,来对应三种不同的流:

除了上面三个标准的描述符外,我们还可以在进程中去自定义其他的数字作为文件描述符,后面例子中会出现自定义数字。每一个文件描述符会对应一个打开文件,同时,不同的文件描述符也可以对应同一个打开文件;同一个文件可以被不同的进程打开,也可以被同一个进程多次打开。

我们可以写一个测试脚本/tmp/test.sh,内容如下:

#!/bin/bash

echo “该进程的pid为$$”

exec 1>/tmp/test.log 2>&1

ls -l /proc/$$/fd/

执行该脚本 sh /tmp/test.sh,然后查看/tmp/test.log内容为:

总用量 0

lrwx—— 1 root root 64 11月 22 10:26 0 -> /dev/pts/3

l-wx—— 1 root root 64 11月 22 10:26 1 -> /tmp/test.log

l-wx—— 1 root root 64 11月 22 10:26 2 -> /tmp/test.log

lr-x—— 1 root root 64 11月 22 10:26 255 -> /tmp/test.sh

lrwx—— 1 root root 64 11月 22 10:26 3 -> socket:[196912101]

其中0为标准输入,也就是当前终端pts/3,1和2全部指向到了/tmp/test.log,另外两个数字,咱们暂时不关注。

2 命名管道

我们之前接触过的管道“1”,其实叫做匿名管道,它左边的输出作为右边命令的输入。这个匿名管道只能为两边的命令提供服务,它是无法让其他进程连接的。

实际上,这两个进程(cat和less)并不知道管道的存在,它们只是从标准文件描述符中读取数据和写入数据。

另外一种管道叫做命名管道,英文(First In First Out,简称FIFO)。

FIFO本质上和匿名管道的功能一样,只不过它有一些特点:

1)在文件系统中,FIFO拥有名称,并且是以设备特俗文件的形式存在的;

2)任何进程都可以通过FIFO共享数据;

3)除非FIFO两端同时有读与写的进程,否则FIFO的数据流通将会阻塞;

4)匿名管道是由shell自动创建的,存在于内核中;而FIFO则是由程序创建的(比如mkfifo命令),存在于文件系统中;

5)匿名管道是单向的字节流,而FIFO则是双向的字节流;

有了上面的基础知识储备后,下面我们来用FIFO来实现shell的多进程并发控制。

需求背景:

领导要求小明备份数据库服务器里面的100个库(数据量在几十到几百G),需要以最快的时间完成(5小时内),并且不能影响服务器性能。

需求分析:

由于数据量比较大,单个库备份时间少则10几分钟,多则几个小时,我们算平均每个库30分钟,若一个库一个库的去备份,则需要3000分钟,相当于50个小时。很明显不可取。但全部丢到后台去备份,100个并发,数据库服务器也无法承受。所以,需要写一个脚本,能够控制并发数就可以实现了。

控制并发的shell脚本示例:

#!/bin/sh

function a_sub {
    sleep 2;
    endtime=`date +%s`
    sumtime=$[$endtime-$starttime]
    echo "我是$i,运行了2秒,整个脚本已经执行了$sumtime秒"
}

starttime=`date +%s`
export starttime

##其中$$为该进程的pid
tmp_fifofile="/tmp/$$.fifo"

##创建命名管道
mkfifo $tmp_fifofile

##把文件描述符6和FIFO进行绑定
exec 6<>$tmp_fifofile

##绑定后,该文件就可以删除了
rm -f $tmp_fifofile

##并发量为8,用这个数字来控制并发数
thread=8

for ((i=0;i<$thread;i++));
do
    ##写一个空行到管道里,因为管道文件的读取以行为单位
    echo >&6
done

##循环100次,相当于要备份100个库
for ((i=0;i<100;i++))
do
    ##读取管道中的一行,每次读取后,管道都会少一行
    read -u6
    {
        a_sub || {echo "a_sub is failed"}
        ##每次执行完a_sub函数后,再增加一个空行,这样下面的进程才可以继续执行
        echo >&6
    } & ##这里要放入后台去,否则并发实现不了
done

##这里的wait意思是,需要等待以上所有操作(包括后台的进程)都结束后,再往下执行。
wait

##关闭文件描述符6的写
exec 6>&-