Android 源碼部署到服務(wù)器(Git+GitLab+Repo)

Android 源碼部署到服務(wù)器(Git+GitLab+Repo)

Android 源碼部署到服務(wù)器端爆班,一共分為七個(gè)部分衷掷。

  1. 軟件環(huán)境
  2. GitLab 服務(wù)端部署
  3. Repo Manifest.xml 生成
  4. GitLab 建倉
  5. Git Push 源碼到服務(wù)器
  6. Repo 同步源碼
  7. 提交修改后的代碼

一、軟件環(huán)境

服務(wù)器端系統(tǒng):Ubuntu 16.04

GitLab 軟件:GitLab Community Edition

客戶端系統(tǒng):Ubuntu 14.04

Git 軟件:Git 2.27.0

二柿菩、GitLab 服務(wù)端部署

  1. 必要組件安裝
sudo apt-get update
sudo apt-get install -y curl openssh-server ca-certificates
sudo apt-get install -y postfix

在安裝 postfix 時(shí)候戚嗅,需要使用左右鍵和回車鍵確認(rèn),并在下拉列表選擇 Internet Site 并確認(rèn)枢舶。

  1. 信任 GitLab 的 GPG 公鑰
curl https://packages.gitlab.com/gpg.key 2> /dev/null | sudo apt-key add - &>/dev/null  

  1. 配置鏡像路徑

如果沒有安裝 vim 先進(jìn)行安裝

vim /etc/apt/sources.list.d/gitlab-ce.list

打開 gitlab-ce.list 后懦胞,寫入:

deb https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/ubuntu xenial main

如果 gitlab-ce.list 文件不存在,自行創(chuàng)建即可凉泄,并賦予權(quán)限躏尉,可在 root 權(quán)限下進(jìn)行。

touch /etc/apt/sources.list.d/gitlab-ce.list
chmod 777 /etc/apt/sources.list.d/gitlab-ce.list

  1. 安裝 gitlab-ce
sudo apt-get update
sudo apt-get install gitlab-ce

  1. 執(zhí)行配置
sudo gitlab-ctl reconfigure

  1. 啟動(dòng) GitLab
sudo gitlab-ctl start

  1. 修改 external_url
sudo gedit /etc/gitlab/gitlab.rb 

修改如下路徑:

external_url 'http://gitlab.example.com'

具體要換成你服務(wù)端的 IP后众,比如胀糜,我這里使用的是 192.168.50.10

external_url 'http://192.168.50.10'

這里一定要重新配置,再次執(zhí)行配置命令

sudo gitlab-ctl reconfigure 

  1. 訪問你的 GitLab 服務(wù)

打開同一網(wǎng)段的任何電腦上的瀏覽器蒂誉,前提是電腦可以互相訪問教藻,如果使用了虛擬機(jī),則要配置網(wǎng)絡(luò)類型為橋接右锨,并將虛擬機(jī)都配置在同一網(wǎng)段內(nèi)怖竭,并且可以互相訪問,可以 ping 一下陡蝇,保證網(wǎng)絡(luò)暢通。

瀏覽器地址欄輸入:http://192.168.50.10(需要更換為你自己的 url)哮肚。

[圖片上傳失敗...(image-54367b-1612399398269)]

接下來可以創(chuàng)建 root 用戶登夫,輸入密碼并確認(rèn)。注冊其他用戶等等允趟。

三恼策、Repo Manifest.xml 生成

為什么需要自己去生成 Manifest.xml?如果你手上的代碼已經(jīng)不知道哪里同步來的潮剪,或者是方案廠商提供的涣楷,總之不是使用 Repo 管理代碼,可能把修改的部分作為一個(gè)單獨(dú)的 git 倉上庫了抗碰。如此我們就需要根據(jù)這份現(xiàn)有的源碼去生成 Manifest.xml狮斗。

前提是基于源碼修改的倉都用 git 上庫了,或者是增加了一些倉但是和 Manifest.xml 不同步弧蝇,這都需要修改 Manifest.xml 保持源碼倉和 Manifest.xml 對等碳褒。

因?yàn)樵创a中每個(gè)倉都有 .git 了景殷,所以我們需要統(tǒng)計(jì)所有的 .git 攀芯,這是為了找出所以的 git 倉,然后寫入 Manifest.xml,如此我們就可以使用 Repo 管理這些倉了伊约。

  1. 找出所有 git 倉庫
find myandroid/ -type d -name '.git' > git_pro.txt

打開 git_pro.txt 就會(huì)看到如下行

......
/home/snake/Share/art/.git
......

使用 bash 指令“掐頭去尾”(刪掉前綴路徑 /home/snake/Share/ 和后綴 .git)

cat git_pro.txt | cut -c 18- | sed 's/.....$//' > path.txt

得到如下路徑:

art

接著需要生成清單文件。

gen_xml.sh

#!/bin/bash
echo -e "
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<manifest>
  <remote  name=\"aosp\"
           fetch=\"..\"/>
  <default revision=\"master\"
           remote=\"aosp\"
           sync-j=\"4\" />" >>$1

while read line; do
    echo "  <project path=\"$line\" name=\"$line\" />" >>$1
done
echo -e "\n</manifest>" >>$1

運(yùn)行腳本 gen_xml.sh 即可闲询。

cat path.txt | ./gen_xml.sh default.xml

default.xml 內(nèi)容如下竭望,這就是我們要的清單文件(Manifest.xml)。

<?xml version="1.0" encoding="UTF-8"?>
<manifest>
  <remote  name="aosp"
           fetch=".."/>
  <default revision="master"
           remote="aosp"
           sync-j="4" />

  <project path="art" name="art" />
  <project path="abi/cpp" name="abi/cpp" />
  ......
</manifest>

fetch 是 “…” 代表返回到上級目錄是复,我這里將 manifest 倉庫放在了 android6newc 組下面删顶,詳見下文。

revision 是 master 代表主干分支佑笋,這個(gè)要和 android6newc 組下面源碼倉分支對應(yīng)翼闹。

這二者配置不正確,repo 無法正常同步源碼倉蒋纬。

四猎荠、GitLab 建倉

源碼中倉庫太多了,不可能在瀏覽器內(nèi)一個(gè)一個(gè)創(chuàng)建蜀备,所以需要借助 python-gitlab 庫來自動(dòng)完成关摇。將 default.xml 放在和腳本同一目錄,運(yùn)行它碾阁。等待建倉完成输虱,有點(diǎn)耗時(shí),可能要半小時(shí)脂凶。如果沒有安裝 python-gitlab 可以借助 pip 進(jìn)行安裝宪睹。

腳本內(nèi)寫死了父組名(Android6NewC),這個(gè)組需要在 GitLab 網(wǎng)頁中自行創(chuàng)建蚕钦。同樣 url 和 token 需要更換為你自己的亭病,生成 token 是在 GitLab Settings -> Access Tokens -> Add a personal access token。

AndroidSourceCodeGitlabManager.py

#!/usr/bin/python3

import gitlab
import os
import re
import time

MANIFEST_XML = "default.xml"
ROOT = os.getcwd()
ROOT_GROUP = "Android6NewC"
MANIFEST_XML_PATH_NAME_RE = re.compile(r"<project\s+path=\"(?P<path>[^\"]+)\"\s+name=\"(?P<name>[^\"]+)\"\s+/>",
                                       re.DOTALL)

gl = gitlab.Gitlab('http://192.168.50.10/', private_token='xxxxxxx')

manifest_xml_project_paths = []

def parse_repo_manifest():
    with open(os.path.join(ROOT, MANIFEST_XML), "rb") as strReader:
        for line in strReader:
            if line is not None and len(line) != 0:
                this_temp_line = line.decode()
                if line.find("path".encode(encoding="utf-8")):

                    s = MANIFEST_XML_PATH_NAME_RE.search(this_temp_line)

                    if s is not None:
                        manifest_xml_project_paths.append(s.group("path"))

    print("manifest_xml_project_paths=" + str(manifest_xml_project_paths))
    print("manifest_xml_project_paths len=" + str(len(manifest_xml_project_paths)))

def create_group_and_project():
    all_groups = gl.groups.list(all=True)
    print("all_groups=" + str(all_groups))
    group_parent = None

    for g in all_groups:
        if g.name == ROOT_GROUP:
            group_parent = g
            break
    print("group parent=" + str(group_parent))

    for path in manifest_xml_project_paths:
        print("path=" + path)
        paths = path.split("/")
        print("paths=" + str(paths))

        last_path_index = len(paths) - 1

        group = group_parent
        for index in range(0, last_path_index):
            p = paths[index]
            print("p=" + p)
            # is the group exist
            print("parent group=" + group.name)
            try:
                all_groups = group.subgroups.list(all=True)
            except AttributeError:
                all_groups = []
                print("AttributeError: clear all subgroups")

            is_group_exist = False
            for g in all_groups:
                if g.name == p:
                    is_group_exist = True
                    group = g
                    print("group exist=" + g.name)
                    break
            if is_group_exist:
                continue
            # create subgroup
            data = {
                "name": p,
                "path": p,
                "parent_id": group.id
            }

            try:
                group = gl.groups.create(data)
                print("group create success name=" + p)
                time.sleep(1)
            except gitlab.exceptions.GitlabCreateError as e:
                if e.response_code == 400:
                    print("group:" + p + " has already been created")

                    query_groups = gl.groups.list(all=True)
                    print("query_groups:" + str(query_groups))
                    for query_group in query_groups:
                        if query_group.name == p and query_group.parent_id == group.id:
                            group = query_group
                            print("update exit group:" + group.name)
                            break

        project = paths[last_path_index]
        print("group project list group=" + group.name)
        real_group = gl.groups.get(group.id, lazy=True)
        all_projects = real_group.projects.list(all=True)
        print("group all projects=" + str(all_projects))
        is_project_exist = False
        for p in all_projects:
            if p.name == project:
                is_project_exist = True
                print("project exist=" + p.name)
                break
        if not is_project_exist:
            print("create project=" + project)
            gl.projects.create({'name': project, 'path': project, 'namespace_id': group.id})
            print("project create success name=" + project)
            time.sleep(1)

def test_create_project_with_dot_name():
    # need use path field, if don't use path, GitLab url will replace "." to "_"
    gl.projects.create({'name': "xxx.yy.xy", 'path': "xxx.yy.xy"})

if __name__ == '__main__':
    parse_repo_manifest()
    create_group_and_project()

腳本基本工作原理較為簡單嘶居,通過正則表達(dá)式解析 default.xml 中的 project 標(biāo)簽?zāi)玫?path罪帖,根據(jù) path 創(chuàng)建 group (包括 subgroup),最后再創(chuàng)建 project邮屁。

腳本正確運(yùn)行的話輸出類似以下片段:

......
path=external/mtd-utils
paths=['external', 'mtd-utils']
p=external
parent group=Android6NewC
group exist=external
group project list group=external
group all projects=[...]
create project=mtd-utils
project create success name=mtd-utils
......
Process finished with exit code 0

腳本運(yùn)行完以后圍觀一下 GitLab 組頁面整袁,生成了我們需要的目錄結(jié)構(gòu)。

[圖片上傳失敗...(image-717933-1612399398267)]

五佑吝、Git Push 源碼到服務(wù)器

首先安裝 Git坐昙,然后編寫自動(dòng)提交腳本將源碼提交到倉庫。

1. 安裝 Git

使用以下命令在 Ubuntu 14.04 LTS 上安裝 Git

apt-get install git

安裝成功后鍵入命令可以查看 Git 版本芋忿,提示 git version 2.7.4民珍,說明已經(jīng)安裝成功襟士。

git --version

Git 全局配置用戶名和郵箱

git config --global user.name "xxx"
git config --global user.email "xxx email address"

生成 SSH key

ssh-keygen -t ed25519 -C "xxx email address"

生成提示如下,以下生成信息已經(jīng)抹除了敏感信息嚷量,你的生成信息會(huì)變化陋桂。

Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/captain/.ssh/id_ed25519):         
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/captain/.ssh/id_ed25519.
Your public key has been saved in /home/captain/.ssh/id_ed25519.pub.
The key fingerprint is:
xxxxxx xxx email address
The key's randomart image is:
+--[ED25519  256--+
|      =          |
|     x *         |
|    . x x        |
|   xo            |
|  * o = S o      |
| o = x o x       |
|  x o.4 .        |
|      x+         |
|     xx          |
+-----------------+

查看 SSH key

cat /home/captain/.ssh/id_ed25519.pub

顯示如下所示

ssh-ed25519 AAAAC3NzaC1lZXXXXXXXXXXXXXXsULA48NC2f+oOLf5EoFSpn4 xxx email address

GitLab 中新增 SSH key,將以上 key 粘貼到 Settings -> SSH Keys -> Add an SSH key蝶溶,確認(rèn)即可嗜历。

Push 存在源碼文件夾工程到倉庫,下面是一個(gè)例子抖所,腳本實(shí)際上就是包裝了這些命令梨州。

cd existing_folder
git init
git remote add origin git@192.168.50.10:android6newc/build.git
git add .
git commit -m "Initial commit"
git push -u origin master

當(dāng)然由于以前存在使用 Git 同步過代碼,因此需要先刪除 .git田轧,使用 rm 命令刪除即可暴匠。

rm -rf .git

2. Push Manifest 清單文件到 GitLab 服務(wù)端

在 android6newc 組(Android6NewC)下(網(wǎng)頁內(nèi)操作)新建 manifest project。并將客戶端的 default.xml push 過去傻粘。

cd existing_folder
git init
git remote add origin git@192.168.50.10:android6newc/manifest.git
git add .
git commit -m "Initial commit"
git push -u origin master

3. 自動(dòng) Push 代碼到 GitLab 服務(wù)端

這需要開發(fā)一個(gè)腳本執(zhí)行每窖,這里還是用 python 實(shí)現(xiàn),一定要注意切換到工作路徑下弦悉,不然就踩坑了窒典,當(dāng)然腳本已經(jīng)修復(fù)了這個(gè) bug。

PushAndroidSourceCode2GitLab.py

#!/usr/bin/python3

import os
import re

MANIFEST_XML = "default.xml"
ROOT = os.getcwd()
LOG_FILE_PATH = os.path.join(ROOT, "push.log")

MANIFEST_XML_PATH_NAME_RE = re.compile(r"<project\s+path=\"(?P<path>[^\"]+)\"\s+name=\"(?P<name>[^\"]+)\"\s+/>",
                                       re.DOTALL)
SOURCE_CODE_ROOT = "/home/captain/myandroid/"
REMOTE = "git@192.168.50.10:android6newc/"
manifest_xml_project_paths = []

def parse_repo_manifest():
    with open(os.path.join(ROOT, MANIFEST_XML), "rb") as strReader:
        for line in strReader:
            if line is not None and len(line) != 0:
                this_temp_line = line.decode()
                if line.find("path".encode(encoding="utf-8")):

                    s = MANIFEST_XML_PATH_NAME_RE.search(this_temp_line)

                    if s is not None:
                        manifest_xml_project_paths.append(s.group("path"))

    print("manifest_xml_project_paths=" + str(manifest_xml_project_paths))
    print("manifest_xml_project_paths len=" + str(len(manifest_xml_project_paths)))

def push_source_code_by_folder(str_writer):
    for path in manifest_xml_project_paths:
        print("path=" + path)
        abs_path = SOURCE_CODE_ROOT + path
        if os.path.exists(abs_path):
            # change current work dir
            os.chdir(abs_path + "/")
            # 1\. delete .git & .gitignore folder
            rm_git_cmd = "rm -rf .git"
            rm_gitignore_cmd = "rm -rf .gitignore"
            os.popen(rm_git_cmd)
            os.popen(rm_gitignore_cmd)

            # 2\. list dir
            dir_data = os.listdir(os.getcwd())

            cmd_list = []

            print("changed cwd=" + os.getcwd())

            if len(dir_data) == 0:
                echo_cmd = "echo \"This is a empty repository.\" > ReadMe.md"
                str_writer.write("empty repository:" + abs_path)
                str_writer.write("\r\n")
                cmd_list.append(echo_cmd)

            git_init_cmd = "git init"
            cmd_list.append(git_init_cmd)

            git_remote_cmd = "git remote add origin " + REMOTE + path + ".git"
            cmd_list.append(git_remote_cmd)

            git_add_dot_cmd = "git add ."
            cmd_list.append(git_add_dot_cmd)

            git_commit_cmd = "git commit -m \"Initial commit\""
            cmd_list.append(git_commit_cmd)

            git_push_cmd = "git push -u origin master"
            cmd_list.append(git_push_cmd)

            for cmd in cmd_list:
                print("begin exec cmd=" + cmd)
                os.popen(cmd)
                print("end exec cmd=" + cmd)
        else:
            print("abs_path=" + abs_path + " is not exist.")
            str_writer.write("folder not exist:" + abs_path)
            str_writer.write("\r\n")

def wrapper_push_source_code_write_log():
    with open(LOG_FILE_PATH, 'wb+') as strWriter:
        push_source_code_by_folder(strWriter)
        strWriter.close()

def test_only_dot_git_folder():
    subdir_and_file = os.listdir(os.getcwd())
    print("subdir_and_file=" + str(subdir_and_file))
    with open(LOG_FILE_PATH, 'wb+') as strWriter:
        strWriter.write(str(subdir_and_file))
        strWriter.write("\r\n")
        strWriter.write(str(subdir_and_file))
        strWriter.close()

if __name__ == '__main__':
    parse_repo_manifest()
    wrapper_push_source_code_write_log()
    # test_only_dot_git_folder()

將 default.xml 放在和腳本同一目錄稽莉,運(yùn)行它瀑志。運(yùn)行結(jié)束會(huì)把所有的源碼都同步到 GitLab。

六污秆、Repo 同步源碼

由于源碼是部署在局域網(wǎng)劈猪,局域網(wǎng)不能訪問互聯(lián)網(wǎng)。因此還需要把 repo 部署到服務(wù)器上良拼。

1. repo 部署到服務(wù)器

到能夠訪問互聯(lián)網(wǎng)的電腦 clone 一份 repo战得。

git clone https://github.com/GerritCodeReview/git-repo.git

然后將它打包

tar cvf git-repo.tar git-repo/

拷貝 git-repo.tar 到內(nèi)網(wǎng)電腦,并解壓将饺。

tar xvf git-repo.tar

刪除 git-repo/ 下的 .git。

在 Android-Tools 組下(網(wǎng)頁內(nèi)操作)新建 git-repo project痛黎。并將 git-repo push 過去予弧。

cd existing_folder
git init
git remote add origin git@192.168.50.10:android-tools/git-repo.git
git add .
git commit -m "add repo tool"
git push -u origin master

2. 客戶端 repo 同步代碼

在上一步中 git-repo 路徑中找到 repo 文件。將其放到 ~/bin 下湖饱,賦予執(zhí)行權(quán)限掖蛤,并添加到環(huán)境變量 PATH。此文件也可以部署在 httpd 服務(wù)器上井厌,安裝 apache2 服務(wù)蚓庭。

sudo apt-get install apache2

查看安裝是否成功致讥。

sudo systemctl status apache2

修改監(jiān)聽端口,我這里改為了 10086器赞。我們知道 http 默認(rèn)在 80 端口垢袱,但是這個(gè)端口已經(jīng)被 GitLab 使用了,所以要騰出來“地盤”港柜。

sudo vim /etc/apache2/ports.conf

將 repo 拷貝到 /var/www/html 目錄下请契。

重啟 apache2 服務(wù)。

sudo service apache2 restart

~/bin/ 目錄下夏醉,下載 repo爽锥。

curl  http://192.168.50.10:10086/repo > repo

修改權(quán)限和添加環(huán)境變量。

chmod a+x ~/bin/repo
export PATH=$PATH:~/bin

現(xiàn)在可以新建一個(gè)文件夾用來存放源碼了畔柔。先 repo init氯夷,然后 repo sync。

repo init -u git@192.168.50.10:android6newc/manifest.git --repo-url=git@192.168.50.10:android-tools/git-repo.git --no-repo-verify

init 成功以后會(huì)在當(dāng)前文件夾下創(chuàng)建 .repo 文件夾“胁粒現(xiàn)在可以運(yùn)行 repo sync 開始同步代碼腮考。

repo sync

防止下載中跳出,我們使用以下腳本奢啥,先創(chuàng)建秸仙。

vim down.sh

寫入下面內(nèi)容:

#!/bin/sh
repo sync
while [ $? -ne 0 ]
do
repo sync
done

用這段腳本執(zhí)行,替換 repo sync 這條命令桩盲。

chmod a+x down.sh
./down.sh

編譯的時(shí)候 make 命令無法使用寂纪,是由于沒有 Makefile 造成的,對比一下上庫之前的代碼赌结,把源碼目錄下 Makefile 拷貝過來即可捞蛋。此文件內(nèi)容非常簡單,就是把 build/core/main.mk 包含進(jìn)來柬姚。

### DO NOT EDIT THIS FILE ###
include build/core/main.mk
### DO NOT EDIT THIS FILE ###

七拟杉、提交修改后的代碼

給所有倉庫創(chuàng)建一個(gè)本地分支,分支名 dev 可以任取量承。

repo start dev --all

提交代碼到 remote搬设。

git add .
git commit -m "xxx"
git push aosp dev

git push <遠(yuǎn)程主機(jī)名> <本地分支名>,這會(huì)在遠(yuǎn)程創(chuàng)建創(chuàng)建一個(gè) dev 分支撕捍,請求合并拿穴。

aosp 是遠(yuǎn)程倉庫名,不確定可以使用 git branch -a 查詢忧风。

repo upload . (注意最后有個(gè)點(diǎn)號)無法使用默色,因?yàn)槲覀儧]有配置 Gerrit 服務(wù)器。

另外同步代碼可以使用 pull 命令狮腿。

git pull --rebase

高級用法

repo forall -c xxx 對所有倉庫執(zhí)行 -c 指定的命令

repo forall -c git add .
repo forall -c git commit -m "xxx"
repo forall -c git pull --rebase
repo forall -c git push aosp dev

八腿宰、遇到的錯(cuò)誤記錄

1. default.xml fetch 配置錯(cuò)誤

下面這張圖是因?yàn)?default.xml fetch 配置錯(cuò)誤造成的呕诉。

[圖片上傳失敗...(image-b017f2-1612399398264)]

2. 空倉未提交內(nèi)容

repo sync 期間報(bào)錯(cuò) fatal: Couldn’t find remote ref refs/heads/master,是因?yàn)樯蠋斓膫}是個(gè)空的吃度,需要追加內(nèi)容記錄甩挫,已修正腳本。

[圖片上傳失敗...(image-79515c-1612399398264)]

3. Git 版本低

git commit

git: ‘interpret-trailers’ is not a git command. See ‘git --help’.

cannot insert change-id line in .git/COMMIT_EDITMSG

[圖片上傳失敗...(image-c71a45-1612399398263)]

使用下面的命令更新

sudo add-apt-repository ppa:git-core/ppa
sudo apt-get update
sudo apt-get install git

4. 編譯缺少文件

這是因?yàn)?git push 源碼倉的時(shí)候规肴,某些文件加入到了 .gitignore捶闸,但忽略配置文件和實(shí)際編譯需要的文件沒有完全匹配,就會(huì)造成此問題拖刃。腳本中直接把此文件刪除删壮,已更正。

如果還是無法編譯通過兑牡,一定是上庫時(shí)央碟,源碼倉某些子文件夾下面還有 .gitignore,可以根據(jù)報(bào)錯(cuò)信息將相應(yīng)文件上庫均函。

比如下面缺了 netlink/version.h 頭文件亿虽。

external/libnl/include/netlink/netlink.h:29:29: fatal error: netlink/version.h: No such file or directory
 #include <netlink/version.h>

參考資料:

  1. https://blog.csdn.net/xiezhi123456/article/details/80030593
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市苞也,隨后出現(xiàn)的幾起案子洛勉,更是在濱河造成了極大的恐慌,老刑警劉巖如迟,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件收毫,死亡現(xiàn)場離奇詭異,居然都是意外死亡殷勘,警方通過查閱死者的電腦和手機(jī)此再,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來玲销,“玉大人输拇,你說我怎么就攤上這事∠托保” “怎么了策吠?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長瘩绒。 經(jīng)常有香客問我猴抹,道長,這世上最難降的妖魔是什么草讶? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任洽糟,我火速辦了婚禮炉菲,結(jié)果婚禮上堕战,老公的妹妹穿的比我還像新娘坤溃。我一直安慰自己,他們只是感情好嘱丢,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布薪介。 她就那樣靜靜地躺著,像睡著了一般越驻。 火紅的嫁衣襯著肌膚如雪汁政。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天缀旁,我揣著相機(jī)與錄音记劈,去河邊找鬼。 笑死并巍,一個(gè)胖子當(dāng)著我的面吹牛目木,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播懊渡,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼刽射,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了剃执?” 一聲冷哼從身側(cè)響起誓禁,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎肾档,沒想到半個(gè)月后摹恰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡阁最,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年戒祠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片速种。...
    茶點(diǎn)故事閱讀 39,834評論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡姜盈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出配阵,到底是詐尸還是另有隱情馏颂,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布棋傍,位于F島的核電站救拉,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏瘫拣。R本人自食惡果不足惜亿絮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧派昧,春花似錦黔姜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至五慈,卻和暖如春纳寂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背泻拦。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工毙芜, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人争拐。 一個(gè)月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓爷肝,卻偏偏與公主長得像,于是被迫代替她去往敵國和親陆错。 傳聞我的和親對象是個(gè)殘疾皇子灯抛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評論 2 354

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