Mac生产力系列-Mac下的软件安装

本文前驱铺垫梳理了从 linux 源码安装软件到 DPKG/RPM 软件包管理机制,阐述了 *UNX 平台的软件安装包管理机制的演变和现代化。
后半部分介绍了 Mac 下的软件安装包格式 —— pkg & dmg,以及软件包管理工具 —— brew 及 brew-cask,并梳理日常 Command Usage。

linux 软件的安装与管理

linux 是一套免费使用和自由传播的基于 POSIX 和 UNIX 的多用户、多任务、支持多线程和多 CPU 的开源的类 Unix 操作系统。
由于 linux 操作系统开放源代码,因而在其上安装的大部分也都是开源软件。开源软件的开发者往往仅需在开源代码托管平台上发布一份源码包,用户即可自由下载源码包到本地,基于源码包编译安装软件。这倒是非常符合 C 语言的设计哲学:一次编写,到处编译。

基于源码安装软件

基于源码安装软件一般由以下几个步骤组成:

  • 下载解压源码
  • 阅读 README、INSTALL 等说明文档,这一步至关重要
  • 分析安装平台环境(ifconfigure)
  • 编译安装软件(make,make install)

基于源代码安装软件的好处是:用户可以自由配置编译选项,按需编译实现功能定制,极大地满足个性化需求。此外,用户还可以自己选择安装路径,方便管理。卸载软件也很方便,只需删除对应的安装目录即可。
但是,配置、编译命令需要了解操作系统本身,并且依赖开源项目所使用的编程语言对应的工具链。为了使用一个应用软件,用户需要熟悉 linux 系统的文件组织架构和一堆 Shell 交互命令,还得解决编译过程中可能涉及到的繁杂的依赖关系。一定的英文水平也是必需的,关键是要有折腾不息的精神和顽强的动手能力!
English、OS、Linux、命令行交互方式、…,这些令人望而却步的门槛足以将普通用户拒之门外。安装后,你可能都不知道安装到哪里去了;甚至离开了 Windows 桌面,你都不知道从哪里启动软件。我依稀地记得刚接触 linux 那会儿,为了能在 linux 上播放个视频文件,废了老大劲才安装好一个 MPlayer。当时就森森地觉得 linux 真不是一般人能折腾得起,尽管现在已经折腾惯了,但依然觉得费脑伤神。
作为一个曾经的计算机旁系学生(自动化,别名计算机控制)、现在的半职业化软件攻城狮(涉猎甚广,浅显浮泛)和伪自由软件追崇者(用过盗版,不懂破解,从无贡献),因为工作关系经常穿梭于 Windows 和 Mac OS X 之间(游离其间,无所专精),不折腾下 Linux/Unix 都觉得没法混 github。
尽管对于 vim 键盘型用户(估计基本都是程序员吧),很喜欢那种游离于指尖的”自由感”,但对于普通鼠标型 Windows 用户,若无力驾驭,自由便是负担。

只有开发人员才需要学习一个操作系统本身,用户只需要学习操作系统里面的每个“应用程序”怎么使用。
—— Linus Torvalds

DPKG / RPM

伴随着 linux 的发展普及,linux 开发商开始在固定的硬件平台与操作系统上将要安装或升级的软件编译好,然后将这个软件的所有相关文件打包成一个特殊格式的文件。在这个软件内,还包含了预先检测系统与依赖软件(或动态链接库)的脚本,并提供记载该软件提供的所有文件信息等,最终将这个软件发布。
客户端取得软件后,只要通过特定的命令来安装,那么该软件就会按照内部的脚本来检测相关的前驱软件是否存在。若安装的环境和条件符合要求,则开始安装。软件在安装完成后,还会将信息写入软件管理机制中,以便完成未来的升级、删除(反安装)等操作。

目前,在 Linux 界最常见的软件安装方式有两种:

  1. DPKG

    • DPKG(Debian Packager)是由 Debian Linux 社区所开发出来的,著名的 package 概念由此被引入到 GNU/Linux 系统中。
    • 通过 DPKG 机制,Debian 提供的软件就能够简单安装起来,同时还能提供安装后的软件信息。派生于 Debian 的其他 Linux Distributions 大多使用 dpkg 机制来管理软件,包括 B2DUbuntuLinux Mint 等。
    • Debian 为解决软件包更新问题,引入了 APT(Advanced Package Tool)在线升级机制,并在 /etc/apt/sources.list 文件列出了可获得软件包的镜像站点地址。
      • APT 由几个名字以 apt- 打头的程序组成,apt-get、apt-cache 和 apt-cdrom 是处理软件包的命令行工具。
      • apt 作为 dpkg 的前端工具,自动管理关联文件和维护已有配置文件,拥有出色的解决软件依赖问题的能力。
  2. RPM

    • RPM(RedHat Package Manager)是由 Red Hat 公司所开发出来的软件包管理程序。除了可以用来安装(-i)外,还可以进行查询(-q)、验证(-V)、更新(-U)、删除(-e)等操作,这些功能选项让软件的管理更加方便。包括 FedoraCenterOSSUSE/openSUSE 等知名的 linux 发行版本都使用 RPM 作为软件安装的管理机制。
    • RPM 包的封装格式一般有两种,分别是 RPMSRPM。RPM 格式的文件 xxx.rpm 内含已经经过编译的二进制包和配置文件等数据。SRPM(Source RPM)对应的 RPM 文件类似于 xxx.src.rpm 格式,它包含了源码文件和一些编译指定的参数文件。因而,在使用的时候,需要先以 RPM 管理的方式编译为 RPM 文件(rpmbuild,再将编译完成的 RPM 文件安装到 Linux 系统中。
    • RPM 无法自动解决软件的依赖关系,使用与 APT 对应的 YUM (Yellowdog Updater Modified) 机制可以解决属性依赖问题YUM 作为基于 RPM 的 Shell 前端软件包管理器,主要用于自动升级、安装/移除 RPM 软件包。它能够自动查找并解决 RPM 包之间的依赖关系,而无需管理员逐个手工的去安装每一个 RPM 包。
Distribution 代表 包管理机制 使用命令 在线升级机制(命令)
Red Hat / Fedora RPM rpm,rpmbuild YUM(yum)
Debian / Ubuntu DPKG dpkg APT(apt-get)

linux 众多发行版中,ubuntu 占领桌面,RHEL/CentOS 占领服务器,比较小众的 Gentoo 采用独特的 Portage 包管理系统。Gentoo 的软件树称为 Portage,对应的包管理器是 emerge,包元文件称为 ebuild。
Gentoo 是个强调能自由选择的分发版,它使用源码来做包管理的方式。由于能自己编译及调整源码依赖等选项,而获得至高的自定义性及优化的软件,在源码包也有相当多新旧版本的选择,因此吸引了许多狂热爱好者以及专业人士。

RPM / SRPM

RPM 软件包命名规范:name-version-release.arch.rpm
其中,version 表示系统的发行版,如 fc18、el6 表明这个软件包是在 Fedora 18、RHEL 6.x / CentOS 6.x 下使用的;arch 表示硬件平台,常见的有 i386、x86_64 等。

rp-pppoe-3.1-5.i386.rpm 是一个典型的 RPM 安装包,它由几个部分构成:

  • rp-pppoe:名称
  • 3.1:版本信息
  • 5:发布次数
  • .i386:适合的硬件平台
  • .rpm:扩展名

RPM 文件必须要在相同的 linux 环境才能安装,而 SRPM 是源代码格式。我们可以通过修改 SRAM 内的参数,按需编译生成适合我们 linux 环境的 RPM 文件,而不必与原作者打包的 Linux 环境相同。
通常一个软件在发布的时候,都会同时释放出该软件的 RPM 与 SRPM。

文件格式 扩展名格式 直接安装与否 内含程序类型 可否修改参数并编译
RPM xxx.rpm 已编译 ×
SRPM xxx.src.rpm × 未编译的源码

RPM 建包的原理并不复杂,可以理解为按照标准的格式整理一些信息,包括:软件基础信息,以及安装、卸载前后执行的脚本,对源码包解压、打补丁、编译,安装路径和文件等。我们可以基于标准规范,来使用 rpmbuild 制作自己的 RPM 包

Mac 软件包管理工具

linux 平台下的 apt-get 和 yum 命令行工具分别适用于 deb、rpm 包管理方式的发行版本,主要用于自动从互联网的软件仓库中搜索、安装、升级和卸载软件。在 Mac OS X 平台下,除了直接从 AppleStore 下载认证上架的软件进行安装外,还可以在系统偏好设置的【安全性与隐私】中允许从任何来源下载的应用。

dmg & pkg

一些应用会提供 dmg、pkg 安装包,例如 git-2.5.3-intel-universal-mavericks.dmgSubversion-1.9.2_10.10.x.pkg

  1. dmg 是苹果的压缩镜像文件(类似 Windows 下的 iso ),它是 Mac 应用软件通用的打包格式(相当于 ipa),里面一般包含 应用程序.app 的图标和一个应用程序文件夹(/Applications)快捷方式,直接将 应用程序.app 拖曳至应用程序文件夹即可完成安装。卸载也同样绿色,直接在 Launchpad 中或 cd 到 /Applications 目录下删除应用(文件夹)即可。

  2. pkg 属于系统级软件的安装程序,相当于 iOS 越狱后装的 deb,一般会修改系统配置,权限较高。pkg 安装一般要求 sudo 授权,卸载 pkg 安装的应用 也比较麻烦。pkg 类似 Windows 下的安装程序 Setup.exe 和 *.msi
    Windows 下可以使用 Install Shield制作安装程序,可使用 Xcode 自带的 PackageMaker 或打包命令行工具 pkgbuild+productbuild+pkgutilIceberg(an Integrated Packaging Environment (IPE) )来制作安装包

  3. mpkg:pkg 是单个应用程序的安装包,而 mpkg(multi pkg)是多个 pkg 。我们来看一下从 AppleStore 下载的 OS X EI Capitan 安装器文件——安装 OS X EI Capitan.app/Contents/SharedSupport 目录:

    <figure class="highlight" style="display: block; margin: 20px 0px; background-color: rgb(0, 36, 81); padding: 15px; overflow: auto; font-size: 13px; color: rgb(255, 255, 255); line-height: 1.6;">

    | |

    </figure>

    下载完 安装 OS X EI Capitan.app 之后,可以使用 createinstallmedia 命令制作 U 盘安装盘,或恢复到 U 盘制作启动盘

  4. dmg with pkg:像 git-2.5.3-intel-universal-mavericks.dmg 这种 dmg 打包的是 git command CLI 的安装 pkg,需要使用 DiskImageMounter 挂载 dmg,然后打开 pkg(使用 Installer),按照引导一步步 next 即可安装完成。当然也可使用 命令行 完成挂载安装操作。

除了使用 dmg、pkg 来安装软件外,Mac 下同样有优秀的软件包管理工具,可以下载、安装和管理大量 AppleStore 没有提供、而又经常会用到的开源软件。我们有两种选择 —— MacPorts 和 Homebrew。

MacPorts

MacPorts (DarwinPorts) 是由 FreeBSD 的 port 移植而来的软件包管理系统,,用来简化 Mac OS X和 Darwin 操作系统上软件的安装。在 Mac 中安装 MacPorts 让你在Mac 的 Shell 下更加游刃有余
MacPorts 有个原则,对于软件包之间的依赖,都在 MacPorts 内部(/opt/local)解决,无论系统本身是否包含了需要的库,都不会加以利用。这使得 MacPorts 庞大臃肿,导致系统出现大量软件包的冗余,占用不小的磁盘空间,同时稍大型一点的软件编译时间都会难以忍受。

Homebrew

Homebrew(简称 brew)是 Mac OS X 不可或缺的软件管理工具(The missing package manager for OS X),让 Mac 拥有类似 apt-get 的功能,用以简化软件的安装、升级和卸载过程。

Homebrew is the easiest and most flexible way to install the UNIX tools.

Homebrew 是一款使用 Ruby 进行开发的托管于 GitHub 上的自由及开放源代码的软件包管理系统,通过用户的贡献扩大对软件包的支持。

MacPorts vs Homebrew

MacPorts 和 Homebrew 这两种包管理系统的工作方式都是下载源代码,然后在本地编译。但是这两种包管理系统还是存在很大差异的,主要差异有以下三点:

  • MacPorts 的理念是尽量减少对系统现有库的依赖,编译时间较长;而 Homebrew 则是尽量依赖系统现有库,编译时间会显著减少。
  • MacPorts 的 Package 是安装到 /opt/local ,不会与系统现有的软件发生冲突;而 Homebrew 的 Package 是安装到 /usr/local,可能与系统自带的软件发生冲突。
  • Macports 使用 rsync 进行同步(也可以使用svn),而 Homebrew 使用 git 进行同步。

总体来说,Homebrew 使用简单,编译时间短,比较适合新手使用。MacPorts 编译时间长,命令还要带上 sudo,易用性上没有 Homebrew 好,但是比较干净,适合有洁癖的人使用。

以上梳理了 Linux 和 Mac 下的包管理机制,下面重点介绍 Mac OS X 上的包管理 CLI 命令行工具 brew 及其增强工具 brew-cask。

brew (homebrew)

brew 是从软件包仓库下载源代码码到本地进行解压,进而执行 ./configure && make install ,将软件编译安装到单独的目录(/usr/local/Cellar)下,然后软链(symlink)到 /usr/local 目录下,同时会自动检测下载相关依赖库,并自动配置好各种环境变量。
这个对程序员来说简直是福音,使用简单的指令就能快速安装、升级和卸载本地的各种开发环境。

安装 brew

brew 的安装很简单,使用一条 ruby 命令调用 curl 下载安装即可。

1.Mac OS X 上默认已安装 ruby

<figure class="highlight cpp" style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; display: block; margin: 20px 0px; background-color: rgb(0, 36, 81); padding: 15px; overflow: auto; font-size: 13px; color: rgb(255, 255, 255); line-height: 1.6; font-family: Lato, "PingFang SC", "Microsoft YaHei", sans-serif; text-align: justify;">

| |

</figure>

2.Mac OS X 上默认已内置了 curl(Command Line URL Viewer):

说明:

curl 是基于跨平台网络协议库 libcurl 的利用 URL 语法在命令行方式下工作的开源文件传输工具。
curl常用命令 可参考 curl 详解curl网站开发指南

旧的安装

很早之前,homebrew 的安装 url 是 https://raw.github.com/Homebrew/homebrew/go/install

首次执行 brew install 安装软件时,将提示不能创建 /usr/local/Cellar 目录,原因是没有 /usr/local 的写权限。

解决方法

执行 chown 命令改变 /usr/local 的所有者为 whoami-R 表示递归(Recursive)。

<figure class="highlight" style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; display: block; margin: 20px 0px; background-color: rgb(0, 36, 81); padding: 15px; overflow: auto; font-size: 13px; color: rgb(255, 255, 255); line-height: 1.6; font-family: Lato, "PingFang SC", "Microsoft YaHei", sans-serif; text-align: justify;">

| |

</figure>

新的安装

可以在 brew 的官网首页的末尾看到最新的安装代码:

最新的安装过程中将会要求输入密码授权 sudo chown ${whoami} /usr/local/*

brew help

brew -v / –version

安装完 brew,执行 brew -v 命令可以查看安装的 brew 版本信息:

brew 常用命令

执行 brew 查看帮助概要(Example usage、Troubleshooting、Brewing):

-h / –h / –help / help

  1. 执行 man brew 可查看详细的 brew 帮助文档。
  2. 执行 man home 可调用浏览器打开 brew 官方网站。
命令 说明
brew update 更新 brew
brew search FORMULA 查找软件包,可使用正则表达式
brew info FORMULA 显示软件的信息
brew deps FORMULA 显示包依赖
brew install FORMULA 安装软件包
brew uninstall FORMULA 卸载软件包
brew list 列出已安装的软件包,可指定 FORMULA
brew outdated 列出可升级的软件包
brew upgrade 更新已安装的软件包,可指定 FORMULA
brew doctor 诊断 homebrew 环境
brew prune 删除 /usr/local 下的无效链接(remove broken symlinks)

brew info

brew info 显示软件包信息,一般包括:

  • 软件概要信息
  • 本地是否已安装:Not installed / Poured from bottle
  • 依赖包:==> Dependencies,Build、Required、Recommended、Optional
  • 编译、安装选项: ==> Options
  • 预警信息:==> Caveats

brew info 查看 plist 文件

brew install 示例

tree

linux 下的 tree 命令以树形结构显示文件目录结构,Mac 下默认并没有该命令,只有普通的 ls 命令。可以利用 brew 查找并安装 tree 命令行工具:

  1. homebrew 下载已经编译好的二进制包 tree 到缓存目录 /Library/Caches/Homebrew/tree-1.7.0.el_capitan.bottle.1.tar.gz
  2. 解压 tree-1.7.0.el_capitan.bottle.1.tar.gz/usr/local/Cellar/tree/ 目录,根据版本存放到文件夹 1.7.0 下。
  3. /usr/local/Cellar/tree/1.7.0/bin/tree 软链到 /usr/local/bin/tree,后者是前者的替身,执行 tree 命令时,真正调用的是其在 Cellar 中的真身。

Axel

以下示例查找比 wget 下载速度高几倍的支持断点续传多线程下载 CLI 命令行工具 axel,并显示软件包信息和依赖关系,然后安装该工具:

  1. 从 homebrew 官方仓库 homebrew.bintray.com 下载 axel 失败后,自动从镜像源 mirrors.ocf.berkeley.edu重新下载。下载的源码缓存到目录 /Library/Caches/Homebrew/axel-2.4.tar.gz
  2. 下载完成后,依次执行 ./configuremakemake install 将软件编译安装到 /usr/local/Cellar/axel/ 目录下,根据版本存放到文件夹 2.4 下。
  3. usr/local/Cellar/axel/2.4/bin/axel 软链到 /usr/local/bin/axel,后者是前者的替身,执行 axel 命令时,真正调用的是其在 Cellar 中的真身。

subversion

search-info-deps-install 过程日志参考 brew install subversion.log

brew cask

Homebrew 作为 Ruby 社区极富想象力的作品,使得 Mac 下安装 Mysql 等常用包不再困难。那么,是否也可以通过 brew install mysql 这样简单的方式来安装 Google Chrome 浏览器呢?为解决这一问题,phinze 的作品 homebrew-cask 应运而生。

about

Homebrew 可以管理 Mac 下的命令行工具(wget、node),brew cask 则是一套建立在 brew 上的增强命令行工具,支持管理 Mac 下的 GUI 程序,例如 qq、 google-chrome、evernote 等。
cask 从镜像源下载已经编译好了的应用软件二进制包(.dmg/.pkg)到本地解压到单独的目录(/opt/homebrew-cask/Caskroom)下,然后软链(symlink)到 /Applications 目录下。
cask 包含了很多在 AppStore 里没有的常用软件,省掉了手动下载、解压、拖拽(安装)等步骤,且卸载也相当容易与干净,使用起来非常方便。

假设你已安装好了 Homebrew,执行以下命令查找 cask 包并显示软件包信息和依赖关系:

install

安装 cask 极其简单,打开终端输入:

brew tap phinze/homebrew-cask

由于 brew 和包含的包源都是通过 github 来管理,人为的维护管理。除了默认的仓库,还允许别人的源添加进来。通过 brew tap 指定第三方包源:

$ brew tap

默认的源是 caskroom/cask,以下显式 tap 原作者的源(phinze/homebrew-cask):

brew install brew-cask

本机已经安装了 brew-cask 的依赖软件 emacs :

如果没有安装 emacs,则 brew 在安装 cask 之前会自动帮我们下载安装 emacs

brew cask

执行 brew caskbrew-cask 可查看帮助概要(首次需输入 sudo 密码):

执行 brew-cask --version 命令可以查看安装的 brew-cask 版本信息:

command usage

brew cask 大部分命令和 brew 保持一致,新增了以下几条命令:

命令 说明
brew cask audit 查询指定 Cask 的可安装性
brew cask cat 查看指定 Cask 安装源信息
brew cask zap 打包指定 Cask
brew cask cleanup 清理缓存及软链

安装了 cask 之后,就可以像 brew 一样来搜索安装软件,以下示例 google-chrome :

搜索安装包

查询安装性

查询包信息

1.执行 brew-cask cat 查询指定 Cask 的源信息:

2.执行 brew-cask info 查询指定 Cask 的包信息:

安装/卸载 应用

brew-cask 安装和卸载的命令同 brew ,都是使用 install / uninstall

1.执行 brew cask install google-chrome 命令安装 google-chrome:

2.执行 brew cask uninstall google-chrome 命令卸载 google-chrome:

uninstall 命令将删除 /opt/homebrew-cask/Caskroom/google-chrome 及其在 ~/Applications/ 下的软链(symlink)。
我们也可手动删除 homebrew 下载目录中缓存的 google-chrome 安装包 /Library/Caches/Homebrew/google-chrome-latest.dmg 及其软链 /Library/Caches/Homebrew/Casks/google-chrome-latest.dmg

升级更新软件

brew-cask 并没有提供 brew 的 upgrade 命令,升级更新软件只能通过 DIY:

  1. 进入应用软件的【关于】,手动检查是否可更新升级,使用软件自己的更新流程。
  2. 卸载重装 (brew cask uninstall && brew cask install) ,实现间接升级。

brew-cask install 示例

文件预览插件

有些插件可以让 Mac 上的文件预览更有效,比如语法高亮、markdown 渲染、json 预览等等。通过 brew cask install命令可以安装这些插件:

Visual Studio Code

Wireshark

search-info-cat-audit-install 过程日志参考 brew-cask install wireshark.log

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容