2012-07-11 35 views
6

Nói rằng tôi có:Tạo cảnh báo khi nhiều thực thi trên đường khi thực hiện lệnh trong bash

>which -a foo 
/bin/foo 
/usr/bin/foo 

Tôi muốn một cái gì đó như:

>foo 
Warning: multiple foo in PATH 
... foo gets executed ... 

Chức năng này sẽ có lưu tôi thực sự thực sự rất nhiều thời gian hiện nay . Tôi nên đoán điều này đang xảy ra trước đó nhưng vấn đề không rõ ràng là với tôi lúc bắt đầu và tôi bắt đầu đào theo hướng hoàn toàn ngược lại.

Trả lời

6

Vâng, bạn có thể làm điều đó, nhưng nó không phải là quá dễ dàng như bạn có thể nghĩ.

Trước tiên, bạn cần tạo một hàm sẽ kiểm tra tất cả các thư mục trong PATH và tìm ở đó cho lệnh bạn cố gắng chạy. Sau đó, bạn cần phải liên kết hàm này với bẫy DEBUG của trình bao hiện tại của bạn.

Tôi đã viết một kịch bản nhỏ nào đó:

$ cat /tmp/1.sh 

check_command() 
{ 
    n=0 
    DIRS="" 
    for i in $(echo $PATH| tr : " ") 
    do 
     if [ -x "$i/$1" ] 
     then 
      n=$[n+1] 
      DIRS="$DIRS $i" 
     fi 
    done 
    if [ "$n" -gt 1 ] 
    then 
     echo "Warning: there are multiple commands in different PATH directories: "$DIRS 
    fi 
} 

preexec() { 
    check_command $1 
} 
preexec_invoke_exec() { 
    [ -n "$COMP_LINE" ] && return # do nothing if completing 
    local this_command=`history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//g"`; 
    preexec "$this_command" 
} 
trap 'preexec_invoke_exec' DEBUG 

Ví dụ về sử dụng:

$ . /tmp/1.sh 
$ sudo cp /bin/date /usr/bin/test_it 
$ sudo cp /bin/date /bin/test_it 
$ test_it 
Warning: there are multiple commands in different PATH directories: /usr/bin /bin 
Wed Jul 11 15:14:43 CEST 2012 
$ 
+2

Thay vì lặp qua '$ PATH', bạn có thể sử dụng' type -pa "$ 1" '. Ngoài ra, bạn có thể sử dụng '$ BASH_COMMAND' thay vì phân tích cú pháp' lịch sử'. Hàm 'preexec' phải phục vụ một mục đích trong ngữ cảnh khác, nhưng nó không liên quan ở đây. –

+0

Ồ, tôi nghĩ tôi sẽ được thông báo bằng email về câu trả lời cho câu hỏi. ** Cảm ơn bạn. ** Tôi đoán câu trả lời ngắn sẽ là "sử dụng bẫy DEBUG") như những thứ khác là rõ ràng hơn bash mashinery. Về vấn đề này câu trả lời của bạn và @lynxlynxlynx một là cả hai tốt nhất. Tuy nhiên, tôi bình chọn của bạn như là câu trả lời chỉ trên đầu trang, không có lý do khác. – nshy

2

Có thể, mặc dù một mẹo nhỏ để khái quát hóa. Xem câu trả lời của tôi cho https://unix.stackexchange.com/q/42579/20437 cho phép thuật historyPROMPT_COMMAND. Chức năng checkSanity của bạn sẽ trông giống như sau:

checkSanity() { 
    cmd="${1%% *}" # strip everything but the first word 
    candidates=$(which -a $cmd | wc -l) 
    if ((candidates > 1)); then 
    echo "Warning: multiple $cmd in PATH" 
    fi 
} 

Nhưng điều đó sẽ in cảnh báo sau khi lệnh kết thúc, không phải lúc đầu. Sử dụng các bẫy DEBUG thay vì để có được kết quả mong muốn:

trap 'checkSanity "$BASH_COMMAND"' DEBUG 
+1

như xa như tôi có thể hiểu được, PROMPT_COMMAND sẽ không giúp đỡ ở đây; nó được thực hiện trước khi bạn nhập dòng lệnh, không phải sau. –

+0

nó hoạt động, nhưng bạn nhận được cảnh báo sau khi lệnh kết thúc. Các bẫy DEBUG là linh hoạt hơn trong vấn đề đó. – lynxlynxlynx

+0

khó khăn; và ý tưởng này với lịch sử -a cũng không tốt lắm, bởi vì nó có tác dụng phụ; bạn không muốn luôn luôn lưu lịch sử của bạn. tại sao bạn không muốn chỉ cần kiểm tra đầu ra lịch sử? –

Các vấn đề liên quan