2012-03-22 138 views
4

你看到有人試圖「記錄我運行的命令和命令的輸出」的次數?它經常發生,並且對於看到您運行的命令set -v很好,(set -x也很好,但它可能更難讀),但是當您想捕獲正在運行的命令時會發生什麼......但不是所有命令正在運行?bash:捕獲set的輸出-v

交互式運行我沒有看到一種方法來捕獲set -v輸出。

set -v 
echo a 1>/dev/null # 'echo a 1>/dev/null' is printed to the screen 
echo a 2>/dev/null # 'echo a 2>/dev/null\na' is printed to the screen 

,我可以把這個腳本,事情變得更好:

echo 'set -v'$'\n''echo a' > setvtest.sh 

bash setvtest.sh 1>/dev/null # 'echo a' is printed to the screen 
bash setvtest.sh 2>/dev/null # 'a' is printed to the screen 

啊哈,所以從劇本就進入標準錯誤。內聯怎麼樣?

set +v 
{ set -v ; echo a ; } 1>/dev/null # no output 
set +v 
(set -v ; echo a ;) 1>/dev/null # no output 

嗯,那裏沒有運氣。

有趣的是,作爲一個側面說明,這不產生輸出:

echo 'set -v ; echo a' > setvtest.sh 
bash setvtest.sh 1>/dev/null 

我不知道爲什麼,但也許這也是爲什麼子shell版本沒有返回。

shell函數呢?

setvtest2() { 
    set -v 
    echo a 
} 

setvtest2    # 'a' 
set +v 
setvtest2 1>/dev/null # nothing 
set +v 
setvtest2 2>/dev/null # nothing 

現在的問題:有沒有捕捉到的set -v輸出的好辦法?

這是我的不是,好的黑客,所以我在尋找不太瘋狂的東西:

#!/usr/bin/env bash 

script=/tmp/$$.script 
output=/tmp/$$.out 

echo 'set -v'$'\n'"$1" >"$script" 

bash "$script" 1>"$output" 
cat "$output" 
rm -f "$script" "$output" 

現在,我可以執行簡單的腳本

bash gen.sh 'echo a' 1>/dev/null # prints 'echo a' 
bash gen.sh 'echo a' 2>/dev/null # prints 'a' 

但肯定有更好的方法。

回答

4

您可以通過set與選項-v運行bash的,而不是打開和關閉:

bash -v -c "echo a" 1>/dev/null # prints 'echo a' 
bash -v -c "echo a" 2>/dev/null # prints 'a' 

這種解決方案的黑暗的一面是,每個這樣的線將需要創建新的bash進程,但是您不必記得關閉v選項,因爲它僅在子進程中打開。

+0

現在*那*是少得多哈克。無論如何,我的解決方法產生了大量的bash進程,所以這是一個直接的改進。 – Sorpigal 2012-03-22 20:07:10

+0

鑑於沒有人似乎有更好的主意,我接受這一個。 – Sorpigal 2012-03-23 16:58:47

1

怎麼樣

#!/bin/bash 
set -o xtrace 
Stuff..... 
+0

超出範圍!我不是想解決原始問題,我想捕獲'set -v'的輸出。 – Sorpigal 2012-03-22 18:47:20

+1

也許你可以使用-o選項調用bash,它只會將它傳遞給被生成的shell。比如bash -o xtrace gen.sh,那麼你可以捕獲stderr中的輸出。我認爲set -v與set -o verbose相同,所以bash -o verbose gen.sh應該完成這項工作。 – pizza 2012-03-22 19:07:24