Puppet扩展篇1-自定义fact结合ENC(hirea)的应用实践
零基础学习Puppet自动化配置管理系列文档
在大量节点加入Puppet之后,你至少会面临两个比较大的问题:
1、由于节点数的增多,site.pp文件必然会编写更多的节点条目,以及节点包含的类。假设你用Puppet管理500个节点,存在三种情况:1、所有节点有共同的类,也可以理解为模块;2、所有节点分成了50组,每组节点有不同的应用,每组应用编写一个模块;3、每个节点也应该有一个自己的模块,在这种环境下,可想而知,site.pp文件是多么的复杂,多么的难以维护。
2、在使用MCO推送更新的时候,后面可以跟上fact变量用于过滤一组节点。而官方给的facter只能满足普遍存在的fact变量,可是,你要对一组节点进行归类怎么办呢,比如有10个节点的应用是Apache,15个节点属于Nginx等,那么就要自定义fact变量。现在面临的问题是,所有节点都要自定义fact变量,又如何做到集中管理呢?
一、先来解决节点与类结合的问题
其实、节点与类之间的结合,更多时候是要借助ENC(外部节点分类器)来完成,因为puppet软件本身并不具备此类功能。Puppet-dashboard企业版和Foreman已经具备了这方面的功能,而且是图形界面操作,还是很方便的。众所周知,Puppet-dashboard社区版目前最新版本为1.2.23,到目前为止已经有一年多未更新了,可见Puppetlabs的意图很明确,逼着你用企业版。而Foreman部署和使用略复杂些,其次Foreman很重,它的内部并不仅仅是包含puppet还包含了很多其它管理工具,非常庞大,可以酌情考虑使用。接下来要介绍的是官方推荐的hiera软件,一个很强大的ENC,编写的文件只要遵循yaml格式即可,使用非常方便,可惜的是没有图形界面。但这并不代表你不会开发图形界面哦。
1、在Master端安装hiera工具
hiera工具和Puppetmaster结合需要通过hiera-puppet工具完成,在puppet-server 3.0.*版本后,这个工具已经集成到了puppet-server安装包中。而我们现在使用的环境仍然是puppet2.7版本,所以需要安装hiera-puppet工具。
[root@puppetmaster RHEL6U4]# yum install hiera hiera-puppet #注意依赖关系 ... Dependencies Resolved =========================================================================== Package Arch Version Repository Size =========================================================================== Installing: hiera noarch 1.3.2-1.el6 rhel-puppet 23 k hiera-puppet noarch 1.0.0-1.el6 rhel-puppet 14 k Installing fordependencies: ruby-irb x86_64 1.8.7.352-7.el6_2 rhel-base 311 k ruby-rdoc x86_64 1.8.7.352-7.el6_2 rhel-base 375 k rubygem-json x86_64 1.5.5-1.el6 rhel-puppet 763 k rubygems noarch 1.3.7-1.el6 rhel-puppet 206 k Transaction Summary =========================================================================== ...
2、编辑hiera主配置文件hiera.yaml
2.1、创建软连接
默认hiera.yaml主配置文件在/etc目录下,为了结合后期版本控制系统集中管理,建议将此文件copy到/etc/puppet目录下,然后创建软连接指向/etc/hiera.yaml即可。
[root@puppetmaster ~]# mv /etc/hiera.yaml /etc/puppet/ [root@puppetmaster ~]# ln -s /etc/puppet/hiera.yaml /etc/hiera.yaml [root@puppetmaster ~]# ll /etc/hiera.yaml lrwxrwxrwx 1root root 22Apr 2020:05/etc/hiera.yaml -> /etc/puppet/hiera.yaml
2.2、编辑hiera.yaml
添加全局变量common,注释掉defaults、global和clientcert。
添加系统类型变量osfamily
添加主机名变量hostname
添加datadir路径位置,中间用了puppet环境变量,这里的环境变量和puppet应用的环境变量是一致的。如果你只有一种环境,只需要将其中变量去掉即可。
备注: 以上变量其实就是fact变量。
[root@puppetmaster ~]# vim /etc/puppet/hiera.yaml --- :backends: - yaml :hierarchy: # - defaults # - "%{clientcert}" - common - "%{environment}" - "%{osfamily}" - "%{hostname}" # - global :yaml: :datadir:"/etc/puppet/environments/%{environment}/hiera"
hiera主配置文件编写完成之后,需要重启puppetmaster后方可生效。
[root@puppetmaster hiera]# /etc/init.d/puppetmaster restart Stopping puppetmaster: [ OK ] Starting puppetmaster: [ OK ]
2.3、创建变量common对应的文件
[root@puppetmaster hiera]# vim common.yaml --- puppetserver: - 'puppetmaster.kisspuppet.com'
通过hiera命令测试
[root@puppetmaster ~]# hiera puppetserver environment=kissprd ["puppetmaster.kisspuppet.com"] [root@puppetmaster ~]# hiera puppetserver environment=kissdev nil
通过以上命令可以得知在环境为kissprd的情况下,puppetserver的变量为puppetmaster.kisspuppet.com,值为nil的意思是不存在。
2.4、创建变量osfamily对应的文件
[root@agent1 ~]# facter osfamily RedHat [root@puppetmaster hiera]# vim RedHat.yaml --- classes: - 'puppet' - 'yum'
通过hiera命令测试
[root@puppetmaster hiera]# hiera classes environment=kissprd nil [root@puppetmaster hiera]# hiera classes environment=kissprd osfamily=RedHat ["motd", "puppet", "yum"] [root@puppetmaster hiera]# hiera classes environment=kissprd osfamily=SLES nil
通过以上命令可以得在环境为kissprd,系统为RedHat的情况下,classes的变量为三个值(puppet、yum)。
2.5、创建变量hostname对应的所有节点文件
[root@agent1 ~]# facter hostname agent1 [root@puppetmaster hiera]# vim agent1.yaml --- classes: - 'motd' certname: - 'agent1_cert.kisspuppet.com' [root@puppetmaster hiera]# vim agent2.yaml --- classes: - 'motd' certname: - 'agent2_cert.kisspuppet.com' [root@puppetmaster hiera]# vim agent3.yaml --- certname: - 'agent3_cert.kisspuppet.com'
通过hiera命令测试
[root@puppetmaster hiera]# hiera classes environment=kissprd hostname=agent 1 ["motd"] [root@puppetmaster hiera]# hiera classes environment=kissprd hostname=agent 2 ["motd"] [root@puppetmaster hiera]# hiera classes environment=kissprd hostname=agent 3 nil [root@puppetmaster hiera]# hiera certname environment=kissprd hostname=agent1 ["agent1_cert.kisspuppet.com"] [root@puppetmaster hiera]# hiera certname environment=kissprd hostname=agent2 ["agent2_cert.kisspuppet.com"] [root@puppetmaster hiera]# hiera certname environment=kissprd hostname=agent3 ["agent3_cert.kisspuppet.com"]
通过以上命令测试可以得知,系统fact变量hostname为agent1和agent2的情况下,hiera变量classes为motd。certname变量为各自的certname变量。
3、应用hiera变量于Puppetmaster
3.1、将hiera变量应用于site.pp文件中
以前的写法:
[root@puppetmaster ~]# vim /etc/puppet/environments/kissprd/manifests/site.pp $puppetserver = 'puppetmaster.kisspuppet.com' classenvironments{ includepuppet,yum } node 'puppetmaster_cert.kisspuppet.com'{ includeenvironments } node 'agent1_cert.kisspuppet.com'{ includeenvironments,motd } node 'agent2_cert.kisspuppet.com'{ includeenvironments,motd } node 'agent3_cert.kisspuppet.com'{ includeenvironments }
应用了hiera之后的写法:
[root@puppetmaster ~]# vim /etc/puppet/environments/kissprd/manifests/site.pp $puppetserver = hiera('puppetserver') #引用了hiera中common.yaml中的全局变量puppetserver node default{ hiera_include('classes') #引用了hiera中osfamily和hostname变量 }
备注:以后添加节点,只需要编写yaml文件即可,而site.pp文件无需在进行修改。
3.2、将hiera变量应用于模块puppet中
未使用hiera之前的编写方式
[root@puppetmaster hiera]# vim /etc/puppet/environments/kissprd/environment/modules/puppet/manifests/params.pp classpuppet::params { $puppetserver = 'puppetmaster.kisspuppet.com' $certname = "${::hostname}_cert.kisspuppet.com" case$operatingsystemmajrelease{ 5: { $puppet_release = '2.7.23-1.el5' $facter_release = '1.7.3-1.el5' } 6: { $puppet_release = '2.7.23-1.el6' $facter_release = '1.7.3-1.el6' } default: { fail("Module puppet is not supported on ${::operatingsystem}") } } }
应用了hiera变量之后的编写方式
[root@puppetmaster hiera]# vim /etc/puppet/environments/kissprd/environment/modules/puppet/manifests/params.pp classpuppet::params { $puppetserver = hiera('puppetserver') #应用了hiera全局文件common.yaml中的puppetserver变量 $certname = hiera('certname') #应用了hiera中变量hostname对应的节点文件$hostname.yaml中的certname变量 case$operatingsystemmajrelease{ 5: { $puppet_release = '2.7.23-1.el5' $facter_release = '1.7.3-1.el5' } 6: { $puppet_release = '2.7.23-1.el6' $facter_release = '1.7.3-1.el6' } default: { fail("Module puppet is not supported on ${::operatingsystem}") } } }
4、测试
4.1、测试classes
4.2、测试hiera变量certname和puppetserver
[root@agent3 ~]# vim /etc/puppet/puppet.conf ### config by puppet ### [main] logdir = /var/log/puppet rundir = /var/run/puppet ssldir = $vardir/ssl pluginsync = true [agent] classfile = $vardir/classes.txt localconfig = $vardir/localconfig # server = puppetmaster.kisspuppet.com #注释掉进行测试 # certname = agent3_cert.kisspuppet.com runinterval = 10 [root@agent3 ~]# puppet agent -t --environment=kissprd --server=puppetmaster.kisspuppet.com --certname=agent3_cert.kisspuppet.com info: Retrieving plugin info: Loading facts in/var/lib/puppet/lib/facter/hwclock.rb info: Caching catalog foragent3_cert.kisspuppet.com info: Applying configuration version '1398008880' notice: /Stage[main]/Puppet::Config/File[/etc/puppet/puppet.conf]/content: --- /etc/puppet/puppet.conf 2014-04-2023:46:05.839948111+0800 +++ /tmp/puppet-file20140420-5618-45rytg-02014-04-2023:48:01.653944253+0800 @@ -7,6+7,6@@ [agent] classfile = $vardir/classes.txt localconfig = $vardir/localconfig -# server = puppetmaster.kisspuppet.com -# certname = agent3_cert.kisspuppet.com + server = puppetmaster.kisspuppet.com + certname = agent3_cert.kisspuppet.com runinterval = 10 info: FileBucket adding {md5}13430e5962e7584c9422e5adc1f3ba43 info: /Stage[main]/Puppet::Config/File[/etc/puppet/puppet.conf]: Filebucketed /etc/puppet/puppet.conf to puppet withsum 13430e5962e7584c9422e5adc1f3ba43 notice: /Stage[main]/Puppet::Config/File[/etc/puppet/puppet.conf]/content: content changed '{md5}13430e5962e7584c9422e5adc1f3ba43'to '{md5}23545b7afd09af671920f122a20db952' info: /Stage[main]/Puppet::Config/File[/etc/puppet/puppet.conf]: Scheduling refresh of Class[Puppet::Service] info: Class[Puppet::Service]: Scheduling refresh of Service[puppet] notice: /Service[puppet]: Triggered 'refresh'from 1events notice: Finished catalog run in0.54seconds [root@agent3 ~]# cat /etc/puppet/puppet.conf ### config by puppet ### [main] logdir = /var/log/puppet rundir = /var/run/puppet ssldir = $vardir/ssl pluginsync = true [agent] classfile = $vardir/classes.txt localconfig = $vardir/localconfig server = puppetmaster.kisspuppet.com certname = agent3_cert.kisspuppet.com runinterval = 10
通过以上测试可以得知hiera变量certname和puppetserver传输正常。
特别说明: 由于hiera定义的变量需要通过转换才能变为puppet能够使用的变量,而这个转换是需要耗费CPU资源的,笔者曾经测试过一组节点(50个)同时传输hiera的变量数超过2000个,出现CPU负载过高的性能瓶颈问题需要特别注意。其次hiera数据除了用yaml格式保存外还可以存放在redis数据库中,这样查询起来性能会高很多,具体可参考官网,《pro puppet 》第二版也有这方面的介绍,可参阅。
通过以上测试至少解决了两个问题:
site.pp编写繁琐复杂的问题。
certname名定义问题(可以不适用其他fact变量进行定义,比如不再使用hostname变量,这样做的好处是即使节点hostname名变化也不会影响puppet通信)
二、集中管理自定义fact变量
思路: 参考Puppet基础篇10-自定义fact实现的四种方式介绍 在puppetmaster端编写一个facts模块,传输一个变量文件至节点对应的目录里面,变量文件名可以通过主机名进行定义。
1、在现有facts模块中直接添加
之前facts模块中的结构
[root@puppetmaster modules]# tree facts/ facts/ ├── files ├── lib │ └── facter │ └── hwclock.rb #通过pluginsync模式发布的自定义fact变量,无需修改 ├── manifests └── templates 5directories, 1file
2、添加管理file资源的pp文件
[root@puppetmaster manifests]# vim config.pp #定义file资源 classfacts::config{ file{ "/etc/facter/facts.d/$hostname.txt": #文件名称通过变量hostname获取 owner => "root", group => "root", mode => 0400, source => "puppet:///modules/facts/facts.d/$hostname.txt", #文件名称通过节点变量hostname获取 require => Class['facts::exec'], } } [root@puppetmaster manifests]# vim exec.pp #定义可执行资源保证目录 /etc/facter/facts.d 存在 classfacts::exec{ exec {"create fact external": command => "mkdir -p /etc/facter/facts.d ", path => ["/usr/bin","/usr/sbin","/bin","/sbin"], creates => "/etc/facter/facts.d", } } [root@puppetmaster manifests]# vim init.pp classfacts{ includefacts::config,facts::exec }
3、创建file资源对应的下载文件
[root@puppetmaster facts.d]# pwd /etc/puppet/environments/kissprd/environment/modules/facts/files/facts.d [root@puppetmaster facts.d]# vim agent1.txt env=prd app=weblogic [root@puppetmaster facts.d]# vim agent2.txt env=qa app=db2 [root@puppetmaster facts.d]# vim agent3.txt env=prd app=nginx
4、应用模块facts至hiera中
由于模块facts属于全局的,应用于common.ymal或者RedHat.ymal中即可。
[root@puppetmaster hiera]# vim RedHat.yaml --- classes: - 'puppet' - 'yum' - 'facts'
5、节点测试
[root@agent3 ~]# ll /etc/facter/facts.d ls: cannot access /etc/facter/facts.d: No such file or directory [root@agent3 ~]# puppet agent -t --environment=kissprd info: Retrieving plugin info: Loading facts in/var/lib/puppet/lib/facter/hwclock.rb info: Caching catalog foragent3_cert.kisspuppet.com info: Applying configuration version '1398010573' notice: /Stage[main]/Facts::Exec/Exec[create fact external]/returns: executed successfully notice: /Stage[main]/Facts::Config/File[/etc/facter/facts.d/agent3.txt]/ensure: defined content as'{md5}3330b8efe95f6747de47a9eca3a5411e' notice: Finished catalog run in0.66seconds [root@agent3 ~]# cat /etc/facter/facts.d/agent3.txt env=prd app=nginx [root@agent3 ~]# facter env prd [root@agent3 ~]# facter app nginx
其它节点测试略
注意:以上方法只是提供给你一种集中管理自定义fact的思路,并不是最好的解决方案,只不过这种方法目前笔者用于上产环境中感觉还不错,特此分享。
相关文章:

C#WinForm制作异形窗体/控件
制作异形窗体或控件的思路一般都是想办法生成一个region,然后设置给指定的窗口或控件。生成region的方法有很多,最常用的就是从一幅图片生成,把该图片中的透明色部分“抠”掉,剩下的部分作为一个region。设置窗口或控件的region可…

谷歌提出纯 MLP 构成的视觉架构,无需卷积、注意力 !
来源 | 迈微AI研习社责编 | 寇雪芹头图 | 下载于视觉中国当前,卷积神经网络(CNN)和基于自注意力的网络(如近来大火的 ViT)是计算机视觉领域的主流选择,但研究人员没有停止探索视觉网络架构的脚步。近日&…

HttpApplication事件ASP.NET页面周期
学习吧少年........................... 修改中........... 当一次请求到达IIS 1、http.sys将请求发送到指定的应用程序池。 2、应用程序池再将请求交给池中的工作进程(w3wp.exe), 3、w3wp.exe根据请求URL的后缀,决定加载那个ISAP…

C#实现对象的Xml格式序列化及反序列化
要序列化的对象的类: [Serializable]public class Person{private string name;public string Name{get{return name;}set{namevalue;}}public string Sex;public int Age31;public Course[] Courses;public Person(){}public Person(string Name){nameName;Sex&qu…

outlook2010 打开总是提示“正在加载配置文件”
公司员工的电脑一打开OUTLOOK2010的时候,总是提示“正在加载配置文件”,要重新启动,还是无法打开,尝试了卸载和重装的方法也没有用.其实,只需下载一个windows search 4.0即可解决.转载于:https://blog.51cto.com/shidilun/1400227

腾讯云存储产品矩阵全面升级,发布三维生态战略
5月10日,腾讯云在北京举行存储产品战略发布会,发布了业界首款十微秒级的极速型云硬盘、业界首款突破百GB 吞吐的文件存储、以及业界首创能够10倍提升数据湖存储分析性能的对象存储三级加速器等新一代云存储产品矩阵。 同时,腾讯云还宣布将围…

围绕云计算 虚拟化技术又呈现新面貌
本文讲的是围绕云计算 虚拟化技术又呈现新面貌,【IT168 资讯】虚拟化技术的三项基本使命-即作为客户端技术,作为服务器技术和作为网络技术,如今正在围绕云计算理念相结合在一起。 起源于X86服务器的虚拟化技术已经快速扩展到存储和网络领域。…

C#字符串处理类
首先介绍一下常用的几个功能: Compare(str1,str2)——比较两个字符串 str1,str2的大小,如果大于返回正数,等于返回0,小于返回负数! IndexOf——定位字符串中第一次出现某个给定字符串的位置PadLeft和PadRight——在字…

linux严谨的telnet搭建并用防火墙开通与禁行
今天本打算练练防火墙iptables的东西,本想拿telnet的23号端口练手,没想到在敲实验的时候遇到了些曲折,经过一番努力,把本次实验过程生成文档。实验环境:rhel5.6及系统盘实验目的:通过iptables对telnet服务2…

孩子、老人与海豚,如何用 AI 伴他们走出孤独
“万里归来颜愈少。微笑。笑时犹带岭梅香。试问岭南应不好。却道。此心安处是吾乡。”苏轼的一首《定风波》道出老人心愿,道出人生百态,也道尽世间炎凉。当你走出万里,无论天涯或是海角,每个人的身上都带着自己独有的印记。这份印…

Linux之 手动释放内存
我们在进程中要怎样去描述一个文件呢?我们用目录项(dentry)和索引节点(inode)。它们的定义如下: 所谓"文件", 就是按一定的形式存储在介质上的信息,所以一个文件其实包含了两方面的信息,一是存储的数据本身,二是有关该文…

C#操作Excel导入导出
前些日子,有很多朋友说需要C#导出到Excel的代码,现共享给大家 /// <summary> /// 读取Excel文档 /// </summary> /// <param name"Path">文件名称</param> /// <returns>返回一个数据集</returns> …

中国安全态势越来越好,专访山石网科CSO蒋东毅 | 拟合
从无序中寻找踪迹,从眼前事探索未来。2021 年正值黄金十年新开端,CSDN 以中立技术社区专业、客观的角度,深度探讨中国前沿 IT 技术演进,推出年度重磅企划栏目——「拟合」,通过对话企业技术高管大咖,跟踪报…

《大数据、小数据、无数据:网络世界的数据学术》一 导读
前 言‖ 在“大数据”风靡的当代,学术研究中的“小数据”依旧不容小觑。随着绝对数据量的增加,学者们进行个体研究的能力却不断退化。因为他们从未距离研究对象如此遥远。新工具和新视角成为学术研究的必需品。但相对于“小数据”而言,“大…

UIView旋转角度
2019独角兽企业重金招聘Python工程师标准>>> 最近做一个视图的旋转、放大、拖动、拉伸,其他的都慢慢解决了,就是旋转之后各种问题不好处理,最终归结到旋转角度的不能获取,纠结了好几天,终于找到了获取旋转角…

生成静态文件的新闻系统核心代码
在网上看了许多能生成静态页的新闻系统,但基于asp.net的系统极少,闲下时间来自己写了一个,发出来,大家一起研究,代码没做什么优化,只是实现了功能 using System;using System.Collections;using System.Com…

「软件」2.0时代已经到来,你需要这样的开发工具
互联网催生了软件的繁荣,而在AI浪潮的推动下,软件正在朝着更「智能」的方向发展,也就是「软件2.0」时代。「软件2.0」其实就是神经网络,也就是这一波AI浪潮的基石。 在「软件1.0」时代,程序员用Java、Python、C等语言…

WF4 Beta,RC版文章总结
Visual Studio 2010明天就要发布正式版了,伴随Visual Studio 2010的发布微软的新一代工作流框架Workflow Foundation 4也会正式发布。从Beta版开始就断断续续的开始关注了,并写了一些文章,今天总结下: WF4 Beta1的几篇文章&#x…

亚马逊云科技在中国区域上线机器学习新服务,打造广泛而深入的人工智能与机器学习工具集
2021年5月11日,在完全托管的机器学习服务Amazon SageMaker落地中国区域一周年之际,亚马逊云科技宣布通过与光环新网和西云数据的紧密合作在中国区域进一步落地多项人工智能与机器学习的新服务和功能,丰富了其针对不同企业需求而打造的人工智能…

mysql ERROR 1045
2019独角兽企业重金招聘Python工程师标准>>> C:\Program Files\MySQL\MySQL Server 5.0\bin> mysql -u root -p Enter password: ERROR 1045 (28000): Access denied for user rootlocalhost (using password: YES) 编辑mysql配置文件my.ini(不知道在…

C#:将另一个应用程序的主窗口移至屏幕最前
2019独角兽企业重金招聘Python工程师标准>>> 使用WindowsAPI函数SwitchToThisWindow,可以将指定窗口移动到屏幕最前。 如果要将另一个应用程序的窗口移动到最前,只需要找到该窗口的句柄,再调用SwitchToThisWindow函数即可。可通过…

阿里技术文档:Redis+Nginx+Spring全家桶+Dubbo精选
最近花了很长的时间去搜罗整理Java核心技术好文,我把每个Java核心技术的优选文章都整理成了一个又一个的文档。今天就把这些东西分享给老铁们,也能为老铁们省去不少麻烦,想学什么技能了,遇到哪方面的问题了 直接打开文档学一学就好…

网页刷新方法集合
代码如下: <input typebutton value刷新 οnclick"history.go(0)"> 代码如下: <input typebutton value刷新 οnclick"location.reload()"> 代码如下: <input typebutton value刷新 οnclick"…

MOS管体二极管的作用
这里有两种解释: 1、mos管本身自带有寄生二极管,作用是防止VDD过压的情况下,烧坏mos管,因为在过压对MOS管造成破坏之前,二极管先反向击穿,将大电流直接到地,从而避免MOS管被烧坏。 2、防止管子的…

Complex Instance Placement
转自: https://specs.openstack.org/openstack/openstack-user-stories/user-stories/proposed/complex-instance-placement.html This work is licensed under a Creative Commons Attribution 3.0 Unported License.http://creativecommons.org/licenses/by/3.0/…

在SecureCRT下使用sz下载和rz上传文件
之前通过FTP来下载Linux机器上的文件,在Windows编辑完后再上传,如此比较麻烦,刚听同事说用sz和rz命令可以实现在SecureCRT中上传下载。 配置上传下载目录:选择某个session 标签,点鼠标右键,弹出菜单…

开源的 6 条社会契约
作者 | Brett Cannon 译者 | 弯月 责编 | 欧阳姝黎出品 | CSDN(ID:CSDNnews)以下为译文:本文探讨一下关于开源用户权利的问题。我想指出一点,开源维护者不欠用户什么,而粗鲁地对待他们是一种不道德的行为…

理解linux tr命令
2019独角兽企业重金招聘Python工程师标准>>> 1. tr 命令的功能 tr命名是简化了的sed命令。其主要的功能包括: a. 用一个字符来替换另外一个字符。 b. 删除字符串中的指定子串。 c. 合并字符串中重复串。 2. 常见的命令格式: tr -c -d -s [&qu…

Lambda中的常用sql方法
1、Groupby 对集合进行分组,如: var dllList _menuMan.Load(c > c.TXT_ASSEMBLYNAME ! null).GroupBy(c>c.TXT_ASSEMBLYNAME).OrderByDescending(c>c.Count()).Select(c>c.Key).ToList(); 这里Goupby后面的OrderByDescending表示对每组数量…

刚发现的 Wi-Fi 安全漏洞,可能危及全球所有设备!
作者 | Carol出品 | CSDN(ID:CSDNnews)近日,纽约大学阿布扎比分校的安全研究员 Mathy Vanhoef (马蒂范霍夫)发现了一组可能会影响到数百万设备的 Wi-Fi漏洞。可怕的是,其中部分漏洞甚至可以追溯…