2010-07-26 26 views
35

Khi tôi sử dụng lệnh "bẫy" trong bash, bẫy trước đó cho tín hiệu đã cho được thay thế.nhiều bash bẫy cho cùng một tín hiệu

Có cách nào tạo ra nhiều hơn một bẫy lửa cho cùng một tín hiệu không?

+0

Tôi đã gặp phải sự cố tương tự và đã đưa ra [this] (http://stackoverflow.com/a/16115145/1449569) –

Trả lời

18

Edit:

Dường như tôi không nhận định câu hỏi. Câu trả lời rất đơn giản:

handler1() { do_something; } 
handler2() { do_something_else; } 
handler3() { handler1; handler2; } 

trap handler3 SIGNAL1 SIGNAL2 ... 

gốc:

Chỉ cần liệt kê nhiều tín hiệu ở phần cuối của lệnh:

trap function-name SIGNAL1 SIGNAL2 SIGNAL3 ... 

Bạn có thể tìm thấy các chức năng liên kết với một tín hiệu đặc biệt sử dụng trap -p:

trap -p SIGINT 

Lưu ý rằng nó liệt kê riêng từng tín hiệu ngay cả khi chúng được xử lý bởi cùng một chức năng.

Bạn có thể thêm một tín hiệu cho thêm một tiếng bằng cách làm này:

eval "$(trap -p SIGUSR1) SIGUSR2" 

này hoạt động ngay cả khi có tín hiệu bổ sung khác được xử lý bởi các chức năng tương tự. Nói cách khác, giả sử một hàm đã xử lý ba tín hiệu - bạn có thể thêm hai chỉ bằng cách tham chiếu đến một tín hiệu hiện có và thêm hai dấu nữa (chỉ có một dấu hiệu được hiển thị ở trên bên trong dấu ngoặc kép đóng).

Nếu bạn đang sử dụng Bash> = 3.2, bạn có thể thực hiện thao tác như thế này để trích xuất chức năng cho tín hiệu. Lưu ý rằng nó không hoàn toàn mạnh mẽ vì các dấu nháy đơn khác có thể xuất hiện.

[[ $(trap -p SIGUSR1) =~ trap\ --\ \'([^\047])\'.* ]] 
function_name=${BASH_REMATCH[1]} 

Sau đó, bạn có thể xây dựng lại lệnh bẫy của mình từ đầu nếu bạn cần sử dụng tên chức năng, v.v.

+0

Anh ấy yêu cầu nhiều bẫy cho cùng một tín hiệu, chứ không phải cùng một bẫy cho nhiều tín hiệu. – Darron

+0

@Darron: Rất tiếc, tôi đã đọc sai câu hỏi. Câu trả lời cho câu hỏi ** ** thực tế đơn giản hơn nhiều và tôi đã thêm nó ở trên cùng. –

+4

bạn vẫn chỉ bắn một cái bẫy - rằng cái bẫy trong câu hỏi gọi nhiều chức năng và đạt được hiệu quả là ít nhiều không thể chối cãi. Lý do duy nhất để nghĩ rằng có thể có bất kỳ căn cứ nào để tranh chấp là nếu handler1 được cài đặt trước, và nó được thiết kế để thoát, thì handler2 sẽ không bị sa thải. Nhưng vẫn chỉ có một hành động bị sa thải. (Bạn luôn có thể có một chuỗi các hoạt động phức tạp tùy ý trong hành động được kích hoạt.) –

7

Không

Về là tốt nhất bạn có thể làm là chạy nhiều lệnh từ một đơn trap cho một tín hiệu nào đó, nhưng bạn không thể có nhiều bẫy đồng thời cho một tín hiệu duy nhất. Ví dụ:

$ trap "rm -f /tmp/xyz; exit 1" 2 
$ trap 
trap -- 'rm -f /tmp/xyz; exit 1' INT 
$ trap 2 
$ trap 
$ 

Dòng đầu tiên đặt bẫy trên tín hiệu 2 (SIGINT). Dòng thứ hai in các bẫy hiện tại - bạn sẽ phải nắm bắt đầu ra tiêu chuẩn từ này và phân tích cú pháp nó cho tín hiệu bạn muốn. Sau đó, bạn có thể thêm mã của mình vào những gì đã có sẵn - lưu ý rằng mã trước nhất có thể sẽ bao gồm cả thao tác 'thoát'. Lệnh gọi thứ ba của bẫy sẽ xóa bẫy trên 2/INT. Người cuối cùng cho thấy rằng không có bẫy xuất sắc.

Bạn cũng có thể sử dụng trap -p INT hoặc trap -p 2 để in bẫy cho một tín hiệu cụ thể.

36

Về mặt kỹ thuật, bạn không thể đặt nhiều bẫy cho các tín hiệu tương tự, nhưng bạn có thể thêm vào một cái bẫy hiện:

  1. Fetch mã bẫy hiện sử dụng trap -p
  2. Thêm lệnh của bạn, cách nhau bằng một dấu chấm phẩy hoặc xuống dòng
  3. Đặt bẫy để kết quả của # 2

đây là một chức năng bash mà không được ở trên:

# note: printf is used instead of echo to avoid backslash 
# processing and to properly handle values that begin with a '-'. 

log() { printf '%s\n' "$*"; } 
error() { log "ERROR: $*" >&2; } 
fatal() { error "[email protected]"; exit 1; } 

# appends a command to a trap 
# 
# - 1st arg: code to add 
# - remaining args: names of traps to modify 
# 
trap_add() { 
    trap_add_cmd=$1; shift || fatal "${FUNCNAME} usage error" 
    for trap_add_name in "[email protected]"; do 
     trap -- "$(
      # helper fn to get existing trap command from output 
      # of trap -p 
      extract_trap_cmd() { printf '%s\n' "$3"; } 
      # print existing trap command with newline 
      eval "extract_trap_cmd $(trap -p "${trap_add_name}")" 
      # print the new trap command 
      printf '%s\n' "${trap_add_cmd}" 
     )" "${trap_add_name}" \ 
      || fatal "unable to add to trap ${trap_add_name}" 
    done 
} 
# set the trace attribute for the above function. this is 
# required to modify DEBUG or RETURN traps because functions don't 
# inherit them unless the trace attribute is set 
declare -f -t trap_add 

Ví dụ sử dụng:

trap_add 'echo "in trap DEBUG"' DEBUG 
+1

Đây là câu trả lời trực tiếp hơn cho http://stackoverflow.com/q/16115144/754997 –

3

Đây là một lựa chọn:

on_exit_acc() { 
    local next="$1" 
    eval "on_exit() { 
     local oldcmd='$(echo "$next" | sed -e s/\'/\'\\\\\'\'/g)' 
     local newcmd=\"\$oldcmd; \$1\" 
     trap -- \"\$newcmd\" 0 
     on_exit_acc \"\$newcmd\" 
    }" 
} 
on_exit_acc true 

Cách sử dụng:

$ on_exit date 
$ on_exit 'echo "Goodbye from '\''`uname`'\''!"' 
$ exit 
exit 
Sat Jan 18 18:31:49 PST 2014 
Goodbye from 'FreeBSD'! 
tap# 
3

Tôi thích câu trả lời Richard Hansen, nhưng tôi không quan tâm cho nhúng chức năng để thay thế là:

#=================================================================== 
# FUNCTION trap_add() 
# 
# Purpose: appends a command to a trap 
# 
# - 1st arg: code to add 
# - remaining args: names of traps to modify 
# 
# Example: trap_add 'echo "in trap DEBUG"' DEBUG 
# 
# See: http://stackoverflow.com/questions/3338030/multiple-bash-traps-for-the-same-signal 
#=================================================================== 
trap_add() { 
    trap_add_cmd=$1; shift || fatal "${FUNCNAME} usage error" 
    new_cmd= 
    for trap_add_name in "[email protected]"; do 
     # Grab the currently defined trap commands for this trap 
     existing_cmd=`trap -p "${trap_add_name}" | awk -F"'" '{print $2}'` 

     # Define default command 
     [ -z "${existing_cmd}" ] && existing_cmd="echo exiting @ `date`" 

     # Generate the new command 
     new_cmd="${existing_cmd};${trap_add_cmd}" 

     # Assign the test 
     trap "${new_cmd}" "${trap_add_name}" || \ 
       fatal "unable to add to trap ${trap_add_name}" 
    done 
} 
0

Tôi không thích phải chơi với những thao tác chuỗi được bối rối lúc tốt nhất của lần, vì vậy tôi đã đưa ra một cái gì đó như thế này:

(rõ ràng bạn có thể sửa đổi nó cho các tín hiệu khác)

exit_trap_command="" 
function cleanup { 
    eval "$exit_trap_command" 
} 
trap cleanup EXIT 

function add_exit_trap { 
    local to_add=$1 
    if [[ -z "$exit_trap_command" ]] 
    then 
     exit_trap_command="$to_add" 
    else 
     exit_trap_command="$exit_trap_command; $to_add" 
    fi 
} 
Các vấn đề liên quan