{"users":[{"id":"8304922","platform device id":"wx"}]}

可选配置项
mutate 插件可以在字段上执行变换,包括重命名、删除、替换和修改。这个插件相当常用。
你已经根据 Grok 表达式将 Tomcat 日志的内容放到各个字段中,想把状态码、字节大小或是响应时间,转换成整型;
你已经根据正则表达式将日志内容放到各个字段中,但是字段的值,大小写都有,这对于 Elasticsearch 的全文检索来说,显然用处不大,那么可以用该插件,将字段内容全部转换成小写。
该插件必须是用 mutate 包裹,如下所示:
可用的配置选项如下表所示:
periodic_flush
remove_field
remove_tag
其中,add_field、remove_field、add_tag、remove_tag 是所有 Logstash 插件都有。它们在插件过滤成功后生效。虽然 Logstash 叫过滤,但不仅仅过滤功能。
tag 作用是,当你对字段处理期间,还期望进行后续处理,就先作个标记。Logstash 有个内置 tags 数组,包含了期间产生的 tag,无论是 Logstash 自己产生的,还是你添加的,比如,你用 grok 解析日志,但是错了,那么 Logstash 自己就会自己添加一个 _grokparsefailure 的 tag。这样,你在 output 时,可以对解析失败的日志不做任何处理;
而 field 作用是,对字段的操作,比如,你想利用已有的字段,创建新的字段。这些在后面再说。
另外,你会发现,上表中所有选项,要么是动词,要么是动宾短语。估计你也猜到了,选项其实就是 ruby 函数,而它们后面,即“=&”,跟着的肯定是一堆参数(要是你写程序,你也会这么干)。第一个参数,肯定是字段,也就是你期望该函数作用在哪个字段上,从第二个字段开始往后,是具体参数~
什么是字段?比如,你想解析 Tomcat 日志,把一行访问日志拆分后,得到客户端IP、字节大小、响应时间等放到指定变量,那么这个变量就是字段。
下面具体介绍各个选项。
假设有 Tomcat access 日志:
192.168.6.25 - - [24/Apr/:53 +0800] GET &/goLogin& && 2 23 &http://10.1.8.193:8080/goMain& &Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0&
192.168.6.25 - - [24/Apr/:53 +0800] GET &/js/common/jquery-1.10.2.min.js& &&
- 67 &http://10.1.8.193:8080/goLogin& &Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0&
192.168.6.25 - - [24/Apr/:53 +0800] GET &/css/common/login.css& &&
- 75 &http://10.1.8.193:8080/goLogin& &Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0&
192.168.6.25 - - [24/Apr/:53 +0800] GET &/js/system/login.js& &&
- 53 &http://10.1.8.193:8080/goLogin& &Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0&
它是按如下 Tomcat 配置产生的:
&Valve className=&org.apache.catalina.valves.AccessLogValve& directory=&logs&
prefix=&localhost_access_log.& suffix=&.txt&
pattern=&%h %l %u %t %m &%U& &%q& %p %s %b %D &%{Referer}i& &%{User-Agent}i&& /&
若用如下 Grok 表达式解析该日志:
%{IPORHOST:clientip} %{NOTSPACE:identd} %{NOTSPACE:auth} \[%{HTTPDATE:timestamp}\] %{WORD:http_method} %{NOTSPACE:request} %{NOTSPACE:request_query|-} %{NUMBER:port} %{NUMBER:statusCode} (%{NOTSPACE:bytes}|-) %{NUMBER:reqTime} %{QS:referer} %{QS:userAgent}
会得到如下结果:
&message& =& &192.168.6.25 - - [24/Apr/:53 +0800] GET \&/goLogin\& \&\& 2 23 \&http://10.1.8.193:8080/goMain\& \&Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0\&&,
&@version& =& &1&,
&@timestamp& =& &T08:26:07.794Z&,
&host& =& &vcyber&,
&clientip& =& &192.168.6.25&,
&identd& =& &-&,
&auth& =& &-&,
&timestamp& =& &24/Apr/:53 +0800&,
&http_method& =& &GET&,
&request& =& &\&/goLogin\&&,
&request_query& =& &\&\&&,
&port& =& &8080&,
&statusCode& =& &200&,
&bytes& =& &1692&,
&reqTime& =& &23&,
&referer& =& &\&http://10.1.8.193:8080/goMain\&&,
&userAgent& =& &\&Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0\&&
注意,日志拆分到各个字段后的数据类型。port、statusCode、bytes、reqTime 字段肯定是(最好是)数字,不过这里暂时先用字符串。后面会介绍,下面的示例都在此基础上。
可配置选项
值是散列,就是键值对,比如 add_field =& {&field1&=&&value1&,&field2&=&&value2&}。
默认值是空对象,即 {}
添加新的字段。
match=&[&message&,&%{IPORHOST:clientip} %{NOTSPACE:identd} %{NOTSPACE:auth} \[%{HTTPDATE:timestamp}\] %{WORD:http_method} %{NOTSPACE:request} %{NOTSPACE:request_query|-} %{NUMBER:port} %{NUMBER:statusCode} (%{NOTSPACE:bytes}|-) %{NUMBER:reqTime} %{QS:referer} %{QS:userAgent}&]
add_field=&{
&SayHi&=&&Hello , %{clientip}&
codec=&rubydebug
注意黑体部分,如果用这个配置,解析前面的 Tcomat access 日志,会得到如下结果:
&message& =& &192.168.6.25 - - [24/Apr/:53 +0800] GET \&/goLogin\& \&\& 2 23 \&http://10.1.8.193:8080/goMain\& \&Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0\&&,
&@version& =& &1&,
&@timestamp& =& &T04:52:02.031Z&,
&host& =& &vcyber&,
&clientip& =& &192.168.6.25&,
&identd& =& &-&,
&auth& =& &-&,
&timestamp& =& &24/Apr/:53 +0800&,
&http_method& =& &GET&,
&request& =& &\&/goLogin\&&,
&request_query& =& &\&\&&,
&port& =& &8080&,
&statusCode& =& &200&,
&bytes& =& &1692&,
&reqTime& =& &23&,
&referer& =& &\&http://10.1.8.193:8080/goMain\&&,
&userAgent& =& &\&Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0\&&,
&SayHi& =& &Hello , 192.168.6.25&
你会看到多了一个 SayHi 字段。这个字段是写死的,当然也可以动态。如果将
&SayHi&=&&Hello , %{clientip}&
&another_%{clientip}&=&&Hello , %{clientip}&
你会看到如下结果:
&message& =& &192.168.6.25 - - [24/Apr/:53 +0800] GET \&/goLogin\& \&\& 2 23 \&http://10.1.8.193:8080/goMain\& \&Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0\&&,
&@version& =& &1&,
&@timestamp& =& &T06:38:04.427Z&,
&host& =& &vcyber&,
&clientip& =& &192.168.6.25&,
&identd& =& &-&,
&auth& =& &-&,
&timestamp& =& &24/Apr/:53 +0800&,
&http_method& =& &GET&,
&request& =& &\&/goLogin\&&,
&request_query& =& &\&\&&,
&port& =& &8080&,
&statusCode& =& &200&,
&bytes& =& &1692&,
&reqTime& =& &23&,
&referer& =& &\&http://10.1.8.193:8080/goMain\&&,
&userAgent& =& &\&Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0\&&,
&another_192.168.6.25& =& &Hello , 192.168.6.25&
虽然这个例子不太合理,但你现在知道,用已有字段的值,可以生成新的字段和它的值。
上面示例只添加了一个字段,你也可以添加多个字段:
add_field=&{
&another_%{clientip}&=&&Hello , %{clientip}&
&another_%{http_method}&=&&Hello, %{http_method}&
默认值为空数组,即 []
添加新的标签。
add_tag=&[
&foo_%{clientip}&
你会看到如下结果:
&message& =& &192.168.6.25 - - [24/Apr/:53 +0800] GET \&/goLogin\& \&\& 2 23 \&http://10.1.8.193:8080/goMain\& \&Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0\&&,
&@version& =& &1&,
&@timestamp& =& &T06:48:43.278Z&,
&host& =& &vcyber&,
&clientip& =& &192.168.6.25&,
&identd& =& &-&,
&auth& =& &-&,
&timestamp& =& &24/Apr/:53 +0800&,
&http_method& =& &GET&,
&request& =& &\&/goLogin\&&,
&request_query& =& &\&\&&,
&port& =& &8080&,
&statusCode& =& &200&,
&bytes& =& &1692&,
&reqTime& =& &23&,
&referer& =& &\&http://10.1.8.193:8080/goMain\&&,
&userAgent& =& &\&Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0\&&,
&tags& =& [
[0] &foo_192.168.6.25&
与 add_field 类似,也可以一次添加多个 tags。
注意,add_tag 是数组 [],不是 {}。
数据类型转换。
如果要转换成 boolean,那么可接受的数据是:
true, t, yes, y, 和 1
false, f, no, n, 和 0
另外,还可转换成 integer, float, string。
#convert=&[&reqTime&,&integer&,&statusCode&,&integer&,&bytes&,&integer&]
convert=&{&port&=&&integer&}
convert 有两种写法。一种是用数组,两个为一组;另一种是散列。得到如下结果:
&message& =& &192.168.6.25 - - [24/Apr/:53 +0800] GET \&/goLogin\& \&\& 2 23 \&http://10.1.8.193:8080/goMain\& \&Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0\&&,
&@version& =& &1&,
&@timestamp& =& &T09:06:25.360Z&,
&host& =& &vcyber&,
&clientip& =& &192.168.6.25&,
&identd& =& &-&,
&auth& =& &-&,
&timestamp& =& &24/Apr/:53 +0800&,
&http_method& =& &GET&,
&request& =& &\&/goLogin\&&,
&request_query& =& &\&\&&,
&port& =& 8080,
&statusCode& =& &200&,
&bytes& =& &1692&,
&reqTime& =& &23&,
&referer& =& &\&http://10.1.8.193:8080/goMain\&&,
&userAgent& =& &\&Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0\&&
port 字段,已经没有双引号啦。
mutate 插件选项的值类型设计得很简单,要么是散列(键值对),要么数组……比如,convert=&[&reqTime&,&integer&,&statusCode&,&integer&],两个为一组,第一个表示字段,第二个为想转换的数据类型,并没有采用嵌套或是复合类型。看来作者的意图是——简单,复杂的数据类型,虽然看起来容易,但要付出成本的。简单没关系,约定好就行。Logstash 很多插件和其选项都这样。
字符串替换。用正则表达式和字符串都行。它只能用于字符串,如果不是字符串,那么什么都不会做,也不会报错。
该配置的值是数组,三个为一组,分别表示:字段名称,待匹配的字符串(或正则表达式),待替换的字符串。
示例:在解析 Tomcat 日志,会遇到一种情况,资源的字节大小,可能会是“-”,因此,需要将“-”,替换成0,然后在用convert转换成数字型。
match=&[&message&,&%{IPORHOST:clientip} %{NOTSPACE:identd} %{NOTSPACE:auth} \[%{HTTPDATE:timestamp}\] %{WORD:http_method} %{NOTSPACE:request} %{NOTSPACE:request_query|-} %{NUMBER:port} %{NUMBER:statusCode} (%{NOTSPACE:bytes}|-) %{NUMBER:reqTime} %{QS:referer} %{QS:userAgent}&]
gsub=&[&bytes&,&_&,&0&]
convert=&[&port&,&integer&,&reqTime&,&integer&,&statusCode&,&integer&,&bytes&,&integer&]
codec=&rubydebug
得到如下结果:
&message& =& &192.168.6.25 - - [24/Apr/:53 +0800] GET \&/js/common/jquery-1.10.2.min.js\& \&\&
- 67 \&http://10.1.8.193:8080/goLogin\& \&Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0\&&,
&@version& =& &1&,
&@timestamp& =& &T09:17:21.745Z&,
&host& =& &vcyber&,
&clientip& =& &192.168.6.25&,
&identd& =& &-&,
&auth& =& &-&,
&timestamp& =& &24/Apr/:53 +0800&,
&http_method& =& &GET&,
&request& =& &\&/js/common/jquery-1.10.2.min.js\&&,
&request_query& =& &\&\&&,
&port& =& 8080,
&statusCode& =& 304,
&bytes& =& 0,
&reqTime& =& 67,
&referer& =& &\&http://10.1.8.193:8080/goLogin\&&,
&userAgent& =& &\&Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0\&&
用分隔符连接数组. 如果字段不是数组,那什么都不做。
join =&{&fieldname&=&&,&}}}
lowercase 和 uppercase
没有默认值
把字符串转换成小写或大写。
lowercase =&[&fieldname&]}}
uppercase =&[&fieldname&]}}
合并两个数组或散列字段。存在三种情况,合并后是数组:
数组和字符串,可以合并
字符串和字符串,可以合并
数组和散列不能合并
add_field=&{&arr_clientip&=&&%{clientip}&}
add_field=&{&arrmstr_clientip&=&&%{clientip}&}
add_field=&{&arrmarr_clientip&=&&%{clientip}&}
#merge=&{&merge_clientip&=&&clientip&}
split=&{&arr_clientip&=&&.&}
split=&{&arrmstr_clientip&=&&.&}
split=&{&arrmarr_clientip&=&&.&}
merge=&{&arrmstr_clientip&=&&clientip&}
merge=&{&arrmarr_clientip&=&&arr_clientip&}
=& 后面的字段值会合并到前面的字段。
得到如下结果:
&message& =& &192.168.6.25 - - [24/Apr/:53 +0800] GET \&/goLogin\& \&\& 2 23 \&http://10.1.8.193:8080/goMain\& \&Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0\&&,
&@version& =& &1&,
&@timestamp& =& &T02:53:35.671Z&,
&host& =& &vcyber&,
&clientip& =& &192.168.6.25&,
&identd& =& &-&,
&auth& =& &-&,
&timestamp& =& &24/Apr/:53 +0800&,
&http_method& =& &GET&,
&request& =& &\&/goLogin\&&,
&request_query& =& &\&\&&,
&port& =& &8080&,
&statusCode& =& &200&,
&bytes& =& &1692&,
&reqTime& =& &23&,
&referer& =& &\&http://10.1.8.193:8080/goMain\&&,
&userAgent& =& &\&Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0\&&,
&arr_clientip& =& [
[0] &192&,
[1] &168&,
&arrmstr_clientip& =& [
[0] &192&,
[1] &168&,
[4] &192.168.6.25&
&arrmarr_clientip& =& [
[0] &192&,
[1] &168&,
[4] &192&,
[5] &168&,
periodic_flush
默认值是 false
按时间间隔调用。可选。
remove_field
默认值是数组 []
移除字段。
示例:移除 message 字段。
remove_field=&[&message&]
得到如下结果:
&@version& =& &1&,
&@timestamp& =& &T02:04:16.879Z&,
&host& =& &vcyber&,
&clientip& =& &192.168.6.25&,
&identd& =& &-&,
&auth& =& &-&,
&timestamp& =& &24/Apr/:53 +0800&,
&http_method& =& &GET&,
&request& =& &\&/goLogin\&&,
&request_query& =& &\&\&&,
&port& =& &8080&,
&statusCode& =& &200&,
&bytes& =& &1692&,
&reqTime& =& &23&,
&referer& =& &\&http://10.1.8.193:8080/goMain\&&,
&userAgent& =& &\&Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0\&&
message 字段已经没有了~message 字段保存了原始日志,如果保留的话,就意味着日志存了两份:分割前和分割后。
当然,也可以一次移除多个字段。
remove_tag
默认值是 []
移除标识。
remove_tag =&[&foo_%{somefield}&]}}
也可以一次移动多个 tag:
remove_tag =&[&foo_%{somefield}&,&sad_unwanted_tag&]}}
重命名一个或多个字段。
match=&[&message&,&%{IPORHOST:clientip} %{NOTSPACE:identd} %{NOTSPACE:auth} \[%{HTTPDATE:timestamp}\] %{WORD:http_method} %{NOTSPACE:request} %{NOTSPACE:request_query|-} %{NUMBER:port} %{NUMBER:statusCode} (%{NOTSPACE:bytes}|-) %{NUMBER:reqTime} %{QS:referer} %{QS:userAgent}&]
rename=&{&clientip&=&&host&}
codec=&rubydebug
得到如下结果:
&message& =& &192.168.6.25 - - [24/Apr/:53 +0800] GET \&/goLogin\& \&\& 2 23 \&http://10.1.8.193:8080/goMain\& \&Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0\&&,
&@version& =& &1&,
&@timestamp& =& &T09:29:44.018Z&,
&host& =& &192.168.6.25&,
&identd& =& &-&,
&auth& =& &-&,
&timestamp& =& &24/Apr/:53 +0800&,
&http_method& =& &GET&,
&request& =& &\&/goLogin\&&,
&request_query& =& &\&\&&,
&port& =& &8080&,
&statusCode& =& &200&,
&bytes& =& &1692&,
&reqTime& =& &23&,
&referer& =& &\&http://10.1.8.193:8080/goMain\&&,
&userAgent& =& &\&Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0\&&
Grok 里,客户端IP本来叫 clientip,但是可以在 mutate 里重新命名为 host。
用一个新的值替换掉指定字段的值。
match=&[&message&,&%{IPORHOST:clientip} %{NOTSPACE:identd} %{NOTSPACE:auth} \[%{HTTPDATE:timestamp}\] %{WORD:http_method} %{NOTSPACE:request} %{NOTSPACE:request_query|-} %{NUMBER:port} %{NUMBER:statusCode} (%{NOTSPACE:bytes}|-) %{NUMBER:reqTime} %{QS:referer} %{QS:userAgent}&]
replace=&{&message&=&&%{clientip}: My new Message.&}
codec=&rubydebug
得到如下结果:
&message& =& &192.168.6.25: My new Message.&,
&@version& =& &1&,
&@timestamp& =& &T01:55:34.566Z&,
&host& =& &vcyber&,
&clientip& =& &192.168.6.25&,
&identd& =& &-&,
&auth& =& &-&,
&timestamp& =& &24/Apr/:53 +0800&,
&http_method& =& &GET&,
&request& =& &\&/goLogin\&&,
&request_query& =& &\&\&&,
&port& =& &8080&,
&statusCode& =& &200&,
&bytes& =& &1692&,
&reqTime& =& &23&,
&referer& =& &\&http://10.1.8.193:8080/goMain\&&,
&userAgent& =& &\&Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0\&&
message 字段的值已经变了。
用分隔符或字符分割一个字符串。只能应用在字符串上。
示例:把客户端IP按英文句号分割成数组。
split=&{&clientip&=&&.&}
得到如下结果:
&message& =& &192.168.6.25 - - [24/Apr/:53 +0800] GET \&/goLogin\& \&\& 2 23 \&http://10.1.8.193:8080/goMain\& \&Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0\&&,
&@version& =& &1&,
&@timestamp& =& &T01:58:40.687Z&,
&host& =& &vcyber&,
&clientip& =& [
[0] &192&,
[1] &168&,
&identd& =& &-&,
&auth& =& &-&,
&timestamp& =& &24/Apr/:53 +0800&,
&http_method& =& &GET&,
&request& =& &\&/goLogin\&&,
&request_query& =& &\&\&&,
&port& =& &8080&,
&statusCode& =& &200&,
&bytes& =& &1692&,
&reqTime& =& &23&,
&referer& =& &\&http://10.1.8.193:8080/goMain\&&,
&userAgent& =& &\&Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/ Firefox/46.0\&&
去掉字段首尾的空格。
strip =&[&field1&,&field2&]}}
Update an existing field with a new value. If the field does not exist, then no action will be taken.
update =&{&sample&=&&My new message&}}}
阅读(...) 评论()深入安卓Package Manager和Package Installer - 文章 - 伯乐在线
& 深入安卓Package Manager和Package Installer
我们每天都在安装和卸载APK(安卓应用程序包文件),或许一天会有好几次,但是你有想过下面问题吗?
什么是Package Manager(包管理器)和Package Installer(程序安装包)?
APK文件保存在Android的哪个地方?
APK文件安装过程的细节是怎样的?
Package Manager(包管理器)是怎样保存数据的?
我应该去哪里找Package Manager和Package Installer的源码?
1、什么是Package Manager和Package Installer
PackageInstaller是安卓上默认的应用程序,用它来交互式地安装普通包文件。PackageInstaller提供了用户界面来管理应用或者包文件。PackageInstaller调用一个叫InstallAppProgress的activity来获取用户发出的指令。InstallAppProgress会请求Package Manager服务,然后通过indalld来安装包文件。源码提供在/packages/apps/PackageInstaller上。
Installd这个系统守护程序的首要角色是获取来自Package Manager服务的请求,而该请求是通过Linux套接字/dev/socket/installed获得的。
Installd使用管理员权限执行一系列的步骤来安装APK。参考:
Package Manger是一个实际上管理应用程序安装、卸载和升级的API。当我们安装APK文件时,Package Manager会解析APK包文件和显示确认信息。当我们点击OK按钮后,Package Manger会调用一个叫“InstallPackage”的方法,这个方法有四个参数,也就是uri、installFlags、observer和installPackagename。Package Manger会启动一个叫“package”的service(服务),现在所有模糊的东西会发生在这个service中。你可以在PackageInstaller源码中查看“PackageInstallAcitivity.java”和“InstallAppProgress.java”。Package Manger服务运行在系统服务进程中,而安装守护程序(installd)作为一个本地进程运行着,他们都在系统启动时开始运行。
2、APK文件保存在Android的哪个地方?
预装程序(即相机,日历和浏览器等)保存在/system/app/中。
用户安装程序(APIDemo,Any.do等)保存在/data/app/中。
Package Manager创建数据目录/data/data//来保存数据库、shared preference、本地函数库和缓存数据。
你可能会看到apk文件和同一个APK的*.odex文件,而ODEX文件是完全不同的讨论和目的了。
3、APK文件安装过程的细节是怎样的?
下面的过程执行在Package Manger服务中。
添加一个包文件到安装进程的队列中;
确定合适的地方来安装包文件;
复制apk文件到一个给定的目录下;
确定应用的UID;
请求installd守护程序进程;
创建应用目录和设置权限;
提取dex代码到缓存目录中;
解析packages.list、system、data和packages.xml的最新状态;
向系统发送广播消息,消息带有安装完成效果的名字Intent.ACTION_PACKAGE_ADDED:如果是更新,会带有新的(Intent.ACTION_PACKAGE_REPLACED)。
4、Package Manager(包管理器)是怎样保存数据的?
Package Manager保存应用程序的信息在/data/system目录下的三个文件里。下面的例子是从Android 4 ICS(Ice Cream Sandwich)模拟器提取出来的图片。
1. packages.xml:这个文件包含所有的权限和Packages/Applications。
&packages&
&last-platform-version external=&15& internal=&15&&
&permission-trees&
&permissions&
&item name=&android.permission.CHANGE_WIFI_MULTICAST_STATE& package=&android& protection=&1&&
&item name=&android.permission.CLEAR_APP_USER_DATA& package=&android& protection=&2&&
&/item&&/item&&/permissions&
&package codepath=&/system/app/Contacts.apk& flags=&1& ft=&0& it=&0& name=&com.android.contacts& nativelibrarypath=&/data/data/com.android.contacts/lib& shareduserid=&10001& ut=&0& version=&15&&
&sigs count=&1&&
&cert index=&2&&
&/cert&&/sigs&
&/package&
&package codepath=&/data/app/com.project.t2i-2.apk& flags=&0& ft=&13a837c2068& it=&13a83704ea3& name=&com.project.t2i& nativelibrarypath=&/data/data/com.project.t2i/lib& userid=&10040& ut=&13a837c2ecb& version=&1&&
&sigs count=&1&&
&cert index=&3& key=&85ae300d06092a86
10b040a13074
16ee1e170d31
a170d5a906035
416e819f300df70d818d003
09ce1c5fd64db794fda2dccf6798ddd2fd6e1d8ab04cd8cdd9e
bf721fb3ed6be1d67c55ce729b1e1d32b200cbcfc91c798ef056bc9b2cbc66a396aed6b
af11a11c3bf4eb41b2ac
b5ef536fd9edffcd52dcbdf88cf43c580abd0d0
f70d3bed85a51fca
63fa6c5c46fde9a862b56b6d6f17ddaa38bf8
d568e349a93bc6afa1a51e1658ee34aca48ae38
609803dfbe6e78dd0be26fe35ffc85f9fcf8bc
&/cert&&/sigs&
&item name=&android.permission.WRITE_EXTERNAL_STORAGE&&
&/item&&/perms&
&/package&
&/permission-trees&&/last-platform-version&&/packages&
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
<packages><last-platform-version external="15" internal="15"><permission-trees><permissions><item name="android.permission.CHANGE_WIFI_MULTICAST_STATE" package="android" protection="1"><item name="android.permission.CLEAR_APP_USER_DATA" package="android" protection="2">.... </item></item></permissions>&<package codepath="/system/app/Contacts.apk" flags="1" ft="0" it="0" name="com.android.contacts" nativelibrarypath="/data/data/com.android.contacts/lib" shareduserid="10001" ut="0" version="15"><sigs count="1"><cert index="2"></cert></sigs></package>....<package codepath="/data/app/com.project.t2i-2.apk" flags="0" ft="13a837c2068" it="13a83704ea3" name="com.project.t2i" nativelibrarypath="/data/data/com.project.t2i/lib" userid="10040" ut="13a837c2ecb" version="1"><sigs count="1"><cert index="3" key="85ae300d06092a8610b040a1307416ee1e170d31a170d5a906035f0d416e819f300df70d818d00309ce1c5fd64db794fda2dccf6798ddd2fd6e1d8ab04cd8cdd9ebf721fb3ed6be1d67c55ce729b1e1d32b200cbcfc91c798ef056bc9b2cbc66a396aed6baf11a11c3bf4eb41b2acb5ef536fd9edffcd52dcbdf88cf43c580abd0d0f70d3bed85a51fca63fa6c5c46fde9a862b56b6d6f17ddaa38bf8d568e349a93bc6afa1a51e1658ee34aca48ae38609803dfbe6e78dd0be26fe35ffc85f9fcf8bcc5c7a"></cert></sigs><perms><item name="android.permission.WRITE_EXTERNAL_STORAGE"></item></perms></package>.....</permission-trees></last-platform-version></packages>
这个xml文件包含两种信息,权限和package(application)。 权限是保存在标签里的。每个Permission(权限)有三个属性,即name、package和protection。Name属性包含权限的名字,也就是我们在AndroidManifest.xml所用的,Package属性表明权限所属的包。在大多数情况下,“android”是一个值,因为标签包含默认的权限,以及protection表明安全的等级。
package标签包含10个属性和一些子标签。
APK文件安装路径(/system/app/ 或 /data/app/)
nativeLibraryPath
本地函数库(*.so文件),默认路径/data/data/&package name&/lib/
存储ApplicationInfo标记[http://developer.android.com/reference/android/content/pm/ApplicationInfo.html](http://developer.android.com/reference/android/content/pm/ApplicationInfo.html)
十六进制时间戳timestamp
首次安装十六进制时间戳
最后更新十六进制时间戳
AndroidManifest.xml文件中的版本代码
[http://developer.android.com/guide/topics/manifest/manifest-element.html#vcode]
sharedUserId
Linux用户ID名称,其他应用可查看此ID。与在AndroidManifest.xml中的定义一致[http://developer.android.com/guide/topics/manifest/manifest-element.html#uid]
Linux用户ID名称
sigs 签名信息,count属性代表cert标签的数量。
cert 包含证书的key,index属性代表证书的全局索引,当新的证书安装时,我发现index会随着增加。
perms 包含开发者已经在AndroidManifest.xml中设置好的权限。
2. packages.list: 这是一个简单的文本文件,包含了包名、用户id、flag和数据目录,我找不到更加完美的描述了,但是我设想它可提供更快速的已安装包的查找,因为这个文件一直只保存重要的信息。
com.android.launcher 10013 0 /data/data/com.android.launcher
com.android.quicksearchbox 10033 0 /data/data/com.android.quicksearchbox
com.android.contacts 10001 0 /data/data/com.android.contacts
com.android.inputmethod.latin 10006 0 /data/data/com.android.inputmethod.latin
com.android.launcher 10013 0 /data/data/com.android.launchercom.android.quicksearchbox 10033 0 /data/data/com.android.quicksearchboxcom.android.contacts 10001 0 /data/data/com.android.contactscom.android.inputmethod.latin 10006 0 /data/data/com.android.inputmethod.latin
3.packages-stoped.xml:这个文件包含了已经是停止状态的包的列表,停止状态的应用是不能接收任何的广播的。参考这个链接来了解更多关于停止状态应用的信息。
&stopped-packages&
&pkg name=&com.android.widgetpreview& nl=&1&&&/pkg&
&pkg name=&com.example.android.livecubes& nl=&1&&&/pkg&
&pkg name=&com.android.gesture.builder& nl=&1&&&/pkg&
&pkg name=&com.example.android.softkeyboard& nl=&1&&&/pkg&
&/stopped-packages&
<stopped-packages><pkg name="com.android.widgetpreview" nl="1"></pkg><pkg name="com.example.android.livecubes" nl="1"></pkg><pkg name="com.android.gesture.builder" nl="1"></pkg><pkg name="com.example.android.softkeyboard" nl="1"></pkg></stopped-packages>
5、去哪里可以找到Package Manager和Package Installer的源码?
Package Manger
Package Installer
关于作者:
可能感兴趣的话题
关于伯乐在线博客
在这个信息爆炸的时代,人们已然被大量、快速并且简短的信息所包围。然而,我们相信:过多“快餐”式的阅读只会令人“虚胖”,缺乏实质的内涵。伯乐在线内容团队正试图以我们微薄的力量,把优秀的原创文章和译文分享给读者,为“快餐”添加一些“营养”元素。
新浪微博:
推荐微信号
(加好友请注明来意)
– 好的话题、有启发的回复、值得信赖的圈子
– 分享和发现有价值的内容与观点
– 为IT单身男女服务的征婚传播平台
– 优秀的工具资源导航
– 翻译传播优秀的外文文章
– 国内外的精选文章
– UI,网页,交互和用户体验
– 专注iOS技术分享
– 专注Android技术分享
– JavaScript, HTML5, CSS
– 专注Java技术分享
– 专注Python技术分享
& 2018 伯乐在线}

我要回帖

更多关于 platformid 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信