Jenkins搭建iOS持續(xù)集成打包平臺(tái)

準(zhǔn)備工作

Jenkins的安裝

Jenkins依賴于Java環(huán)境,首先需安裝和配置Java環(huán)境(PS:在下載的時(shí)候注意選擇JDK,而非JRE)

1.使用brew安裝:

brew install jenkins

如果報(bào)錯(cuò) brew: command not found掐禁,這是由于當(dāng)前環(huán)境沒有安裝homebrew

安裝homebrew 允扇,代碼執(zhí)行:

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

安裝成功后威恼,請重新安裝brew install jenkins

安裝成功后商乎,瀏覽器會(huì)自動(dòng)打開Jenkins網(wǎng)頁服務(wù),如果沒有打開押逼,請?jiān)跒g覽器輸入 http://localhost:8080/习寸。如果不能打開 http://localhost:8080/ ,可能是Jenkins服務(wù)未開啟:

開啟Jenkins :

sudo launchctl load /Library/LaunchDaemons/org.jenkins-ci.plist

停用Jenkins :

sudo launchctl unload /Library/LaunchDaemons/org.jenkins-ci.plist

如果報(bào)錯(cuò):/Library/LaunchDaemons/org.jenkins-ci.plist: No such file or directory

可以在命令行中開啟服務(wù):

jenkins

此時(shí)Jenkins會(huì)在命令行里打印相關(guān)的運(yùn)行日志胶惰,再在瀏覽器里輸入: http://localhost:8080/ 這種情況的話,如果關(guān)閉執(zhí)行 jenkins命令的命令行窗口霞溪,Jenkins也會(huì)停止服務(wù)

Jenkins的配置

點(diǎn)擊系統(tǒng)管理->管理插件孵滞,在插件管理里面下載幾個(gè)比較有用的插件中捆,當(dāng)然可以根據(jù)自己的需求增減

1.插件的安裝

Xcode integration(用來配置打包參數(shù)的,需配置的參數(shù)和步驟較多坊饶,改用腳本打包)
Keychains and Provisioning Profiles Management(用來配置鑰匙串參數(shù)的泄伪,配合Xcode integration一同使用)
GitLab Plugin(用來關(guān)聯(lián)gitlab倉庫)
Gitlab Hook Plugin(用來配置hookurl,使gitlab在獲得push 等事件的時(shí)候能喚起Jenkins)
fir-plugin(用來上傳到fir的插件幼东,易報(bào)錯(cuò)臂容,已改用腳本上傳)
Email Extension Plugin(用來在構(gòu)建后發(fā)送郵件給測試的,smtp配置易出錯(cuò)根蟹,已改用腳步發(fā)送)
Changelog Environment Plugin(用來獲取commits日志的脓杉,獲取插件請?jiān)L問 https://twiceyuan.com/2017/02/21/jenkins-changelog/)
BearyChat Plugin(用來在構(gòu)建后發(fā)送通知給bearchat的,bearchat中選擇Jenkins機(jī)器人即可接受消息)

2.插件的使用

gitlab plugin

Markdown
  • 倉庫地址

  • 驗(yàn)證方式(用戶名密碼或ssh)

  • 分支(想要構(gòu)建的分支名稱简逮,圖中傳了一個(gè)自定義的參數(shù))

gitlab hook

Markdown
  • 在gitlab中設(shè)置-webhook中加入該URL球散,Jenkins即可在獲取push/merge事件后開始構(gòu)建

changelog plugin

  • 勾選該選項(xiàng)后,即可獲取${SCM_CHANGELOG} commit日志參數(shù)散庶,傳入腳步

bearchat plugin

  • 勾選該選項(xiàng)后蕉堰,即可在構(gòu)建完成后通知給bearchat中的Jenkins機(jī)器人

項(xiàng)目設(shè)置

在Jenkins中,構(gòu)建項(xiàng)目以Job的形式存在悲龟,因此需要針對(duì)每個(gè)項(xiàng)目創(chuàng)建一個(gè)Job屋讶。有時(shí)候,一個(gè)項(xiàng)目中可能有多個(gè)分支同時(shí)在進(jìn)行開發(fā)须教,為了分別進(jìn)行構(gòu)建皿渗,也可以針對(duì)每個(gè)分支創(chuàng)建一個(gè)Job。
創(chuàng)建Job的方式有多種轻腺,本次只需要?jiǎng)?chuàng)建Freestyle project類型的即可乐疆。
Main page -> New Item -> Freestyle project

對(duì)于一個(gè)持續(xù)集成打包平臺(tái),每次打包都由4步組成:觸發(fā)構(gòu)建贬养、拉取代碼挤土、執(zhí)行構(gòu)建、構(gòu)建后處理误算。對(duì)應(yīng)的仰美,在每個(gè)Job中也對(duì)應(yīng)了這幾項(xiàng)的配置。

1.Jenkins主頁儿礼,點(diǎn)擊左上角的新建按鈕開始新建一個(gè)Item

2.輸入Item的名稱筒占,選擇構(gòu)建一個(gè)自由風(fēng)格的軟件項(xiàng)目

3.這里可以設(shè)置包的保留天數(shù)還有最大個(gè)數(shù)

4.配置參數(shù)化內(nèi)容,如圖,可以用${name}在shell命令中取出對(duì)應(yīng)的值

5.在源碼管理里面選擇git蜘犁,然后配置git信息

要對(duì)項(xiàng)目進(jìn)行構(gòu)建翰苫,配置項(xiàng)目的代碼倉庫是必不可少的。由于當(dāng)前我們的項(xiàng)目托管在Gitlab私有倉庫中,因此在此需要對(duì)Git進(jìn)行配置奏窑。
【Source Code Management】配置欄目下导披,如果之前Gitlab plugin安裝成功,則會(huì)出現(xiàn)Git選項(xiàng)埃唯。

配置Git代碼倉庫時(shí)撩匕,有三項(xiàng)是必須配置的:倉庫URL地址(Repository URL)、倉庫權(quán)限校驗(yàn)方式(Credentials)墨叛,以及當(dāng)前Job需要構(gòu)建的代碼分支(Branches to build)止毕。
在配置Repository URL時(shí),選擇HTTPS URL或SSH URL均可漠趁。不過需要注意的是扁凛,Credentials要和Repository URL對(duì)應(yīng),也就是說:
如果Repository URL是HTTPS URL形式的闯传,那么Credentials就要采用Gitlab用戶名密碼的校驗(yàn)方式谨朝;如果Repository URL是SSH URL形式的,那么就需要先在Jenkins所在的服務(wù)器上創(chuàng)建一個(gè)SSH秘鑰對(duì)甥绿,并將公鑰添加到GitHub的SSH keys中字币,然后在填寫Credentials時(shí),選擇SSH Username with private key的校驗(yàn)方式共缕,填入Gitlab Username洗出、SSH私鑰、以及創(chuàng)建SSH秘鑰對(duì)時(shí)設(shè)置的Passphrase图谷。

在配置Branches to build時(shí)翩活,可以采用多種形式,包括分支名稱(branchName)蜓萄、tagName隅茎、commitId等澄峰。其中分支名稱的形式用的最多嫉沽,例如,若是構(gòu)建master分支俏竞,則填寫master绸硕,若是構(gòu)建develop分支,則填寫develop魂毁。
除了以上關(guān)于Git的必填配置項(xiàng)玻佩,有時(shí)根據(jù)項(xiàng)目的實(shí)際情況,可能還需要對(duì)Jenkins的默認(rèn)配置項(xiàng)進(jìn)行修改席楚。比較常見的一種情況就是對(duì)clone的配置進(jìn)行修改咬崔。

在Jenkins的默認(rèn)配置中,clone代碼時(shí)會(huì)拉取所有歷史版本的代碼,而且默認(rèn)的超時(shí)時(shí)限只有10分鐘垮斯。這就造成在某些項(xiàng)目中郎仆,由于代碼量本身就比較大,歷史版本也比較多兜蠕,再加上網(wǎng)絡(luò)環(huán)境不是特別好扰肌,Jenkins根本沒法在10分鐘之內(nèi)拉取完所有代碼,超時(shí)后任務(wù)就會(huì)被自動(dòng)終止了(錯(cuò)誤狀態(tài)碼143)熊杨。
這種問題的解決方式也很簡單曙旭,無非就是兩種思路,要么少拉取點(diǎn)代碼(不獲取歷史版本)晶府,要么提高超時(shí)時(shí)限桂躏。對(duì)應(yīng)的配置在Advanced clone behaviours中:

Shallow clone:勾選后不獲取歷史版本;
Timeout (in minutes) for clone and fetch operation:配置后覆蓋默認(rèn)的超時(shí)時(shí)限郊霎。

Markdown

6.配置構(gòu)建觸發(fā)器

代碼倉庫配置好了沼头,意味著Jenkins具有了訪問GitHub代碼倉庫的權(quán)限,可以成功地拉取代碼书劝。

那Jenkins什么時(shí)候執(zhí)行構(gòu)建呢进倍?

這就需要配置構(gòu)建觸發(fā)策略,即構(gòu)建觸發(fā)器购对,配置項(xiàng)位于【Build Triggers】欄目猾昆。

觸發(fā)器支持多種類型,常用的有:

  • 定期進(jìn)行構(gòu)建(Build periodically)
  • 根據(jù)提交進(jìn)行構(gòu)建(Build when a change is pushed to GitHub)
  • 定期檢測代碼更新骡苞,如有更新則進(jìn)行構(gòu)建(Poll SCM)

構(gòu)建觸發(fā)器的選擇為復(fù)合選項(xiàng)垂蜗,若選擇多種類型,則任一類型滿足構(gòu)建條件時(shí)就會(huì)執(zhí)行構(gòu)建工作解幽。如果所有類型都不選擇贴见,則該Jenkins Job不執(zhí)行自動(dòng)構(gòu)建,但可通過手動(dòng)點(diǎn)擊【Build Now】觸發(fā)構(gòu)建躲株。

關(guān)于定時(shí)器(Schedule)的格式片部,簡述如下:

分鐘(0-59) 小時(shí)(0-23) 日期(1-31) 月(1-12) 周幾(0-7,0和7都是周日)


7.配置構(gòu)建方式

常用的構(gòu)建方式是根據(jù)構(gòu)建對(duì)象的具體類型,安裝對(duì)應(yīng)的插件霜定,然后采用相應(yīng)的構(gòu)建方式档悠。例如,若是構(gòu)建iOS應(yīng)用望浩,安裝Xcode integration插件之后辖所,就可以選擇Xcode,然后選擇Xcode進(jìn)行構(gòu)建磨德。

該種方式的優(yōu)勢是操作簡單缘回,UI可視化,在場景不復(fù)雜的情況下可以快速滿足需求。不過缺點(diǎn)就是依賴于插件已有的功能酥宴,如果場景較復(fù)雜時(shí)可能單個(gè)插件還無法滿足需求揩环,需要再安裝其它插件。而且幅虑,有些插件可能還存在一些問題丰滑,例如對(duì)某些操作系統(tǒng)版本或XCode版本兼容不佳,出現(xiàn)問題時(shí)我們就會(huì)比較被動(dòng)倒庵。
我個(gè)人更傾向于另外一種方式褒墨,就是自己編寫打包腳本,在腳本中自定義實(shí)現(xiàn)所有的構(gòu)建功能擎宝,然后在Execute Shell中執(zhí)行郁妈。這種方式的靈活度更高,各種場景的構(gòu)建需求都能滿足绍申,出現(xiàn)問題后也能自行快速修復(fù)噩咪。

另外,對(duì)于iOS應(yīng)用的構(gòu)建极阅,還有一個(gè)需要額外關(guān)注的點(diǎn)胃碾,就是開發(fā)者證書的配置。
如果是采用Xcode integration插件進(jìn)行構(gòu)建筋搏,配置會(huì)比較復(fù)雜仆百,需要在Jenkins中導(dǎo)入開發(fā)證書,并填寫多個(gè)配置項(xiàng)奔脐。不過俄周,如果是采用打包腳本進(jìn)行構(gòu)建的話,情況就會(huì)簡單許多髓迎。只要在Jenkins所運(yùn)行的計(jì)算機(jī)中安裝好開發(fā)者證書峦朗,打包命令在Shell中能正常工作,那么在Jenkins中執(zhí)行打包腳本也不會(huì)有什么問題排龄。

8.至此波势,我們的Jenkins設(shè)置就全部完成了

點(diǎn)擊構(gòu)建,就會(huì)開始構(gòu)建項(xiàng)目了涣雕,構(gòu)建一次艰亮,各個(gè)顏色代表的意義如下:


如果構(gòu)建失敗了闭翩,可以去查看Console Output可以查看log日志:


關(guān)于iOS的構(gòu)建

對(duì)iOS源碼進(jìn)行構(gòu)建挣郭,目標(biāo)是要生成.ipa文件,即iOS應(yīng)用安裝包疗韵。
當(dāng)前兑障,構(gòu)建方式主要包括兩種:

xcodeuild:

  • 源碼 -> .archive文件 -> .ipa文件

xcrun:(xcode8后已被淘汰)

  • 源碼 -> .app文件 -> .ipa文件

這兩種方式的主要差異是生成的中間產(chǎn)物不同,對(duì)應(yīng)的,兩種構(gòu)建方式采用的命令也不同流译,我們只看xcodebuild這種.

源碼 -> .archive

# build archive file from source code
xcodebuild archive -workspace ${project_name}.xcworkspace \
                   -scheme ${scheme_name} \
                   -configuration ${build_configuration} \
                   -archivePath ${export_archive_path}

archive:對(duì)編譯結(jié)果進(jìn)行歸檔逞怨,會(huì)生成一個(gè).xcarchive的文件,位于-archivePath指定的目錄中福澡。

需要注意的是叠赦,對(duì)模擬器類型的sdk無法使用archive命令.

.archive -> .ipa

# export ipa file from .archive
xcodebuild  -exportArchive \
            -archivePath ${export_archive_path} \
            -exportPath ${export_ipa_path} \
            -exportOptionsPlist ${ExportOptionsPlistPath}

參數(shù)說明

xcodebuild參數(shù):

  • -workspace:需要打包的workspace,后面接的文件一定要是.xcworkspace結(jié)尾的革砸;
  • -scheme:需要打包的Scheme除秀,一般與${project_name}相同;
  • -configuration:需要打包的配置文件算利,我們一般在項(xiàng)目中添加多個(gè)配置册踩,適合不同的環(huán)境,Release/Debug效拭;
  • -archivePath:.xcarchive文件的路徑暂吉;
  • -exportPath:導(dǎo)出文件(.ipa)的路徑;
  • -exportOptionsPlist:根據(jù)configuration對(duì)應(yīng)的plist文件缎患;

補(bǔ)充說明

1慕的、獲取Targets、Schemes挤渔、Configurations參數(shù)

在填寫target/workspace/scheme/configuration等參數(shù)時(shí)业稼,如果不知道該怎么填寫,可以在項(xiàng)目根目錄下執(zhí)行xcodebuild -list命令蚂蕴,它會(huì)列出當(dāng)前項(xiàng)目的所有可選參數(shù)低散。

Information about project "Store":
    Targets:
        Store
        StoreCI
    Build Configurations:
        Debug
        Release
    If no build configuration is specified and -scheme is not passed then "Release" is used.
    Schemes:
        Store
        StoreCI

2.清除緩存文件

在每次build之后,工程目錄下會(huì)遺留一些緩存文件骡楼,以便下次build時(shí)減少編譯時(shí)間熔号。然而,若因?yàn)楣こ膛渲缅e(cuò)誤等問題造成編譯失敗后鸟整,下次再編譯時(shí)就可能會(huì)受到緩存的影響引镊。
因此,在持續(xù)集成構(gòu)建腳本中篮条,比較好的做法是在每次build之前都清理一下上一次編譯遺留的緩存文件弟头。

xcodebuild clean -workspace ${project_name}.xcworkspace \
                 -scheme ${scheme_name} \
                 -configuration ${build_configuration}

3.處理Cocoapod依賴庫

若項(xiàng)目是采用Cocoapod管理項(xiàng)目依賴,每次拉取最新代碼后直接編譯可能會(huì)報(bào)錯(cuò)涉茧。這往往是因?yàn)槠渌赂铝艘蕾噹欤ㄐ略隽说谌綆旎蛏?jí)了某些庫)赴恨,而本地還采用之前的第三方庫進(jìn)行編譯,從而會(huì)出現(xiàn)依賴庫缺失或版本不匹配等問題伴栓。
應(yīng)對(duì)的做法是伦连,在每次build之前都更新一下Cocoapod雨饺。

# Update pod repository
pod repo update
# Install pod dependencies
pod install
# Install pod dependencies not update spec
pod install --verbose --no-repo-update

4.上傳FIR

fir publish ./xxx.ipa -T xxxxxx

5.提交AppStore(未完成)

/Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Versions/A/Support/altool --validate-app -f ./xxx.ipa -u xxx -p xxx -t ios --output-format xml
/Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Versions/A/Support/altool --upload-app -f ./xxx.ipa -u xxx -p xxx -t ios --output-format xml

6.發(fā)郵件

python sendEmail.py "日志" "用戶郵箱"

遇到的問題

Q1:Jenkins Xcode 證書設(shè)置錯(cuò)誤 Code Sign error: No matching codesigning identity found: No codesigning identities

A1:Jenkins 集成Xcode 項(xiàng)目的時(shí)候在證書上遇到了問題。實(shí)際上如果在本地的話惑淳。只要Xcode工程里選擇了項(xiàng)目就不需要重新設(shè)置證書了额港。jenkins會(huì)自動(dòng)找到這個(gè)證書,只要在build setting 里設(shè)置的是正常的歧焦。并且在xcode 里能正常編譯移斩。

Check dependencies
Code Sign error: No codesigning identities found: No codesigning identities (i.e. certificate and private key pairs) that match the provisioning profile specified in your build settings (“qingyunDeveloper”) were found.

如果遇到類似的錯(cuò)誤 解決辦法:
因?yàn)閖enkins運(yùn)行在Mac的守護(hù)進(jìn)程模式,只是認(rèn)為它是一個(gè)不同的用戶绢馍,所以不會(huì)有機(jī)會(huì)獲得鑰匙串或提供個(gè)人資料作為您登錄使用您的憑據(jù)叹哭,而我的證書是裝在“登錄”下的,這會(huì)導(dǎo)致代碼簽名有問題
解決辦法是首先打開keychain keys 找到apple 的開發(fā)者證書痕貌。然后復(fù)制风罩。 再選擇左邊的系統(tǒng)(system)把剛復(fù)制的證書放進(jìn)去。

如果這個(gè)還沒有解決舵稠。

接下來第二步:

找到你用戶下的Provisioning Profiles 文件超升。目錄為 /Users/xxx/Library/MobileDevice/Provisioning Profiles xxx表示你自己的用戶名
把這里面所有的證書復(fù)制到/Users/Shared/Jenkins/Library/MobileDevice/Provisioning Profile 這個(gè)文件。

參考資料:
http://code-dojo.blogspot.co.uk/2012/09/fix-ios-code-signing-issue-when-using.html

Q2:打包iOS有pod的項(xiàng)目哺徊,shell執(zhí)行pod install時(shí)室琢,提示pod command not found

A2:需要在shell第一行加上 #bin/bash -l 就行了,所以最終是這樣:

#!/bin/bash -l
export LANG=en_US.UTF-8
pod install --verbose --no-repo-update

Q3:有pod的項(xiàng)目提示schema找不到

A3:需要用xcode打開一次.xcworkspace就好了落追,或者在shell pod install之后下加上 open x.xcworkspace

Q4:jenkins 命令 command not found

A4:由于jenkins是用jenkins用戶啟動(dòng)的盈滴,所以很多環(huán)境變量就沒有,導(dǎo)致很多命令起不來轿钠,所以需要把jenkins改為自己常用的用戶來啟動(dòng)巢钓。默認(rèn)jenkins的目錄是在/User/Share/Jenkins下的。這是安裝.pkg文件成功后自動(dòng)創(chuàng)建了jenkins用戶疗垛,下面我們開始切換到常用用戶下症汹。

1)我們先把jenkins停掉,執(zhí)行:
sudo launchctl unload /Library/LaunchDaemons/org.jenkins-ci.plist

然后刷新瀏覽器贷腕,發(fā)現(xiàn)jenkins頁面打不開了背镇,說明成功停掉了

2)到Finder->application下找到j(luò)enkins/jenkins.war,雙擊啟動(dòng)泽裳。然后刷新瀏覽器瞒斩,發(fā)現(xiàn)又重新進(jìn)入了jenkins的配置過程,正常配置完涮总,返現(xiàn)jenkins根目錄變了胸囱,變成/User/當(dāng)前用戶/.jenkins/

Q5:jenkins打包的時(shí)候需要鑰匙串密碼

A5:這個(gè)密碼是本地登陸密碼,如果不行,就得用jenkins用戶的密碼,直接重置jenkins密碼妹卿。在命令行執(zhí)行
sudo passwd jenkins
可能要求先輸入當(dāng)前用戶密碼旺矾,然后就提示Changing password for jenkins.設(shè)置新密碼就行了.

Q6:在使用jenkins打包時(shí) 出現(xiàn)xcodebuild: error: The workspace named "XXXX" does not contain a scheme named “XXX"

A6:首先在項(xiàng)目根目錄中使用 xcodebuild -list 獲得schema名稱
然后在該schema中勾選shared選項(xiàng)

Markdown

Q7:jenkins使用shell命令打IOS包報(bào)錯(cuò):user interaction is not allowed

A7:在編譯命令前加入以下命令:

security unlock-keychain -p "123456" ~/Library/Keychains/login.keychain

或者

echo "123456" | security unlock-keychain  ~/Library/Keychains/login.keychain

[要把鑰匙串解鎖,并配置訪問鑰匙串的密碼即可]

Q8:在自動(dòng)化部署的時(shí)候,gitlab中的webhook無法訪問jenkins,報(bào)錯(cuò)execution expired

A8:暫時(shí)沒找到辦法解決,可能是架設(shè)gitlab的局域網(wǎng)網(wǎng)段和jenkins的網(wǎng)段不一致

Q9:不能打包adHuc/appstore包的問題

A9:下載描述文件(需要把extension的描述文件一起下下來) p12文件一起安裝

Q10:在打包時(shí)出現(xiàn)多語言包損壞的問題

A10:不要用cocoapods的beta版

Q11:打包腳本報(bào)錯(cuò)teamid不匹配

A11:Xcode近年來致力于自動(dòng)管理開發(fā)證書,每個(gè)大版本都會(huì)有修改(有方便的地方也有坑的地方)夺克。到了Xcode8箕宙,在target的General設(shè)置面板中直接新增了“Signing”,看得出來铺纽,Automatically manage signing選項(xiàng)是蘋果推薦的簽名方式柬帕。如果恰巧不幸,你的證書里的App ID與Xcode中的bundle ID不符狡门,就應(yīng)該關(guān)閉該選項(xiàng)陷寝,手動(dòng)為某個(gè)configuration指定打包證書。不要忘記在腳本中-exportOptionsPlist指定的plist中配置對(duì)應(yīng)的teamID其馏。

總結(jié)

  • 自動(dòng)打包是iOS開發(fā)中的一項(xiàng)基礎(chǔ)工作凤跑,作為自動(dòng)化工作的一小部分往往被應(yīng)用于CI系統(tǒng)。持續(xù)集成的內(nèi)容很多叛复,還有自動(dòng)化測試仔引、代碼靜態(tài)檢查、持續(xù)交付等內(nèi)容褐奥。這篇文章是概括了其中一些方面咖耘,我們要做的還有很多。

接下來要做什么

  • OCLint -- 做為一個(gè)靜態(tài)代碼分析工具撬码,我們引入 OCLint 的目的主要是為了提高我們的代碼質(zhì)量儿倒。通常我們提高代碼質(zhì)量的方式是通過 CodeReview,但是這個(gè)過程耗費(fèi)的人工和時(shí)間往往較大呜笑,所以我們想通過 OCLint 的一些規(guī)則夫否,讓機(jī)器幫我們完成一部分代碼質(zhì)量的檢測,從而提高我們的工作效率叫胁。
    參考鏈接:

    iOS 工程自動(dòng)化 - OCLint

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市曹抬,隨后出現(xiàn)的幾起案子溉瓶,更是在濱河造成了極大的恐慌,老刑警劉巖谤民,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件堰酿,死亡現(xiàn)場離奇詭異,居然都是意外死亡张足,警方通過查閱死者的電腦和手機(jī)触创,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來为牍,“玉大人哼绑,你說我怎么就攤上這事岩馍。” “怎么了抖韩?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵蛀恩,是天一觀的道長。 經(jīng)常有香客問我茂浮,道長双谆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任席揽,我火速辦了婚禮顽馋,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘幌羞。我一直安慰自己寸谜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布属桦。 她就那樣靜靜地躺著程帕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪地啰。 梳的紋絲不亂的頭發(fā)上愁拭,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音亏吝,去河邊找鬼岭埠。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蔚鸥,可吹牛的內(nèi)容都是我干的惜论。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼止喷,長吁一口氣:“原來是場噩夢啊……” “哼馆类!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起弹谁,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤乾巧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后预愤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沟于,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年植康,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了旷太。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖供璧,靈堂內(nèi)的尸體忽然破棺而出存崖,到底是詐尸還是另有隱情,我是刑警寧澤睡毒,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布来惧,位于F島的核電站,受9級(jí)特大地震影響吕嘀,放射性物質(zhì)發(fā)生泄漏违寞。R本人自食惡果不足惜贞瞒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一偶房、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧军浆,春花似錦棕洋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至赞季,卻和暖如春愧捕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背申钩。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國打工次绘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人撒遣。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓邮偎,卻偏偏與公主長得像,于是被迫代替她去往敵國和親义黎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子禾进,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容