05-Nextflow Processes(2)

指令(Directives)

使用指令声明块,可以提供影响当前进程执行的可选设置。

它们必须在进程体的顶部输入,在其他声明块(如输入、输出等)之前,语法如下:

name value [, value2 [,..]]

有些指令通常对所有进程都可用,有些指令则依赖于当前定义的执行器。

指令有:


accelerator

accelerator指令允许你指定任务执行所需的硬件加速器,例如GPU处理器。例如:

process foo {
    accelerator 4, type: 'nvidia-tesla-k80'

    script:
    """
    your_gpu_enabled --command --line
    """
}

上面的例子将要求4个nvidia-tesla-k80类型的gpu。

Note
这个指令只被AWS Batch,谷歌Life Sciences和Kubernetes执行器支持。

Tip
加速器类型选项值取决于目标执行平台。有关可用加速器的详细信息,请参阅目标平台文档。AWS, Google, Kubernetes.


afterScript

afterScript指令允许您在主进程运行后立即执行自定义(Bash)代码段。这可能对清理暂存区很有用。


beforeScript

beforecript指令允许您在运行主进程脚本之前执行自定义(Bash)代码段。这对于初始化底层集群环境或其他自定义初始化可能很有用

例如:

process foo {

  beforeScript 'source /cluster/bin/setup'

  """
  echo bar
  """

}

cache

缓存指令允许您将进程结果存储到本地缓存中。当启用缓存并使用resume选项启动管道时,后续执行进程的任何尝试以及相同的输入都将导致跳过进程执行,生成存储的数据作为实际结果。

缓存特性通过索引流程脚本和输入来生成唯一的键。此键用于单一地标识流程执行产生的输出。

缓存在默认情况下是启用的,你可以通过将缓存指令设置为false来禁用它。例如:

process noCacheThis {
  cache false

  script:
  <your command string here>
}

cache指令的可能值如下表所示:

Value Description
false 禁用缓存功能
true (default) 启用缓存。缓存keys是为输入文件元数据信息(名称、大小和最后更新时间戳属性)创建的索引
'deep' 启用缓存。缓存keys是为输入文件内容创建索引的
'lenient' 启用缓存。缓存keys被创建为输入文件的路径和大小属性索引(此策略为由于文件时间戳不一致而在共享文件系统上观察到的错误缓存失效提供了一个解决方案;需要0.32版本。x或更高版本)

conda

conda指令允许使用conda包管理器定义流程依赖项。
Nextflow自动为conda指令中列出的给定包名设置一个环境。例如:

process foo {
  conda 'bwa=0.7.15'

  '''
  your_command --here
  '''
}

可以指定多个包,用空格分隔它们。bwa = 0.7.15 fastqc = 0.11.5。需要下载特定包的频道名可以使用通常的Conda表示法指定,即在包前面加上频道名,如bioconda::bwa=0.7.15所示。

conda目录还允许指定conda环境文件路径或现有环境目录的路径。有关更多细节,请参阅Conda environments页面。


container

容器指令允许你在Docker容器中执行进程脚本。

它要求Docker守护进程运行在执行管道的机器上,即使用本地执行器时运行在本地机器上,或者通过网格执行器部署管道时运行在集群节点上。

例如:

process runThisInDocker {

  container 'dockerbox:tag'

  """
  <your holy script here>
  """

}

只需将上面的脚本dockerbox:tag替换为您想要使用的Docker映像名称。

Tip
这对于在可复制的自包含环境中执行脚本或在云中部署管道非常有用。


containerOptions

containerOptions指令允许你指定底层容器引擎支持的任何容器执行选项(ie. Docker, Singularity, etc)。这对于只提供特定进程的容器设置很有用,例如挂载自定义路径:

process runThisWithDocker {

    container 'busybox:latest'
    containerOptions '--volume /data/db:/db'

    output: file 'output.txt'

    '''
    your_command --data /db > output.txt
    '''
}

Warning
AWS、Batch和Kubernetes执行程序不支持此特性。


cpus

CPU指令允许你定义进程任务所需的(逻辑)CPU数量。例如:

process big_job {

  cpus 8
  executor 'sge'

  """
  blastp -query input_sequence -num_threads ${task.cpus}
  """
}

这个指令对于执行多进程或多线程命令/工具的任务是必需的,它是为了在通过集群资源管理器执行管道任务时预留足够的cpu。
See also: penv, memory, time, queue, maxForks


clusterOptions

clusterOptions指令允许使用您的集群提交命令接受的任何本机配置选项。您可以使用它来请求非标准资源,或者使用特定于您的集群的、Nextflow不支持的开箱即用的设置。

Note
这个指令只在使用基于网格的执行器时被考虑:SGE, LSF, SLURM, PBS/Torque, PBS Pro, Moab和HTCondor执行器。


disk

磁盘指令允许您定义进程可以使用多少本地磁盘存储。例如:

process big_job {

    disk '2 GB'
    executor 'cirrus'

    """
    your task script here
    """
}

当指定磁盘值时,可以使用以下内存单元后缀:

Unit Description
B Bytes
KB Kilobytes
MB Megabytes
GB Gigabytes
TB Terabytes

Note
该指令目前只被Ignite和HTCondor执行者考虑。
See also: cpus, memory time, queue and Dynamic computing resources.


echo

默认情况下,在所有进程中执行的命令生成的标准输出将被忽略。将echo指令设置为true,就可以将进程标准输出转发到当前运行的最顶端的进程标准输出文件,并在shell终端中显示它。

例如:

process sayHello {
  echo true

  script:
  "echo Hello"
}
Hello

如果没有指定echo true,在执行上面的示例时,您将看不到输出的Hello字符串。


errorStrategy

errorStrategy指令允许您定义进程如何管理错误条件。默认情况下,当执行的脚本返回错误状态时,进程立即停止。这反过来又迫使整个管道终止。

可用的error strategies:

Name Executor
terminate 一旦报告错误条件,就终止执行。挂起的jobs被杀死(默认)
finish 在引发错误条件时,启动有序的管道关闭,等待任何提交的作业完成
ignore 忽略流程执行错误
retry 重新提交返回错误条件的进程以执行

当将errorStrategy指令设置为ignore,进程不会在错误条件下停止时,它只报告一条通知错误事件的消息。

例如:

process ignoreAnyError {
   errorStrategy 'ignore'

   script:
   <your command string here>
}

Tip
根据定义,当命令脚本以非零退出状态结束时,它将失败。要更改此行为,请参见validExitStatus

重试错误策略,允许您为执行重新提交返回错误条件的进程。例如:

process retryIfFail {
   errorStrategy 'retry'

   script:
   <your command string here>
}

失败进程的重新执行次数由maxRetries和maxErrors指令定义。

Note
更复杂的策略取决于任务退出状态或其他参数值,可以使用动态errorStrategy指令定义。有关详细信息,请参阅Dynamic directives一节。
See also: maxErrors, maxRetries and Dynamic computing resources


executor

执行器定义了执行进程的底层系统。 默认情况下,进程使用nextflow.config文件中全局定义的执行程序。

executor指令允许您配置进程必须使用的executor,覆盖默认配置。可以使用以下值:

Name Executor
local 进程在启动Nextflow的计算机中执行
sge 该流程使用Sun Grid Engine / Open Grid Engine执行
uge 该进程使用Univa Grid Engine作业调度程序执行
lsf 该进程使用Platform LSF作业调度程序执行
slurm 该进程使用SLURM作业调度程序执行
pbs 进程使用PBS/Torque作业调度程序执行
pbspro 进程使用PBS Pro作业调度程序执行
moab 该进程使用Moab作业调度程序执行
condor 该进程使用HTCondor作业调度程序执行
nqsii 该进程使用NQSII作业调度程序执行
ignite 该过程使用Apache Ignite集群执行
k8s 该进程使用Kubernetes集群执行
awsbatch 该流程使用AWS Batch服务执行
google-pipelines 该流程使用谷歌Genomics pipeline服务执行

以下示例显示了如何设置进程的执行程序:

process doSomething {

   executor 'sge'

   script:
   <your script here>

}

Note
每个执行器都提供了自己的一组配置选项,可以在指令声明块中设置这些选项。请参阅Executors一节来阅读具体的executor指令。


ext

ext 是一个特殊指令,用作用户自定义流程指令的命名空间。 这对于高级配置选项很有用。 例如:

process mapping {
  container "biocontainers/star:${task.ext.version}"

  input:
  file genome from genome_file
  set sampleId, file(reads) from reads_ch

  """
  STAR --genomeDir $genome --readFilesIn $reads
  """
}

在上面的例子中,进程使用了一个容器,其版本由ext.version属性控制。这可以在nextflow.config中定义,如下所示:

process.ext.version = '2.5.3'

machineType

在使用谷歌管道执行器运行时,可以使用machineType指定一个预定义的谷歌计算平台机器类型

这个指令是可选的,如果指定了,它将覆盖cpu和内存指令:

process foo {
  machineType 'n1-highmem-8'

  """
  <your script here>
  """
}

Note
该特性需要Nextflow 19.07.0或更高版本。


maxErrors

maxErrors指令允许您指定使用重试错误策略时进程可能失败的最大次数。默认情况下,这个指令是禁用的,你可以如下所示设置它:

process retryIfFail {
  errorStrategy 'retry'
  maxErrors 5

  """
  echo 'do this as that .. '
  """
}

Note
此设置考虑给定流程在所有实例中累积的错误总数。如果您想控制流程实例(也就是任务)失败的次数,请使用maxRetries


maxForks

maxForks指令允许您定义可以并行执行的最大进程数。默认情况下,该值等于可用CPU核数减1。

process doNotParallelizeIt {

   maxForks 1

   '''
   <your script here>
   '''

}

maxRetries

maxRetries指令允许您定义一个流程实例在失败时可以重新提交的最大次数。此值仅在使用重试错误策略时应用。默认情况下,只允许一次重试,您可以增加该值,如下所示:

process retryIfFail {
    errorStrategy 'retry'
    maxRetries 3

    """
    echo 'do this as that .. '
    """
}

Note
maxRetries和maxErrors指令之间有一个细微但重要的区别。后者定义了流程执行期间允许的错误总数(同一个流程可以启动不同的执行实例),而maxRetries定义了在出现错误时可以重试同一流程执行的最大次数。

See also: errorStrategy and maxErrors.


memory

内存指令允许你定义进程可以使用多少内存。例如:

process big_job {

    memory '2 GB'
    executor 'sge'

    """
    your task script here
    """
}

当指定内存值时,可以使用以下内存单元后缀:

Unit Description
B Bytes
KB Kilobytes
MB Megabytes
GB Gigabytes
TB Terabytes

See also: cpus, time, queue and Dynamic computing resources.


module

Environment Modules是一个包管理器,允许您动态配置执行环境,并轻松地在同一软件工具的多个版本之间切换

如果在您的系统中可以使用它,您可以将它与Nextflow一起使用,以便在管道中配置流程执行环境。

在流程定义中,您可以使用module指令来加载流程执行环境中使用的特定模块版本。例如:

process basicExample {

  module 'ncbi-blast/2.2.27'

  """
  blastp -query <etc..>
  """
}

你可以为你需要加载的每个模块重复module指令。或者,可以在一个module指令中指定多个模块,使用:(冒号)字符分隔所有模块名,如下所示:

 process manyModules {

   module 'ncbi-blast/2.2.27:t_coffee/10.0:clustalw/2.1'

   """
   blastp -query <etc..>
   """
}

penv

penv指令允许你在向SGE资源管理器提交并行任务时定义要使用的并行环境。例如:

process big_job {

  cpus 4
  penv 'smp'
  executor 'sge'

  """
  blastp -query input_sequence -num_threads ${task.cpus}
  """
}

此配置取决于网格引擎安装提供的并行环境。请参阅集群文档或联系管理员了解更多相关信息。

Note
该设置在使用SGE执行器时可用。

See also: cpus, memory, time


pod

pod指令允许在使用Kubernetes执行器时定义pod特定的设置,比如环境变量、秘密和配置映射。

例如:

process your_task {
  pod env: 'FOO', value: 'bar'

  '''
  echo $FOO
  '''
}

上面的代码片段定义了一个名为FOO的环境变量,其值为bar。

pod指令选项见pod options

在Nextflow配置文件中定义pod设置时,可以使用规范关联数组语法定义pod设置。例如:

process {
  pod = [env: 'FOO', value: 'bar']
}

当需要提供多个设置时,它们必须包含在列表定义中,如下所示:

process {
  pod = [ [env: 'FOO', value: 'bar'], [secret: 'my-secret/key1', mountPath: '/etc/file.txt'] ]
}

publishDir

publishDir指令允许您将进程输出文件发布到指定的文件夹。例如:

process foo {

    publishDir '/data/chunks'

    output:
    file 'chunk_*' into letters

    '''
    printf 'Hola' | split -b 1 - chunk_
    '''
}

上面的例子将字符串Hola分割成单个字节的文件块。当完成时,chunk_*输出文件被发布到/data/chunks文件夹中。

Tip
可以多次指定publishDir指令,以便将输出文件发布到不同的目标目录。该特性需要0.29.0或更高版本。

默认情况下,将文件发布到目标文件夹,为每个流程输出创建符号链接,将生成的文件链接到流程工作目录。可以使用mode参数修改此行为。

可与publishDir指令一起使用的可选参数表:

Name Description
mode 文件发布方法。有关可能的值,请参见下表
overwrite 当为真时,指定文件夹中的任何现有文件将被覆盖(默认值:在正常管道执行期间为真,在管道执行恢复时为假)
pattern 指定一个glob文件模式,该模式从整个输出文件集中选择要发布的文件
path 指定需要发布文件的目录。注意:语法publishDir '/some/dir'是publishDir路径'/some/dir'的快捷方式
saveAs 一个闭包,给定要发布的文件的名称,它返回实际的文件名或需要存储文件的完整路径。可以使用自定义策略动态地重命名或更改已发布文件的目标目录。从闭包返回null值以不发布文件。当流程有多个输出文件,但您只想发布其中的一些文件时,这是非常有用的
enabled 根据指定的布尔值启用或禁用发布规则(默认值:true)

发布方式表:

Mode Description
symlink 在发布目录中为每个进程输出文件创建绝对符号链接(默认)
rellink 在发布目录中为每个流程输出文件创建一个相对符号链接
link 在发布目录中为每个流程输出文件创建硬链接
copy 将输出文件复制到发布的目录中
copyNoFollow 复制输出文件到发布目录,而不遵循符号链接ie。复制链接本身
move 将输出文件移动到发布目录中。注意:这只适用于一个终止过程,即一个输出不被任何其他下游过程消耗的过程

Note
模式值需要指定为字符串字面量,即用引号括起来。多个参数之间需要用冒号分隔。

例如:

process foo {

    publishDir '/data/chunks', mode: 'copy', overwrite: false

    output:
    file 'chunk_*' into letters

    '''
    printf 'Hola' | split -b 1 - chunk_
    '''
}

Warning
文件以异步方式复制到指定的目录中,因此在进程执行结束时,它们可能不会立即在发布的目录中可用。由于这个原因,流程发布的文件不能被其他下游流程访问

后面流程需要调用结果时,谨慎使用copy模式!


queue

当在管道中使用基于网格的执行器时,队列目录允许您设置调度作业的队列。例如:

process grid_job {

    queue 'long'
    executor 'sge'

    """
    your task script here
    """
}

多个队列可以用逗号分隔,例如:

process grid_job {

    queue 'short,long,cn-el6'
    executor 'sge'

    """
    your task script here
    """
}

Note
这个指令只被以下执行器考虑: SGE, LSF, SLURM和PBS/Torque执行器。


label

label指令允许使用您选择的助记符标识符来注释进程。例如:

process bigTask {

  label 'big_mem'

  '''
  <task script>
  '''
}

同一个标签可以应用到多个进程,并且使用label指令可以不止一次地将多个标签应用到同一个进程。

Note
标签必须由字母数字字符或_组成,必须以字母字符开始,以字母数字字符结束。

标签有助于将工作流程组织成不同的组,这些组可参考配置文件,以选择和配置具有类似计算要求的流程子集。

有关详细信息,请参阅Process selectors文档。


scratch

scratch指令允许您在执行节点本地的临时文件夹中执行流程。

当使用网格执行器启动管道时,这是非常有用的,因为它允许您在实际执行节点的本地磁盘的临时目录中运行管道进程,从而减少NFS开销。只有流程定义中声明为输出的文件才会复制到管道工作区中。

在其基本形式中,只需在指令值处指定true,如下所示:

process simpleTask {

  scratch true

  output:
  file 'data_out'

  '''
  <task script>
  '''
}

通过这样做,它尝试在执行节点中变量$TMPDIR定义的目录中执行脚本。如果这个变量不存在,它将使用Linux命令mktemp创建一个新的临时目录。

除了$TMPDIR之外,还可以通过简单地使用它作为scratch值来指定自定义环境变量,例如:

scratch '$MY_GRID_TMP'

注意,它必须用单引号字符包装,否则变量将在管道脚本上下文中计算。

你也可以提供一个特定的文件夹路径作为scratch值,例如:

scratch '/tmp/my/path'

这样,每次执行进程时,将在指定的路径中创建一个新的临时目录。

最后,当RAM -disk字符串作为scratch值提供时,进程将在节点RAM虚拟磁盘中执行。

允许值的汇总:

scratch Description
false 不要使用scratch文件夹
true 在$TMPDIR变量定义的目录中创建一个scratch文件夹;如果该变量不存在,则回退到mktemp /tmp
$YOUR_VAR 在$YOUR_VAR环境变量定义的目录中创建一个scratch文件夹;如果该变量不存在,则回退到mktemp /tmp
/my/tmp 在指定的目录中创建一个暂存文件夹
ram-disk 在RAM磁盘/dev/shm/(实验性)中创建一个scratch文件夹

storeDir

storeDir指令允许您定义一个目录,该目录用作进程结果的永久缓存。

更详细地说,它主要通过两种方式影响流程执行:
1、仅当 storeDir 指令指定的目录中不存在 output 子句中声明的文件时,才会执行该过程。 当文件存在时,流程执行被跳过,这些文件被用作实际的流程结果。
2、每当进程成功完成时,输出声明块中列出的文件都会移动到 storeDir 指令指定的目录中。

下面的例子展示了如何使用storeDir指令创建一个包含由输入参数指定的每个物种的BLAST数据库的目录:

genomes = Channel.fromPath(params.genomes)

process formatBlastDatabases {

  storeDir '/db/genomes'

  input:
  file species from genomes

  output:
  file "${dbName}.*" into blastDb

  script:
  dbName = species.baseName
  """
  makeblastdb -dbtype nucl -in ${species} -out ${dbName}
  """

}

Warning
storeDir指令是用于长期的进程缓存,不应该用于将进程产生的文件输出到特定的文件夹或在语义目录结构中组织结果数据。在这些情况下,你可以使用publishDir指令。

Note
支持使用AWS S3路径,但需要在目标计算节点上安装AWS CLI tool(即AWS)。


stageInMode

stageInMode指令定义了如何将输入文件阶入到进程工作目录。允许设置如下值:

Value Description
copy 通过创建一个副本,输入文件被暂存到流程工作目录中
link 通过为每个输入文件创建一个(硬)链接,输入文件被暂存到流程工作目录中
symlink 通过为每个输入文件创建带有绝对路径的符号链接(默认),将输入文件暂存到流程工作目录中
rellink 通过为每个输入文件创建一个具有相对路径的符号链接,输入文件将被暂存到流程工作目录中

stageOutMode

stageOutMode指令定义了如何将输出文件从暂存目录分段移到进程工作目录。允许设置如下值:

Value Description
copy 输出文件从scratch目录复制到工作目录
move 输出文件从scratch目录移动到工作目录
rsync 使用rsync实用程序将输出文件从scratch目录复制到工作目录

See also: scratch.


tag

tag指令允许您将每个流程执行与自定义标签关联起来,以便更容易在日志文件或跟踪执行报告中识别它们。例如:

process foo {
  tag "$code"

  input:
  val code from 'alpha', 'gamma', 'omega'

  """
  echo $code
  """
}

上面的代码片段将打印一个类似于下面的日志,其中进程名包含标记值:

[6e/28919b] Submitted process > foo (alpha)
[d2/1c6175] Submitted process > foo (gamma)
[1c/3ef220] Submitted process > foo (omega)

See also Trace execution report


time

time指令允许您定义允许进程运行多长时间。例如:

process big_job {

    time '1h'

    """
    your task script here
    """
}

当指定持续时间值时,可以使用以下时间单位后缀:

Unit Description
s Seconds
m Minutes
h Hours
d Days

dynamic directivess

指令可以在进程执行期间动态赋值,因此它的实际值可以根据一个或多个进程的输入值来计算。

为了以动态方式定义指令的值,需要使用闭包语句来表示,如下面的例子所示:

process foo {

  executor 'sge'
  queue { entries > 100 ? 'long' : 'short' }

  input:
  set entries, file(x) from data

  script:
  """
  < your job here >
  """
}

在上面的例子中,queue指令是动态计算的(三元运算符返回值),这取决于输入值条目。当它大于100时,作业将被提交到long队列,否则将使用short队列。

除了下面的两个指令外,所有的指令都可以被赋给一个动态值:

Note
您可以使用隐式变量task在流程脚本中检索动态指令的当前值,该变量任务保存在当前流程实例中定义的指令值。

例如:

process foo {

   queue { entries > 100 ? 'long' : 'short' }

   input:
   set entries, file(x) from data

   script:
   """
   echo Current queue: ${task.queue}
   """
 }

dynamic computing resources

一个非常常见的场景是,同一进程的不同实例在计算资源方面可能有非常不同的需求。例如,在这种情况下,请求的内存量过低将导致某些任务失败。相反,使用适合执行中的所有任务的更高的限制可能会显著降低作业的执行优先级。

动态指令计算特性可用于在进程失败的情况下修改请求的计算资源量,并尝试使用更高的限制重新执行它。例如:

process foo {

    memory { 2.GB * task.attempt }
    time { 1.hour * task.attempt }

    errorStrategy { task.exitStatus in 137..140 ? 'retry' : 'terminate' }
    maxRetries 3

    script:
    <your job here>

}

在上面的例子中,内存和执行时间限制是动态定义的。流程第一次执行任务时。attempt设置为1,因此它将请求2 GB内存和1小时的最大执行时间。

如果任务执行失败,报告的退出状态在137和140之间,任务将被重新提交(否则立即终止)。这次是任务的价值。attempt为2,因此将内存数量增加到4gb,时间增加到2小时,以此类推。

指令maxRetries设置了相同任务可以重新执行的最大时间。


dynamic Retry with backoff

在某些情况下,所需的执行资源可能暂时不可用,例如网络拥塞。在这些情况下,立即重新执行任务可能会导致相同的错误。具有指数回退延迟的重试可以更好地恢复这些错误条件:

process foo {
  errorStrategy { sleep(Math.pow(2, task.attempt) * 200 as long); return 'retry' }
  maxRetries 5
  script:
  '''
  your_command --here
  '''
}

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

推荐阅读更多精彩内容