GNU/Linux >> Znalost Linux >  >> Linux

Jak zachytit stav návratu a zároveň použít čaj v Korn Shell?

Tato otázka zde již obsahuje odpovědi :Získejte stav ukončení procesu, který je přesměrován do jiného

(16 odpovědí)
Uzavřeno před 7 lety.

Zvažte zdrojový kód:

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;

Výstup:

Exit status: 1
Exit status: 0
  • Proměnná $exit_status zachycuje stav ukončení Child.sh a stejně tak 1 .
  • Ve 2. případě $exit_status zachycuje výstupní stav odpaliště, což je .

Jak tedy mohu zachytit stav odchodu a také použít tee?

Přijatá odpověď:

Reprodukováno (a vylepšeno) z comp.unix.shell FAQ (protože jsem náhodou napsal tuto sekci FAQ):

Jak získám výstupní kód cmd1 v cmd1|cmd2

Nejprve si uvědomte, že výstupní kód cmd1 může být nenulový a stále to
neznamená chybu. To se děje například v

cmd | head -n 1

můžete pozorovat stav ukončení 141 (nebo 269 s ksh93 nebo 397 s yash) cmd ,
ale je to proto, že cmd byl přerušen signálem SIGPIPE, když head -n 1 ukončeno po přečtení jednoho řádku.

Chcete-li znát výstupní stav prvků potrubí

cmd1 | cmd2 | cmd3

se zsh (a fish 3.1+):

Výstupní kódy jsou uvedeny v pipestatus speciální pole. cmd1 výstupní kód je v $pipestatus[1] , cmd3 výstupní kód v $pipestatus[3] , takže $status /$? je vždy stejný jako $pipestatus[-1] .

s bash:

Výstupní kódy jsou uvedeny v PIPESTATUS speciální pole. cmd1 výstupní kód je v ${PIPESTATUS[0]} , cmd3 výstupní kód v ${PIPESTATUS[2]} , takže $? je vždy stejný jako ${PIPESTATUS[-1]} (nebo ${PIPESTATUS[@]: -1} pro verze starší než 4.2).

s jakýmikoli jinými Bourneovými mušlemi

K předání výstupních kódů do hlavního shellu musíte použít trik. Můžete to udělat
pomocí potrubí (2). Místo spouštění cmd1 , spustíte cmd1; echo "$?" a ujistěte se
$? dostane cestu do shellu.

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"

Výstupní kódy v $ec1 , $ec2 , $ec3 .

s shellem POSIX

Tuto funkci můžete použít pro usnadnění:

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"
}

Použijte jej jako:

run cmd1 | cmd2 | cmd3

výstupní kódy jsou v $pipestatus_1 , $pipestatus_2 , $pipestatus_3 a $? je nenulový výstupní stav zcela vpravo (jako u pipefail možnost některých mušlí).

Související:Obnovení omylem smazaných souborů?
Linux
  1. Jak zkopírovat soubor a vytvořit cílové adresáře současně?

  2. Jak nainstalovat a používat příkaz Ping v Linuxu

  3. Jak mohu v Bash používat společně příkazy watch a jobs?

  1. Jak používat Linux Touch Command + příklady

  2. Jak vytvořit alias a používat příkaz Alias ​​v Linuxu

  3. Kopírovat a chmod/chown zároveň

  1. Jak kopírovat soubory a měnit vlastnictví, oprávnění současně

  2. Bash + Jak opustit sekundární skript a hlavní skript v obou případech?

  3. Jak získat stav ukončení smyčky v bash