Handling SIGPIPE error in snakemake
Asked Answered
D

2

7

The following snakemake script:

rule all:
    input:
        'test.done'

rule pipe:
   output:
       'test.done'
   shell:
        """
        seq 1 10000 | head > test.done
        """

fails with the following error:

snakemake -s test.snake

Provided cores: 1
Rules claiming more threads will be scaled down.
Job counts:
    count   jobs
    1   all
    1   pipe
    2

rule pipe:
    output: test.done
    jobid: 1

Error in job pipe while creating output file test.done.
RuleException:
CalledProcessError in line 9 of /Users/db291g/Tritume/test.snake:
Command '
        seq 1 10000 | head > test.done
        ' returned non-zero exit status 141.
  File "/Users/db291g/Tritume/test.snake", line 9, in __rule_pipe
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/concurrent/futures/thread.py", line 55, in run
Removing output files of failed job pipe since they might be corrupted:
test.done
Will exit after finishing currently running jobs.
Exiting because a job execution failed. Look above for error message

The explanation returned non-zero exit status 141 seems to say that snakemake has caught the SIGPIPE fail sent by head. I guess strictly speaking snakemake is doing the right thing in catching the fail, but I wonder if it would be possible to ignore some types of errors like this one. I have a snakemake script using the head command and I'm trying to find a workaround this error.

Delusive answered 4/10, 2017 at 15:56 Comment(2)
Yes, Snakemake sets pipefail by default, because in most cases this is people implicitly expect. You can always deactivate it for specific commands by prepending set +o pipefail; to the shell command.Famish
Thank you! If you post that as an answer I will accept it.Delusive
A
8

Yes, Snakemake sets pipefail by default, because in most cases this is what people implicitly expect. You can always deactivate it for specific commands by prepending set +o pipefail; to the shell command.

Archival answered 7/10, 2017 at 15:27 Comment(3)
Thank you. Maybe just a note of warning... set +o pipefail should be used with care since it will make succeed also a broken command like this seq 1 10000 | FooBar | head > {output}Delusive
Exactly, that is why Snakemake enables pipefail by default.Famish
I just use alternatives awk 'NR<=10' or ` sed -n '1,10p'` instead of head in order to avoid issues mentioned by @dariober.Careless
D
4

A somehow clunky solution is to append || true to the script. This will make the command always exit cleanly, which is not acceptable. To check whether the script actually succeded you can query the array variable ${PIPESTATUS[@]} to ensure it contains the expected exit codes:

This script is ok:

seq 1 10000 | head | grep 1 > test.done || true
echo ${PIPESTATUS[@]}
141 0 0

This is not ok:

seq 1 10000 | head | FOOBAR > test.done || true
echo ${PIPESTATUS[@]}
0
Delusive answered 5/10, 2017 at 8:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.