終了コードが0の場合、ファイルにstdoutをどのように書き込むことができますか?

終了コードが0の場合、ファイルにstdoutをどのように書き込むことができますか?

これスポンジ「標準入力を受け取り、ファイルに書き込む」コマンドを使用すると、同じファイル間でパイプを接続できます。私は、スポンジのようなユーティリティにパイプする同様の作業をしたいのですが、ソースコマンドが失敗した場合(ゼロ以外のシャットダウンがある場合)、スポンジのようなユーティリティはターゲットファイルを変更せずにそのままにしたいと思います。

おおよそ次のようになります。

cue export package.cue | prettier --stdin-filepath .json
 | spongelike --abort-on-non-zero package.json

(この特定のパイプラインを2つの別々のコマンドで書き直すことができますが、これは他のトリッキーなシナリオでも役に立つかもしれません)。

ベストアンサー1

で同時に開始され、cmd1 | cmd2すべてがシェルの子ですcmd1cmd2

cmd2いつ死ぬのか分からず、cmd1終了状態を得ることもできません。親(ここではシェル)のみが可能です。

したがって、必要な操作を実行するコマンドがある場合は、次のように呼び出すことはできません。

cmd | that-command output-file

次のようにする必要があります。

that-command output-file cmd

サブプロセスから始まり、パイプを介して標準出力を収集し、/またはどこか(メモリまたは一時ファイル)に保存し、サブプロセスを待ち、成功するとそこに保存された that-command出力を開いてダンプします。cmdoutput-file

これはシェルスクリプトを介して行うことができます。たとえば、次のようになります。

#! /bin/sh -
usage() {
  printf >&2 'Usage: %s <output> <cmd> [<args>...]\n' "${0##*/}"
  exit 1
}
[ "$#" -ge 2 ] || usage
output=$1; shift

tmp=$(mktemp) || exit
exec > "$tmp" 3< "$tmp"
rm -f -- "$tmp" || exit

"$@" 3<&- && cat <&3 3<&- > "$output"

mktempまだ標準ではありませんが、一般的です)。

ここで使用されます:

cue export package.cue | that-script package.json prettier --stdin-filepath .json

または両方が成功cueしたことを確認してくださいprettier

that-script package.json ksh -o pipefail -c '
  cue export package.cue | prettier --stdin-filepath .json'

または、kshオプションがインストールされていて、この機能をサポートする他のシェルpipefail(少なくともzsh、bash、mksh、yashを含む)。このオプションはPOSIX規格の次のバージョンに表示される予定であるため、すでにsh持っている可能性があります。この場合、次のこともできます。

that-script package.json eval 'set -o pipefail
  cue export package.cue | prettier --stdin-filepath .json'

このステートメント内で実行されるコードは、eval出力ファイルの生成方法に影響を与える可能性があります。たとえば、umaskを設定し、破損を防ぐために使用できるthat-script output eval 'cd /some/dir; cmd'出力ファイルを作成します。/some/dirthat-script output eval 'umask 077; set -o noclobber; cmd'

おすすめ記事