Linux命令行与shell脚本编程 3e

第三章 基本的bash shell命令

3.3 bash手册

man keyword / keyword -help

3.4浏览文件系统

cd
相对路径,绝对路径,当前目录,父目录 ,根目录
.. . ./ ~

  • -返回进入此目录之前所在的目录

ls

  • -d仅展示目录名,而不展示目录下的内容列表
  • -F 区分 文件夹和文件
  • -R 递归子目录和子文件
  • -l 展示详细信息
  • -a 显示隐藏 文件
  • -i 显示系统为文件分配的唯一编号 inode 编号
  • script_name:过滤,可以配合通配符 * ? 使用
  • --time=atime:显示的事件为访问时间而非更改时间。

3.6 处理文件

创建 touch

  • -a 只改变访问时间,不更改修改时间

复制 cp source destination

  • -i是否覆盖已有文件
  • destination可以是地址+文件名 也可以只有地址。但注意只有地址的时候,目录的最后一定加上/。避免最后一级文件在复制前其实并不存在的情况,在这种情况,将会复制一个与文件目录最后一级同名的文件。
  • 单点'.'在复制文件这里很适合用于将其他目录的文件复制到当前目录下
cp /etc/NetworkManager/NetworkManager.conf  .
  • -R:递归地复制整个目录

链接文件

  • ln -s data_file ln_data_file 符号链接,ln_data_file为独立的文件,拥有不同的修改时间,并且有不同于原文件的大小
  • ls -i data_file ln_data_file 硬链接,拥有相同的编号,文件大小,修改时间
  • 硬链接只能在同一储存媒体创建。
  • 不要创建链接文件的链接文件,应该选择对原文件创建链接文件,一面连接链错乱。

移动或重命名文件:mv

  • mv a b a和b在同一个目录,名字不同则为重命名。 ab目录不同则为移动目录,移动目录的文件名字也可以不同,此时既移动了目录,也更改了名字。

3.6删除文件:rm

  • -i确认是否要删除该文件
  • -f不受提示影响,强制删除文件
  • -r 递归

3.7 处理目录

3.7.1创建目录 mkdir

  • -p连续创建多个父子连接的目录 mkdir parent_floder/child_floder

3.7.2 删除目录

  • rmdir:删除空目录
  • rm -r 删除文件夹内的文件后,再删除文件夹
  • -rm -rf 强制删除文件夹及其中内容,且无提示

3.8查看文件内容

3.8.1查看文件类型 file

3.8.2 查看整个文件

1) cat

  • -n 显示行号
  • -b 只给有文本内容的行加上行号
  • -T 不显示制表符效果,使用^I替换所有制表符
    more/lsee
  • 空格翻页,回车下一行。
  • 可退出形式的查看部分文件:more/less(less提供更多功能)

3.8.3查看部分文件:tail/head

tail/head file_name:显示最后/开头10行
tail -n num 显示最后num行文本

第四章 更多的bash shell 命令

4.1检测程序

4.1.1 探查进程 ps

  • 默认只展示运行在当前控制台下属于当前用户的进程。
    ps的3中命令行参数类型:Unix, BSD, GNU 单破折线/无破折线/双破折线
  • a 全部进程
  • l 长列表

4.1.2事实监测进程 top

4.1.3结束进程

kill命令
kill [pid]
killall命令:通过进程名来识别需要结束的任务
kill process_name 可以使用通配符

4.2监测磁盘空间

第6章 使用Linux环境变量

6.1 什么是环境变量

用于储存有关shell会话和工作环境的信息
分为全局变量和局部变量

6.1.1全局环境变量

  • 所有的shell以及其子shell都是可见的。
  • printenv/env 不带参数可以查看所有的全局变量
  • printenv env_var / env $env_var 可以展示指定环境变量的内容

6.1.2局部环境变量

  • 没有单独变量用于展示局部环境变量,set用于展示包含全局和局部环境变量。

6.2设置用户定义变量

6.2.1 设置局部用户定义变量

  • 赋值 my_variable='zz' 注意整个语句不能有空格,否则会将第一个空格前的内容解释为shell命令。提示command not found
  • 引用 echomy_variable
  • 局部变量一般使用小写,全局变量使用大写
  • 自定义变量只在当前shell可用,不可在其余shell(包含该shell的子shell或父shell)

6.2.2设置全局环境变量

  • 先建立全局变量,再把它导入到全局变量中
$ my_variable='zz'
$ export my_variable
$ #此时的变量将可以在子shell中使用
  • 更改子shell中的全局变量,不影响其他shell中该变量的值。

6.3 删除环境变量 uset

unset my_variable #注意不需要$符号
  • 在子进程中删除了一个全局环境变量,父进程中该全局环境变量不受影响。

6.4默认的shell环境变量

参见本书的p111表 6-1

6.5设置PATH环境变量

  • 作用系统会搜索在PATH环境变量包含的目录,这些文件夹下的可执行文件,可以不指定路径而直接以文件名执行。
  • 查看 echo $PATH
  • 添加PATH环境变量
$ PATH=$PATH:/home/ubuntu/Scripts
  • 若当前的工作目录需要加入PATH环境变量
$ PATH=$PATH:. #直接以.代表当前目录即可
  • 本节定义的变量只能持续到退出或系统重启

6.2定义系统环境变量(让环境变量持久化)

  • 启动文件/环境文件: 当登入Linux系统启动一个bash shell时,bash会朝招几个文件中的命令。这些文件被称为启动文件/环境文件
  • 启动bash shell有三种方式,下面为三种方式的启动文件的介绍。(登录时作为默认登录shell/作为非登录shell的交互式shell/作为运行脚本的非交互式shell)

6.6.1 登录shell

以下五个启动文件

  • /etc/profile
  • $HOME/.bash_profile
  • $HOME/.bash_login
  • $HOME/.profile
  • $HOME/.bashrc
1)/etc/profile

系统上默认的bash shell的主启动文件。系统上的每个用户登录时都会执行。

  • 使用for循环运行/etc/profile.d目录下的所有文件。
        if [ -d /etc/profile.d ]; then 
            for i in  /etc/profile.d/*.sh; do 
                if [ -r $i ]; then . $i 
                fi 
             done 
        unset i
    
    
2) 其余4个$HOME目录下的启动文件
  • 提供一个用户专属的启动文件来定义该用户所用到的环境变量,大多数Linux发行版只使用这其中的一到两个。
    shell会按照顺序运行前三个文件,如果其中一个被运行,余下的则被忽略。
  • $HOME/.bash_profile
  • $HOME/.bash_login
  • $HOME/.profile

6.6.2 交互式shell进程

如果不是登录系统是启动的,则称为交互式shell。
则不会访问/etc/profile启动文件,只会访问HOME目录中的.bashrc文件。(这就是为什么在配置Jupyter notebook的时候,将相关路径加入~/.bashrc而非上方的3个文件)

6.6.3非交互式shell

  • 系统执行脚本时使用的shell。它没有命令行提示符。
  • BASH_ENV用于这种情况下,运行一些特定启动的命令。
  • 如果没有设置BASH_ENV,shell脚本可以继承并使用父shell中已经设置并且导出的变量。

6.6.4 环境变量持久化

方法:将变量放入环境变量。

  • /etc/profile 可能随着发行版的升级而更新覆盖,自定义的变量将失效
  • 在/etc/profile.d中新建一个.sh文件。把所有修改/定义的变量放入这个文件。系统启动运行etc/profile时将运行这里的sh文件。
  • 大多数发行版中,使用~/.bashrc储存永久性bash shell文件。但如果设置了BASH_ENV变量,如果BASH_ENV没有指向~/.bashrc,那么将不会生效。

6.7数组变量

$ # 括号中 空格分隔
$ myarr=(one two three)
$ #使用索引来引用对应的值
$ echo $(myarr[1])
$ #查看整个数组 索引值改为星号
$ #使用unset来删除数组的值。

第7章 理解Linux文件权限

7.1 Linux的安全性

  • uid 登录名-密码

7.1.1 /etc/passwd

包含以下内容

  • 用户登录名
  • 用户密码(默认显示为x)
  • 用户账户的uid
  • 用户账户的组ID
  • 用户账户的文本描述
  • 用户HOME目录的位置
  • 用户的默认shell

7.1.2 /etc/shadow文件

用于管理用户的密码以及密码有效期限的文件

  • 登录名
  • 加密后的密码
  • 自上次修改密码后过去的天数密码
  • 多少天后才能更改密码
  • 多少天后必须更改密码
  • 密码过期前多少天提醒用户更改密码
  • 密码过期后多少天禁用用户账户
  • 用户账户被禁用的日期
  • 预留字段

7.1.3 添加新用户 useradd

  • m 新建HOME目录
$ useradd -m test

7.1.4 删除用户 userdel

  • r 删除用户的HOME目录以及邮件目录
$ userdel -r test

7.1.4 用户修改

1. usermod

  • -l 修改登录名
  • -L 锁定账户
  • -p 修改账户的密码
  • -U 解除锁定,使用户能够登陆。

2. passwd和chpasswd
passwd:更改单个用户密码

  • e 下次登录必须更改密码
$ passwd test
$ #会让重复输入两次密码以更改该用户密码

chpasswd:使用标准文件批量更改用户密码
文件每行为 userid:passwd
3. chsh, chfn和change

7.2使用Linux组

7.2.1 /cat/group文件

  • 组名
  • 组密码
  • GID
  • 属于该组的用户列表

当一个用户在/etc/passwd文件中指定某个组为默认组时,用户账户不会作为该组成员再出现在/etc/group文件中。
当一个用户同时是多个组中的成员时,在/etc/passwd文件中记录的是用户所属的主组,也就是登录时所属的默认组,而其他组称为附加组。

7.2.2 创建新组

groupadd 创建无用户新组

$ groupadd groupname

usermod 往新组添加用户

  • g 更改用户的默认组
  • G添加该组到用户的属组的列表里,不会影响默认组
$ user -G/g shared test

7.2.3修改组 groupmod

  • -n 修改组名
  • -g 修改组id
$ groupmod -n new_name shared

7.3 理解文件权限

7.3.1使用文件权限符

ls -l 展示的第一个字段就是描述文件和目录权限的编码。
第一个字符描述了类型

    • 文件
  • d目录
  • l链接
  • c代表字符型设备
  • b代表块设备
  • n代表网络设备
    之后有3组字符的编码。分别为属主/属组/系统的其他用户。
    每个组内的权限包含3类rwx,若某个位置为-则表示没有该种权限。

7.3.2 默认文件权限

umask 查看新建文件的默认权限。
umask 返回4位数字。第一位为黏着位
后3位分别代表3个属的文件权限



但注意umask是返回的掩码,新建文件的默认权限实际上是使用全权限值(文件666目录777)减去umask值(8进制的计算)。比如若umask 为026,那么文件的默认权限为640(rw-r-----)。

7.4 改变安全性设置

7.4.1改变权限:chmod

  • 格式chmod options mode file
  • mode分为两种:八进制模式和符号模式

1)选项option

  • -R配合file的通配符,递归的将权限操作应用于多个文件和子目录。

2)八进制模式
chmod 760 file
3)符号模式
[ugoa][+-=][rwxXstugo]
3各参数分别表示

  • 用户组
  • 增减等于
  • 要应用的权限
$ chmod o+r file #对所有三个属 增加 r(读取权限)
$ chmod g-x file #对属组用户移除执行权限

7.4.2 改变所属关系

1) chown 改变文件属主
chown options owner[.group] file

$ chown dan newfile #改变文件属主
$ chown dan.shared newfile #改变文件的属主(dan)和属组(shared)
$ chown .shared new file #只改变文件的默认属组
$ chown test. newfile #如果Linux采用和用户登录名匹配的组名,在属主后加.,可以同时改变属主和属组

  • 只有root用户可以改变用户的属主,任何属主都可以改变用户的属组,只要属主属于更改前后两个属组的成员。
    2) chgrp改变文件的默认属组
    chgrp shared newfile

第9章 安装软件程序

  • PMS(package management system):曝光李系统
  • 基于Debian的发行版(如Ubuntu和Linux Mint)使用dpkg命令
  • 基于Red Hat的发行版(Fedora,openSUSE)使用rmp命令
  • 书本介绍了两种,仅总结dpkg的aptidue命令。
  • aptitude 和 apt-get/cache的比较

9.2 基于Debian的系统

用aptitude管理软件包

aptitude

  • show pkgname :查看包信息
  • install pkgname:安装包
  • remove pkgname:移除包
  • search pkgname:不完全匹配方式搜索包
    • 展示所有匹配的包
    • 包名前的i表示已安装。vp表示可安装
  • purge pkgname:移除包以及相关的配置文件和文件夹
  • safe-upgrade:安全升级全部包
  • full-upgrade/dist-upgrade:稍激进的升级策略
    dpkg
  • -L pkgname 展示这个已安装包的全部文件
  • -search absolute_file_name 展示这个绝对文件路径属于的包

aptitude仓库

清单地址:/etc/apt/sources.list

第10章 使用编辑器

第11章 构建基本脚本

11.2创建shell脚本文件

基本脚本实例

#!/bin/bash
date
who
  • 井号后的内容为注释,不会进行运行。
  • 在脚本目录下直接以脚本名运行,如果该目录不在环境变量PATH内,将无法找到该可执行文件。可以通过添加至$PATH或使用./script_name的方式来运行。
  • 新创建的问价你如果用户没有执行权限,需要新增用户对文件的执行权限。
$ chmod u+x file_name

11.3显示消息:echo

  • 如果需要展示双引号/单引号,那么使用单引号/双引号来划定字符串。
  • -n 将文本字符串和命令输出显示在同一行
$ echo "who is running this:"
$ who

11.4使用变量

11.4.1使用环境变量

  • 使用美元符号引用
  • 可以在双引号中引用
  • 如果需要展示美元符号$而非引用变量,可以使用反斜杠进行反转义。
  • ${}也是常见的变量引用方式,花括号用于帮助系统识别变量名。

11.4.2用户变量

  • 组成:字母,数字,下划线
  • 区分大小写
  • 系统会自动决定变量的数据类型
  • 变量在对应的shell脚本的结束前将一直有效
  • 与系统变量的引用方式一致。
  • 定义举例
var1=10
var2=testing
var3="more params"

11.4.3 命令替换

将b命令的输出赋值给b变量。

  • 反引号符和$()格式
$testing=`date`
$testing=${date}

11.5 重定向输入和输出

11.5.1 输出重定向

  • 指定输出的接收

$ date > receive_file
  • >> 两个大于号,表示追加而非替换,当receive_file存在时
$ who >> receive_file

11.5.2 输入重定向

将文件的内容重定向到命令。

  • 普通输入重定向
$ wc < test6
    2   11  6
# wc 直接接文件名,将会多返回一个字符串--文件名
$wc test6
    2   11  6   test6
  • 内联输入重定向:使用命令行而非文件来输入字符。开始和结尾使用相同的符号囊括内容。
$ wc << EOF
>wuliking
>jung un
>EOF
2 2 16

11.6 管道

  • 使用管道符号 “|”拼接多个命令,前一个命令的输出将作为后一个命令的输入。
  • 下方的命令会以more的方式展示sort后的file_name文件的内容
$ cat file_name|sort|more

11.7 执行数学运算

11.7.1 expr命令

$ expr 1 + 5
    6
$ expr 1 * 4
    expr: syntax error
$ expr 1 \* 4
    4

11.7.2 方括号

$ var1=$[1 + 5]
$ echo $var1
6
# 不赋值或不是用echo命令,直接写方括号表达式将报错
$ $[1 + 2]
3: command not found
# 因为算式的结果直接输入,将3作为命令解释
  • 星号也不会被解释成通配符,可以直接使用
  • 但是不能进行浮点计算

11.7.3 浮点解决方案

使用bash内建的bc计算器:bc
基本用法:shell下使用bc命令行进入bash计算器

$ bc #进入bc计算器
$ bc -q #进入bc计算器,且不显示普通进入时展示的bc欢迎信息
1+2
3# 进入后shell输入后,shell输入符消失,可以进行运算输入输出
  • 在bc内可以设置scale符号,指定输出结果的小数位数
  • quit退出bc
    脚本中使用bc
  • 基本格式:variable=$echo "options; expression" | bc)
variable=$echo "scale=4; 3.44/5" | bc)
echo $var1

./test
.6880
  • 使用内联重定向

$ cat test12 
#!/bin/bash 
var1=10.46 
var2=43.67 
var3=33.2 
var4=71 
var5=$(bc << EOF 
scale = 4 
a1 = ( $var1 * $var2) 
b1 = ($var3 * $var4)
$ #这一串输入的最终输出是a1 + b1
a1 + b1 
EOF
) 
echo The anwser is $var5

11.8 退出脚本

  • 退出码:范围0 - 255。0表示正常执行退出。

11.8.1 查看退出状态码

  • 运行中结束后,立刻运行 $? 命令可以返回退出码。

11.8.2 exit命令:指定退出码

  • 脚本最后一行 exit 5/exit $var_name。
  • 但是如果后面指定的常量值或变量的值大于255,那么将会返回整除255的余数。

第12章 使用结构化命令

12.1 使用If-then语句

if command
then commands
fi
  • 只要command运行成功(状态为0),commands就会被执行。

12.2 if-then-else 语句

if command
then 
    commands
else
    commands
fi

12.3嵌套if:elif

12.4 test命令

  • if-then语句无法执行状态码之外的条件。
  • if test variable
  • if [ condition ]

12.4.1 数值比较

  • -eq/ge/gt/le/lt/ne n2
    等于,大于等于,大于,小于等于,小于,不等于
  • 无法测试浮点数

12.4.2 字符串比较

  • str1=/!=/</>/ str2
    • 等于,不等于,小于,大于
    • 大于小于号必须进行转义,否则会解释为重定向。
    • 大于小于的顺序和sort命令的顺序是不同的。比较命令认为大小小于小写,而sort相反。因为比较使用

      ASCII顺序,而sort使用本地的设置,本地设置的小写字母在大写字母前。

  • -n/z str1
    长度为非0,长度为0

12.4.3 文件比较

![0b22ac682d375b9f946b6691110d334a.png](en-resource://database/16725:0)

12.5 复合条件

  • and:[ condition1 ] && [ condition2 ]
  • or: [ condition1 ] || [ condition2 ]

12.6 if-then的高级特性

12.6.1使用双括号:数学表达式

((expression))


除了表中的高级表达式外,也可以使用上方的大于小于等基础比较符号,且不需要使用反转义符。

12.6.2 使用方括号:高级字符串表达式

[[expression]]
可以使用匹配模式

$ if [[ $USER == r* ]] # 如果用户名是r开头

12.7 case命令


case variable in 
pattern1 | pattern2) commands1;; 
pattern3) commands2;; 
*) # 在上方列出的模式外的所有情况,执行默认指令 
    default commands;; 
esac
  • pattern是可以使用通配符的。

第13章 更多的结构化命令

13.1 for命令

基本格式

for var in list
do
    commands
done

13.1.1读取列表中的值

for test in hunan hubei shanxi

  • 使用空格分隔
  • 如果需要使用单引号,或单个元素中间需要使用空格,可以使用双引号囊括

13.1.3 从变量读取列表

list="hunan hubei shanxi"
# 在已有字符串变量后新增字符串的方法
list=$list" henan"

for state in $list
do 
    echo "Have you ever visited $state"
done

13.1.4 从命令中读取值

file="states"
# cat获取文件states中的内容,再使用for进行遍历
for state in $(cat  $file)
do
    echo "Visiting $state
done

13.1.5 更改字符分隔符

  • IFS Internal field separator,内部字段分隔符
  • bash shell默认空格,制表符,换行符为IFS
  • 修改IFS:IFS=$'\n
  • 备份当前IFS并在之后恢复:IFS.OLD=IFS;IFS='\n';IFS=$IFS.OLD
  • 指定多个字符为IFS: IFS='\n:;'#换行,分号,冒号为IFS

13.1.6 用通配符读取目录

for file in CHAP13/* #file遍历全部文件和文件夹
可以在一个for语句,连续遍历多个文件夹,以空格分隔即可
for file in CHAP13/* CHAP14/*

13.2 C语言风格的for命令

基本格式
for (( variable assignment ; condition ; iteration process))

# 并不需要使用美元符来引用变量
for (( a = 1 ; a < 10 ; a++))
do
    echo "The next number is $i"
done

13.2.2 使用多个变量

# 同时迭代a和b
for (( a = 1, b = 10; a <= 10; a++, b-- ))
do
    echo "$a - $b"
done

13.3 while命令

13.3.1 基本格式

while command
do
    commands
 done

13.3.2 使用多个测试命令

  • while后进行多个测试命令。最后一个测试命令的退出状态码会决定是否退出循环。
var1 = 10
while echo $var1
# 每个测试命令为单独一行
    [ $var1 -ge 0]
do
    echo "loop is not ended"
    var1=$[ $var1 - 1]
done

13.4 until命令

格式,多个命令测试与while一致;跳出循环的方式与while相反

13.5嵌套循环

(与其他语言一样) while, for, until都是可以互相嵌套的。

13.6 循环处理文件数据

使用两个for嵌套循环,每层分别指定不同的IFS,来遍历/etc/paswd的每行,每个冒号分隔符的内容。

13.7 控制循环

13.7.1 break命令

1.一层循环时,跳出循环
2.多层循环时,break:跳出最内层循环 break n 由内往外在停止n层的循环

13.7.2 continue循环

与break终止一层循环不同,continue只会提前终止某次循环(在这次循环中,不执行continue后的命令)
continue n 可以指定往外跳多少层,继续命令。

13.8 处理循环的输出

在done命令 加一个输出命令实现for循环内的所有输出到屏幕的内容输出到文件。
也可以像管道一样,将整个循环作为管道中的一节(一个命令)。

第14章 处理用户输入

$0 程序名

  • 在程序启用语句后,以空格分隔参数 ./test3.sh param1 param2
  • 如果单个参数内包含空格,以双引号包围该参数
    1 -9 第i个参数
    参数序号大于9时的参数引用方式 ${10}
  • 如果不是在当前目录下直接调用脚本,那么$0将传递包含路径的脚本名。可以使用basename命令引用不包含路径的脚本名
$ name=${basename $0}
  • 判断参数是否存在
$ if [ -n "$1" ]
$   ...
$fi

14.2特殊参数变量

  • $# 返回参数的个数
  • 花括号内不能使用美元符,而需使用感叹符或赋值给其他参数
$ #使用叹号引用
$ echo the last parameter was ${!#}
$ #使用参数赋值方法引用
$ params=$#
$ echo the last parameter was $params

14.2.2 获取所有参数

  • $* 将所有参数作为一个整体引用。
  • $@ 将所有参数作为多个独立的单词,可以使用for等方式进行遍历。
  • 注意使用时需要在*@ 加上双引号[why?]

14.3 移动变量

shift :所有参数往左移动一个位置,第一个被删除。理解成python的list pop(0)

  • 常用于传了未知个数的参数,使用一个while [ -n "1"]的循环,依次遍历1这个变量,再shift,以此遍历全部参数。
  • 可以加参数n来移动n个位置: shift n。

14.4 处理选项

第X章 零散

cron 周期性调度
crontab -l

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