跳到主要内容

Linux 修行之路 · Blog

Linux修行之路 - 技术博客

分享Kubernetes、Linux、Python、网络安全等技术文章

文章数量169
技术分类9
查看分类
6

CentOS 升级内核

· 阅读需 4 分钟

CentOS 升级内核

1、查看当前内核版本

$ uname -a
Linux k8s-master 3.10.0-514.el7.x86_64 #1 SMP Tue Nov 22 16:42:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
2、升级内核

更新 yum 源仓库

$ yum -y update

启用 ELRepo 仓库

ELRepo 仓库是基于社区的用于企业级 Linux 仓库,提供对 RedHat Enterprise (RHEL) 和 其他基于 RHEL的 Linux 发行版(CentOS、Scientific、Fedora 等)的支持。 ELRepo 聚焦于和硬件相关的软件包,包括文件系统驱动、显卡驱动、网络驱动、声卡驱动和摄像头驱动等。

#导入ELRepo仓库的公共密钥
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org

#安装ELRepo仓库的yum源
rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm

3、查看可用的系统内核包

$ yum --disablerepo="*" --enablerepo="elrepo-kernel" list available
# 可以看到 lt 的和 ml 两个版本的

4、安装最新版本内核

$ yum --enablerepo=elrepo-kernel install kernel-ml

--enablerepo 选项开启 CentOS 系统上的指定仓库。默认开启的是 elrepo,这里用 elrepo-kernel 替换。

5、设置 grub2

内核安装好后,需要设置为默认启动选项并重启后才会生效

查看系统上的所有可用内核:

$ sudo awk -F\' '$1=="menuentry " {print i++ " : " $2}' /etc/grub2.cfg
0 : CentOS Linux (4.18.7-1.el7.elrepo.x86_64) 7 (Core)
1 : CentOS Linux (3.10.0-862.11.6.el7.x86_64) 7 (Core)
2 : CentOS Linux (3.10.0-514.el7.x86_64) 7 (Core)
3 : CentOS Linux (0-rescue-063ec330caa04d4baae54c6902c62e54) 7 (Core)

设置新的内核为grub2的默认版本

服务器上存在4 个内核,我们要使用 4.18 这个版本,可以通过 grub2-set-default 0 命令或编辑 /etc/default/grub 文件来设置

方法1、通过 grub2-set-default 0 命令设置

# 其中 0 是上面查询出来的可用内核
grub2-set-default 0

方法2、编辑 /etc/default/grub 文件

# 设置 GRUB_DEFAULT=0,通过上面查询显示的编号为 0 的内核作为默认内核:

$ vim /etc/default/grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=0
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=cl/root rhgb quiet"
GRUB_DISABLE_RECOVERY="true"

生成 grub 配置文件并重启

$ grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-4.18.7-1.el7.elrepo.x86_64
Found initrd image: /boot/initramfs-4.18.7-1.el7.elrepo.x86_64.img
Found linux image: /boot/vmlinuz-3.10.0-862.11.6.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-862.11.6.el7.x86_64.img
Found linux image: /boot/vmlinuz-3.10.0-514.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-514.el7.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-063ec330caa04d4baae54c6902c62e54
Found initrd image: /boot/initramfs-0-rescue-063ec330caa04d4baae54c6902c62e54.img
done

$ reboot

6、验证

$ uname -a
Linux test 5.4.155-1.el7.elrepo.x86_64 #1 SMP Mon Oct 18 17:53:28 EDT 2021 x86_64 x86_64 x86_64 GNU/Linux

7、删除旧内核(可选)

查看系统中全部的内核:

$ rpm -qa | grep kernel
kernel-3.10.0-514.el7.x86_64
kernel-ml-4.18.7-1.el7.elrepo.x86_64
kernel-tools-libs-3.10.0-862.11.6.el7.x86_64
kernel-tools-3.10.0-862.11.6.el7.x86_64
kernel-3.10.0-862.11.6.el7.x86_64

方法1、yum remove 删除旧内核的 RPM 包

$ yum remove kernel-3.10.0-514.el7.x86_64 \
kernel-tools-libs-3.10.0-862.11.6.el7.x86_64 \
kernel-tools-3.10.0-862.11.6.el7.x86_64 \
kernel-3.10.0-862.11.6.el7.x86_64

方法2、yum-utils 工具

# 如果安装的内核不多于 3 个,yum-utils 工具不会删除任何一个。只有在安装的内核大于 3 个时,才会自动删除旧内核。

# 安装yum-utils
$ yum install yum-utils

# 删除旧版本
package-cleanup --oldkernels

Centos 源码编译指定版本内核

· 阅读需 1 分钟

Centos 源码编译指定版本内核

# 下载目标内核源。例如:
wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.14.49.tar.xz
tar -xf linux-4.14.49.tar.xz
cd linux-4.14.49

# 应用补丁 (https://github.com/wavezhang/k8s-ipvs-toa)
patch -p1 < ../k8s-ipvs-toa/k8s-ipvs.patch

# 踩了很多坑,需要安装很多工具
yum groupinstall "Development Tools" -y

yum install openssl patch gcc automake autoconf libtool make \
zlib-devel elfutils elfutils-libelf-devel -y

yum install epel-release -y
yum install openssl-devel bc -y
yum install ncurses-devel ntpdate -y


cp /boot/config-3.10.0-229.el7.x86_64 .config

sh -c 'yes "" | make oldconfig'

make -j30 bzImage

make -j30 modules

make -j30 modules_install

make install


# 查看插入顺序,看一下
cat /boot/grub2/grub.cfg |grep "menuentry "
awk -F\' '$1=="menuentry " {print $2}' /etc/grub2.cfg

# 修改启动顺序
grub2-set-default 'CentOS Linux (4.14.49) 7 (Core)'

# 查看启动顺序
grub2-editenv list

# 重启生效
reboot

编译指定(toa)模块

# toa 模块
wget https://github.com/Huawei/TCP_option_address/archive/master.zip

unzip master.zip
cd TCP_option_address-master/src

# 编译,加载模块
make
insmod toa.ko

# 查看模块
lsmod | grep toa

CrawlSpider 的基本用法

· 阅读需 7 分钟

CrawlSpider 的基本用法

CrawlSpider 是 Spider 的一个子类。Spider 是爬虫文件中爬虫类的父类。

一般来讲,子类的功能要比父类多,所以 CrawlSpider 的功能是比 Spider 更完善更强大的。

CrawlSpider 的作用:常被用作于专业实现全站数据爬取,也就是将一个页面下所有页码对应的数据进行爬取。

CrawlSpider 的基本使用:

  1. 创建一个工程

  2. cd 到这个工程根目录

  3. 创建一个基于 CrawlSpider 的爬虫文件

    scrapy genspider -t crawl SpiderName www.xxx.com
  4. 执行工程

注意:

  1. 一个链接提取器对应一个规则解析器(多个链接提取器和多个规则解析器)
  2. 在实现深度爬取的过程中需要和 scrapy.Request() 结合使用

需求:爬取校花网图片

网址 url:http://www.521609.com/daxuexiaohua/

示例代码:

import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule

class FirstSpider(CrawlSpider):
name = 'first'
# allowed_domains = ['www.521609.com']
start_urls = ['http://www.521609.com/daxuexiaohua/']

# 实例化LinkExtractor对象
# 链接提取器:根据指定规则(allow参数)在页面中进行连接(url)的提取
# allow='正则':提取链接的规则
# link = LinkExtractor(allow=r'list3\d+\.html')
link = LinkExtractor(allow=r'') #取出网站全站的链接
rules = (
# 实例化一个Rule对象
# 规则解析器:接收链接提取器提取到的链接,对其发起请求,然后根据指定规则(callback)解析数据
Rule(link, callback='parse_item', follow=True),
)
# follow=True:
# 将链接提取器 继续作用到 连接提取器提取到的页码 所对应的 页面中
def parse_item(self, response):
print(response)
# 基于response实现数据解析

问:如何将一个网站中全站所有的链接都进行爬取。

答:把正交规则写成空字符串 '' 即可。如果仅要爬取本站所有内容,需要设置 allowed_domains 为当前域名,避免爬取到其他网站。

使用 CrawlSpider 实现深度爬取

需求:爬取阳光热线问政平台最新问政的问政标题、状态和问政详细信息。

网址 url:http://wz.sun0769.com/political/index/politicsNewest?id=1&type=4&page=

分析:问政标题和状态均可在首页得到,但是详细信息需要爬取详情页内容。使用 crawl 确实可以获取到每一个详情页的网址,并获取详细信息,但是如果要将首页的问政标题和状态与详情页的详细信息匹配,需要下一番功夫。(事实上,我们可以在详情页拿到所有这三个信息,但是为了学习和训练,我们分别从首页和详情页抓取。)

我们可以使用问政编号,作为数据的标识。如此一来,可以将首页内容和详情页内容一一对应了。

基于上面的思路,我们可以编写出爬虫的源代码:

from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from sunPro.items import SunproItem, SunproDeatilItem


class SunSpider(CrawlSpider):
name = 'sun'
# allowed_domains = ['www.xxx.com']
start_urls = ['http://wz.sun0769.com/political/index/politicsNewest?id=1&type=4&page=']

rules = (
# 提取页码链接,解析每一个页码对应页面中的数据
Rule(LinkExtractor(allow=r'id=1&page=\d+'), callback='parse_item', follow=True),
# 提取详情页连接,解析详情页中的数据
Rule(LinkExtractor(allow=r'index\?id=\d+'), callback='parse_detail', follow=False),
)

def parse_item(self, response):
"""首页,用来提取标题和状态"""
li_list = response.xpath('//ul[@class="title-state-ul"]/li')
for li in li_list:
item = SunproItem()
qid = li.xpath('./span[1]/text()').extract_first().strip()
status = li.xpath('./span[2]/text()').extract_first().strip()
title = li.xpath('./span[3]/a/text()').extract_first().strip()
item['qid'] = qid
item['status'] = status
item['title'] = title
yield item

# 实现深度爬取:爬取详情页中的数据
# 1.对详情页的url进行捕获
# 2.对详情页的url发起请求获取数据
def parse_detail(self, response):
"""详情页,用来提取详细信息,实现深度爬取"""
qid = response.xpath('//div[@class="mr-three"]/div[1]/span[4]/text()').extract_first().replace('编号:', '').strip()
content = response.xpath('//div[@class="mr-three"]/div[2]/pre/text()').extract_first().strip()
item = SunproDeatilItem()
item['qid'] = qid
item['content'] = content
yield item

数据通过问政 id 进行标识,数据存储的时候,相同的问政 id 保存在一起就好。

别忘了在 items.py 中写好两个 Item 类,SunproItem 和 SunproDetailItem。

但是现在还有一个问题:首页和详情页解析出来的数据统统给了管道。但是这两种数据是不同的,处理方式也是有差异的。我们该如何在管道中区分这两种数据,并对其进行分别存储呢?

很简单,这两个 item 是不同类的实例化对象,我们只需要通过查询类名,即可对两种数据进行区分。item 类名的查询方式为:

item.__class__.__name__

通过判断类名,分别处理,根据 qid 进行一一对应存储,我这里就不详细写了:

class SunproPipeline(object):
def process_item(self, item, spider):
"""数据持久化存储,根据qid进行一一对应,就不详细写了"""
qid = item['qid']
if item.__class__.__name__ == 'SunproItem':
title = item['title']
status = item['status']
print(qid, title, status)
else:
content = item['content']
print(qid, content)
return item

CrawlSpider 结合 Spider 实现深度爬取

像上面那种,单独使用 CrawlSpider 确实能够实现深度爬取。但是我们发现,坑一个接着一个:首页和详情页的数据不容易一一对应,两个不同的 item 对象传入管道,携带的数据和数据处理方式也不同,需要区别对待。

链接获取和发送请求的过程的确是节省了,但是又多出了许多其他的麻烦,有些得不偿失。所以对于深度爬取的任务,我们更倾向于使用的方法是,通过 CrawlSpider 与 spider.Request 结合使用的方式,实现深度爬取。

这就很容易处理了,手动请求,加上请求参数传递即可实现:

import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from sunPro.items import SunproItem, SunproDeatilItem

class SunSpider(CrawlSpider):
name = 'sun'
# allowed_domains = ['www.xxx.com']
start_urls = ['http://wz.sun0769.com/political/index/politicsNewest?id=1&type=4&page=']

rules = (
# 提取页码链接,解析每一个页码对应页面中的数据
Rule(LinkExtractor(allow=r'id=1&page=\d+'), callback='parse_item', follow=False),
# # 提取详情页连接,解析详情页中的数据
# Rule(LinkExtractor(allow=r'index\?id=\d+'), callback='parse_detail', follow=False),
)

def parse_item(self, response):
"""首页,用来提取标题和状态"""
li_list = response.xpath('//ul[@class="title-state-ul"]/li')
for li in li_list:
item = SunproItem()
qid = li.xpath('./span[1]/text()').extract_first().strip()
status = li.xpath('./span[2]/text()').extract_first().strip()
title = li.xpath('./span[3]/a/text()').extract_first().strip()
url = 'http://wz.sun0769.com/' + li.xpath('./span[3]/a/@href').extract_first().strip()
item['qid'] = qid
item['status'] = status
item['title'] = title
yield scrapy.Request(url, callback=self.parse_detail, meta={'item': item})

def parse_detail(self, response):
item = response.meta['item']
qid = response.xpath('//div[@class="mr-three"]/div[1]/span[4]/text()').extract_first().replace('编号:', '').strip()
content = response.xpath('//div[@class="mr-three"]/div[2]/pre/text()').extract_first().strip()
item['qid'] = qid
item['content'] = content
yield item

这样,只会有一种 item 对象,里面是我们需要的所有数据。在管道中,不需要分类处理,不需要考虑首页和详情页一一对应的问题。一切都变得很简单了。