2011-09-28 102 views
6

我想轉以下幾點:bash進程替換和退出代碼

git status --short && (git status --short | xargs -Istr test -z str)

這讓我鏡像輸出到標準輸出和對結果做一個零長度檢查到的東西的期望的結果接近:

git status --short | tee >(xargs -Istr test -z str)

不幸返回三通管的退出代碼(總是零)。

有什麼辦法可以優雅地獲得替代過程的退出代碼嗎?

[編輯]

我與現在的下面,它可以防止運行相同的命令兩次會,但似乎乞求更好的東西:

OUT=$(git status --short) && echo "${OUT}" && test -z "${OUT}"

+0

對不起,你究竟想要達到什麼目的?只需檢查該目錄中是否有git狀態? –

+0

是的,它是部署腳本的一部分,如果目錄很髒,應該退出非零值。 – jodell

回答

5

看看這裏:

 
    $ echo xxx | tee >(xargs test -n); echo $? 
xxx 
0 
    $ echo xxx | tee >(xargs test -z); echo $? 
xxx 
0 

看這裏:

 
    $echo xxx | tee >(xargs test -z; echo "${PIPESTATUS[*]}") 
xxx 
123 
    $echo xxx | tee >(xargs test -n; echo "${PIPESTATUS[*]}") 
xxx 
0 

那是?

又見Pipe status after command substitution

+0

我不知道PIPESTATUS,這很有幫助,謝謝。 – jodell

+4

如果有其他人出現,並認爲PIPESTATUS解決了這個問題,它不會。如果echo $?被移動到>(...)構造內,它也表現得如預期。如果將PIPESTATUS版本移出外部,則在兩種情況下都會返回0。 –

0
#!/bin/bash 
if read q < <(git status -s) 
then 
    echo $q 
    exit 
fi 
2

我一直工作在這一段時間,似乎是沒有辦法做到這一點與過程替代,除了訴諸內嵌信號,並能真的只能用於輸入管道,所以我不打算擴展它。

但是,bash-4.0提供了coprocesses,它可以用來取代在這種情況下的進程替換,並提供清晰的收穫。

你提供下面的代碼片段:

git status --short | tee >(xargs -Istr test -z str) 

可以通過東西都被替換爲:

coproc GIT_XARGS { xargs -Istr test -z str; } 
{ git status --short | tee; } >&${GIT_XARGS[1]} 
exec {GIT_XARGS[1]}>&- 
wait ${GIT_XARGS_PID} 

現在,對於一些解釋:

coproc調用創建一個新的協進程,命名它GIT_XARGS(你可以使用任何你喜歡的名字),並運行大括號中的命令。爲協處理創建了一對管道,重定向其標準輸入和標準輸出。

coproc調用設置兩個變量:

  1. ${GIT_XARGS[@]}含有管道處理stdin和stdout,適當地([0]從標準輸出讀,[1]寫入標準輸入),
  2. ${GIT_XARGS_PID}含有協進程PID。

然後,運行命令並將其輸出定向到第二個管道(即coprocess的stdin)。看似隱祕的>&${GIT_XARGS[1]}部分擴展到>&60這是常規的輸出到fd重定向。

請注意,我需要把你的命令放在大括號中。這是因爲管道會導致子進程生成,並且它們不會從父進程繼承文件描述符。換句話說,執行以下操作:

git status --short | tee >&${GIT_XARGS[1]} 

會失敗,無效的文件描述符錯誤,因爲相關的FD的父進程存在,而不是催生tee過程。將其放在大括號中會導致bash將重定向應用於整個管道。

exec調用用於關閉到您的協處理的管道。在使用進程替換時,該進程會作爲輸出重定向的一部分生成,並且在重定向不再生效後立即關閉該進程的管道。由於協處理管道的生命週期超出了單個重定向,我們需要明確地關閉它。

關閉輸出管道應該會導致進程在標準輸入上獲得EOF條件並正常終止。我們使用wait等待終止並收穫。 wait返回協處理器的退出狀態。

作爲最後一個注意事項,請注意,在這種情況下,您不能使用kill來終止協處理,因爲這會改變其退出狀態。

+0

tee在這裏其實沒什麼用處,stdout net會重定向到stdout。 – weynhamz

+0

'exec {GIT_XARGS [1]}>& - 'returns' -bash:exec:{GIT_XARGS [1]}:找不到我的。 –

+0

你有bash-4.0或更新版本嗎? –