Bash set + x mà không in


92

Có ai biết nếu chúng tôi có thể nói set +xtrong bash mà nó không được in:

set -x
command
set +x

dấu vết

+ command
+ set +x

nhưng nó chỉ nên in

+ command

Bash là Phiên bản 4.1.10 (4). Điều này làm tôi khó chịu trong một thời gian - đầu ra bị lộn xộn với set +xcác dòng vô dụng , làm cho cơ sở theo dõi không hữu ích như nó có thể.


Này không trả lời câu hỏi của bạn, nhưng khi bạn chạy script của bạn tại sao không:script.sh 2>&1 | grep -v 'set +x'
cdarke

Câu trả lời:


145

Tôi đã gặp vấn đề tương tự và tôi có thể tìm thấy giải pháp không sử dụng vỏ con:

set -x
command
{ set +x; } 2>/dev/null

10
Câu trả lời tuyệt vời, chỉ cần một lưu ý: nếu không có dấu chấm phẩy sau lệnh, điều này sẽ không hoạt động; và với dấu chấm phẩy nhưng không có dấu cách trong dấu ngoặc nhọn, lỗi cú pháp sẽ được phát sinh.
sdaau

9
Điều này làm cho trạng thái thoát.
Garth Kidd

8
@GarthKidd Trạng thái thoát bằng 0 với mọi lệnh thành công. set +xlà một lệnh thành công
Daniel Alder

3
Trong trường hợp bạn cần có trạng thái thoát của command, sự thay đổi này là một giải pháp: { STATUS=$?; set +x; } 2>/dev/null. Sau đó kiểm tra $STATUScác dòng tiếp theo khi bạn rảnh rỗi.
Giá Greg

5
Riêng biệt, đây là một phiên bản golfed nhẹ hơn nữa: { set +x; } 2>&-. Điều đó đóng fd 2 hoàn toàn thay vì làm cho nó trỏ vào / dev / null. Một số chương trình không xử lý tốt điều đó khi chúng cố gắng in sang stderr, đó là lý do tại sao / dev / null nói chung là kiểu tốt; nhưng set -xdấu vết của shell xử lý nó rất tốt, vì vậy nó hoạt động hoàn hảo ở đây và nó làm cho câu thần chú này ngắn hơn một chút.
Giá Greg

43

Bạn có thể sử dụng một vỏ con. Khi thoát khỏi vỏ con, cài đặt xsẽ bị mất:

( set -x ; command )

Vâng, cảm ơn ... điểm tốt. Trên thực tế, tôi biết "thủ thuật vỏ phụ". Tôi hy vọng nó có thể dễ dàng hơn thế. Nó liên quan đến những thay đổi đáng kể trong mã, làm cho mã phức tạp hơn và khó đọc hơn. IMHO đó sẽ là tồi tệ hơn sống chung với các thiết lập + x dòng ...
Andreas Spindler

Tôi không thấy làm thế nào ( set -x \n command \n )là bất kỳ tệ hơn set -x \n command \n set +x.
chepner

3
@chepner: Bạn không thể đặt biến.
choroba

2
... và bạn không thể cd: nó không thay đổi thư mục hiện tại trong vỏ mẹ.
Andreas Spindler

Xin lỗi, tôi không chắc tôi nghĩ phản đối thực sự của bạn là gì. Đã một tuần dài ...
chepner

8

Tôi đã tìm ra giải pháp cho vấn đề này gần đây khi tôi cảm thấy khó chịu với nó:

shopt -s expand_aliases
_xtrace() {
    case $1 in
        on) set -x ;;
        off) set +x ;;
    esac
}
alias xtrace='{ _xtrace $(cat); } 2>/dev/null <<<'

Điều này cho phép bạn bật và tắt xtrace như sau, nơi tôi ghi lại cách các đối số được gán cho các biến:

xtrace on
ARG1=$1
ARG2=$2
xtrace off

Và bạn nhận được kết quả giống như sau:

$ ./script.sh one two
+ ARG1=one
+ ARG2=two

Thủ thuật thông minh (mặc dù bạn không cần /dev/stdinphần này). Lưu ý là việc bật tính năng mở rộng bí danh trong các tập lệnh có thể có những tác dụng phụ không mong muốn.
mklement0

Bạn đúng. Tôi đã chỉnh sửa câu trả lời để loại bỏ những thứ thừa /dev/stdin. Tôi không biết về bất kỳ tác dụng phụ cụ thể nào, vì môi trường không tương tác sẽ không tải bất kỳ tệp nào xác định bí danh. Những tác dụng phụ có thể có?
user108471

1
Đó là một điểm tốt - tôi quên rằng bí danh không được kế thừa, vì vậy rủi ro nhỏ hơn nhiều so với tôi nghĩ (theo giả thuyết, tập lệnh của bạn có thể tìm nguồn cung cấp mã của bên thứ ba để xác định bí danh, nhưng tôi đồng ý rằng đó có thể không phải là thực- thế giới quan tâm). +1
mklement0

1
@AndreasSpindler Bạn có thể giải thích thêm tại sao bạn cho rằng kỹ thuật này có nhiều khả năng làm rò rỉ thông tin nhạy cảm hơn không?
user108471

1
... về cơ bản vì bí danh và hàm là các cấu trúc cấp cao. set +xkhó hơn nhiều (nếu không muốn nói là không thể) để thỏa hiệp. Nhưng nó vẫn là một giải pháp tốt và dễ hiểu - có lẽ là giải pháp tốt nhất cho đến nay.
Andreas Spindler

7

Làm thế nào về một giải pháp dựa trên phiên bản đơn giản của @ user108471:

shopt -s expand_aliases
alias trace_on='set -x'
alias trace_off='{ set +x; } 2>/dev/null'

trace_on
...stuff...
trace_off

Còn cái này thì sao? function () { set_plus_x='{ set +x; } 2>/dev/null' }
LexH 19/1218

1

Đây là sự kết hợp của một vài ý tưởng có thể bao quanh một khối mã và duy trì trạng thái thoát.

#!/bin/bash
shopt -s expand_aliases
alias trace_on='set -x'
alias trace_off='{ PREV_STATUS=$? ; set +x; } 2>/dev/null; (exit $PREV_STATUS)'

trace_on
echo hello
trace_off
echo "status: $?"

trace_on
(exit 56)
trace_off

Khi thực hiện:

$ ./test.sh 
+ echo hello
hello
status: 0
+ exit 56
status: 56

Rất nỗ lực nhưng tôi nghĩ ()xung quanh exitkhông cần thiết. Đồng ý. Có lẽ đó là của hoang tưởng, nhưng nếu mã này được sử dụng nói chung bạn có một vector tấn công tốt: Định nghĩa lại trace_ontrace_offvà mã bơm mà đọc lệnh thực thi. Nếu bạn chỉ sử dụng các "tiện ích" như vậy thì đó là hướng dẫn, nhưng nếu mã được sử dụng với những người khác, bạn phải xem xét liệu lợi ích của các chức năng không được tiêu chuẩn hóa đó có lớn hơn bất lợi không. Cá nhân tôi đã giải quyết { set +x; } 2>/dev/nullvì cấu trúc này thường được hiểu và cũng không thay đổi trạng thái thoát.
Andreas Spindler
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.