首页 文章 精选 留言 我的

精选列表

搜索[快速],共10000篇文章
优秀的个人博客,低调大师

直播揭秘飞冰 | 淘系中后台负责人教你快速搭建企业微前端架构

主题:微前端 + icejs 助力企业级中后台开发时间:3月5日 19:00-20:00嘉宾:大果 阿里巴巴淘系技术前端技术专家 ★上期直播地址:http://mudu.tv/watch/4662084★PPT获取:关注「淘系技术」微信公众号,后台回复“前端”即可获取全部PPT资料! 分享简介 icejs 是飞冰团队在 2020 年初发布的一个 React 研发框架,目前已广泛应用于淘系中后台业务中。icejs 致力于建设一套上手简单、生态完善的研发框架,从基础的路由到状态管理再到 SSR、微前端等我们是如何思考与设计的?icejs 与社区已有的框架 nextjs、nuxtjs 等又有哪些区别?本次直播带你一探究竟。 另一方面,今年在国内前端社区突然火起来的微前端到底是解决什么问题的?在淘系业务场景下微前端方案 icestark 又是怎

优秀的个人博客,低调大师

19、 Python快速开发分布式搜索引擎Scrapy精讲—css选择器

css选择器 1、 2、 3、 ::attr()获取元素属性,css选择器 ::text获取标签文本 举例: extract_first('')获取过滤后的数据,返回字符串,有一个默认参数,也就是如果没有数据默认是什么,一般我们设置为空字符串 extract()获取过滤后的数据,返回字符串列表 #-*-coding:utf-8-*- importscrapy classPachSpider(scrapy.Spider): name='pach' allowed_domains=['blog.jobbole.com'] start_urls=['http://blog.jobbole.com/all-posts/'] defparse(self,response): asd=response.css('.archive-title::text').extract()#这里也可以用extract_first('')获取返回字符串 #print(asd) foriinasd: print(i) 【转载自:http://www.lqkweb.com】

优秀的个人博客,低调大师

如何用SAP WebIDE的Fiori创建向导基于ABAP OData service快速创建UI5应用

如果我们手上已经有可以正常工作的OData服务,无论位于ABAP on-premise系统还是public上的internet OData service,都可以用SAP WebIDE里的Fiori创建向导,几分钟之内轻松创建出可以持续开发的UI5应用。 打开SAP云平台上的WebIDE,New->Project from Template: 选择Master Detail风格的Fiori应用: 这里就要指定这个UI5应用消费的OData服务url了。下拉菜单里看到的是一个我在SAP云平台创建的Destination,指向on premise系统: url路径选择/sap/opu/odata/sap/CRM_OPPORTUNITY,做过CRM的朋友们会知道这个路径指向的是CRM ABAP里的OData服务CRM_OPPORTUNIT

优秀的个人博客,低调大师

将你的物联网设备位置快速接入到地图上,只需要10分钟!

楼主作为一个物联网方面的萌新,喜欢玩玩阿里云物联网平台的各种现成功能,然后和自己的设备做下简单组合,往往就能实现一些之前比较麻烦的功能。最近看到阿里云物联网平台新上了一个数据分析菜单,对于动手党来说,先别管什么东西?玩玩先。 在产品和服务里,搜物联网,先进物联网平台控制台。 看到这个数据分析目录了么,就是这个新出现的目录。 简单点点几个功能目录,发现除了最后一个空间数据可视化以外,都是和数据相关的,看来大数据和物联网结合的潮流已经势不可挡了,不过像楼主这种普通码农,手上的设备有限,数据更是没有多少,这些功能看来短时间是用不上了,不过点到最后一个空间数据可视化,楼主的眼睛开始冒小星星了。 创建场景 先点下创建场景,看到可以选择产品或者设备组,但是在产品的下拉菜单里没有找到我的产品,问号脸??? 看了上面有个文档链接,进去有个视频教程,15分钟的样子,讲的内容很全,从创建设备到配置地图都有。快快看一下,知道原因了,这个功能需要高级版设备(其实在页面上已经提示了,但是眼睛太大没有看到,o(╯□╰)o)。so,建一个呗,反正又不要钱。 创建产品和设备 高级版的设备,有不少现成的类型可以选,我在这里选了一个自定义的设备,然后用这个产品新建了几个设备三元组: 这个时候再回到二维可视化这里,就能看到刚才新建的产品了: 新建好的场景进来是这样的:提示设备没有位置。 上传设备位置 下一步就是如何给楼主的设备设置位置了,看了下官方的设备定位文档链接,有两种方法,一种是在设备详情页面给设备给个位置的标签,就像下面图上的这样,用鼠标在地图上选一下设备的位置,这种方式估计是为了给没有gps模块、同时位置又不怎么变动的设备用的; 作为程序员的楼主,怎么能用这么偷懒的办法呢,还有一种办法是给设备添加一个代表位置的属性,然后把经纬度通过这个属性post到云端来。楼主手上没有gps模块的设备,不过可以用阿里云提供的mqtt客户端sdk程序模拟一个设备来做测试。SDK的版本有很多,C、java、python、nodejs等等,楼主这里为了方便,就用java版本的sdk在自己的本本上直接跑了。阿里云物联网java SDK的链接在这里,有一个demo功能,我直接下回来改改, 这里楼主因为建产品的时候选择的自定义的产品,根据官方文档,要给产品添加位置属性才可以,楼主在添加标准属性的时候,搜了下位置关键字,选了个和官方文档上一样的标识符是GeoLocation的属性(后面有属性的试用类别,楼主根本没有care,^_^): 下面就是跑代码把设备位置传上来了,很激动有木有! 把设备三元组填到demo的device_id.json文件里。如图:demo程序的入口在HelloWorld.java,看了下里面的代码,把上报属性以外的方法都干掉,最后精简以后的demo长这样: public class HelloWorld { private static final String TAG = "HelloWorld"; private String pk, dn; private ThingSample thingTestManager = null; public static void main(String[] args) { ALog.d(TAG, "Hello world!"); ALog.setLevel(ALog.LEVEL_DEBUG); HelloWorld manager = new HelloWorld(); ALog.d(TAG, "args=" + Arrays.toString(args)); System.out.println(System.getProperty("user.dir")); String diPath = System.getProperty("user.dir") + "/device_id.json"; String deviceInfo = FileUtils.readFile(diPath); if (deviceInfo == null) { ALog.e(TAG, "main - need device info path."); return; } Gson mGson = new Gson(); DeviceInfoData deviceInfoData = mGson.fromJson(deviceInfo, DeviceInfoData.class); if (deviceInfoData == null) { ALog.e(TAG, "main - deviceInfo format error."); return; } ALog.d(TAG, "测试一机一密和物模型"); manager.init(deviceInfoData); } public void init(final DeviceInfoData deviceInfoData) { this.pk = deviceInfoData.productKey; this.dn = deviceInfoData.deviceName; LinkKitInitParams params = new LinkKitInitParams(); /** * 设置 Mqtt 初始化参数 */ IoTMqttClientConfig config = new IoTMqttClientConfig(); config.productKey = deviceInfoData.productKey; config.deviceName = deviceInfoData.deviceName; config.deviceSecret = deviceInfoData.deviceSecret; config.channelHost = pk + ".iot-as-mqtt." + deviceInfoData.region + ".aliyuncs.com:1883"; /** * 是否接受离线消息 * 对应 mqtt 的 cleanSession 字段 */ config.receiveOfflineMsg = false; params.mqttClientConfig = config; /** * 设置初始化三元组信息,用户传入 */ DeviceInfo deviceInfo = new DeviceInfo(); deviceInfo.productKey = pk; deviceInfo.deviceName = dn; deviceInfo.deviceSecret = deviceInfoData.deviceSecret; params.deviceInfo = deviceInfo; /** * 设置设备当前的初始状态值,属性需要和云端创建的物模型属性一致 * 如果这里什么属性都不填,物模型就没有当前设备相关属性的初始值。 * 用户调用物模型上报接口之后,物模型会有相关数据缓存。 */ Map<String, ValueWrapper> propertyValues = new HashMap<String, ValueWrapper>(); // 示例 // propertyValues.put("LightSwitch", new ValueWrapper.BooleanValueWrapper(0)); params.propertyValues = propertyValues; thingTestManager = new ThingSample(pk, dn); LinkKit.getInstance().init(params, new ILinkKitConnectListener() { public void onError(AError aError) { ALog.e(TAG, "Init Error error=" + aError); } public void onInitDone(InitResult initResult) { ALog.i(TAG, "onInitDone result=" + initResult); thingTestManager.readData(System.getProperty("user.dir") + "/test_case.json"); thingTestManager.report(); } }); } } 对于设备要上报的位置属性设置,要填在test_case.json里。由于GeoLocation属性定义是struct结构体,所以value要填结构体子属性的json串,子属性的名字点击下面框出来的红框里的编辑查看:填好以后的test_case.json长这个样子:这里碰到一个坑,楼主只填写了struct里的经度和纬度两个属性,结果云端返回"6312:tsl parse: struct param size error -> GeoLocation",看来struct里的全部属性都要填。CoordinateSystem这个属性查了下,是google用标准国外标准和国标的区别,两个坐标系之间会有少许偏移,这里只是测试,所以先填1。这里给大家推荐高德的坐标拾取器,很好用的:link最后就是跑下HelloWorld的main方法了,见证奇迹的时候到了!!!看到云端返回: {"code":200,"data":{},"id":"526900545","message":"success","method":"thing.event.property.post","version":"1.0"} 说明上传成功,哈哈,开心。这个时候再看看我的场景: **大功告成,总结一下,总共三个步骤, 1、创建带位置属性的高级版产品和设备; 2、用产品来创建场景; 3、上传设备位置。 其他的工作这个云产品都帮你做了,如果第三步楼主不是用代码,而是在控制台上直接设置,整个过程用不了10分钟,是不是挺简单?简单在页面点点,还发现了其他的功能,这个留着楼主下期分享。**

优秀的个人博客,低调大师

30K iOS程序员的简述:如何快速进阶成为高级开发人员

前言: 本篇文章适用于所有在这个行业已经有了几年时间后想要在职业生涯中取得突破的开发人员,编程人员和程序员(或者你可能刚刚开始,但希望你能看到你的路径) 本文适合那些有着简单愿望的人:你想成为一名高级开发人员,并希望在你的领域中脱颖而出。在阅读完这篇文章后,您将获得一组具有最佳资源列表的路径,供您升级并成为高级开发人员。 作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个我的iOS交流群:638302184,不管你是小白还是大牛欢迎入驻 ,分享BAT,阿里面试题、面试经验,讨论技术, 大家一起交流学习成长!希望帮助开发者少走弯路。 免责声明:与生活中的所有事物一样,您可以随时设定自己的路径。尽管这不是唯一的方法,但是这是我在自己的职业生涯中发现的一种方法,并且通过我在过去一年中与我认为是社区中资深和受人尊敬的程序员的人进行了许多对话和访谈。 我已经积累了这篇文章的所有共同点。所有这些不仅仅是一篇关于如何成为更好的开发人员的文章。这是一个如何指导您如何使用高效实用的工具来优化您的时间,从而让您从生活中获得最大收益。将来你可以在任何地方进行这种学习 我们想要什么?1,我们都努力做好工作。该声明的具体内容可能取决于个人。但是,大多数人可以同意一些常见的事情: 2,我们不希望经历被视为“无能”的生活, 3,我们希望得到我们同事的尊重 4,我们希望感觉自己聪明,并且做到了 5,我们想感受赞赏 为了实现上述目标,我们不能仅仅停留在我们的能力上,并期望事情会发生。特别是在编程领域,技术在不断变化,我们掌握的信息量非常之大,我们希望将注意力集中在成长和学习上,而不是消耗殆尽。随着越来越多的开发者走出大学和训练营,我们需要保持技能的锐利,而让自己与众不同的方法是在学习时保持智能和高效。谈得很多,让我们一起潜入。我们将一如既往地尝试并采取最好的方法。 什么是高级开发人员?作为一个可以使用十种不同编程语言编写代码并构建了自己版本的多语言编程人员,并不会让您成为高级开发人员(尽管您非常有才华)。这是因为高级开发人员是为公司带来增量利益的人员。它是一个能够让周围的人变得更好,并且能够长期愿景,实现并持续创造商业价值的人。您可以了解全球所有功能强大的编程技术,但如果您无法与团队沟通,或者无法专注于为客户提供实际价值,则您不是高级开发人员。这是重要的一点:你为贵公司/创业/企业带来了什么价值,如果你是为数不多的能为您的公司或企业带来数量级(有些人喜欢10倍的想法)价值的人之一,那么你是一位高级开发人员。高级开发人员不仅仅是另一个职位,而是能够利用您的经验为利益相关方提供真正的利益。 **我如何成为一个高级程序员?得到它。**这是你们所有人一直在等待的部分(或者我想象的是......也许没人读这个......在这种情况下,我会一直跟自己说话)。让我们深入了解一下,看看我们是否能够完成所有事情。按照以下资源,花一些时间了解每个主题。如果你能够积极研究下面的技能,你将远远领先于其他任何人。我把这称为开发者边缘:在一个领域总会有比你更有经验的人,但是你可以更聪明地工作,并以更有效的方式积累不同的技能组合,让你分开。这不仅使你成为一个更好的开发者,它还增加了你的整体幸福感,因为你正在为人们提供真正的价值。 学习中经常被忽视的一个方面是,你需要专注于一件事而专注于一件事。然而,这不是生活的方式。生活中非常罕见,你只需要一种技能。特别是在像技术领域发生变化的领域(谁知道机器学习工程师将在5年内完成什么?),您需要拥有多种可转换技能,这将转化为适应性。 这些是您需要被视为高级开发人员的6项核心技能:**1.技术技能** 这通常是大多数人想到的第一个技巧。希望通过这一点你相信它是一个更大的馅饼的一小部分。不要误解我的意思,你确实需要这个技能,而且你不能伪造它。然而,你可以聪明地关注你关注的内容。高级开发人员花时间了解Why的技术。为什么这个问题存在?为什么这个框架存在?这个图书馆解决什么问题?作为一名开发人员,您需要对所有有利于开发生命周期的工具和想法有所了解,并选择在项目中获得最大利益的工具。他们没有专注于这个超级奇特的测试框架的每一个新版本功能,而是试图为公司解决实际问题时专注于每个测试框架的优缺点。他们会问“我们的持续过程中可以改进哪些方面以提供更好的产品?” 他们也明白事情是如何连接的。为了开始这样思考,思维导图是一个很好的熟悉工具。它本质上是一种工具,可以用来将学习推向更高层次。思维导图帮助你的大脑在不同的想法和技术之间建立联系。 举个例子:如果我是一个iOS开发,一旦掌握了行业中的工具和技术,就需要制定产品在扩展时面临哪些问题的思路图,以及何时过早优化是一件坏事。通过在上述所有方面掌握这种关系,您可以通过广泛的视角而不是狭隘的焦点,将公司的资源集中在最重要的事情上。 如果你是从训练营走出来的,或者你没有计算机科学学位,那么你需要开始学习数据结构,算法和其他计算机科学主题。为什么?因为尽管框架和技术发生了变化,但计算机科学的主要原则(大部分)保持不变。通过理解这些更高层次的主题,您可以再次看到,大多数软件问题和良好实践在不同的语言和时间中通常是不变的。这本书(Rob Conery)和这本书(Gayle Laakmann McDowell)可能是我发现提升你的技能的最好工具。虽然它们只是表面上的,但它将为今后的学习奠定基础。 开始收听软件工程日报等播客,这样您就可以了解整个行业的当前问题和未来前景。 最后,阅读这篇文章从纯粹技术角度来看部分技巧。 2.团队技能 这是一个经常被忽视的技巧。你如何与团队成员合作?你是否对PR评论感到愤怒和意见,并对有其做出贡献?或者你是否体贴,合作和鼓励你的团队成员?高级开发人员没有大的自负。他们知道他们很好,不需要向他人证明自己。他们编写干净简单的代码,而不是编写代码来炫耀其他团队成员无法读懂的技能。他们愿意帮助别人,当他们不知道某事时,他们愿意提问。 这就是情商出现的地方。社会心理学是提高这种技能的重要工具,没有什么比“ 如何赢得朋友和影响力的人”更好。记住:你如何能让你身边的人变得更好?如果你的团队中有5人,那么1 + 1 + 1 + 1 + 1应该大于5,因为你可以让你身边的人变得更好(现在我从数学纯粹主义者那里得到邪恶的眼睛......)。 如果你是任何一个项目的参与者,或者你参与的任何一个团队,那么你就能够与你的队友相处并让其他人一起工作,你已经远远领先于大多数人。您还可以让经理,主管,Scrum大师和CTO的生活更轻松。那些是得到晋升的人,更重要的是那些是为公司提供最大价值的人。 3.客户/用户技能 您是否能够与客户或用户交谈,并清楚地了解他们的需求?当他们向你提出一些建议时,你是否了解他们面临的问题?高级开发人员是一个可以独立与客户并可以成为优秀听众的人,然后就最佳步骤向前迈进提供建议。他们在组建关系方面非常出色,他们不会将意见推给客户。他们明白,目标是一个非零和游戏,客户和开发者都可以从互动中获益。 最后,您需要能够向非技术人员解释复杂的编程概念。通过观看大神分解复杂的话题开始开发这项技能。虽然他们正在教练困难的话题,但你可以观察他们之间的一些共同点。 4.成长技巧 高级开发人员每天都在学习新的东西。这并不意味着他们每天花14小时坐在电脑前阅读文章。他们比这更有效率。他们一直在寻找与其他开发人员交谈,提出问题或探索新主题。他们不专注于一个技能组合。在做一件事情时,你可以成为世界上最好的人,但是如果你不知道整个范围或者对你解决什么问题有一个大概的了解,那么你就不再是最好的了。 他们有一个成长的思维模式(相信智力是可塑的),他们相信有意识的练习。他们明白,学习一切都是不可能的,他们选择把时间花在他们喜欢的事情和最重要的事情上。 他们不只是说“哦,我讨厌这个!”大多数时候,说这些东西的人会因为不完全理解而憎恨某些东西。例如,不要只说“我讨厌Switf。只有部分的开发人员使用Switf“并且声名显赫。高级开发人员说,“Switf在iOS开发方面发挥了重要作用”。他们的观点可以改变,因为他们喜欢从别人那里学习,并且在他们决定“憎恨”某些事物之前尝试新的概念。 5.销售/面试技巧 高级开发人员能够让自己担任高级职位,因为他们能够与做出这些决策的人进行交流和销售。你能够看到你的雇主或企业的需求,并且你可以向他们灌输你是解决问题的人的信心。你有信心,但谦虚。高级开发人员也有足够的信心承担这些角色,并能够承受压力。他们也知道,如果你永远不会问答案总是否定的,那么他们会要求晋升或挑战他们的角色,因为他们认为他们是适合工作的人选。虽然销售和谈判对某些人来说可能会很不起眼,但这是您需要掌握的宝贵技能。有一篇很棒的文章。虽然它谈到薪酬谈判,但其中一些原则可以应用于其他情况。 6.社区技能 高级开发人员为开发者社区做出贡献 ,无论是做技术讲座,在聚会上发言,为开源贡献,甚至写文章。他们是与行业共享信息的人。他们并不是只关在工作空间的封闭盒子里,而是和其他社区的人交流,让他们拓宽视野。这有点像旅行:你遇到并且交谈的文化越多,你越了解人与人之间的相似和不同之处,并且越是开始欣赏它。 **最后一件事如果你能够积极工作上述技巧,你会立即充满激情。**我已经从这个列表中留下了最重要的主题:你喜欢你在做什么。 如果你不喜欢每天学习有关计算机科学和软件开发的知识,那么你永远不会成为高级开发人员,因为从长远来看,你不会有更好的动力。如果你是这么好,他们不能忽略你,你明白激情已被过度炒作。真正的激情来自你掌握了一项技能。你已经努力成为精通领域的领导者。你已经掌握了这些技能,现在你提供给他人的尊重和好处促使你变得越来越好,从而获得更多这样的好感受。你就是这样开发的 你对工作的热情。 结论 如果你已经学会了编码,并且正在寻找职业生涯的下一步,那么你需要以不同的方式思考。你怎么能够脱颖而出?你怎样才能成长?你如何能够帮助人们解决实际问题并提供价值?你不做简单的事情就会成为高级开发人员。你做的事情,推动和挑战你的头脑和舒适水平。你要学习,并且要一天一天地做出适应,就像你第一次写了第一段代码一样。每一步都很小,但是在一生中,一小步就会变成几公里。 永远不要停止阅读,永远不要停止学习,但也要知道什么是你宝贵的时间,什么不宝贵。 作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要这是一个我的iOS交流群:638302184,不管你是小白还是大牛欢迎入驻 ,分享BAT,阿里面试题、面试经验,讨论技术, 大家一起交流学习成长!

优秀的个人博客,低调大师

[雪峰磁针石博客]数据分析工具pandas快速入门教程5-处理缺失数据

第5章 缺失数据 介绍 很少没有任何缺失值的数据集。 有许多缺失数据的表示。 在数据库中是NULL值,一些编程语言使用NA。缺失值可以是空字符串:''或者甚至是数值88或99等。Pandas显示缺失值为NaN。 本章将涵盖: 什么是缺失值 如何创建缺失值 如何重新编码并使用缺失值进行计算 什么是缺失值 可以从numpy中获得NaN值,在Python中看到缺失值使用几种方式显示:NaN,NAN或nan,他们都是相等的。 NaN不等于0或空字符串''。 In [1]: from numpy import NaN, NAN, nan In [2]: print(NaN == True, NaN == False, NaN == 0, NaN == '', sep='|') False|False|False|False In [3]: print(NaN == NaN, NaN == nan, NaN == NAN, nan == NAN, sep='|') False|False|False|False In [4]: import pandas as pd In [5]: print(pd.isnull(NaN), pd.isnull(nan), pd.isnull(NAN), sep='|') True|True|True In [6]: print(pd.notnull(NaN), pd.notnull(99), pd.notnull("https://china-testing.github.io"), sep='|') False|True|True 缺失值的来源 来自加载数据或数据处理 加载数据 当我们加载数据时,pandas会自动找到该缺少数据的单元格,并填充NaN值。在read_csv函数中,参数na_values, keep_default_na, na_filter用于处理缺失值。比如:na_values=[99]。na_filter设置为False,在读大文件时会提升性能。 5-1.py import pandas as pd visited_file = 'data/survey_visited.csv' print(pd.read_csv(visited_file)) print(pd.read_csv(visited_file, keep_default_na=False)) print(pd.read_csv(visited_file, na_values=[''], keep_default_na=False)) 执行结果 $ python3 5-1.py ident site dated 0 619 DR-1 1927-02-08 1 622 DR-1 1927-02-10 2 734 DR-3 1939-01-07 3 735 DR-3 1930-01-12 4 751 DR-3 1930-02-26 5 752 DR-3 NaN 6 837 MSK-4 1932-01-14 7 844 DR-1 1932-03-22 ident site dated 0 619 DR-1 1927-02-08 1 622 DR-1 1927-02-10 2 734 DR-3 1939-01-07 3 735 DR-3 1930-01-12 4 751 DR-3 1930-02-26 5 752 DR-3 6 837 MSK-4 1932-01-14 7 844 DR-1 1932-03-22 ident site dated 0 619 DR-1 1927-02-08 1 622 DR-1 1927-02-10 2 734 DR-3 1939-01-07 3 735 DR-3 1930-01-12 4 751 DR-3 1930-02-26 5 752 DR-3 NaN 6 837 MSK-4 1932-01-14 7 844 DR-1 1932-03-22 合并数据 import pandas as pd visited = pd.read_csv('data/survey_visited.csv') survey = pd.read_csv('data/survey_survey.csv') print(visited) print(survey) vs = visited.merge(survey, left_on='ident', right_on='taken') print(vs) 执行结果 $ python3 5-2.py ident site dated 0 619 DR-1 1927-02-08 1 622 DR-1 1927-02-10 2 734 DR-3 1939-01-07 3 735 DR-3 1930-01-12 4 751 DR-3 1930-02-26 5 752 DR-3 NaN 6 837 MSK-4 1932-01-14 7 844 DR-1 1932-03-22 taken person quant reading 0 619 dyer rad 9.82 1 619 dyer sal 0.13 2 622 dyer rad 7.80 3 622 dyer sal 0.09 4 734 pb rad 8.41 5 734 lake sal 0.05 6 734 pb temp -21.50 7 735 pb rad 7.22 8 735 NaN sal 0.06 9 735 NaN temp -26.00 10 751 pb rad 4.35 11 751 pb temp -18.50 12 751 lake sal 0.10 13 752 lake rad 2.19 14 752 lake sal 0.09 15 752 lake temp -16.00 16 752 roe sal 41.60 17 837 lake rad 1.46 18 837 lake sal 0.21 19 837 roe sal 22.50 20 844 roe rad 11.25 ident site dated taken person quant reading 0 619 DR-1 1927-02-08 619 dyer rad 9.82 1 619 DR-1 1927-02-08 619 dyer sal 0.13 2 622 DR-1 1927-02-10 622 dyer rad 7.80 3 622 DR-1 1927-02-10 622 dyer sal 0.09 4 734 DR-3 1939-01-07 734 pb rad 8.41 5 734 DR-3 1939-01-07 734 lake sal 0.05 6 734 DR-3 1939-01-07 734 pb temp -21.50 7 735 DR-3 1930-01-12 735 pb rad 7.22 8 735 DR-3 1930-01-12 735 NaN sal 0.06 9 735 DR-3 1930-01-12 735 NaN temp -26.00 10 751 DR-3 1930-02-26 751 pb rad 4.35 11 751 DR-3 1930-02-26 751 pb temp -18.50 12 751 DR-3 1930-02-26 751 lake sal 0.10 13 752 DR-3 NaN 752 lake rad 2.19 14 752 DR-3 NaN 752 lake sal 0.09 15 752 DR-3 NaN 752 lake temp -16.00 16 752 DR-3 NaN 752 roe sal 41.60 17 837 MSK-4 1932-01-14 837 lake rad 1.46 18 837 MSK-4 1932-01-14 837 lake sal 0.21 19 837 MSK-4 1932-01-14 837 roe sal 22.50 20 844 DR-1 1932-03-22 844 roe rad 11.25 用户输入 import pandas as pd from numpy import NaN, NAN, nan num_legs = pd.Series({'goat': 4, 'amoeba': nan}) print(num_legs) scientists = pd.DataFrame({'Name': ['Rosaline Franklin', 'William Gosset'], 'Occupation': ['Chemist', 'Statistician'], 'Born': ['1920-07-25', '1876-06-13'], 'Died': ['1958-04-16', '1937-10-16'], 'missing': [NaN, nan]}) print(scientists) scientists['missing'] = nan print(scientists) 执行结果 $ python3 5-3.py amoeba NaN goat 4.0 dtype: float64 Born Died Name Occupation missing 0 1920-07-25 1958-04-16 Rosaline Franklin Chemist NaN 1 1876-06-13 1937-10-16 William Gosset Statistician NaN Born Died Name Occupation missing 0 1920-07-25 1958-04-16 Rosaline Franklin Chemist NaN 1 1876-06-13 1937-10-16 William Gosset Statistician NaN 重新索引 5-4.py import pandas as pd from numpy import NaN, NAN, nan gapminder = pd.read_csv('data/gapminder.tsv', sep='\t') life_exp = gapminder.groupby(['year'])['lifeExp'].mean() print(life_exp) print(life_exp.reindex(range(2000, 2010))) 执行结果 year 1952 49.057620 1957 51.507401 1962 53.609249 1967 55.678290 1972 57.647386 1977 59.570157 1982 61.533197 1987 63.212613 1992 64.160338 1997 65.014676 2002 65.694923 2007 67.007423 Name: lifeExp, dtype: float64 year 2000 NaN 2001 NaN 2002 65.694923 2003 NaN 2004 NaN 2005 NaN 2006 NaN 2007 67.007423 2008 NaN 2009 NaN Name: lifeExp, dtype: float64 处理缺失数据 统计缺失数据 5-5.py import pandas as pd from numpy import NaN, NAN, nan import numpy as np ebola = pd.read_csv('data/country_timeseries.csv') print(ebola.head()) print(ebola.count()) num_rows = ebola.shape[0] print("num_rows") print(num_rows) num_missing = num_rows - ebola.count() print("num_missing:") print(num_missing) print(np.count_nonzero(ebola.isnull())) print(np.count_nonzero(ebola['Cases_Guinea'].isnull())) print(ebola.Cases_Guinea.value_counts(dropna=False).head()) 执行结果 Date Day Cases_Guinea Cases_Liberia Cases_SierraLeone \ 0 1/5/2015 289 2776.0 NaN 10030.0 1 1/4/2015 288 2775.0 NaN 9780.0 2 1/3/2015 287 2769.0 8166.0 9722.0 3 1/2/2015 286 NaN 8157.0 NaN 4 12/31/2014 284 2730.0 8115.0 9633.0 Cases_Nigeria Cases_Senegal Cases_UnitedStates Cases_Spain Cases_Mali \ 0 NaN NaN NaN NaN NaN 1 NaN NaN NaN NaN NaN 2 NaN NaN NaN NaN NaN 3 NaN NaN NaN NaN NaN 4 NaN NaN NaN NaN NaN Deaths_Guinea Deaths_Liberia Deaths_SierraLeone Deaths_Nigeria \ 0 1786.0 NaN 2977.0 NaN 1 1781.0 NaN 2943.0 NaN 2 1767.0 3496.0 2915.0 NaN 3 NaN 3496.0 NaN NaN 4 1739.0 3471.0 2827.0 NaN Deaths_Senegal Deaths_UnitedStates Deaths_Spain Deaths_Mali 0 NaN NaN NaN NaN 1 NaN NaN NaN NaN 2 NaN NaN NaN NaN 3 NaN NaN NaN NaN 4 NaN NaN NaN NaN Date 122 Day 122 Cases_Guinea 93 Cases_Liberia 83 Cases_SierraLeone 87 Cases_Nigeria 38 Cases_Senegal 25 Cases_UnitedStates 18 Cases_Spain 16 Cases_Mali 12 Deaths_Guinea 92 Deaths_Liberia 81 Deaths_SierraLeone 87 Deaths_Nigeria 38 Deaths_Senegal 22 Deaths_UnitedStates 18 Deaths_Spain 16 Deaths_Mali 12 dtype: int64 num_rows 122 num_missing: Date 0 Day 0 Cases_Guinea 29 Cases_Liberia 39 Cases_SierraLeone 35 Cases_Nigeria 84 Cases_Senegal 97 Cases_UnitedStates 104 Cases_Spain 106 Cases_Mali 110 Deaths_Guinea 30 Deaths_Liberia 41 Deaths_SierraLeone 35 Deaths_Nigeria 84 Deaths_Senegal 100 Deaths_UnitedStates 104 Deaths_Spain 106 Deaths_Mali 110 dtype: int64 1214 29 NaN 29 86.0 3 495.0 2 112.0 2 390.0 2 Name: Cases_Guinea, dtype: int64 处理缺失数据 5-6.py import pandas as pd from numpy import NaN, NAN, nan import numpy as np ebola = pd.read_csv('data/country_timeseries.csv') print(ebola.iloc[0:10, 0:5]) print(ebola.fillna(0).iloc[0:10, 0:5]) # 前向填充 print(ebola.fillna(method='ffill').iloc[0:10, 0:5]) # 后向填充 print(ebola.fillna(method='bfill').iloc[0:10, 0:5]) print(ebola.interpolate().iloc[0:10, 0:5]) print(ebola.shape) ebola_dropna = ebola.dropna() print(ebola_dropna.shape) print(ebola_dropna) ebola['Cases_multiple'] = ebola['Cases_Guinea'] + ebola['Cases_Liberia'] + \ ebola['Cases_SierraLeone'] ebola_subset = ebola.loc[:, ['Cases_Guinea', 'Cases_Liberia', 'Cases_SierraLeone', 'Cases_multiple']] print(ebola_subset.head(n=10)) print(ebola.Cases_Guinea.sum(skipna = True)) print(ebola.Cases_Guinea.sum(skipna = False)) 执行结果 Date Day Cases_Guinea Cases_Liberia Cases_SierraLeone 0 1/5/2015 289 2776.0 NaN 10030.0 1 1/4/2015 288 2775.0 NaN 9780.0 2 1/3/2015 287 2769.0 8166.0 9722.0 3 1/2/2015 286 NaN 8157.0 NaN 4 12/31/2014 284 2730.0 8115.0 9633.0 5 12/28/2014 281 2706.0 8018.0 9446.0 6 12/27/2014 280 2695.0 NaN 9409.0 7 12/24/2014 277 2630.0 7977.0 9203.0 8 12/21/2014 273 2597.0 NaN 9004.0 9 12/20/2014 272 2571.0 7862.0 8939.0 Date Day Cases_Guinea Cases_Liberia Cases_SierraLeone 0 1/5/2015 289 2776.0 0.0 10030.0 1 1/4/2015 288 2775.0 0.0 9780.0 2 1/3/2015 287 2769.0 8166.0 9722.0 3 1/2/2015 286 0.0 8157.0 0.0 4 12/31/2014 284 2730.0 8115.0 9633.0 5 12/28/2014 281 2706.0 8018.0 9446.0 6 12/27/2014 280 2695.0 0.0 9409.0 7 12/24/2014 277 2630.0 7977.0 9203.0 8 12/21/2014 273 2597.0 0.0 9004.0 9 12/20/2014 272 2571.0 7862.0 8939.0 Date Day Cases_Guinea Cases_Liberia Cases_SierraLeone 0 1/5/2015 289 2776.0 NaN 10030.0 1 1/4/2015 288 2775.0 NaN 9780.0 2 1/3/2015 287 2769.0 8166.0 9722.0 3 1/2/2015 286 2769.0 8157.0 9722.0 4 12/31/2014 284 2730.0 8115.0 9633.0 5 12/28/2014 281 2706.0 8018.0 9446.0 6 12/27/2014 280 2695.0 8018.0 9409.0 7 12/24/2014 277 2630.0 7977.0 9203.0 8 12/21/2014 273 2597.0 7977.0 9004.0 9 12/20/2014 272 2571.0 7862.0 8939.0 Date Day Cases_Guinea Cases_Liberia Cases_SierraLeone 0 1/5/2015 289 2776.0 8166.0 10030.0 1 1/4/2015 288 2775.0 8166.0 9780.0 2 1/3/2015 287 2769.0 8166.0 9722.0 3 1/2/2015 286 2730.0 8157.0 9633.0 4 12/31/2014 284 2730.0 8115.0 9633.0 5 12/28/2014 281 2706.0 8018.0 9446.0 6 12/27/2014 280 2695.0 7977.0 9409.0 7 12/24/2014 277 2630.0 7977.0 9203.0 8 12/21/2014 273 2597.0 7862.0 9004.0 9 12/20/2014 272 2571.0 7862.0 8939.0 Date Day Cases_Guinea Cases_Liberia Cases_SierraLeone 0 1/5/2015 289 2776.0 NaN 10030.0 1 1/4/2015 288 2775.0 NaN 9780.0 2 1/3/2015 287 2769.0 8166.0 9722.0 3 1/2/2015 286 2749.5 8157.0 9677.5 4 12/31/2014 284 2730.0 8115.0 9633.0 5 12/28/2014 281 2706.0 8018.0 9446.0 6 12/27/2014 280 2695.0 7997.5 9409.0 7 12/24/2014 277 2630.0 7977.0 9203.0 8 12/21/2014 273 2597.0 7919.5 9004.0 9 12/20/2014 272 2571.0 7862.0 8939.0 (122, 18) (1, 18) Date Day Cases_Guinea Cases_Liberia Cases_SierraLeone \ 19 11/18/2014 241 2047.0 7082.0 6190.0 Cases_Nigeria Cases_Senegal Cases_UnitedStates Cases_Spain Cases_Mali \ 19 20.0 1.0 4.0 1.0 6.0 Deaths_Guinea Deaths_Liberia Deaths_SierraLeone Deaths_Nigeria \ 19 1214.0 2963.0 1267.0 8.0 Deaths_Senegal Deaths_UnitedStates Deaths_Spain Deaths_Mali 19 0.0 1.0 0.0 6.0 Cases_Guinea Cases_Liberia Cases_SierraLeone Cases_multiple 0 2776.0 NaN 10030.0 NaN 1 2775.0 NaN 9780.0 NaN 2 2769.0 8166.0 9722.0 20657.0 3 NaN 8157.0 NaN NaN 4 2730.0 8115.0 9633.0 20478.0 5 2706.0 8018.0 9446.0 20170.0 6 2695.0 NaN 9409.0 NaN 7 2630.0 7977.0 9203.0 19810.0 8 2597.0 NaN 9004.0 NaN 9 2571.0 7862.0 8939.0 19372.0 84729.0 nan 参考资料 技术支持qq群144081101 591302926 567351477 钉钉免费群21745728 本文最新版本地址 本文涉及的python测试开发库 谢谢点赞! 本文相关海量书籍下载 源码下载 本文英文版书籍下载

优秀的个人博客,低调大师

智能运维(AIOps)时代开启,一文帮你快速了解其定义与发展现状

得益于IT外包服务的发达,现在的运维已经不包括搬机器上架、接网线、安装操作系统等基础工作,运维人员一般会从一台已安装好指定版本的操作系统、分配好IP地址和账号的服务器入手,工作范围大致包括:服务器管理(操作系统层面,比如重启、下线)、软件包管理、代码上下线、日志管理和分析、监控(区分系统、业务)和告警、流量管理(分发、转移、降级、限流等),以及一些日常的优化、故障排查等。 随着业务的发展、服务器规模的扩大,才及云化(公有云和混合云)、虚拟化的逐步落实,运维工作就扩展到了容量管理、弹性(自动化)扩缩容、安全管理,以及(引入各种容器、开源框架带来的复杂度提高而导致的)故障分析和定位等范围。 听上去每一类工作都不简单。不过,好在这些领域都有成熟的解决方案、开源软件和系统,运维工作的重点就是如何应用好这些工具来解决问题。 传统的运维工作经过不断发展(服务器规模的不断扩大),大致经历了人工、工具和自动化、平台化和智能运维(AIOps)几个阶段。这里的AIOps不是指Artificial Intelligence for IT Operations,而是指Algorithmic IT Operations(基于Gartner的定义标准)。 基于算法的IT运维,能利用数据和算法提高运维的自动化程度和效率,比如将其用于告警收敛和合并、Root分析、关联分析、容量评估、自动扩缩容等运维工作中。 在Monitoring(监控)、Service Desk(服务台)、Automation(自动化)之上,利用大数据和机器学习持续优化,用机器智能扩展人类的能力极限,这就是智能运维的实质含义。 智能运维具体的落地方式,各团队也都在摸索中,较早见效的是在异常检测、故障分析和定位(有赖于业务系统标准化的推进)等方面的应用。智能运维平台逻辑架构如图所示。 智能运维平台逻辑架构图 智能运维决不是一个跳跃发展的过程,而是一个长期演进的系统,其根基还是运维自动化、监控、数据收集、分析和处理等具体的工程。人们很容易忽略智能运维在工程上的投入,认为只要有算法就可以了,其实工程能力和算法能力在这里同样重要。 智能运维需要解决的问题有:海量数据存储、分析、处理,多维度,多数据源,信息过载,复杂业务模型下的故障定位。这些难题是否会随着智能运维的深入应用而得到一定程度的解决呢?我们会在下一篇文章中逐步展开这些问题,并提供一些解决方案。 本文选自《智能运维:从0搭建大规模分布式AIOps系统》,作者彭冬、朱伟、刘俊等,电子工业出版社2018年7月出版。 本书结合大企业的智能运维实践,全面完整地介绍智能运维的技术体系,让读者更加了解运维技术的现状和发展。同时,帮助运维工程师在一定程度上了解机器学习的常见算法模型,以及如何将它们应用到运维工作中。 图书详情:https://item.jd.com/12403162.html

优秀的个人博客,低调大师

记一种分布式超大规模数据的实时快速排序算法

引言 对数据进行处理的同学,经常会遇到排序需求,无论是内存数据还是磁盘数据。 对于单点的数据,我们的处理比较简单,比如: select field_a from table_b order by field_a limit 100, 10; db.collection_b.find().sort({"field_a":1}).skip(100).limit(10); 存储服务的处理流程一般可抽象如下: 信息爆炸的时代,数据早已不是单点所能承载的了,数据一般分布在大量节点上,假设某库中的数据均匀地分布在以下的所有节点上。 这时sort, limit的一般方法是选择一个中间节点或者中间件来做合并处理: 一般处理流程的动态表示如下: 我们将过程抽象,流程简化如下: 注意第三步在数据节点中的查询结果范围为[0,skip+limit]。当我们想查询[skip

优秀的个人博客,低调大师

Shell脚本快速部署Kubernetes(K8S v1.1版本)集群系统

提醒:即使按照本篇文章一步一步做,也不一定部署成功。原因你懂得!如果失败,也建议你仔细看看脚本内容,从中寻找解决办法。同时,相信你也会从脚本中获取到其他有价值的信息。 实验环境: 操作系统:Ubuntu14.04_x64 master:192.168.1.150 minion01: 192.168.1.151 容器网段:172.17.1.0/24 minion02: 192.168.1.152 容器网段:172.17.2.0/24 安装包下载: etcd:http://pan.baidu.com/s/1c1wITMw kubernetes:http://pan.baidu.com/s/1kUoxgYb 相关脚本下载:http://pan.baidu.com/s/1o7nEaca 脚本说明: config_ssh_root_remote.sh #配置root SSH登录(默认ubuntu系统禁止root SSH登录) ssh_keypair_auth.sh #配置master主机与minion主机SSH免交互认证 kubernetes-install.sh #安装kubernetes的master端与minion端 config_gre_channel.sh #配置两台Docker主机容器实现跨主机访问(OVS) 安装步骤(请按照步骤做): 1)在minion主机root权限开启root允许SSH远程登录 操作命令:$ sudo bash config_ssh_root_remote.sh 脚本内容:$ cat config_ssh_root_remote.sh 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 #!/bin/bash #Description:configurationrootaccountsshremotelogin if [$USER!= "root" ]; then echo "Pleaseuserootaccountoperationorsudo!" exit 1 fi function color_echo(){ if [$1== "green" ]; then echo -e "\033[32;40m$2\033[0m" elif [$1== "red" ]; then echo -e "\033[31;40m$2\033[0m" fi } function check_pkg(){ if !$(dpkg-l$PKG_NAME> /dev/null 2>&1); then echo no else echo yes fi } function install_pkg(){ local PKG_NAME=$1 if [$(check_pkg$PKG_NAME)== "no" ]; then apt-get install $PKG_NAME-y if [$(check_pkg$PKG_NAME)== "no" ]; then color_echogreen "$PKG_NAMEinstallationfailure!Trytoinstallagain." apt-getautoremove&&apt-getupdate apt-get install $PKG_NAME--force- yes -y [$(check_pkg$PKG_NAME)== "no" ]&&color_echored "The$PKG_NAMEinstallationfailure!" && exit 1 fi fi } install_pkgexpect #modifysshconfigfile sed -r-i 's/(PermitRootLogin).*/\1yes/' /etc/ssh/sshd_config service ssh restart> /dev/null #setrootaccountpassword echo "------------------------------------------------------>" while true ; do read -p "Pleaseenteryouwanttosettherootaccountpassword:" ROOT_PASS if [-n "$ROOT_PASS" ]; then break else color_echored "Passwordcannotbeempty!" continue fi done expect-c" spawn passwd root expect{ \"EnternewUNIXpassword:\"{send\"$ROOT_PASS\r\";exp_continue} \"RetypenewUNIXpassword:\"{send\"$ROOT_PASS\r\"} } expecteof "> /dev/null color_echogreen "Therootaccountpasswordis:$ROOT_PASS" 2)在master主机切换到root用户执行脚本与minion主机root用户建立SSH免交互登录 操作命令:# bashssh_keypair_auth.sh root@192.168.1.151-152@123 脚本内容:# catssh_keypair_auth.sh 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 #!/bin/bash #Description:configurationlocalhostandremotehostsshkeypairauthentication,SupportUbuntuandCentOSoperationsystem. function color_echo(){ if [$1== "green" ]; then echo -e "\033[32;40m$2\033[0m" elif [$1== "red" ]; then echo -e "\033[31;40m$2\033[0m" fi } function os_version(){ local OS_V=$( cat /etc/issue | awk 'NR==1{print$1}' ) if [$OS_V== "\S" -o$OS_V== "CentOS" ]; then echo "CentOS" elif [$OS_V== "Ubuntu" ]; then echo "Ubuntu" fi } function check_ssh_auth(){ if $( grep "Permissiondenied" $EXP_TMP_FILE> /dev/null ); then color_echored "Host$IPSSHauthenticationfailure!Loginpassworderror." exit 1 elif $( ssh $INFO 'echoyes>/dev/null' ); then color_echogreen "Host$IPSSHauthenticationsuccessfully." fi rm $EXP_TMP_FILE> /dev/null } function check_pkg(){ local PKG_NAME=$1 if [$(os_version)== "CentOS" ]; then if !$(rpm-ql$PKG_NAME> /dev/null 2>&1); then echo no else echo yes fi elif [$(os_version)== "Ubuntu" ]; then if !$(dpkg-l$PKG_NAME> /dev/null 2>&1); then echo no else echo yes fi fi } function install_pkg(){ local PKG_NAME=$1 if [$(os_version)== "CentOS" ]; then if [$(check_pkg$PKG_NAME)== "no" ]; then yum install $PKG_NAME-y if [$(check_pkg$PKG_NAME)== "no" ]; then color_echogreen "The$PKG_NAMEinstallationfailure!Trytoinstallagain." yummakecache yum install $PKG_NAME-y [$(check_pkg$PKG_NAME)== "no" ]&&color_echored "The$PKG_NAMEinstallationfailure!" && exit 1 fi fi elif [$(os_version)== "Ubuntu" ]; then if [$(check_pkg$PKG_NAME)== "no" ]; then apt-get install $PKG_NAME-y if [$(check_pkg$PKG_NAME)== "no" ]; then color_echogreen "$PKG_NAMEinstallationfailure!Trytoinstallagain." apt-getautoremove&&apt-getupdate apt-get install $PKG_NAME--force- yes -y [$(check_pkg$PKG_NAME)== "no" ]&&color_echored "The$PKG_NAMEinstallationfailure!" && exit 1 fi fi fi } function generate_keypair(){ if [!-e~/. ssh /id_rsa .pub]; then color_echogreen "Thepublic/privatersakeypairnotexist,startGenerating..." expect-c" spawn ssh -keygen expect{ \" ssh /id_rsa ):\"{send\"\r\";exp_continue} \"passphrase):\"{send\"\r\";exp_continue} \"again:\"{send\"\r\";exp_continue} } "> /dev/null 2>&1 if [-e~/. ssh /id_rsa .pub]; then color_echogreen "Generatingpublic/privatersakeypairsuccessfully." else color_echored "Generatingpublic/privatersakeypairfailure!" exit 1 fi fi } EXP_TMP_FILE= /tmp/expect_ssh .tmp if [[$1=~^[a-z]+@[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}@.*]]; then install_pkgexpect;generate_keypair for i in $@; do USER=$( echo $i| cut -d@-f1) IP=$( echo $i| cut -d@-f2) PASS=$( echo $i| cut -d@-f3) INFO=$USER@$IP expect-c" spawn ssh -copy- id $INFO expect{ \"( yes /no )?\"{send\" yes \r\";exp_continue} \"password:\"{send\"$PASS\r\";exp_continue} } ">$EXP_TMP_FILE #ifloginfailed,loginerrorinfoappendtempfile check_ssh_auth done elif [[$1=~^[a-z]+@[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}-[0-9]{1,3}@.*]]; then install_pkgexpect;generate_keypair START_IP_NUM=$( echo $1| sed -r 's/.*\.(.*)-(.*)@.*/\1/' ) END_IP_NUM=$( echo $1| sed -r 's/.*\.(.*)-(.*)@.*/\2/' ) for ((i=$START_IP_NUM;i<=$END_IP_NUM;i++)); do USER=$( echo $1| cut -d@-f1) PASS=$( echo $1| cut -d@-f3) IP_RANGE=$( echo $1| sed -r 's/.*@(.*\.).*/\1/' ) IP=$IP_RANGE$i INFO=$USER@$IP_RANGE$i expect-c" spawn ssh -copy- id $INFO expect{ \"( yes /no )?\"{send\" yes \r\";exp_continue} \"password:\"{send\"$PASS\r\";exp_continue} } ">$EXP_TMP_FILE check_ssh_auth done else echo "Example1:$0<root@192.168.1.10-15@password>" echo "Example2:$0<root@192.168.1.10@password>" echo "Example3:$0[root@192.168.1.10@passwordroot@192.168.1.11@passwordroot@192.168.1.12@password...]" fi 3)在master主机root权限执行脚本安装master端服务 操作命令:$ sudo bash kubernetes-install.sh master 脚本内容:$ cat kubernetes-install.sh 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 #!/bin/bash #Description:InstallationKubernetes1.1.3 #EtcdDownload:https://github.com/coreos/etcd/releases/download/v2.2.2/etcd-v2.2.2-linux-amd64.tar.gz #K8SDownload:https://storage.googleapis.com/kubernetes-release/release/v1.1.3/kubernetes.tar.gz . /lib/lsb/init-functions if [$( cat /etc/issue | awk '{print$1}' )!= "Ubuntu" ]; then echo "Onlysupportubuntuoperatingsystem!" exit 1 fi if [$USER!= "root" ]; then echo "Pleaseuserootaccountoperation!" exit 1 fi function color_echo(){ if [$1== "green" ]; then echo -e "\033[32;40m$2\033[0m" elif [$1== "red" ]; then echo -e "\033[31;40m$2\033[0m" fi } function check_install_pkg(){ if [!-e$ETCD_FILE-a!-e$K8S_FILE]; then color_echored "$ETCD_FILEand$K8S_FILEfilenotexist!" exit 1 elif [!-e$ETCD_FILE]; then color_echored "$ETCD_FILEfilenotexist!" exit 1 elif [!-e$K8S_FILE]; then color_echored "$K8S_FILEfilenotexist!" exit 1 fi } function local_ip(){ local NUMARRAY_LENGTH NUM=0 for NIC_NAME in $( ls /sys/class/net | grep -vE "lo|docker0" ); do NIC_IP=$( ifconfig $NIC_NAME| awk -F '[:]+' '/inetaddr/{print$4}' ) if [-n "$NIC_IP" ]; then NIC_IP_ARRAY[$NUM]= "$NIC_NAME:$NIC_IP" let NUM++ fi done ARRAY_LENGTH=${ #NIC_IP_ARRAY[*]} if [$ARRAY_LENGTH- eq 1]; then LOCAL_IP=${NIC_IP_ARRAY[0] #*:} return 0 elif [$ARRAY_LENGTH- eq 0]; then color_echored "Noavailablenetworkcard!" exit 1 else #multinetworkcardselect for NIC in ${NIC_IP_ARRAY[*]}; do echo $NIC done while true ; do read -p "Pleaseenterlocalusetonetworkcardname:" INPUT_NIC_NAME for NIC in ${NIC_IP_ARRAY[*]}; do NIC_NAME=${NIC%:*} if [$NIC_NAME== "$INPUT_NIC_NAME" ]; then LOCAL_IP=${NIC_IP_ARRAY[0] #*:} return 0 fi done echo "Notmatch!Pleaseinputagain." done fi } function check_ip(){ local IP=$1 VALID_CHECK=$( echo $IP| awk -F. '$1<=255&&$2<=255&&$3<=255&&$4<=255{print"yes"}' ) if echo $IP| grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" > /dev/null ; then if [${VALID_CHECK:-no}== "yes" ]; then return 0 else echo "IP$IPnotavailable!" return 1 fi else echo "IPformaterror!" return 1 fi } function cluster_ip(){ if [$1== "master" ]; then while true ; do read -p "PleaseentermasterIP:" MASTER_IP check_ip$MASTER_IP [$?- eq 0]&& break done elif [$1== "minion" ]; then while true ; do local MINION_NUM read -p "Pleaseenterclusterminionnodenumber:" MINION_NUM if [[$MINION_NUM=~^[0-9]+$]]; then break else color_echored "Formaterror!" fi done NUM=1 while [$NUM- le $MINION_NUM]; do local MINION_IP read -p "Pleaseenterminionhost$NUMIP:" MINION_IP check_ip$MINION_IP if [$?- eq 0]; then let NUM++ MINION_IP_ARRAY+=($MINION_IP) fi done fi } function modify_init_script(){ if [$1== "master" ]; then cd $MASTER_MODULE_INIT_SCRIPT_DIR elif [$1== "minion" ]; then cd $MINION_MODULE_INIT_SCRIPT_DIR fi for MODULE_INIT_SCRIPT in $( ls | grep - v etcd); do if [-x$MODULE_INIT_SCRIPT]; then sed -r-i '/\/sbin\/initctl/{s/(if)(.*)/\1false\&\&\2/}' $MODULE_INIT_SCRIPT fi done } function check_service_status(){ sleep 1 if [$( ps -ef| grep - v grep | grep -c "$BIN_DIR/$MODULE_INIT_SCRIPT" )- eq 1]; then log_begin_msg "Starting$MODULE_INIT_SCRIPT" log_end_msg0 #0istherightcommandexecutionstatus else log_failure_msg "$(color_echored" Starting$MODULE_INIT_SCRIPT ")" log_end_msg1 #1isthewrongcommandexecutionstatus fi } function check_exec_status(){ if [$?- ne 0]; then color_echogreen "Pleasetrytorunthescript!" exit 1 fi } BASE_DIR=$PWD ETCD_FILE=$BASE_DIR /etcd-v2 .2.2-linux-amd64. tar .gz K8S_FILE=$BASE_DIR /kubernetes . tar .gz BIN_DIR= /opt/bin INIT_SCRIPT_DIR= /etc/init .d OPTS_FILE_DIR= /etc/default MODULE_BIN_DIR=$BASE_DIR /kubernetes/server/bin MASTER_MODULE_INIT_SCRIPT_DIR=$BASE_DIR /kubernetes/cluster/ubuntu/master/init_scripts MINION_MODULE_INIT_SCRIPT_DIR=$BASE_DIR /kubernetes/cluster/ubuntu/minion/init_scripts case $1 in master) check_install_pkg pkilletcd;pkillkube cluster_ipminion #Createbinaryfiledirectory [!-d$BIN_DIR]&& mkdir $BIN_DIR #Installationstoragesystemetcd log_action_msg "Unzipthe$ETCD_FILE" tar zxf$ETCD_FILE;check_exec_status cp $BASE_DIR /etcd-v2 .2.2-linux-amd64 /etc *$BIN_DIR;check_exec_status echo " ETCD_OPTS=\"\ --listen-client-urlshttp: //0 .0.0.0:4001\ --advertise-client-urlshttp: //0 .0.0.0:4001\ --data- dir /var/lib/etcd/default .etcd\" ">$OPTS_FILE_DIR /etcd #Installationmodulekube-apiserverkube-schedulerandkube-controller-manager log_action_msg "Unzipthe$K8S_FILE" tar zxf$BASE_DIR /kubernetes . tar .gz;check_exec_status tar zxf$BASE_DIR /kubernetes/server/kubernetes-server-linux-amd64 . tar .gz;check_exec_status cd $MODULE_BIN_DIR&& cp -akubectlkube-apiserverkube-schedulerkube-controller-manager$BIN_DIR;check_exec_status #Configureinitscripts modify_init_scriptmaster cp -aetcdkube-*$INIT_SCRIPT_DIR;check_exec_status sed -i '63s/.*/"/' $INIT_SCRIPT_DIR /etcd #Removetheappendlogfile,Otherwiseetcdmaycannotbestarted #ModuleConfigureoption log_action_msg "Create$OPTS_FILE_DIR/kube-apiserverstartupoptionsfile..." echo " KUBE_APISERVER_OPTS=\"\ --insecure-bind-address=0.0.0.0\ --insecure-port=8080\ --service-cluster-ip-range=10.0.0.0 /16 \ --etcd_servers=http: //127 .0.0.1:4001\ --logtostderr= true \" ">$OPTS_FILE_DIR /kube-apiserver check_exec_status log_action_msg "Create$OPTS_FILE_DIR/kube-controller-managerstartupoptionsfile..." echo " KUBE_CONTROLLER_MANAGER_OPTS=\"\ --master=127.0.0.1:8080\ --logtostderr= true \" ">$OPTS_FILE_DIR /kube-controller-manager log_action_msg "Create$OPTS_FILE_DIR/kube-schedulerstartupoptionsfile..." echo " KUBE_SCHEDULER_OPTS=\"\ --master=127.0.0.1:8080\ --logtostderr= true \" ">$OPTS_FILE_DIR /kube-scheduler #Startingmodule for MODULE_INIT_SCRIPT in $( ls $INIT_SCRIPT_DIR| grep -E "(etcd|kube.*)" ); do service$MODULE_INIT_SCRIPTstart> /dev/null check_service_status done #setvariable echo "exportPATH=$PATH:$BIN_DIR" >> /etc/profile . /etc/profile #Copymodulekubeletandkube-proxytominion SSH_OPTS= "-oConnectTimeout=1-oConnectionAttempts=3" cd $MODULE_BIN_DIR for MINION_IP in ${MINION_IP_ARRAY[*]}; do log_action_msg "Copymoduleto$MINION_IP:$BIN_DIR..." ssh $SSH_OPTSroot@$MINION_IP "mkdir$BIN_DIR2>/dev/null" ;check_exec_status scp $SSH_OPTSkubeletkube-proxyroot@$MINION_IP:$BIN_DIR done #Copymoduleinitscriptstominion modify_init_scriptminion cd $MINION_MODULE_INIT_SCRIPT_DIR for MINION_IP in ${MINION_IP_ARRAY[*]}; do log_action_msg "Copymoduleinitscriptsto$MINION_IP:$INIT_SCRIPT_DIR..." scp $SSH_OPTSkubeletkube-proxyroot@$MINION_IP:$INIT_SCRIPT_DIR;check_exec_status done color_echogreen "Kubernetesmasterinstallationcomplete." ;; minion) cluster_ipmaster #Noticeinputmasterip local_ip pkillkube #InstallDocker if !$(dpkg-ldocker-engine> /dev/null 2>&1)&&!$(dockerinfo> /dev/null 2>&1); then log_action_msg "StarttheinstallationDocker..." apt-keyadv--keyserverhkp: //p80 .pool.sks-keyservers.net:80--recv-keys58118E89F3A912897C070ADBF76221572C52609D> /dev/null 2>&1 [$?- ne 0]&& echo "Dockersourcesecretkeyregisterfailure!" DOCKER_U_SOURCE= /tmp/docker_source .tmp echo " debhttps: //apt .dockerproject.org /repo ubuntu-precisemain debhttps: //apt .dockerproject.org /repo ubuntu-trustymain debhttps: //apt .dockerproject.org /repo ubuntu-vividmain debhttps: //apt .dockerproject.org /repo ubuntu-wilymain ">$DOCKER_U_SOURCE OS_CODE_V=$(lsb_release-cs) DOKER_SOURCE=$( grep $OS_CODE_V$DOCKER_U_SOURCE) echo "$DOKER_SOURCE" > /etc/apt/sources .list.d /docker .list rm $DOCKER_U_SOURCE apt-getupdate apt-get install docker-engine-y if $(dpkg-ldocker-engine> /dev/null )&&$(dockerinfo> /dev/null ); then color_echogreen "Dockerinstallationsuccessfully." else apt-getremove;apt-get install docker-engine--force- yes -y if !$(dpkg-ldocker-engine> /dev/null )&&!$(dockerinfo> /dev/null ); then color_echored "Dockerinstallationfailure!" exit 1 fi fi fi #ModuleConfigureoption log_action_msg "Create$OPTS_FILE_DIR/kubeletstartupoptionsfile..." echo " KUBELET_OPTS=\"\ --address=0.0.0.0\ --port=10250\ --hostname_override=$LOCAL_IP\ --api_servers=http: // $MASTER_IP:8080\ --pod-infra-container-image=docker.io /kubernetes/pause :latest\ --logtostderr= true \" ">$OPTS_FILE_DIR /kubelet log_action_msg "Create$OPTS_FILE_DIR/kube-proxystartupoptionsfile..." echo " KUBE_PROXY_OPTS=\"\ --master=http: // $MASTER_IP:8080\ --proxy-mode=iptables\ --logtostderr= true \" ">$OPTS_FILE_DIR /kube-proxy #Startingmodule for MODULE_INIT_SCRIPT in $( ls $INIT_SCRIPT_DIR| grep kube.*); do service$MODULE_INIT_SCRIPTstart> /dev/null check_service_status done color_echogreen "Kubernetesminioninstallationcomplete." ;; *) echo "Usage:$0{master|minion}" exit 1 ;; esac 4)在minion主机root权限执行脚本安装minion端服务 操作命令:$ sudo bashkubernetes-install.shminion 脚本内容:同上 5)在minion主机root权限执行脚本创建GRE通道 操作命令:$ sudo bashconfig_gre_channel.sh 脚本内容:$ cat config_gre_channel.sh 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 #!/bin/bash #Description:configurationdockerhostbetweenGREChannel if [$( cat /etc/issue | awk '{print$1}' )!= "Ubuntu" ]; then echo "Onlysupportubuntuoperatingsystem!" exit 1 fi if [$USER!= "root" ]; then echo "Pleaseuserootaccountoperation!" exit 1 fi function color_echo(){ if [$1== "green" ]; then echo -e "\033[32;40m$2\033[0m" elif [$1== "red" ]; then echo -e "\033[31;40m$2\033[0m" fi } function check_ip(){ local IP=$1 local VALID_CHECK=$( echo $IP| awk -F. '$1<=255&&$2<=255&&$3<=255&&$4<=255{print"yes"}' ) if echo $IP| grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" > /dev/null ; then if [${VALID_CHECK:-no}== "yes" ]; then return 0 else echo "IP$IPnotavailable!" return 1 fi else echo "IPformaterror!" return 1 fi } function docker_host_ip(){ color_echogreen "Notice:OnlysupporttwoDockerhostconfigurationGREChannel!" NUM=1 while [$NUM- le 2]; do local DOCKER_IP read -p "PleaseenterDockerhost$NUMIP:" DOCKER_HOST_IP check_ip$DOCKER_HOST_IP if [$?- eq 0]; then let NUM++ DOCKER_HOST_IP_ARRAY+=($DOCKER_HOST_IP) fi done } function local_nic_info(){ local NUMARRAY_LENGTH NUM=0 for NIC_NAME in $( ls /sys/class/net | grep -vE "lo|docker0" ); do NIC_IP=$( ifconfig $NIC_NAME| awk -F '[:]+' '/inetaddr/{print$4}' ) if [-n "$NIC_IP" ]; then NIC_IP_ARRAY[$NUM]= "$NIC_NAME:$NIC_IP" let NUM++ fi done ARRAY_LENGTH=${ #NIC_IP_ARRAY[*]} if [$ARRAY_LENGTH- eq 1]; then LOCAL_NIC=${NIC_IP_ARRAY[0]%:*} LOCAL_IP=${NIC_IP_ARRAY[0] #*:} return 0 elif [$ARRAY_LENGTH- eq 0]; then color_echored "Noavailablenetworkcard!" exit 1 else #multinetworkcardselect for NIC in ${NIC_IP_ARRAY[*]}; do echo $NIC done while true ; do read -p "Pleaseenterlocalusetonetworkcardname:" INPUT_NIC_NAME for NIC in ${NIC_IP_ARRAY[*]}; do NIC_NAME=${NIC%:*} if [$NIC_NAME== "$INPUT_NIC_NAME" ]; then LOCAL_NIC=${NIC_IP_ARRAY[0]%:*} LOCAL_IP=${NIC_IP_ARRAY[0] #*:} return 0 fi done echo "Notmatch!Pleaseinputagain." done fi } function check_pkg(){ if !$(dpkg-l$PKG_NAME> /dev/null 2>&1); then echo no else echo yes fi } function install_pkg(){ local PKG_NAME=$1 if [$(check_pkg$PKG_NAME)== "no" ]; then apt-get install $PKG_NAME-y if [$(check_pkg$PKG_NAME)== "no" ]; then color_echogreen "The$PKG_NAMEinstallationfailure!Trytoinstallagain." apt-getautoremove&&apt-getupdate apt-get install $PKG_NAME--force- yes -y [$(check_pkg$PKG_NAME)== "no" ]&&color_echored "The$PKG_NAMEinstallationfailure!" && exit 1 fi fi } function config_gre_channel(){ install_pkgopenvswitch-switch install_pkgbridge-utils if [${DOCKER_HOST_IP_ARRAY[0]}== "$LOCAL_IP" ]; then REMOTE_HOST_IP=${DOCKER_HOST_IP_ARRAY[1]} #remotehostip REMOTE_DOCKER_IP= "172.17.2.0/24" #remotedockerhostdefaultcontaineriprange LOCAL_DOCKER_IP= "172.17.1.0" #kbr0gateway elif [${DOCKER_HOST_IP_ARRAY[1]}== "$LOCAL_IP" ]; then REMOTE_HOST_IP=${DOCKER_HOST_IP_ARRAY[0]} REMOTE_DOCKER_IP= "172.17.1.0/24" LOCAL_DOCKER_IP= "172.17.2.0" else echo "IPnotmatch!Pleaseinputagain." exit 1 fi ovs-vsctladd-brobr02> /dev/null ovs-vsctladd-portobr0gre0-- set Interfacegre0 type =greoptions:remote_ip=$REMOTE_HOST_IP2> /dev/null brctladdbrkbr02> /dev/null brctladdifkbr0obr02> /dev/null iplink set devkbr0up if [$( grep -cE "kbr0" /etc/network/interfaces )- ne 2]; then echo " autokbr0 ifacekbr0inetstatic address$( echo $LOCAL_DOCKER_IP| sed 's/0$/1/' ) netmask255.255.255.0 gateway$LOCAL_DOCKER_IP bridge_portsobr0 ">> /etc/network/interfaces fi if $( ls /sys/class/net | grep docker0> /dev/null ); then servicedockerstop> /dev/null iplink set devdocker0down iplinkdeletedevdocker0 echo "DOCKER_OPTS=\"-b=kbr0\"" > /etc/default/docker servicedockerstart> /dev/null fi ifdownkbr0> /dev/null 2>&1;ifupkbr0> /dev/null 2>&1 #rebootinvalid #iprouteadd$REMOTE_DOCKER_IPvia$REMOTE_HOST_IPdev$LOCAL_NIC2>/dev/null #permanentvalid if !$( grep "$REMOTE_DOCKER_IPvia$REMOTE_HOST_IP" /etc/rc . local > /dev/null ); then sed -i "$i\iprouteadd$REMOTE_DOCKER_IPvia$REMOTE_HOST_IPdev$LOCAL_NIC" /etc/rc . local fi } #main docker_host_ip echo "--------------------------------------------" local_nic_info config_gre_channel color_echogreen "GREChannelconfigurationcomplete." brctlshow echo "-------------------------------------------------" ovs-vsctlshow 1、配置minion主机root SSH登录 先将config_gre_channel.sh、config_ssh_root_remote.sh和kubernetes-install.sh这三个文件上传各自的minion主机,以备后用。 说明:操作成功,root密码为123 2、配置master主机与minion主机SSH免交互认证 将kubernetes-install.sh、ssh_keypair_auth.sh和etcd-v2.2.2-linux-amd64.tar.gz、kubernetes.tar.gz安装包上传到master主机 3、安装master端 说明:先解压文件,在创建启动选项文件,再启动服务,最后将minion相关包通过scp工具拷贝过去。通过ps工具看到服务进程已经启动。 4、安装minion端 说明:Docker源秘钥注册失败,没关系,一般不会影响安装。当提示安装docker成功后才能继续,否则报错退出。通过ps 工具看到服务进程都已经启动。 5、配置GRE通道 说明:目前配置GRE通道脚本只支持两台Docker主机 6、查看集群是否配置成功 # 通过kubectl命令创建一个pod 说明:在master端可以看到两台minion端状态是Ready,并且创建的Pod已经成功运行。 注意:如果没有kubectl命令,先尝试执行source /etc/profile下看看,如果还没有,直接使用/opt/bin/kubectl 本文转自 李振良OK 51CTO博客,原文链接:http://blog.51cto.com/lizhenliang/1738807,如需转载请自行联系原作者

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册