- oracle免费机器配置稍微比gcp的要好
- 反正都是走cloudflare速度什么的也就不考虑了
原域名freenom无缘无故停止解析了,使用新域名aiui.cf
更新了hexo版本,新的默认模板还有些小问题需要调
畅言2018年停止服务,disqus访问麻烦,所有内容也只是我自己的记录而且更新应该不会频繁,暂时不打算加评论系统了。
还没想好用什么标题
原域名freenom无缘无故停止解析了,使用新域名aiui.cf
更新了hexo版本,新的默认模板还有些小问题需要调
畅言2018年停止服务,disqus访问麻烦,所有内容也只是我自己的记录而且更新应该不会频繁,暂时不打算加评论系统了。
待更
上次尝试将小米开源的内核Xiaomi_Kernel_OpenSource升级到最新版本,花了几天时间解决lineageos编译报错
最后总算成功编译出镜像文件了
but
twrp刷入镜像在启动界面无限循环,失败。
还需要继续看下原理及排错方式,希望明年可以用上自己的lineageos(包括内核更新,提取最新vendor,devices)
mysql慢日志太多,需要分析下具体有哪些慢日志
mysql可以直接记录所有慢日志,现在的问题是将日志文件sql进行去重
想了老半天该怎样将sql的查询字段去掉进行排序,没有get到重点。后来发现mysql自带提供了mysqldumpslow工具用于解析慢日志
下面是选项:
Option Name | Description |
---|---|
-a | Do not abstract all numbers to N and strings to ‘S’ |
-n | Abstract numbers with at least the specified digits |
–de | bug Write debugging information |
-g | Only consider statements that match the pattern |
–he | lp Display help message and exit |
-h | Host name of the server in the log file name |
-i | Name of the server instance |
-l | Do not subtract lock time from total time |
-r | Reverse the sort order |
-s | How to sort output |
-t | Display only first num queries |
–verbose | Verbose mode |
默认添加-a选项将不替换sql的查询参数,导致相同类型的sql只是查询串不一样也作为两条语句了
所以-a选项可以做参考,依然会记录很多重复sql
下面是修改后的文件,当不使用-a选项时添加一个耗时最大的sql作为例子
1 | #!/usr/bin/perl |
可以看到上面的perl脚本很简单,添加example也很简单。之前打算用python来做,是我想复杂了。直接将数字替换为N,引号里面的字符替换成S就可以了。
这个还有一个问题是where后面的条件顺序也会影响,不过这个影响不大
如下面的情况(只是作为示例),不使用-a时正常只显示第一行,现在将显示第一行和执行第2,3,4行sql时耗时最大的一条sql作为示例以便用户分析
1 | select * from mysql.user where N=N; |
转自:https://github.com/ziishaned/learn-regex
正则表达式是一组由字母和符号组成的特殊文本, 它可以用来从文本中找出满足你想要的格式的句子.
一个正则表达式是在一个主体字符串中从左到右匹配字符串时的一种样式.
“Regular expression”这个词比较拗口, 我们常使用缩写的术语”regex”或”regexp”.
正则表达式可以从一个基础字符串中根据一定的匹配模式替换文本中的字符串、验证表单、提取字符串等等.
想象你正在写一个应用, 然后你想设定一个用户命名的规则, 让用户名包含字符,数字,下划线和连字符,以及限制字符的个数,好让名字看起来没那么丑.
我们使用以下正则表达式来验证一个用户名:
以上的正则表达式可以接受 john_doe
, jo-hn_doe
, john12_as
.
但不匹配Jo
, 因为它包含了大写的字母而且太短了.
正则表达式其实就是在执行搜索时的格式, 它由一些字母和数字组合而成.
例如: 一个正则表达式 the
, 它表示一个规则: 由字母t
开始,接着是h
,再接着是e
.
“the” => The fat cat sat on the mat.
正则表达式123
匹配字符串123
. 它逐个字符的与输入的正则表达式做比较.
正则表达式是大小写敏感的, 所以The
不会匹配the
.
“The” => The fat cat sat on the mat.
正则表达式主要依赖于元字符.
元字符不代表他们本身的字面意思, 他们都有特殊的含义. 一些元字符写在方括号中的时候有一些特殊的意思. 以下是一些元字符的介绍:
元字符 | 描述 |
---|---|
. | 句号匹配任意单个字符除了换行符. |
[ ] | 字符种类. 匹配方括号内的任意字符. |
[^ ] | 否定的字符种类. 匹配除了方括号里的任意字符 |
* | 匹配>=0个重复的在*号之前的字符. |
+ | 匹配>=1个重复的+号前的字符. |
? | 标记?之前的字符为可选. |
{n,m} | 匹配num个大括号之前的字符 (n <= num <= m). |
(xyz) | 字符集, 匹配与 xyz 完全相等的字符串. |
| | 或运算符,匹配符号前或后的字符. |
\ | 转义字符,用于匹配一些保留的字符 [ ] ( ) { } . * + ? ^ $ \ | |
^ | 从开始行开始匹配. |
$ | 从末端开始匹配. |
.
.
是元字符中最简单的例子..
匹配任意单个字符, 但不匹配换行符.
例如, 表达式.ar
匹配一个任意字符后面跟着是a
和r
的字符串.
1 | ".ar" => The **car** **par**ked in the **gar**age. |
字符集也叫做字符类.
方括号用来指定一个字符集.
在方括号中使用连字符来指定字符集的范围.
在方括号中的字符集不关心顺序.
例如, 表达式[Tt]he
匹配 the
和 The
.
"[Tt]he" => The car parked in the garage.
方括号的句号就表示句号.
表达式 ar[.]
匹配 ar.
字符串
"ar[.]" => A garage is a good place to park a car.
一般来说 ^
表示一个字符串的开头, 但它用在一个方括号的开头的时候, 它表示这个字符集是否定的.
例如, 表达式[^c]ar
匹配一个后面跟着ar
的除了c
的任意字符.
"[^c]ar" => The car parked in the garage.
后面跟着元字符 +
, *
or ?
的, 用来指定匹配子模式的次数.
这些元字符在不同的情况下有着不同的意思.
*
号*
号匹配 在*
之前的字符出现大于等于0
次.
例如, 表达式 a*
匹配以0或更多个a开头的字符, 因为有0个这个条件, 其实也就匹配了所有的字符. 表达式[a-z]*
匹配一个行中所有以小写字母开头的字符串.
"[a-z]*" => The car parked in the garage #21.
*
字符和.
字符搭配可以匹配所有的字符.*
.*
和表示匹配空格的符号\s
连起来用, 如表达式\s*cat\s*
匹配0或更多个空格开头和0或更多个空格结尾的cat字符串.
"\s*cat\s*" => The fat cat sat on the concatenation.
+
号+
号匹配+
号之前的字符出现 >=1 次.
例如表达式c.+t
匹配以首字母c
开头以t
结尾,中间跟着任意个字符的字符串.
"c.+t" => The fat cat sat on the mat.
?
号在正则表达式中元字符 ?
标记在符号前面的字符为可选, 即出现 0 或 1 次.
例如, 表达式 [T]?he
匹配字符串 he
和 The
.
"[T]he" => The car is parked in the garage.
"[T]?he" => The car is parked in the garage.
{}
号在正则表达式中 {}
是一个量词, 常用来一个或一组字符可以重复出现的次数.
例如, 表达式 [0-9]{2,3}
匹配最少 2 位最多 3 位 0~9 的数字.
"[0-9]{2,3}" => The number was 9.9997 but we rounded it off to 10.0.
我们可以省略第二个参数.
例如, [0-9]{2,}
匹配至少两位 0~9 的数字.
"[0-9]{2,}" => The number was 9.9997 but we rounded it off to 10.0.
如果逗号也省略掉则表示重复固定的次数.
例如, [0-9]{3}
匹配3位数字
"[0-9]{3}" => The number was 9.9997 but we rounded it off to 10.0.
(...)
特征标群特征标群是一组写在 (...)
中的子模式. 例如之前说的 {}
是用来表示前面一个字符出现指定次数. 但如果在 {}
前加入特征标群则表示整个标群内的字符重复 N 次. 例如, 表达式 (ab)*
匹配连续出现 0 或更多个 ab
.
我们还可以在 ()
中用或字符 |
表示或. 例如, (c|g|p)ar
匹配 car
或 gar
或 par
.
"(c|g|p)ar" => The car is parked in the garage.
|
或运算符或运算符就表示或, 用作判断条件.
例如 (T|t)he|car
匹配 (T|t)he
或 car
.
"(T|t)he|car" => The car is parked in the garage.
反斜线 \
在表达式中用于转码紧跟其后的字符. 用于指定 { } [ ] / \ + * . $ ^ | ?
这些特殊字符. 如果想要匹配这些特殊字符则要在其前面加上反斜线 \
.
例如 .
是用来匹配除换行符外的所有字符的. 如果想要匹配句子中的 .
则要写成 \.
以下这个例子 \.?
是选择性匹配.
"(f|c|m)at\.?" => The fat cat sat on the mat.
在正则表达式中, 想要匹配指定开头或结尾的字符串就要使用到锚点. ^
指定开头, $
指定结尾.
^
号^
用来检查匹配的字符串是否在所匹配字符串的开头.
例如, 在 abc
中使用表达式 ^a
会得到结果 a
. 但如果使用 ^b
将匹配不到任何结果. 因为在字符串 abc
中并不是以 b
开头.
例如, ^(T|t)he
匹配以 The
或 the
开头的字符串.
"(T|t)he" => The car is parked in the garage.
"^(T|t)he" => The car is parked in the garage.
$
号同理于 ^
号, $
号用来匹配字符是否是最后一个.
例如, (at\.)$
匹配以 at.
结尾的字符串.
"(at\.)" => The fat cat. sat. on the mat.
"(at\.)$" => The fat cat. sat. on the mat.
正则表达式提供一些常用的字符集简写. 如下:
简写 | 描述 |
---|---|
. | 除换行符外的所有字符 |
\w | 匹配所有字母数字, 等同于 [a-zA-Z0-9_] |
\W | 匹配所有非字母数字, 即符号, 等同于: [^\w] |
\d | 匹配数字: [0-9] |
\D | 匹配非数字: [^\d] |
\s | 匹配所有空格字符, 等同于: [\t\n\f\r\p{Z}] |
\S | 匹配所有非空格字符: [^\s] |
\f | 匹配一个换页符 |
\n | 匹配一个换行符 |
\r | 匹配一个回车符 |
\t | 匹配一个制表符 |
\v | 匹配一个垂直制表符 |
\p | 匹配 CR/LF (等同于 \r\n ),用来匹配 DOS 行终止符 |
先行断言和后发断言都属于非捕获簇(不捕获文本 ,也不针对组合计进行计数).
先行断言用于判断所匹配的格式是否在另一个确定的格式之前, 匹配结果不包含该确定格式(仅作为约束).
例如, 我们想要获得所有跟在 $
符号后的数字, 我们可以使用正后发断言 (?<=\$)[0-9\.]*
.
这个表达式匹配 $
开头, 之后跟着 0,1,2,3,4,5,6,7,8,9,.
这些字符可以出现大于等于 0 次.
零宽度断言如下:
符号 | 描述 |
---|---|
?= | 正先行断言-存在 |
?! | 负先行断言-排除 |
?<= | 正后发断言-存在 |
?<! | 负后发断言-排除 |
?=...
正先行断言?=...
正先行断言, 表示第一部分表达式之后必须跟着 ?=...
定义的表达式.
返回结果只包含满足匹配条件的第一部分表达式.
定义一个正先行断言要使用 ()
. 在括号内部使用一个问号和等号: (?=...)
.
正先行断言的内容写在括号中的等号后面.
例如, 表达式 (T|t)he(?=\sfat)
匹配 The
和 the
, 在括号中我们又定义了正先行断言 (?=\sfat)
,即 The
和 the
后面紧跟着 (空格)fat
.
"(T|t)he(?=\sfat)" => The fat cat sat on the mat.
?!...
负先行断言负先行断言 ?!
用于筛选所有匹配结果, 筛选条件为 其后不跟随着断言中定义的格式.正先行断言
定义和 负先行断言
一样, 区别就是 =
替换成 !
也就是 (?!...)
.
表达式 (T|t)he(?!\sfat)
匹配 The
和 the
, 且其后不跟着 (空格)fat
.
"(T|t)he(?!\sfat)" => The fat cat sat on the mat.
?<= ...
正后发断言正后发断言 记作(?<=...)
用于筛选所有匹配结果, 筛选条件为 其前跟随着断言中定义的格式.
例如, 表达式 (?<=(T|t)he\s)(fat|mat)
匹配 fat
和 mat
, 且其前跟着 The
或 the
.
"(?<=(T|t)he\s)(fat|mat)" => The fat cat sat on the mat.
?<!...
负后发断言负后发断言 记作 (?<!...)
用于筛选所有匹配结果, 筛选条件为 其前不跟随着断言中定义的格式.
例如, 表达式 (?<!(T|t)he\s)(cat)
匹配 cat
, 且其前不跟着 The
或 the
.
"(?<!(T|t)he\s)(cat)" => The cat sat on cat.
标志也叫模式修正符, 因为它可以用来修改表达式的搜索结果.
这些标志可以任意的组合使用, 它也是整个正则表达式的一部分.
标志 | 描述 |
---|---|
i | 忽略大小写. |
g | 全局搜索. |
m | 多行的: 锚点元字符 ^ $ 工作范围在每行的起始. |
修饰语 i
用于忽略大小写.
例如, 表达式 /The/gi
表示在全局搜索 The
, 在后面的 i
将其条件修改为忽略大小写, 则变成搜索 the
和 The
, g
表示全局搜索.
"The" => The fat cat sat on the mat.
"/The/gi" => The fat cat sat on the mat.
修饰符 g
常用于执行一个全局搜索匹配, 即(不仅仅返回第一个匹配的, 而是返回全部).
例如, 表达式 /.(at)/g
表示搜索 任意字符(除了换行) + at
, 并返回全部结果.
"/.(at)/" => The fat cat sat on the mat.
"/.(at)/g" => The fat cat sat on the mat.
多行修饰符 m
常用于执行一个多行匹配.
像之前介绍的 (^,$)
用于检查格式是否是在待检测字符串的开头或结尾. 但我们如果想要它在每行的开头和结尾生效, 我们需要用到多行修饰符 m
.
例如, 表达式 /at(.)?$/gm
表示小写字符 a
后跟小写字符 t
, 末尾可选除换行符外任意字符. 根据 m
修饰符, 现在表达式匹配每行的结尾.
"/.at(.)?$/" => The fat cat sat on the mat.
"/.at(.)?$/gm" => The fat cat sat on the mat.
正则表达式默认采用贪婪匹配模式,在该模式下意味着会匹配尽可能长的子串。我们可以使用 ?
将贪婪匹配模式转化为惰性匹配模式。
"/(.*at)/" => The fat cat sat on the mat.
"/(.*?at)/" => The fat cat sat on the mat.
练习:
使用logstash编写匹配规则,默认的grok规则如下
1 | USERNAME [a-zA-Z0-9._-]+ |
遇到一台机器偶尔cpu使用率达到80%,触发告警。登录查看后一个sshd2程序导致cpu负载高
仔细查看就知道和sshd是两个完全不同的进程,取名sshd2应该只是为了迷惑用户
ps -ef
查看到父进程是一个/tmp/javax/config.sh, 这个文件在当前系统已经删除了,所以只能按照pid号通过lsof -p PID查看打开的文件句柄
在/proc/PID/fd里面顺利找到执行脚本
1 | #!/bin/sh |
从脚本的删除动作来看,可能是通过redis的漏洞进来的,脚本似乎还想努力不让监控发现
修复方案
时间短,修复不是我来操作的。初步并没有发现隐藏的激活方式,所以按照上面脚本的内容反向处理一下应该就可以了,注意防范redis的漏洞。
线上一个mysql主备延迟很大,master节点写入频繁,slave节点积累大量relay-log无法即使写入。
参考:https://www.cnblogs.com/conanwang/p/6006444.html
为什么会出现大量relay-log
首先这个需要从mysql的同步机制说起,同步–>半同步
Master节点的数据库实例并发跑多个线程同时提交事务,提交的事务按照逻辑的时间(数据库LSN号)顺序地写入binary log日志,slave节点通过I/O线程写到本地的relay log日志,为了保证主备数据一致性,slave节点必须按照同样的顺序执行,如果顺序不一致容易造成主备库数据不一致的风险。但是slave节点只有SQL单线程来执行relay log中的日志信息重放主库提交得事务,造成主备数据库存在延迟
处理方法
能物理处理的建议直接物理解决
a. 磁盘使用SSD
b. 磁盘组raid10
c. 从文件系统层面/内核优化层面处理IO问题
mysql的处理方法
想方法让slave多线程执行relay log
MySQL 5.6版本引入并发复制(schema级别),基于schema级别的并发复制核心思想:“不同schema下的表并发提交时的数据不会相互影响,即slave节点可以用对relay log中不同的schema各分配一个类似SQL功能的线程,来重放relay log中主库已经提交的事务,保持数据与主库一致”。
MySQL 5.6基于schema级别的并发复制能够解决当业务数据的表放在不同的database库下,但是实际生产中往往大多数或者全部的业务数据表都放在同一个schema下,在这种场景即使slave_parallel_workers>0设置也无法并发执行relay log中记录的主库提交数据。 高并发的情况下,由于slave无法并发执行同个schema下的业务数据表,依然会造成主备延迟的情况。
MySQL 5.7 引入Enhanced Muti-threaded slaves,当slave配置slave_parallel_workers>0并且global.slave_parallel_type=‘LOGICAL_CLOCK’,可支持一个schema下,slave_parallel_workers个的worker线程并发执行relay log中主库提交的事务。但是要实现以上功能,需要在master机器标记binary log中的提交的事务哪些是可以并发执行,虽然MySQL 5.6已经引入了binary log group commit,但是没有将可以并发执行的事务标记出来。
MySQL 5.7 GA版本推出的 Enhanced Multi-threaded Slaves功能,彻底解决了之前版本主备数据复制延迟的问题,开启该功能参数如下:
1 | # slave机器 |
被selinux坑了。抓包发现端口始终没有流量, 操作过程中还特地dmesg看了c并没发现selinux的异常。
https://www.nginx.com/blog/using-nginx-plus-with-selinux/
https://blog.csdn.net/aqzwss/article/details/51134591
When you upgrade a running system to Red Hat Enterprise Linux (RHEL) 6.6 or CentOS 6.6, the Security Enhanced Linux (SELinux) security permissions that apply to NGINX are relabelled to a much stricter posture. Although the permissions are adequate for the default configuration of NGINX, configuration for additional features can be blocked and you need to permit them explicitly in SELinux. This article describes the possible issues and recommended ways to resolve them.
[Editor: Oracle Linux was not supported at the time this article was originally published. Because it is based on RHEL, this article applies to it as well.]
SELinux is enabled by default on RHEL and CentOS servers. Each operating system object (process, file descriptor, file, etc.) is associated with an SELinux context that defines the permissions and operations the object can perform. During an upgrade to RHEL 6.6 or CentOS 6.6, NGINX’s association is changed to the httpd_t context:
1 | ps auZ | grep nginx |
The httpd_t context permits NGINX to listen on common web server ports, to access configuration files in /etc/nginx, and to access content in the standard docroot location (/usr/share/nginx). It does not permit many other operations, such as proxying to upstream locations or communicating with other processes through sockets.
SELinux can be run in enforcing, permissive, or disabled mode. When you make a configuration change that might breach the current permissions, you can move SELinux from enforcing to permissive mode, on your test environment (if available) or on production. In permissive mode, SELinux permits all operations, but logs operations that would have breached the security policy in enforcing mode.
To add httpd_t to the list of permissive domains, run this command:
1 | # semanage permissive -a httpd_t |
To delete httpd_t from the list of permissive domains, run:
1 | # semanage permissive -d httpd_t |
To set the mode globally to permissive, run:
1 | # setenforce 0 |
To set the mode globally to enforcing, run:
1 | # setenforce 1 |
In permissive mode, security exceptions are logged to /var/log/audit/audit.log. If you encounter a problem that occurs only when NGINX is in enforcing mode, review the exceptions that are logged inpermissive mode and update the security policy to permit them.
By default, the SELinux configuration does not allow NGINX to connect to a remote web, fastCGI, or other server, as indicated by an audit log message like the following:
1 | type=AVC msg=audit(1415714880.156:29): avc: denied { name_connect } for pid=1349 \ |
To interpret the message code (1415714880.156:29), run the audit2why command:
1 | # grep 1415714880.156:29 /var/log/audit/audit.log | audit2why |
The output from audit2why recommends setting one or more Boolean options. To permit the proxy connect operation, you can enable these Boolean options, either temporarily or permanently (add the -Poption).
If you install the setools package (yum install setools), you can run the sesearch command to get more information about the Boolean options. Here we present examples for the httpd_can_network_relay andhttpd_can_network_connect options.
The httpd_can_network_relay Boolean Option
1 | # sesearch -A -s httpd_t -b httpd_can_network_relay |
This output indicates that httpd_can_network_relay permits connection to ports of various types, including type http_port_t:
1 | # semanage port -l | grep http_port_t |
To add more ports to the set (in this case, 8082), run:
1 | # semanage port -a -t http_port_t -p tcp 8082 |
If a message indicates that a port is already defined, as in the following example, it means the port is included in another set. Do not reassign it, because other services might be negatively affected.
1 | # semanage port -a -t http_port_t -p tcp 8080 |
The httpd_can_network_connect Boolean Option
1 | # sesearch -A -s httpd_t -b httpd_can_network_connect |
The httpd_can_network_connect option allows httpd_t to connect to all TCP socket types that have theport_type attribute. To list them, run:
1 | # seinfo -aport_type -x |
By default, the SELinux configuration does not allow NGINX to access files outside of well-known authorized locations, as indicated by an audit log message like the following:
1 | type=AVC msg=audit(1415715270.766:31): avc: denied { getattr } for pid=1380 \ |
To interpret the message code (1415715270.766:31), run the audit2why command:
1 | # grep 1415715270.766:31 /var/log/audit/audit.log | audit2why |
When file access is forbidden, you have two options.
Modify the file label so that the httpd_t domain can access the file:
1 | # chcon -v --type=httpd_sys_content_t /www/t.txt |
By default, this modification is deleted when the file system is relabelled. To make the change permanent, run:
1 | # semanage fcontext -a -t httpd_sys_content_t /www/t.txt |
To modify file labels for groups of files, run:
1 | # semanage fcontext -a -t httpd_sys_content_t /www(/.*)? |
Extend the httpd_t policy to allow access to additional file locations:
1 | # grep nginx /var/log/audit/audit.log | audit2allow -m nginx > nginx.te |
To create a compiled policy, include the -M option:
1 | # grep nginx /var/log/audit/audit.log | audit2allow -M nginx |
To load the policy, run semodule -i, then verify success with semodule -l:
1 | # semodule -i nginx.pp |
This change persists across reboots.
SELinux is a complex and powerful facility for managing operating system permissions. Additional information is available at the following locations.
SELinux Documentation (United States National Security Agency)
Security-Enhanced Linux User Guide (Fedora project)
Security-Enhanced Linux User Guide (Red Hat)
SELinux project home page
SELinux How-to (CentOS)
lineageos 2 – 编译rom包
fu*k小米,手机老是1年左右出现充不进去电。前段时间我的红米note4x突然充不进去电了,只好新买了个手机(买手机先看lineageos支持列表 ^_^),心仪的pixel,和一加都感觉有点贵了,信仰尚不能支撑我购买,退而求其次选了红米note5
fu*k小米,之前买note4x的时候解锁bootloader只需要手机上登录小米账号72小时,现在解锁居然要720小时,买来手机静置30天,总算是到期了,立即刷入lineageos。
解释下静置30天,因为我搜索发现充不进去电可能是尾板坏了,在万能的某宝上买了个尾板,到货后徒手拆后盖(后盖真的很好拆),在拆下旧尾板时将连接尾板和主板的一根线弄坏了(发现是信号天线,实验除sim卡插入后无信号外其他功能均正常),立刻下单个天线,换上新的尾板,测试功能正常(想起之前换note4x也是因为note2充不进去电,可惜note2现在丢了,不然估计还可以抢救下),后面换上天线,一切正常,就不需要note5了,索性放上了30天。
lineageos 15.1即android 8.1对note5是支持的,刷入完全没有问题。因为两个手机了,坏一个也不怕了,索性就来尝试下lineageos16。现在lineageos16官方尚未对note5支持,想要体验只能下载非官方rom。不如我就自己编译个rom吧
首先
网上资料感觉真的很少(可能是我搜索关键字的问题),搜索结果大多是和我上篇说明的一样,都是按照官方说明文档来。总算在一个不起眼的地方看到一篇不错的文章(排版是真的乱啊) https://forum.xda-developers.com/android/software/guide-to-to-build-android-scratch-t3862893
按照这篇文章的意思,编译lineageos非官方的包,需要提供Device tree
,Kernel Source
,Vendor Blobs
三个部分,下面是这些以及一般的命名规则
可以按照对应的命名规则在github上搜索
幸运的是,偶然发现微博上乖奕虎适配了很多rom,并且微博主页上有github上的个人博客地址,在他的github上我需要的三个组件都有支持lineagos16,省去四处搜索了
1 | https://github.com/GuaiYiHu/android_device_xiaomi_whyred |
这里说下lineageos的一般命名,只需要将下划线替换成目录分隔符即可。
比如: android_device_xiaomi_whyred
对应的目录就是 android/device/xiaomi/whyred
下载这三个到对应目录,开始编译
报错了,报错类似这样
1 | DeviceSettings_intermediates/aapt2-flat-overlay-list \\@/home/ctaylor/android/lineage/out/target/product/pme/obj/APPS/DeviceSettings_intermediates/aapt2-flat-list )" |
搜索后在这里找到答案 https://forum.xda-developers.com/showpost.php?p=77073908&postcount=103
后来发现lineageos的依赖是写在文件里面的(https://github.com/LineageOS/hudson/blob/master/updater/device_deps.json),编译官方支持rom时会自动按照文件下载依赖,比如note5的记录如下(还得理清lineageos编译流程啊)
1 | "whyred": [ |
这样会下载device和kernel,因为按照官方编译说明,vender是需要在手机上提取或者在已有rom包提取,这样上面的三个都有了,还多了个 android_packages_resources_devicesettings
这正是上面回答需要的,下载后按照文件名对应到目录路径即可,重新编译,顺利完成
安装
安装的时候也有很多坑,在上篇里面安装也是一大坑。
刷入上面编译好的安装包后,启动到开机认证的页面就会自动重启到recovery
搜索资料,这是手机加密照成的问题 https://forum.xda-developers.com/showpost.php?p=71485684&postcount=5
TWPR里面格式化数据,重新刷入即可
这里再说下device,kernel,vender吧
以kernel来说,lineageos官方每周(现在每晚)会更新官方支持的手机的rom,可是这些rom的内核版本却很少有大的变动
手机厂商开源出来的内核版本,第三方适配的rom基本一直会保持这个大版本不动。
不像openwrt那样基本是紧跟内核主线走,android的内核与linux的内核还是有很多地方需要修改的,也就是说很多android代码并没有合并到内核主线里面
照成升级内核版本实在是有太多工作需要处理,很多代码需要合并,并且需要解决编译问题。device是设备相关,各设备正常工作必不可少;vender这个目前一般都是在厂商已有的rom里面提取
这里对做这些工作的大佬表示敬意,感谢有你们啊
fu*k小米,以后买手机似乎只有一加和pixel可选了(nokia好像也可以啊)。
lineageos 前奏 – 搭建编译环境
我目前使用的手机是红米note4x 目前lineageos15.1已经官方支持,下文是按照官网文档编译安装包操作总结
构建环境搭建主要参考官方文档
参考文档: https://wiki.lineageos.org/devices/mido/build
下面对主要步骤进行简单说明(以ubuntu为例)
1 | bc bison build-essential ccache curl flex g++-multilib gcc-multilib git gnupg gperf imagemagick lib32ncurses5-dev lib32readline-dev lib32z1-dev liblz4-tool libncurses5-dev libsdl1.2-dev libssl-dev libwxgtk3.0-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools xsltproc zip zlib1g-dev |
低于ubuntu16.04需要将libwxgtk3.0-dev
换成 libwxgtk2.8-dev
官网给出的说明
1 | LineageOS 14.1-15.1: OpenJDK 1.8 (install openjdk-8-jdk) |
ubuntu16.04默认java是jdk8, 所以直接apt-get install openjdk-default-jdk
或者 apt-get install openjdk-8-jdk
对于ubuntu14.04默认软件仓库jdk最高只有jdk7,不足以编译lineageos14.1-15.1
这里推荐android官网的解决方案https://source.android.com/setup/build/initializing#installing-the-jdk
直接下载三个对应的debian包进行安装(不必另外添加ppa源对有洁癖的人来说总是好事),这里的jdk版本比较老了,当然也可以直接从oracle官网下载安装(建议还是直接ubuntu16.04,免除不必要的麻烦)
openjdk-8-jre-headless_8u45-b14-1_amd64.deb with SHA256 0f5aba8db39088283b51e00054813063173a4d8809f70033976f83e214ab56c0
openjdk-8-jre_8u45-b14-1_amd64.deb with SHA256 9ef76c4562d39432b69baf6c18f199707c5c56a5b4566847df908b7d74e15849
openjdk-8-jdk_8u45-b14-1_amd64.deb with SHA256 6e47215cf6205aa829e6a0a64985075bd29d1f428a4006a80c9db371c2fc3c4c
这个没什么好说的,建议开个vps直接编译,这里顺便说下我开了一个6核12G内存的机器编译大概花了4个小时完成,设置了30G的ccache,硬盘最好在200G左右,我第一次设置150G造成硬盘用尽
真的想自己机器编译的或者类似情况的可以考虑使用清华大学或者中科大的源进行加速
这是帮助文档 https://mirrors.tuna.tsinghua.edu.cn/help/lineageOS/
可能像pixel这些设备不需要吧 Some devices require a vendor directory to be populated before breakfast will succeed
对于红米note4x是需要的,因为在vps上编译所以采用下载已有zip包并解包的方式,操作参考 https://wiki.lineageos.org/extracting_blobs_from_zips.html
在这里有个地方需要注意,google在lineageos15.1里面的system.transfer.dat
已经改成用brotli压缩了,执行unzip -l path/to/lineage-*.zip
你将发现对应的文件是system.transfer.dat.br
所以需要使用brotli先进行解压,解压工具下载地址 https://android.googlesource.com/platform/external/brotli/
brotli官网提供了好几种安装方式,这里采用Autotools-style CMake
的方式(cmake不在上面的必须软件列表里面,这里需要单独安装),当然也可以尝试直接用python的pip安装
1 | $ mkdir out && cd out |
安装完brotli解压工具后,使用 brotli -d system.new.dat.br -o system.new.dat
进行解压即可
另外对于上面的内容还有个问题需要说明
这步操作的时候sudo mount system.img system/
可以先检测system.img是不是有问题 file system.img
看返回是否正常,如果只是简单的data文件,那么上一步的解压可能存在问题
挂载好system.img后还有个问题,挂载目录下面的vendor是个链接文件,指向 /vendor, 看lineageos官网的介绍好像主要是复制vendor里面的内容,而system.img里面并没有这个文件,查看zip包内容unzip -l path/to/lineage-*.zip
会发现有个 vendor.new.dat.dr
文件,猜测这个就是我们需要的文件,按照上面操作 system.new.dat.dr 文件的步骤再次执行,并挂载到 /vendor 目录即可,后面运行正常无报错
后面就没有什么问题了,等了4个小时,提取 out/target/product
里面的生成文件就可以了
还有个小问题,手机刷入安装包的时候在twrp里面一直找不到zip包,无法挂载手机data分区
最后无奈,将data分区重新格式化,利用adb将zip安装包上传上去,重新刷入
这里有经验的小伙伴可能看出问题了, 是的我格式化了data分区,手机所有数据已丢失 (手动滑稽)
如果你哪天发现我电话打不通,即时聊天软件长时间无回应,那么我可能正在努力修手机中
这里基本都是遵循官网给出的文档进行操作,没有做任何个人修改。后期有时间我将进一步整理lineageos的内容
未完。。。待续。。等。
源码:
1 | """An FTP client class and some helper functions. |
ftp客户端, ftp命令比较多每个都可能调用,是学习ftp命令的好方法