lucifer's blog

记录所有能记录的东西


  • Home

  • Archives

  • Categories

  • Tags

  • Search

奇怪的问题

Posted on 2016-08-19   |   In 技术   |     |   visitors

记录一些奇奇怪怪的问题


Git

  • git提交时报如下错
1
2
3
4
5
fatal: Unable to create '/Users/Luc1fer/lawMonkey-iOS/.git/index.lock': File exists.
If no other git process is currently running, this probably means a
git process crashed in this repository earlier. Make sure no other git
process is running and remove the file manually to continue.
  • 解决方案
1
rm -f ./.git/index.lock

carsh日志捕获和上报

Posted on 2016-08-10   |   In 技术   |     |   visitors

14年记录于有道笔记的老文章,有时间再修改。


崩溃捕获和收集

目的

通过崩溃信息的捕获和收集,可以收集到已发布应用的异常,以便开发人员发现和修改bug,对于提高软件质量有着极大的帮助。

获取系统生成的崩溃日志

  1. iTunes同步
  2. Xcode
  3. iTunes Connect

以上方法中的第一和第二种必须要连接设备,这在我们将App分发到用户设备上之后是不可能实现的,第三种方法如果应用还卖得不多,或者刚上架不久,或者用户关闭了上传日志的选项,iTunes Connect账号上也可能还没有任何崩溃日志。所以显然不能通过收集系统自动生成的崩溃日志来达成我们的目的。

使用第三方统计分析工具

如果是个人开发应用或者没有特殊限制的话,可以直接选择比较知名的第三方统计工具加入到工程中就万事大吉了,其中的错误日志功能完全能够满足需求,而且不需要额外准备接收服务器。

  • 友盟移动统计
  • Talking Data
  • 百度移动统计
  • 腾讯移动统计
  • App Annie
  • Flurry
  • Google Analytics

自定义崩溃收集系统的原理及实现【SFReportSDK】

启动方式及相关配置

1
2
3
SFReportManager * sfReportManager = [SFReportManager sharedSFReportManager];
[sfReportManager configureWithIdentifier:@"com.sf.demo" delegate:self];
[sfReportManager startManager];
1
2
3
4
5
6
7
8
9
10
#define SFREPORT_VERSION @"0.1"
#define SFREPORT_BUILD @"1"
#ifndef SFREPORT_CRASH_REPORTER
# define SFREPORT_CRASH_REPORTER 1
#endif
#ifndef SFREPORT_EVENT_REPORTER
# define SFREPORT_EVENT_REPORTER 1
#endif

捕捉崩溃信息

系统错误时会抛出一个错误信号,在我们的app启动时我们可以通过设定一个回调函数来接受并处理异常。

  • 开启异常捕获监听,用来处理程序崩溃时的回调动作

    NSSetUncaughtExceptionHandler(&uncaught_exception_handler);
    
  • 实现自己的处理函数
static void uncaught_exception_handler (NSException *exception){
        //todo
}

记录和保存崩溃信息

记录日志通常会牵扯到隐私问题,要谨慎考虑哪些信息是不该被记录进日志的,例如用户的用户名和密码或者是信用卡号和密码等。以下是暂时拟出的需要记录的字段及说明。

字段 说明
Incident Identifier 崩溃日志唯一标识符,是一个UUID
CrashReporter Key 是与设备标识相对应的唯一键值。虽然它不是真正的设备标识符,但也是一个非常有用的情报:如果你看到100个崩溃日志的CrashReporter Key值都是相同的,或者只有少数几个不同的CrashReport值,说明这不是一个普遍的问题,只发生在一个或少数几个设备上
Hardware Model 设备类型
Identifier 应用标识符,即bundle identifier
Version 前面是build code,后面是发布版本号。
Code Type ARM (Native)
User ID 用户ID
Date/Time 奔溃时间
Launch Time 应用启动时间
OS Version 操作系统版本
Report Version 105
Exception Type 异常类型
exceptionName 异常类型
exceprionReason 异常原因
CallStackSymbols 堆栈信息

路径:
/Library/Caches/com.sf.report.data/Crash/448525886.txt

上传崩溃信息

*压缩

ZipArchive

*加密

AES

RSA

*上传

crash

carsh日志及解析

Posted on 2016-08-10   |   In 技术   |     |   visitors

14年记录于有道笔记的老文章,有时间再修改。


什么是崩溃日志?

一个App启动之后,用着用着就突然被iOS系统关闭,或者干脆就起不来,在打开的一瞬间关闭,这就是Crash,俗称“闪退”“崩溃”。

iOS设备上的应用闪退时,操作系统会生成一个扩展名为crash的日志文件,这个文件会保存的特定系统目录下。

崩溃日志上有很多有用的信息,上面有每个正在执行线程的完整堆栈跟踪信息,所以你能从中了解到闪退发生时各线程都在做什么,并分辨出闪退发生在哪个线程上和相关的原因。

从哪里能得到它?

  • iTunes

设备与电脑上的iTunes Store同步后,会将崩溃日志保存在电脑上。根据电脑操作系统的不同,崩溃日志将保存在以下位置:

  1. Mac OSX:~/Library/Logs/CrashReporter/MobileDevice/

  2. Windows XP: C:Documents and SettingsApplication DataApple ComputerLogsCrashReporterMobileDevice

  3. Windows Vista or 7: C:UsersAppDataRoamingApple ComputerLogsCrashReporterMobileDevice

当用户抱怨闪退时,你可以要求他让设备与iTunes同步,并根据操作系统的不同,到上述位置把崩溃日志下载下来,然后通过电子邮件发送给你。

你必需尽量获取用户设备生成的所有崩溃日志。因为崩溃日志越多,就越容易诊断问题所在!

  • Xcode

将iOS设备连接到电脑上,然后打开Xcode。从菜单栏上选择 Window 菜单, 然后选择 Devices ,在左侧的导航面板上,点击View Device Logs查看设备的日志,然后查看你对应的appname的日志。

  • App Store

应用提交到App Store后,你也能从 iTunes Connect 获取到用户的崩溃日志. 登录到 iTunes Connect 上, 选择Manage Your Applications, 点击相应的应用, 点击应用图标下面的View Details 按钮, 然后点击右栏Links部分的Crash Reports。

如果应用还卖得不多,或者刚上架不久,或者用户关闭了上传日志的选项,iTunes Connect账号上也可能还没有任何崩溃日志。

什么情况下会产生崩溃日志?

应用违反操作系统规则
  • 在启动、恢复、挂起、退出时watchdog超时

从iOS 4.x开始,退出应用时,应用不会立即终止,而是退到后台。但是,如果你的应用响应不够快,操作系统有可能会终止你的应用,并产生一个崩溃日志。这些事件与下列UIApplicationDelegate方法相对应:
application:didFinishLaunchingWithOptions:
applicationWillResignActive:
applicationDidEnterBackground:
applicationWillEnterForeground:
applicationDidBecomeActive:
applicationWillTerminate:

上面所有这些方法,应用只有有限的时间去完成处理。如果花费时间太长,操作系统将终止应用。

注意: 如果你没有把需要花费时间比较长的操作(如网络访问)放在后台线程上就很容易发生这种情况。

  • 用户强制退出

iOS 4.x开始支持多任务。如果应用阻塞界面并停止响应,用户可以通过在主屏幕上双击Home按钮来终止应用。此时,操作应用将生成一个崩溃日志。

注意: 双击Home按钮后,你将看到运行过的所有应用。那些应用不一定是正在运行,也不一定是被挂起。通常,用户点击Home按钮时,应用将在后台保留约10分钟,然后操作系统自动将其终止。 所以双击Home按钮显示的应用列表只是表明那是一系列过去打开过的应用。删除那些应用的图标不会产生任何崩溃日志。

  • 低内存终止

在前台运行的应用拥有访问和使用内存的最高优化级。然而,这并不意味着该应用能使用设备的所有可用内存 ——每个应用只能使用一部分可用内存。

当内存使用达到一定程度时,操作系统将发出一个 UIApplicationDidReceiveMemoryWarningNotification 通知。同时,调用 didReceiveMemoryWarning 方法。

此时,为了让应用继续正常运行,操作系统开始终止在后台的其他应用以释放一些内存。所有后台应用被终止后,如果你的应用还需要更多内存,操作系统会将你的应用也终止掉,并产生一个崩溃日志。而在这种情况下被终止的其他后台应用,不会产生崩溃日志。

应用中有Bug

大多数闪退都是由于应用中有Bug,比如调用用了Objective-C对象根本不支持的方法(发送消息),非法内存访问,数组越界,参数不符合要求等。

这些问题在调试阶段,我们都可以很容易的通过断点和console中提供的信息快速定位并解决。

但对于已发布的App,如果想重现并利用上述办法来解决,恐怕会比较费时费事。

最有帮助最直接的办法就是根据出现问题时的闪退日志,分析和判断crash的原因,快速准确的定位和解决。

崩溃日志示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/**********进程信息**********/
Incident Identifier: 421FEFDC-E649-42E0-AC34-D3E2E3E5713D
CrashReporter Key: 963c64a27bb863f790c0e751f1991b29ab541923
Hardware Model: iPhone5,2
Process: LiuLianCustomer [6694]
Path: /private/var/mobile/Containers/Bundle/Application/ACFACAB0-E67F-48A6-BBF1-6BE0209D6F1D/LiuLianCustomer.app/LiuLianCustomer
Identifier: com.LLWF.Customer.RC
Version: 1936 (0.0.1)
Code Type: ARM (Native)
Parent Process: launchd [1]
/**********基本信息**********/
Date/Time: 2015-02-11 18:44:04.610 +0800
Launch Time: 2015-02-11 18:30:28.148 +0800
OS Version: iOS 8.1.2 (12B440)
Report Version: 105
/**********异常信息**********/
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Triggered by Thread: 0
/**********线程回溯**********/
Thread 0 name: Dispatch queue: com.apple.main-thread
/**********堆栈信息**********/
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x36111dfc __pthread_kill + 8
1 libsystem_pthread.dylib 0x3618fd32 pthread_kill + 58
2 libsystem_c.dylib 0x360b1904 abort + 72
3 libc++abi.dylib 0x353ef9c4 abort_message + 84
4 libc++abi.dylib 0x3540966c default_terminate_handler() + 264
5 libobjc.A.dylib 0x35acbf22 _objc_terminate() + 190
6 libc++abi.dylib 0x35406de0 std::__terminate(void (*)()) + 76
7 libc++abi.dylib 0x354068aa __cxa_rethrow + 98
8 libobjc.A.dylib 0x35acbdce objc_exception_rethrow + 38
9 CoreFoundation 0x28227458 CFRunLoopRunSpecific + 628
10 CoreFoundation 0x282271ce CFRunLoopRunInMode + 102
11 GraphicsServices 0x2f6250a4 GSEventRunModal + 132
12 UIKit 0x2b836f9c UIApplicationMain + 1436
13 LiuLianCustomer 0x000dbfe6 0x7f000 + 380902
14 libdyld.dylib 0x3604baac start + 0
/**********动态库信息**********/
Binary Images:
0x7f000 - 0x2b6fff LiuLianCustomer armv7 <20c3e1f8927c3f008d675262a64594ba> /var/mobile/Containers/Bundle/Application/ACFACAB0-E67F-48A6-BBF1-6BE0209D6F1D/LiuLianCustomer.app/LiuLianCustomer
0x1fefb000 - 0x1ff1efff dyld armv7s <8ffd813a380c333bbd4a25e1dbe05715> /usr/lib/dyld
0x26955000 - 0x2695dfff AccessibilitySettingsLoader armv7s <eb1b9f48c19f37fc95ef2e98c0af1cb4> /System/Library/AccessibilityBundles/AccessibilitySettingsLoader.bundle/AccessibilitySettingsLoader
0x26dab000 - 0x26f17fff AVFoundation armv7s <23a20af23f733b39b5c87059c080f9f7> /System/Library/Frameworks/AVFoundation.framework/AVFoundation
0x26f18000 - 0x26f76fff libAVFAudio.dylib armv7s <e3f677adf77d37baa08716b5d334486f> /System/Library/Frameworks/AVFoundation.framework/libAVFAudio.dylib
0x26fb0000 - 0x26fb0fff Accelerate armv7s <3c10ee15d8363fa58b719f2abca91b06> /System/Library/Frameworks/Accelerate.framework/Accelerate
进程信息
  1. Incident Identifier 是崩溃报告的唯一标识符。

  2. CrashReporter Key 是与设备标识相对应的唯一键值。虽然它不是真正的设备标识符,但也是一个非常有用的情报:如果你看到100个崩溃日志的CrashReporter Key值都是相同的,或者只有少数几个不同的CrashReport值,说明这不是一个普遍的问题,只发生在一个或少数几个设备上。

  3. Hardware Model 是标识设备类型。 如果很多崩溃日志都是来自相同的设备类型,说明应用只在某特定类型的设备上有问题。上面的日志里,崩溃日志产生的设备是iPhone 4s。

  4. Process 是应用名称。中括号里面的数字是闪退时应用的进程ID。

  1. Identifier 是应用标识符,即bundle identifier。

  2. Version 是应用版本信息,前面是build code,后面是发布版本号。

基本信息

这部分给出了一些基本信息,包括闪退发生的日期和时间,设备的iOS版本。如果有很多崩溃日志都来自iOS 6.0,说明问题只发生在iOS 6.0上。

异常信息

在这部分,你可以看到闪退发生时抛出的异常类型。还能看到异常编码和抛出异常的线程。根据崩溃报告类型的不同,在这部分你还能看到一些另外的信息。

线程回溯

这部分提供应用中所有线程的回溯日志。 回溯是闪退发生时所有活动帧清单。它包含闪退发生时调用函数的清单。看下面这行日志:

1
13 LiuLianCustomer 0x000dbfe6 0x7f000 + 380902

它包括四列:

  1. 模块号:这里是13
  2. 二进制库名:这里是LiuLianCustomer
  3. 调用方法的地址:这里是0x000dbfe6
  4. 第四部分分为两列,基地址和偏移地址。此处基地址为0x7f000,偏移地址为380902。基地址指向crash的模块(也是模块的load地址)如UIKit。偏移地址指向crash代码的行数。
动态库信息

这些信息包括动态库名称、UUID、模块起始地址、模块结束地址、指令集种类、安装路径等信息。

符号化Symbolication

第一次看到崩溃日志上的回溯时,你或许会觉得它没什么意义。我们习惯使用方法名和行数,而非像这样的神秘位置:

1
13 SFtest 0x000ce3d6 0xc7000 + 29654

将这些十六进制地址转化成方法名称和行数的过程称之为符号化。

  • Xcode

从Xcode获取崩溃日志后过几秒钟,崩溃日志将被自动符号化。上面那行被符号化后的版本如下 :

1
2
2 CoreFoundation 0x25dcec30 -[__NSArrayI objectAtIndex:] + 176
3 SFtest 0x000133c4 -[MainViewController viewDidLoad] (MainViewController.m:79)

Xcode符号化崩溃日志时,需要访问与App Store上对应的应用二进制文件以及生成二进制文件时产生的 .dSYM 文件,必需完全匹配才行,否则,日志将无法被完全符号化。所以,保留每个分发给用户的编译版本非常重要。

注意: 你必需同时保留应用二进制文件和.dSYM文件才能将崩溃日志完整符号化。每次提交到iTunes Connect的构建都必需归档。.dSYM文件和二进制文件是特定绑定于每一次构建和后续构建的,即使来自相同的源代码文件,每一次构建也与其他构建不同,不能相互替换。


  • atos

atos就是address to symbol,把地址翻译成符号。是苹果提供的符号化工具,在Mac OS系统下默认安装。

终端下面执行以下命令

1
$ atos -arch cpu指令集种类 -o dysm文件路径 -l 模块load地址 调用方法的地址
  • dysm文件路径:可以在Xcode Organizer的Archives标签栏下找到所有已归档的应用文件。它保存了编译过程的详细信息,其中包括符号信息,路径为 appName.app.dSYM/Contents/Resources/DWARF/appName。
  • 模块load地址:模块加载的基地址,可以在日志的动态库信息中找到对应模块的基地址。
  • cpu指令集种类:可以为armv6 armv7 armv7s arm64。具体用哪个,可以参考对应模块的动态库信息中确定
  • 调用方法地址:想要符号化的地址

  • symbolicatecrash

symbolicatecrash是Xcode自带的一个分析工具,可以通过机器上的崩溃日志和应用的.dSYM文件定位发生崩溃的位置,把crash日志中的地址替换成代码相应位置。

使用方法:

软链接symbollicatecrash到/usr/bin/中,就可以直接使用sybollicatecrash命令

1
sudo ln -s /Applications/Xcode.app/Contents/SharedFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash /usr/bin/symbolicatecrash

设置xcode DEVELOPER_DIR,把下面的内容加入到.bash_profile中即可

1
export DEVELOPER_DIR="/Applications/Xcode.app/Contents/Developer"

符号化崩溃日志(不需要.app文件,符号文件和crash文件也可以不在同一目录)

1
symbolicatecrash xxx.crash xxx.dSYM > xxx.crash

  • dwarfdump

使用dwarfdump验证xxx.crash、xxx.app和xxx.dSYM三者的uuid是否一致。

1
$ dwarfdump --uuid appName.app/appName
1
$ dwarfdump --uuid appName.app.dSYM/Contents/Resources/DWARF/appName

crash文件在动态链接库部分查看对应的UUID,,三者UUID一致才能符号化崩溃日志。

1
dwarfdump --lookup=0x25dcc458 --arch armv7 SFtest.app.dSYM

CocoaPods安装涉及的知识和问题

Posted on 2016-08-10   |   In 技术   |     |   visitors

前几天因为办公电脑出问题换了电脑,然后需要重新装cocoapods,发现每次安装都有些小问题要去网上搜,这次把问题记下来,方便下次查阅。


CocoaPods

CocoaPods是一个用ruby实现的iOS项目依赖管理工具,Github地址。
在使用CocoaPods之前,开发项目需要用到第三方开源库的时候,我们需要
1.把开源库的源代码复制到项目中
2.添加一些依赖框架和动态库
3.设置-ObjC,-fno-objc-arc等参数
4.管理他们的更新
在使用CocoaPods后,我们只需要把用到的开源库放到一个名为Podfile的文件中,然后执行pod install.Cocoapods就会自动将这些第三方开源库的源码下载下来,并且为我们的工程设置好响应的系统依赖和编译参数。
CocoaPods的原理是将所有的依赖库都放到另一个名为Pods的项目中,然后让主项目依赖Pods项目,这样,源码管理工作都从主项目移到了Pods项目中。Pods项目最终会编译成一个名为libPods.a的文件,主项目只需要依赖这个.a文件即可。

安装

1
$ sudo gem update --system
1
$ sudo gem install cocoapods
1
2
3
ERROR: Could not find a valid gem 'cocoapods' (>= 0), here is why:
Unable to download data from https://rubygems.org/ - Errno::ETIMEDOUT: Operation timed out - connect(2) (https://rubygems.org/latest_specs.4.8.gz)
ERROR: Possible alternatives: cocoa pods

如果提示以上错误是因为ruby的软件源rubygems.org因为使用亚马逊的云服务,被天朝屏蔽了,需要切换到淘宝提供的ruby源镜像。可参照下面gem介绍部分的配置。

1
2
ERROR: Error installing cocoa:
activesupport requires Ruby version >= 2.2.2.

如果提示以上错误是因为ruby版本太低,需要升级,可参照下面rvm部分。

####初始化

1
$ pod setup

Terminal会停留在 Setting up CocoaPods master repo 这个状态一段时间,是因为要进行下载安装,而且目录比较大,需要耐心等待一下.如果想加快速度,可使用cocoapods的镜像索引.

1
$ pod --version

正常输出pod版本号说明安装成功

homebrew

homebrew是一个软件包管理系统

ruby

Ruby,一种简单快捷的面向对象(面向对象程序设计)脚本语言,

gem

gem是一个管理ruby项目的包管理器

更新gem
1
$ sudo gem update --system
切换sources
1
$ gem sources --remove https://rubygems.org/
1
$ gem sources -a https://ruby.taobao.org/
1
$ gem sources -l
1
2
3
4
切换成功
*** CURRENT SOURCES ***
http://ruby.taobao.org/

rvm

管理ruby版本的版本管理器

安装rvm
1
$ curl -L get.rvm.io | bash -s stable
1
2
期间可能需要输入管理员密码,以及自动通过homebrew安装依赖包,等待一段时间看到控制台输出如下信息说明成功。
In case of problems: https://rvm.io/help and https://twitter.com/rvm_io
1
$ source ~/.bashrc
1
$source ~/.bash_profile
1
上面2个命令是为了刷新rvm环境
1
$rvm -v
1
2
检查一下是否安装正确,控制台输出如下信息说明安装成功
rvm 1.27.0 (latest) by Wayne E. Seguin <wayneeseguin@gmail.com>, Michal Papis <mpapis@gmail.com> [https://rvm.io/]
用rvm管理ruby
1
$rvm list known
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
列出已知ruby版本
# MRI Rubies
[ruby-]1.8.6[-p420]
[ruby-]1.8.7[-head] # security released on head
[ruby-]1.9.1[-p431]
[ruby-]1.9.2[-p330]
[ruby-]1.9.3[-p551]
[ruby-]2.0.0[-p648]
[ruby-]2.1[.8]
[ruby-]2.2[.4]
[ruby-]2.3[.0]
[ruby-]2.2-head
ruby-head
# for forks use: rvm install ruby-head-<name> --url https://github.com/github/ruby.git --branch 2.2
# JRuby
jruby-1.6[.8]
jruby-1.7[.23]
jruby[-9.0.5.0]
jruby-head
# Rubinius
rbx-1[.4.3]
rbx-2.3[.0]
rbx-2.4[.1]
rbx[-2.5.8]
rbx-head

指定2.2.2版本安装

1
$ rvm install 2.2.2

如果你安装了多个版本,可以指定一个默认版本

1
$ rvm 2.2.2 --default
1
2
3
4
5
6
7
list 查询已经安装的版本
install :: install one or many ruby versions
uninstall :: uninstall one or many ruby versions, leaves their sources
remove :: uninstall one or many ruby versions and remove their sources
reinstall :: reinstall ruby and runs gem pristine on all gems,make sure to read output, use 'all' for all rubies.
migrate :: Lets you migrate all gemsets from one ruby to another.
upgrade :: Lets you upgrade from one version of a ruby to another, including migrating your gemsets semi-automatically.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
控制台输出如下信息说明成功
…… ruby-2.2.2 - #validate archive
ruby-2.2.2 - #extract
ruby-2.2.2 - #validate binary
ruby-2.2.2 - #setup
ruby-2.2.2 - #gemset created /Users/abc/.rvm/gems/ruby-2.2.2@global
ruby-2.2.2 - #importing gemset
/Users/abc/.rvm/gemsets/global.gems..............................
ruby-2.2.2 - #generating global wrappers........
ruby-2.2.2 - #gemset created /Users/abc/.rvm/gems/ruby-2.2.2
ruby-2.2.2 - #importing gemsetfile /Users/abc/.rvm/gemsets/default.gems
  evaluated to empty gem list
ruby-2.2.2 - #generating default wrappers........
Updating certificates in '/etc/openssl/cert.pem'.
mkdir: /etc/openssl: Permission denied
mkdir -p "/etc/openssl" failed, retrying with sudo
Liubin password required for 'mkdir -p /etc/openssl':
and sudo mkdir worked

博客搭建相关

Posted on 2016-08-05   |   In 技术   |     |   visitors

GitHub Pages

GitHub Pages 可以被认为是用户编写的、托管在github上的静态网页。由于它的空间免费稳定, 可以用于介绍托管在github上的Project或者搭建网站。

GitHub Pages 生成的网站的默认域名是 username.github.io 或者 username.github.io/project-name,但gp是支持自定义域名的:Custom Domain Name。购买域名之后,可以和默认的二级域名进行绑定。
教程参考:购买域名、设置DNS

More info:github pages、使用Github Pages建独立博客

Hexo

Hexo 是一个简单地、轻量地、基于Node的一个静态博客框架,可以方便的生成静态网页托管在github上。

推荐阅读Hexo使用攻略

More info:Hexo

NexT

NexT是一个Hexo扩展主题,由iissnan开发,精于心,简于形的理念。主旨在于简洁优雅且易于使用,所以首先要尽量确保 NexT 的简洁易用性。
More info:NexT

三方插件

评论系统:多说
阅读次数统计:LeanCloud
搜索服务:Swiftype

Hello World

Posted on 2016-08-03   |     |   visitors

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

lucifer

lucifer

6 posts
1 categories
12 tags
GitHub WeChat
© 2016 lucifer
Powered by Hexo
Theme - NexT.Mist