android 系统中日志及对应的等级大小为:VERBOSE < DEBUG < INFO < WARN < ERROR
android 底层源码通过宏开关控制相应等级的日志输出。
经常在源码看到这个宏的定义#define LOG_NDEBUG 0
如果宏被注释掉,那么只输出DEBUG及以上的日志,如果要输出全部日志,去掉该条宏定义的注释即可。
android 系统中日志及对应的等级大小为:VERBOSE < DEBUG < INFO < WARN < ERROR
android 底层源码通过宏开关控制相应等级的日志输出。
经常在源码看到这个宏的定义#define LOG_NDEBUG 0
如果宏被注释掉,那么只输出DEBUG及以上的日志,如果要输出全部日志,去掉该条宏定义的注释即可。
目前 5.0 之后项目预置方式通用步骤为:
建立 apk 文件夹;
置目标 apk 到该文件夹下;
解压缩 apk 查看是否包含 lib/文件夹(apk 项目是否包含 lib 库文件);
在该文件夹下编写 Android.mk 脚本 ;
理论上 apk 文件夹可以建立在项目内任意目录,编译系统会自动搜索并根据其内 Android.mk (编译脚本) 来进行编译。
编译系统采用的是递归搜索,在搜索到父文件目录的 Android.mk 脚本后递归便被终止。因此一般可以将需要预置的 apk 文件夹放到一个总文件夹内,并在该文件夹根目录另外写一个 Android.mk (管理脚本) ,以便对所有预置 apk 进行管理。对于 管理脚本 的编写将在文末解释。预置目录如下例:
Apps/
-/Android.mk 管理脚本
-/Test1
—-/Android.mk 编译脚本
—-/Test1.apk
—-/lib/_
-/Test2
—-/Android.mk 编译脚本
—-/Test2.apk
—-/lib/_
…
编译脚本 如下例:
LOCALPATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := Test
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_TAGS := optional
LOCAL_BUILT_MODULE_STEM := package.apk
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_SRC_FILES := Test*.apk
include $(BUILD_PREBUILT)1234567891011
其中,LOCALMODULE := Test 表示了一个预置的 apk 在编译中的唯一标识,同时编译后该 apk 会以此命名;LOCAL_SRC_FILES := Test_.apk 表示了当前要预置的 apk 的文件名,”Test__.apk”匹配任意以”Test_”开头的 apk 文件。
对于 apk 预置路径,在 Android.mk 中可以通过以下方式指名:
a) 默认预置 apk 到 system/app/目录(普通系统 apk,不可卸载),如前文 Android.mk 脚本编写之后即可;
b) 预置 apk 到 system/priv-app/目录(系统核心 apk,不可卸载),在前文 Android.mk 脚本中添加并配置变量:
LOCAL_PRIVILEGED_MODULE := true1
c) 预置 apk 到 data/app/目录并且卸载后不需要再会恢复,在前文 Android.mk 脚本中配置变量:
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)1
d) 预置 apk 到 data/app/目录并且卸载后恢复出厂可以恢复,在前文 Android.mk 简本中配置变量:
LOCAL_MODULE_PATH := $(TARGET_OUT)/vendor/operator/app1
对于包含 lib 库文件的 apk,还需要根据预置目标路径,在 mk 脚本中作不同的处理:
情况一:对于预置到 data/app/目录下的 apk,包括可恢复和不可恢复(即上一段 c) 和 d)), 一般 lib 库文件可以不用手动添加,apk 在首次运行时,会自动将自身的 lib 库抽取安装到自身的根目录;
情况二:对于预置到 system/app/ 和 system/priv-app 目录下的 apk(即上一段 a) 和 b)),因为在 android 系统中,system 分区是不允许应用执行写操作的,因此需要在 Android.mk 脚本中进行配置,手动添加 lib 库文件到编译环境,以便 lib 库文件在编译之后拷贝到对应编译后的 apk 目录下,否则 apk 执行时会因找不到 lib 库而报错;
<一>、首先根据 情况二 所述,添加 lib 库文件到编译环境
方法一 不从 apk 中解压 lib 库而直接添加
如下例,在 Android.mk 中添加并配置变量(注意路径对应):
LOCAL_PREBUILT_JNI_LIBS =
@lib/armeabi-v7a/libcryptox.so
@lib/armeabi-v7a/libfb.so 123
注意前面的 @符号,@标识符会将 apk 中的 so 抽离出来,拷贝到对应编译后的 apk 目录;
方法二 手动解压 lib 文件到当前 apk 的编译目录并添加
先解压当前 apk 内的 lib 文件夹到当前 apk 编译目录,同方法一在 Android.mk 中添加并配置变量(注意路径对应),如下例:
LOCAL_PREBUILT_JNI_LIBS =
lib/armeabi-v7a/libcryptox.so
lib/armeabi-v7a/libfb.so 123
若当前 apk 包含的 lib 库文件数量比较多时,上述代码可以通过修改为如下代码进行优化,优化的思路是用递归搜索来替代手工对 lib 库文件进行添加:
###清空临时变量 JNI_LIBS
JNI_LIBS := ###当前目录递归搜索
$(foreach FILE,$(shell find $(LOCAL_PATH)/lib/ -name *.so), $(eval JNI_LIBS += $(FILE)))
###获取搜索文件目录集(相对目录)
LOCAL_PREBUILT_JNI_LIBS := $(subst $(LOCAL_PATH),,$(JNI_LIBS))123456
<二>、然后需要注意当前 Android 环境是否符合 apk 运行条件(64 位和 32 位)并配置 apk 运行环境
之所以要配置 apk 运行环境,是因为包含 lib 库的 apk 在添加 lib 库到编译环境之后,在 Android 环境和 apk 运行条件不符的情况下,需要在编译环境中指定环境。举例说明:
目前一般的 apk 运行环境为 32 位 Android 系统环境,当在 64 位 Android 系统中预置带有 lib 库的 apk 时,手动添加 lib 库文件到编译环境后,默认情况下编译环境会在编译后 apk 目录建立 64 位的环境的 lib 库路径 /lib/arm64,虽然编译过程未报错,但之后在执行该 apk 时,会出现 apk 因找不到 lib 库而报错
因此,需要在 Android.mk 中对当前 apk 编译环境进行配置,配置的方法常见的也有两种:
<1>指定编译目标为 32 位 或 64 位
在 Android 目标中添加并配置变量:
LOCAL_MULTILIB := ###可选值 /32/64/first/both 12
不同的值含义如下:
“both”: build both 32-bit and 64-bit.
“32”: build only 32-bit.> * “64”: build only 64-bit.
“first”: build for only the first arch (32-bit in 32-bit devices and 64-bit in 64-bit devices).
“”: the default; the build system decides what arch to build based on the module class and other LOCAL_ variables, such as LOCAL_MODULE_TARGET_ARCH, LOCAL_32_BIT_ONLY, etc.
此处,default 值会根据当前已有的其他相关值方式来进行编译
<2>指定目标 lib 库的 类型
在 Android.mk 中添加并配置变量:
LOCAL_MODULE_TARGET_ARCH := ###可选值 arm/arm x86/arm6412
此处, LOCAL_MODULE_TARGET_ARCH 的值只能是当前编译环境所支持的类型,如果需要配置当前系统不支持类型,则需要配置如下另一个变量
LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH := ###可选值 arm/arm x86/arm6412
与 LOCAL_MODULE_TARGET_ARCH 相反, LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH 的值只能是当前编译环境所不支持的类型,否则编译将不会生效
如下是一个完整的 Android.mk 脚本示例,其中 apk 运行环境为 32 位,系统为 64 位:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := UCBrowser
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_TAGS := optional
LOCAL_BUILT_MODULE_STEM := package.apk
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_SRC_FILES := HK_UCBrowser*.apk
LOCAL_PRIVILEGED_MODULE := true
LOCAL_MULTILIB := 32
JNI_LIBS :=
$(foreach FILE,$(shell find $(LOCAL_PATH)/lib/ -name *.so), $(eval JNI_LIBS += $(FILE)))
LOCAL_PREBUILT_JNI_LIBS := $(subst $(LOCAL_PATH),,$(JNI_LIBS))
include $(BUILD_PREBUILT)123456789101112131415
最后编写管理脚本集中管理预置 apk
预置三方 apk 一般根据客户项目的不同而有所差异,因此如前文所述,可以将需要预置的 apk 文件夹放到一个总文件夹内,该文件夹可以采用与客户项目有关的命名用以区分不同客户项目预置,并在该文件夹根目录另外写一个 Android.mk (管理脚本), 这样便可以根据客户项目对预置 apk 进行管理。以下是据此更新后的预置目录,具体可以根据原理自行调整:
Customer1/
-/Android.mk 管理脚本
-/Test1
—-/Android.mk 编译脚本
—-/Test1.apk
—-/lib/_
-/Test2
—-/Android.mk 编译脚本
—-/Test2.apk
—-/lib/_
Customer2/
-/Android.mk 管理脚本
-/Test3
—-/Android.mk 编译脚本
—-/Test1.apk
—-/lib/_
-/Test4
—-/Android.mk 编译脚本
—-/Test2.apk
—-/lib/_
…
对于 管理脚本 的编写,如下例:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
###此处也可以在此添加一个宏变量来控制是否执行以下代码
###if($(strip $(XXX_CUSTOMER1_APP)),yes))
SUB_ANDROID_MK := $(shell find $(LOCAL_PATH)/apps/ -name Android.mk)
$(foreach sub_mk,$(SUB_ANDROID_MK), $(eval include $(sub_mk)))
PRODUCT_PACKAGES +=
Test1
Test2
###endif12345678910
其中 $(shell find $(LOCAL_PATH)/apps/ -name Android.mk) 返回一个遍历搜索子目录 Android.mk 的路径集合,此处也可以采用手动添加指定路径的方式来控制具体预置的 apk 是否编译 :
###替换
###SUB_ANDROID_MK := $(shell find $(LOCAL_PATH)/apps/ -name Android.mk)
###$(foreach sub_mk,$(SUB_ANDROID_MK), $(eval include $(sub_mk))) ###为
include Customer1/Test1/Android.mk
include Customer1/Test2/Android.mk123456
同时,PRODUCT_PACKAGES 变量指定将哪些编译完成的 apk 打包到项目最终编译生成的 Android 系统镜像文件中,如上代码中,其值恰恰就是预置 apk 的编译脚本中定义的 LOCAL_MODULE (即编译后该 apk 的名称)的值。
原文:https://blog.csdn.net/a462533587/article/details/46380795
FDeviceTest
中1 | ############################################################################### |
1 | PRODUCT_PACKAGES += \ |
OHCI、UHCI 都是 USB1.1 的接口标准,而 EHCI 是对应 USB2.0 的接口标准,最新的 xHCI 是 USB3.0 的接口标准。
OHCI( Open Host Controller Interface ) :一个不仅仅是 usb 用的主控制器接口标准。主要是遵循 csr (configuration space register)标准。是其他厂商在设计 usb host controller 时遵循的标准,如 via, nec, ali, 包括 nvidia 等等。支持 USB1.1 的标准。
UHCI (Universal Host Controller Interface ),是 Intel 主导的对 USB1.0、1.1 的接口标准,与 OHCI 不兼容。
EHCI(Enhanced Host Controller Interface ) ,是 Intel 主导的 USB2.0 的接口标准。EHCI 仅提供 USB2.0 的高速功能,而依靠 UHCI 或 OHCI 来提供对全速(full-speed)或低速(low-speed)设备的支持。
xHCI( eXtensible Host Controller Interface ),是最新的 USB3.0 的接口标准,它在速度、节能、虚拟化等方面都比前面 3 中有了较大的提高。xHCI 支持所有种类速度的 USB 设备(USB 3.0 SuperSpeed, USB 2.0 Low-, Full-, and High-speed, USB 1.1 Low- and Full-speed)。xHCI 的目的是为了替换前面三种(UHCI/OHCI/EHCI)。
Example of deployment process which I use in my Nuxt.js projects.
I usually have 3 components running per project: admin-panel SPA, nuxt.js renderer and JSON API.
This manual is relevant for VPS such as DigitalOcean.com or Vultr.com. It’s easier to use things like Now for deployment but for most cases VPS gives more flexebillity needed for projects bigger than a landing page.
UPD: This manual now compatible with nuxt@2.3. For older versions deployment, see revision history.
Let’s assume that you have entered fresh installation of Ubuntu instance via SSH. Let’s rock:
Depending on size of project you have two options: make non-root user or go on with root. I’d suggest you to go with root, which is easier (except nginx part). If you have chosen non-root, check out this tutorial.
Using nvm or directly:
curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
sudo apt-get install -y nodejs
It’s actually up to you, depending on type of your project, but I usually use this structure:
Fill server dir with your API code, in my case it’s nodejs + koa2 + mongoose stack. Place at least favicon and robots.txt to public dir.
Run npm run build
on your local machine. I don’t recommend to build nuxt.js on production server, because it eats lots of memory and causes up to minute of downtime. Take package.json, nuxt.config.js and .nuxt dir and copy them via SFTP (or pull from git) to client dir.
Note that there is a special Nuxt package for running production renderer without useless overhead - nuxt-start
. Intall it as dependency with the same version as your Nuxt package. Move to your client directory on the server and install production dependencies (in most cases you only need nuxt-start package): npm i -—production
.
PM2 is a process manager for node.js. Install PM2 and create config file in your user root dir: config.yml. See config example below. Don’t forget to run pm2 save && pm2 startup
, so your processes will recover on server restart.
Install nginx:
sudo apt-get update
sudo apt-get install nginx
(If you use root user, you have to set right permissions for project dirs to make it work with static files. Or just change user: www-data
to user: root
in /etc/nginx/nginx.conf.)
Then edit config file /etc/nginx/sites-available/default, see config example below. Don’t forget to sudo nginx -s reload
after every nginx config modification.
If you have already connected domain to your project, it’s super easy to set up https (and http2). See this tutorial for installing certbot.
Move to dir that contains your pm2 config file and run pm2 start config.yml –-env production
. Yay, everything should work now, but it doesn’t. Run pm2 logs
to see errors. This manual is complicated for a newbie and imperfect itself, so you will probably have to try several times. But it’s worth it.
Contributions to this manual are appreciated.
1 | (Don't forget to remove comments) |
1 | server { |
参数 解释
空 location 后没有参数直接跟着 标准 URI,表示前缀匹配,代表跟请求中的 URI 从头开始匹配。
= 用于标准 URI 前,要求请求字符串与其精准匹配,成功则立即处理,nginx 停止搜索其他匹配。
^~ 用于标准 URI 前,并要求一旦匹配到就会立即处理,不再去匹配其他的那些个正则 URI,一般用来匹配目录
~ 用于正则 URI 前,表示 URI 包含正则表达式, 区分大小写
~* 用于正则 URI 前, 表示 URI 包含正则表达式, 不区分大小写
@ @ 定义一个命名的 location,@ 定义的 locaiton 名字一般用在内部定向,例如 error_page, try_files 命令中。它的功能类似于编程中的 goto。
nginx 有两层指令来匹配请求 URI 。第一个层次是 server 指令,它通过域名、ip 和端口来做第一层级匹配,当找到匹配的 server 后就进入此 server 的 location 匹配。
location 的匹配并不完全按照其在配置文件中出现的顺序来匹配,请求 URI 会按如下规则进行匹配:
以上规则简单总结就是优先级从高到低依次为(序号越小优先级越高):
1 | location = # 精准匹配 |
1 | server { |
pm2 安装npm install pm2 -g
pm2 的配置文件
1 | module.exports = { |
配置文件更改后,需要 kill pm2, 重新启动才能生效
日志文件分割pm2 install pm2-logrotate
常用命令
pm2 set pm2-logrotate:max_size 10K
pm2 set pm2-logrotate:retain 30
pm2 set pm2-logrotate:compress false
pm2 set pm2-logrotate:dateFormat YYYY-MM-DD_HH-mm-ss
pm2 set pm2-logrotate:workerInterval 30
pm2 set pm2-logrotate:rotateInterval 0 0 * * *
pm2 set pm2-logrotate:rotateModule true
pm2 常用命令
1 | # Fork mode |
这在许多场景中都很有用,有可能网络中断了,但又希望将我们的提交传给合作者们,我们可能不在办公网中并且出于安全考虑没有接入内网的权限,可能无线、有线网卡坏掉了,可能现在没有共享服务器的权限,然而我们又希望通过邮件将更新发送给别人,却不希望通过 format-patch 的方式传输 40 个提交。这些情况下 git bundle 就会很有用,bundle 命令会将 git push 命令所传输的所有内容打包成一个二进制文件,可以将这个文件通过邮件或者闪存传给其他人,然后解包到其他的仓库中。
来看看一个简单的例子,假设有一个包含两个提交的仓库:
如果想把这个仓库发送给其他人但没有其他仓库的权限,或者就是懒得新建一个仓库,就可以用 git bundle create 命令来打包:
然后就会有一个名为 repo.bundle 的文件,该文件包含了所有重建该仓库 master 分支所需的数据。在使用 bundle 命令时,需要列出所有希望打包的引用或者提交的区间,如果希望这个仓库可以在别处被克隆,应该像例子中那样增加一个 HEAD 引用。我们可以将这个 repo.bundle 文件通过邮件或者 U 盘传给别人。
另一方面,假设别人传给我们一个 repo.bundle 文件并希望在这个项目上工作,可以从这个二进制文件中克隆出一个目录,就像从一个 URL 克隆一样:
如果在打包时没有包含 HEAD 引用,还需要在命令后指定一个 -b master 或者其他被引入的分支,否则 Git 不知道应该检出哪一个分支。
现在假设提交了 3 个修订,并且要用邮件或者 U 盘将新的提交放在一个包里传回去:
首先我们需要确认我们希望被打包的提交区间,和网络协议不太一样,网络协议会自动计算出所需传输的最小数据集,而我们需要手动计算。当然可以像上面那样将整个仓库打包,但最好仅仅打包变更的部分,就是我们刚刚在本地做的 3 个提交。
为了实现这个目标,我们需要计算出差别,有很多种方式去指明一个提交区间,我们可以使用 “origin/master…master”或者“master ^origin/master”之类的方法来获取那 3 个在 master 分支而不在原始仓库中的提交。可以用 log 命令来测试:
这样就获取到我们希望被打包的提交列表,让我们将这些提交打包,可以用 git bundle create 命令,加上想用的文件名,以及要打包的提交区间:
现在在目录下会有一个 commits.bundle 文件,如果把这个文件发送给我们的合作者,她可以将这个文件导入到原始的仓库中, 即使在这期间已经有其他的工作提交到这个仓库中。
当她拿到这个包时,她可以在导入到仓库之前查看这个包里包含了什么内容,bundle verify 命令可以检查这个文件是否是一个合法的 Git 包,是否拥有共同的祖先来导入:
如果打包工具仅仅把最后两个提交打包,而不是三个,原始的仓库是无法导入这个包的, 因为这个包缺失了必要的提交记录。这时候 verify 的输出类似:
而我们的第一个包是合法的,所以可以从这个包里提取出提交。如果想查看这边包里可以导入哪些分支,同样有一个命令可以列出这些顶端:
verify 子命令同样可以知道哪些顶端,该功能的目的是查看哪些是可以被拉入的,所以可以使用 fetch 或者 pull 命令从包中导入提交。这里我们要从包中取出 master 分支到我们仓库中的 other-master 分支:
可以看到已经将提交导入到 other-master 分支,以及在这期间我们自己在 master 分支上的提交:
因此,当在没有合适的网络或者可共享仓库的情况下,git bundle 很适合用于共享或者网络类型的操作。