bash: thoát khỏi các dòng riêng lẻ từ `-x` vang vọng


11

Trong bash, khi chạy với -xtùy chọn, có thể miễn các lệnh riêng lẻ không lặp lại?

Tôi đang cố gắng làm cho đầu ra gọn gàng nhất có thể, vì vậy tôi đang chạy một số phần nhất định của tập lệnh của mình trong một khung con set +x. Tuy nhiên, hàng set +xvẫn được lặp lại và không thêm thông tin có giá trị vào đầu ra.

Tôi nhớ lại những .batngày xưa tồi tệ , khi chạy với echo on, các dòng riêng lẻ có thể được miễn bằng cách bắt đầu chúng bằng a @. Có bất kỳ tương đương trong bash?

#!/bin/bash -x

function i_know_what_this_does() {
  (
    set +x
    echo do stuff
  )
}

echo the next-next line still echoes 'set +x', is that avoidable?
i_know_what_this_does
echo and we are back and echoing is back on

Khi chạy ở trên, đầu ra là:

+ echo the next-next line still echoes 'set +x,' is that 'avoidable?'
the next-next line still echoes set +x, is that avoidable?
+ i_know_what_this_does
+ set +x
do stuff
+ echo and we are back and echoing is back on
and we are back and echoing is back on

Câu trả lời:


22

xtraceđầu ra đi vào stderr, vì vậy bạn có thể chuyển hướng stderrđến /dev/null:

i_know_what_this_does() {
  echo do stuff
} 2> /dev/null

Nếu bạn vẫn muốn xem lỗi từ các lệnh chạy bên trong các hàm, bạn có thể làm

i_know_what_this_does() (
  { set +x; } 2> /dev/null # silently disable xtrace
  echo do stuff
)

Lưu ý việc sử dụng (...)thay vì {...}để cung cấp phạm vi cục bộ cho chức năng đó thông qua một lớp con. bash, vì phiên bản 4.4 hiện hỗ trợ local -như trong trình bao Almquist để tạo các tùy chọn cục bộ cho chức năng (tương tự như set -o localoptionstrong zsh), vì vậy bạn có thể tránh được lớp con bằng cách thực hiện:

i_know_what_this_does() {
  { local -; set +x; } 2> /dev/null # silently disable xtrace
  echo do stuff
}

Một thay thế cho bash4.0 đến 4.3 sẽ là sử dụng $BASH_XTRACEFDbiến và mở một bộ mô tả tệp chuyên dụng /dev/nullcho điều đó:

exec 9> /dev/null
set -x
i_know_what_this_does() {
  { local BASH_XTRACEFD=9; } 2> /dev/null # silently disable xtrace
  echo do stuff
}

bashthiếu khả năng đánh dấu một fd bằng cờ close-on-exec , điều đó có tác dụng phụ là rò rỉ fd đó sang các lệnh khác mặc dù.

Xem thêm locvar.sh này có chứa một vài hàm để triển khai phạm vi cục bộ cho các biến và hàm trong tập lệnh POSIX và cũng cung cấp trace_fnvà các untrace_fnhàm để biến chúng thành xtrace d hay không.


Ngọt! Tôi đang tìm kiếm để xem liệu có bất kỳ sửa đổi nào tôi có thể áp dụng cho chính chức năng đó không, nhưng tôi không nghĩ về việc chuyển hướng stderr đơn giản. Cảm ơn!
clacke

1
Btw, stchaz.free.fr/which_interpreter từ cùng một trang là khá tuyệt vời và đáng lo ngại. :-)
clacke

Và bây giờ tôi quay lại đây một lần nữa cho phương thức thứ hai, im lặng set + x mà không làm im lặng đầu ra stderr hữu ích. Cảm ơn một lần nữa!
clacke

2

Lý do set +xđược in là set -xcó nghĩa là "in lệnh bạn sắp chạy, với các bản mở rộng, trước khi chạy nó . Vì vậy, shell không biết rằng bạn muốn nó không in mọi thứ cho đến khi nó đã in dòng không nói với nó để in mọi thứ. Theo hiểu biết tốt nhất của tôi, không có cách nào ngăn chặn điều đó xảy ra.


0

Đây là giải pháp bạn đang tìm kiếm:

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.
    : "$@"
    set +x
  ) 2>&1 | perl -ne 's/^[+] :/+/ and print' 1>&2
  # Execute the original line unmolested
  "$@"
}

Lệnh ban đầu thực thi trong cùng một shell 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 bạn quan tâm mà không spam spam stederr với các bản sao trùng lặp của mỗi lệnh "echo".

# Example
echo "About to do something complicated ..."
xtrace do_something_complicated

Hoặc để tránh perl(và sự cố với các lệnh nhiều dòng):+() { :;} 2> /dev/null; xtrace() { (PS4=; set -x; + "$@";{ set +x; } 2> /dev/null); "$@";}
Stéphane Chazelas

Không, xin lỗi, unix.stackexchange.com/a/60049/17980 là giải pháp tôi đang tìm kiếm. :-) Các set -xthao tác có mua cho tôi bất cứ thứ gì so với chỉ printf >&2 '+ %s\n' "$*"không?
clacke

Như trong:xtrace() { printf >&2 '+ %s\n' "$*"; "$@"; }
clacke
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.