2013-06-28 31 views
6

Tôi đang viết một kịch bản lệnh shell lặp qua một số giá trị và chạy một dòng lệnh dài cho mỗi giá trị. Tôi muốn in ra các lệnh này trên đường đi, giống như make hiện khi chạy một makefile. Tôi biết tôi chỉ có thể "echo" tất cả các lệnh trước khi chạy chúng, nhưng nó cảm thấy không phù hợp. Vì vậy, tôi nhìn vào set -x và tương tự như cơ chế thay vì:cách tắt tiếng xtrace trong tập lệnh shell?

#!/bin/sh 

for value in a long list of values 
do 
    set -v 
    touch $value # imagine a complicated invocation here 
    set +v 
done 

Vấn đề của tôi là: tại mỗi lần lặp, không chỉ là dòng interresting in ra, mà còn là dòng set +x là tốt. Có bằng cách nào đó có thể ngăn chặn điều đó không? Nếu không, bạn đề nghị cách giải quyết nào?

PS: MWE ở trên sử dụng sh, nhưng tôi cũng có bashzsh được cài đặt trong trường hợp giúp.

+1

có thể trùng lặp của [bộ Bash + x mà không có nó được in] (http://stackoverflow.com/questions/13195655/bash-set-x-without-it-being-printed) – Beetle

Trả lời

6

Sandbox nó trong một subshell:

(set -x; do_thing_you_want_traced) 

Dĩ nhiên, những thay đổi để biến hoặc môi trường sản xuất tại subshell đó sẽ bị mất.

Nếu bạn thực sự quan tâm đến điều này, bạn cũng có thể sử dụng một cái bẫy DEBUG (sử dụng set -T để nó được thừa hưởng bởi các chức năng) để thực hiện tương ứng set -x của riêng bạn.

Ví dụ, nếu sử dụng bash:

trap_fn() { 
    [[ $DEBUG && $BASH_COMMAND != "unset DEBUG" ]] && \ 
    printf "[%s:%s] %s\n" "$BASH_SOURCE" "$LINENO" "$BASH_COMMAND" 
    return 0 # do not block execution in extdebug mode 
} 
trap trap_fn DEBUG 

DEBUG=1 
# ...do something you want traced... 
unset DEBUG 

Điều đó nói rằng, phát ra BASH_COMMAND (như một cái bẫy DEBUG có thể làm) không phải là hoàn toàn tương đương với set -x; ví dụ, nó không hiển thị giá trị sau khi mở rộng.

+0

Cảm ơn rất nhiều câu trả lời của bạn! Tôi không chơi với các biến trong các lệnh (chúng thực sự chỉ là các invocations dài) vì vậy tôi đã đi theo cách tiếp cận subshell, và nó phù hợp với nhu cầu của tôi một cách hoàn hảo. – Gyom

+0

wooo, ý tưởng tuyệt vời! :-) –

1

tôi nghĩ

set -x >/dev/null 2>1; echo 1; echo 2; set +x >/dev/null 2>&1 

nhưng có

+ echo 1 
1 
+ echo 2 
2 
+ 1> /dev/null 2>& 1 

Tôi ngạc nhiên bởi những kết quả này. .... Nhưng

set -x ; echo 1; echo 2; set +x 
+ echo 1 
1 
+ echo 2 
2 

sẽ đáp ứng yêu cầu của bạn.

Tôi thấy kết quả tương tự khi tôi đặt từng câu lệnh trên dòng duy nhất của nó (ngoại trừ tập hợp + x)

IHTH.

+0

FYI - Đầu ra 'set -x' chỉ có giá trị stderr, trừ khi được ghi đè bằng BASH_XTRACEFD trong bash 4. –

+0

... nhân tiện, mileage nào _indeed_ khác nhau; Tôi không thể sao chép hành vi được báo cáo ở đây trên bash 4.2.45 (1). –

+0

@charlesDuffy: Tôi sử dụng ksh, nhưng tôi đọc về bash (ở đây) tất cả các thời gian. Cảm ơn các chi tiết! Chúc mọi người may mắn. – shellter

1

Bạn muốn thử sử dụng một dòng đơn xtrace:

function xtrace() { 
    # Print the line as if xtrace was turned on, using perl to filter out 
    # the extra colon character and the following "set +x" line. 
    (
    set -x 
    # Colon is a no-op in bash, so nothing will execute. 
    : "[email protected]" 
    set +x 
) 2>&1 | perl -ne 's/^[+] :/+/ and print' 1>&2 
    # Execute the original line unmolested 
    "[email protected]" 
} 

Lệnh ban đầu thực hiện trong cùng một vỏ dưới một chuyển đổi danh tính. Ngay trước khi chạy, bạn nhận được một xtrace không đệ quy của các đối số. Điều này cho phép bạn xtrace các lệnh mà bạn quan tâm mà không cần spam stederr với các bản sao của mỗi lệnh "echo".

# Example 
for value in $long_list; do 
    computed_value=$(echo "$value" | sed 's/.../...') 
    xtrace some_command -x -y -z $value $computed_value ... 
done 
Các vấn đề liên quan