🐓

CWL の requirements 一巡り: ShellCommandRequirement

2020/12/12に公開

この記事は CWL Advent Calendar 2020 の13日目の記事です。

Common Workflow Language (CWL) では、ワークフロー実行処理系が満たさなければならない機能以外にも、Process requirements と呼ばれる optional features についても標準化が行われています[1]

今回は CWL v1.2 で定義されている ShellCommandRequirement について簡単な解説を行います。また、各サンプルは可能な限り公式の準拠度テストで用いられているファイルを引用します。

対象読者

Conformance test #10: tests/stderr.cwl:

#!/usr/bin/env cwl-runner
class: CommandLineTool
cwlVersion: v1.2
doc: "Test of capturing stderr output."
requirements:
  ShellCommandRequirement: {}
inputs: []
outputs:
  output_file:
    type: File
    outputBinding: {glob: error.txt}
arguments:
 - { valueFrom: "echo foo 1>&2", shellQuote: False }
stderr: error.txt

ShellCommandRequirement を宣言すると、CommandLineBinding (各入力パラメータ中の inputBinding フィールドや、arguments フィールドの各要素として現れます) 中の shellQuote: false[2] が処理系によって解釈されるようになります。これにより、シェルコマンドでのメタキャラクタ (&| など) がエスケープされずに実行されるようになります。

文字のみの説明ではわかりにくいため、以下に具体例を示します。

shellQuote: true もしくは ShellCommandRequirement が宣言されていない場合 (デフォルト)

$ sed -e 's/shellQuote: False/shellQuote: True/' tests/stderr.cwl > stderr-true.cwl
$ grep shellQuote stderr-true.cwl 
 - { valueFrom: "echo foo 1>&2", shellQuote: True }
$ cwltool stderr-true.cwl tests/empty.json 
...
INFO [job stderr-true.cwl] /tmp/miju1_3y$ /bin/sh \
    -c \
    'echo foo 1>&2' 2> /tmp/miju1_3y/error.txt
...
WARNING Final process status is permanentFail
$ cat error.txt 
/bin/sh: 1: echo foo 1>&2: not found

arguments 中の valueFrom: "echo foo 1>&2" がシングルクォートでくくられた状態で実行されています。通常は echo foo 1>&2 という名前のコマンドは存在しないため、標準エラー出力がリダイレクトされた error.txt 中にもそれを示すメッセージが出力されています。

shellQuote: false かつ ShellCommandRequirement が宣言されている場合

$ grep shellQuote tests/stderr.cwl 
 - { valueFrom: "echo foo 1>&2", shellQuote: False }
$ cwltool tests/stderr.cwl tests/empty.json 
...
INFO [job stderr.cwl] /tmp/w45hzji1$ /bin/sh \
    -c \
    echo foo 1>&2 2> /tmp/w45hzji1/error.txt
...
INFO Final process status is success
$ cat error.txt 
foo

arguments 中の valueFrom: "echo foo 1>&2" がシングルクォートでくくられずに実行されています。そのため、echo コマンドで出力された foo がリダイレクトにより error.txt に出力されています。

脚注
  1. つまり、Process requiremens を含むワークフローやツール定義は、全ての CWL 準拠のワークフロー実行処理系で動かせるわけではありません。詳細は別記事を参照してください。 ↩︎

  2. CWL は YAML の一種であるため、例のように shellQuote: False (F が大文字) と書いても問題ありません…と書こうと思いましたが、そう簡単な話ではありませんでした。前提として、CWL のベースとなる規格の SALAD仕様書を見ると、"Conforming Salad v1.1 documents are serialized and loaded using a subset of YAML 1.2 syntax" と明示されています。一方で、False が真偽値の一つとして明示されていたのは古い規格である YAML 1.1 の話です。この記事執筆時点での最新規格である YAML 1.2 では、真偽値の canonical form としては truefalse のどちらかしか取りません。そのため TrueFalse などは規格違反のように見えるのですが、仕様書の 10.3 節では Core Schema と称して TrueFalse なども真偽値として受け付けるようなスキーマが示されており、また "It is also strongly recommended that other schemas should be based on it." という文言も書かれています[3] (参考: stackoverflow)。皆さんは規格に合致してるのかどうかが曖昧で移植性に欠ける書き方をせず、ちゃんと shellQuote: false と書きましょう。 ↩︎

  3. 仕様書中で矛盾するのはやめてほしい… 仕様書に従ってほしいのか無視してほしいのか… ↩︎

Discussion