GNU/Linux >> Linux の 問題 >  >> Linux

Korn Shellでリターンステータスをキャプチャし、同時にTシャツを使用するにはどうすればよいですか?

この質問にはすでに回答があります :別のプロセスにパイプされているプロセスの終了ステータスを取得します

(16の回答)
7年前に終了しました。

ソースコードを検討してください:

1。 Parent.sh

#!/usr/bin/ksh
# No tee
ksh Child.sh;
exit_status=$?;
echo "Exit status: ${exit_status}"
# Using tee
ksh Child.sh | tee -a log.txt;
exit_status=$?;
echo "Exit status: ${exit_status}"

2。 Child.sh

#!/usr/bin/ksh
...
exit 1;

出力:

Exit status: 1
Exit status: 0
  • 変数$exit_status はChild.shの終了ステータスをキャプチャしているため、1もキャプチャされます。 。
  • 2番目のケースでは、$exit_status ティーの終了ステータス()をキャプチャしています 。

では、終了ステータスをキャプチャしてteeを使用するにはどうすればよいですか?

承認された回答:

comp.unix.shell FAQから複製(および改善)されました(FAQのそのセクションをたまたま書いたので):

cmd1|cmd2でcmd1の終了コードを取得するにはどうすればよいですか

まず、cmd1の終了コードがゼロ以外である可能性がありますが、それでも
エラーを意味するわけではないことに注意してください。これは、たとえば

で発生します
cmd | head -n 1

cmdの141(またはksh93の場合は269、yashの場合は397)の終了ステータスが表示される場合があります。 、
しかし、それはcmd head -n 1のときに、SIGPIPEシグナルによって中断されました 1行読んだ後に終了しました。

パイプラインの要素の終了ステータスを知るには

cmd1 | cmd2 | cmd3

zsh(およびfish 3.1+)を使用:

終了コードはpipestatusで提供されます 特別な配列。 cmd1 終了コードは$pipestatus[1]にあります 、cmd3 $pipestatus[3]の終了コード 、そのため、$status / $? 常に$pipestatus[-1]と同じです 。

bash付き:

終了コードはPIPESTATUSで提供されます 特別な配列。 cmd1 終了コードは${PIPESTATUS[0]}にあります 、cmd3 ${PIPESTATUS[2]}の終了コード 、そのため$? 常に${PIPESTATUS[-1]}と同じです (または${PIPESTATUS[@]: -1} 4.2より古いバージョンの場合)。

シェルのような他のボーンと一緒に

トリックを使用して、終了コードをメインシェルに渡す必要があります。
パイプを使って行うことができます(2)。 cmd1を実行する代わりに 、cmd1; echo "$?"
$を確認しますか?シェルに到達します。

exec 3>&1
code=`
  # now, inside the backticks, fd4 goes to the pipe
  # whose other end is read and stored in $code  for
  # later evaluation; fd1 is the normal standard output
  # preserved the line before with exec 3>&1

  exec 4>&1 >&3 3>&- 
  {
    cmd1 4>&-; echo "ec1=$?;" >&4
  } | {
    cmd2 4>&-; echo "ec2=$?;" >&4
  } | cmd3 4>&-
  echo "ec3=$?;" >&4
`
exec 3>&-
eval "$code"

$ec1の終了コード 、$ec2$ec3

POSIXシェルを使用

この関数を使用すると、簡単になります:

run() {
  j=1
  while eval "${pipestatus_$j+:} false"; do
    unset "pipestatus_$j"
    j=$(($j+1))
  done
  j=1 com= k=1 l=
  for arg do
    case $arg in
      ('|')
        com="$com {
               $l "'3>&-
               echo "pipestatus_'$j'=$?" >&3
             } 4>&- |'
        j=$(($j+1)) l=;;
      (*)
        l="$l "${$k}""
    esac
    k=$(($k+1))
  done
  com="$com $l"' 3>&- >&4 4>&-
       echo "pipestatus_'$j'=$?"'

  { eval "$(exec 3>&1; eval "$com")"; } 4>&1
  j=1
  ret=0
  while eval "${pipestatus_$j+:} false"; do
    eval '[ "$pipestatus_'"$j"'" -eq 0 ] || ret=$pipestatus_'"$j"
    j=$(($j+1))
  done
  return "$ret"
}

次のように使用します:

run cmd1 | cmd2 | cmd3

終了コードは$pipestatus_1にあります 、$pipestatus_2$pipestatus_3 および$? 右端のゼロ以外の終了ステータスです(pipefailなど) 一部のシェルのオプション)。

関連:誤って削除されたファイルを回復しますか?
Linux
  1. Bash +セカンダリスクリプトとメインスクリプトの両方を終了する方法は?

  2. bashでループの終了ステータスを取得する方法

  3. Linux:ファイルを入力と出力として同時に使用する方法は?

  1. LinuxTouchコマンドの使用方法+例

  2. Linuxでエイリアスを作成してエイリアスコマンドを使用する方法

  3. ファイルをコピーし、所有権、権限を同時に変更する方法

  1. ファイルをコピーすると同時にターゲットディレクトリを作成するにはどうすればよいですか?

  2. LinuxでPingコマンドをインストールして使用する方法

  3. Bashでwatchコマンドとjobsコマンドを一緒に使用するにはどうすればよいですか?