2010-10-13 29 views
8

Tôi đang tìm cách xử lý tập lệnh shell để xác định:Xác định hàm và phụ thuộc tệp của tập lệnh shell?

  1. lệnh, tập lệnh hoặc hàm nào được gọi trong tập lệnh.
  2. tệp nào được tập lệnh (r hoặc w) truy cập.

Nó không cần phải recurse xuống thông qua các phụ thuộc, chỉ cần liệt kê những gì nó chạy trực tiếp. Tôi có lẽ có thể viết một cái gì đó mà làm điều này bản thân mình, nhưng nó phải có được thực hiện trước khi ... Tôi chỉ không tìm thấy nó.

+0

Câu hỏi thú vị - không tầm thường để trả lời. Hãy xem xét theo dõi đầu ra từ 'sh -x' (nhưng điều đó chỉ hiển thị cho bạn các lệnh được thực thi, chứ không phải những lệnh không được. –

Trả lời

1

Nó sẽ là một tính năng của dự án Loker mà tôi hiện đang phát triển. Hiện tại, trình phân tích cú pháp đã gần hoàn tất và bạn có thể thực hiện một phép tính xấp xỉ hợp lý về những gì bạn muốn trên đầu trang của nó. Tuy nhiên, nói chung nhiệm vụ này rất phức tạp, vì tên của lệnh có thể là kết quả của việc mở rộng biến, tách trường, v.v.

Nếu bạn mô tả bạn cần gì và loại kịch bản nào bạn sẽ phân tích cú pháp I sẽ có thể nói được bao nhiêu nhu cầu của bạn mà Loker có thể đáp ứng ngay bây giờ.

Tùy chọn thay thế, một số phiên bản bash có tùy chọn --rpm-requires, cũng có chức năng tương tự.

+0

Rất thú vị. Tôi sẽ có cái nhìn tốt hơn về Loker khi có thời gian. là khá phức tạp thực sự ... Tôi đã tưởng tượng rằng có thể là một số cách để làm điều này bằng cách chạy các mã bằng cách sử dụng UNIX để theo dõi truy cập tập tin.Tôi không thực sự biết bất cứ điều gì về điều này ... do đó tưởng tượng – mathtick

+0

@mathtick "I đã được tưởng tượng rằng có thể là một số cách để làm điều này bằng cách chạy mã bằng cách sử dụng UNIX để theo dõi truy cập tập tin.Vấn đề là bạn cần phải thực sự chạy mã (phân tích động và tĩnh) và bạn sẽ không thấy tất cả các lệnh/tập tin có thể có - chỉ những lệnh được thực hiện/truy cập trong thời gian này –

+0

Cảm ơn, đó là một điểm khởi đầu tốt, một số kết hợp giữa ptree và pfiles có thể là điểm khởi đầu hữu ích cho phân tích động. – mathtick

5

Bạn có thể sử dụng 'strace' để chạy tập lệnh và xem mọi thứ tập lệnh và quy trình con của nó, bao gồm tìm kiếm và mở tệp. Ví dụ:

$ cat foo.sh 
#!/usr/bin/env bash 

touch /tmp/foon 
$ chmod +x foo.sh 
$ strace -f -e execve,access,open,stat -o foo.trace ./foo.sh 
$ cat foo.trace 
32176 execve("./foo.sh", ["./foo.sh"], [/* 42 vars */]) = 0 
32176 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) 
32176 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) 
32176 open("/usr/local/lib/tls/x86_64/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) 
... 
32176 execve("/bin/bash", ["bash", "./foo.sh"], [/* 42 vars */]) = 0 
... 
32177 execve("/usr/bin/touch", ["touch", "/tmp/foon"], [/* 41 vars */]) = 0 
32177 open("/tmp/foon", O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, 0666) = 3 
... 
32176 --- SIGCHLD (Child exited) @ 0 (0) --- 
$ 

Tôi đã cắt rất nhiều hoạt động khác đang diễn ra ở đó (mở thư viện hệ thống; tra cứu dữ liệu miền địa phương và hơn thế nữa). Kiểm tra 'man strace' để biết chi tiết về ý nghĩa của các tùy chọn; -f, -o, và -e là những cái tôi sử dụng thường xuyên nhất.

+0

Điều này là tốt cho việc hiển thị đường dẫn thực thi của một tập lệnh, nhưng lý tưởng là một giải pháp cho câu hỏi của OP sẽ hiển thị các đường dẫn chưa được thực hiện (theo cách tương tự với –

+0

Có, đây là một chút vấn đề đối với tôi ... có rất nhiều trường hợp ngoại lệ với các trường hợp khác nhau gửi các tập lệnh để truy cập các tệp khác nhau mà nó nhận được một chút d boggling. Chiến lược chính của tôi là sử dụng strace và cắt giảm sản lượng xuống một thứ gì đó mà tôi có thể chạy một cách khác để xem khi nào mọi thứ thay đổi đáng kể. – mathtick

0

Bạn không thể làm điều đó bằng ngôn ngữ động như vậy, công cụ phân tích tĩnh của bạn sẽ không đáng tin cậy và bỏ lỡ một số phụ thuộc. Hãy xem xét mã sau:

#!/bin/sh 

func_foo() { echo 'foo running' ; } 
func_bar() { echo 'bar running' ; } 
# etc... 

printf 'foo, bar,...? ' # for testing 
read RPC 
# rpc_is_in_rpclist "$RPC" || die "invalid call" 
printf 'Calling func_%s\n' "$RPC" 
func_"$RPC" 

Đây không phải là ví dụ phức tạp; Gần đây tôi đã thêm vào một môi trường sản xuất một phiên bản phức tạp hơn với thông số này.

Nếu bạn thực sự cần phân tích tĩnh thì bạn không nên sử dụng ngôn ngữ động ngay từ đầu, chúng đơn giản không tương thích với nhau. Điều tương tự cũng giữ cho mọi ngôn ngữ chức năng khác trong đó các hàm được chuyển thành các đối số: phân tích tĩnh không thể dự đoán thực tế các giá trị của các đối số.

Ngay cả trong một ngôn ngữ rất tĩnh và đơn giản như Java bạn vẫn có thể né tránh phân tích tĩnh nếu bạn cố gắng hết sức và bạn sử dụng sự phản chiếu. Tuy nhiên sự phản ánh là cồng kềnh bởi thiết kế và không được sử dụng rộng rãi, vì vậy việc phân tích Java rất hữu ích trong thực tế: xem Eclipse vv ..

+0

Đúng là bạn muốn có một công cụ phân tích để xử lý mã như bạn hiển thị, nhưng đó không phải là một thiết kế tốt. Để duy trì, vv, một câu lệnh 'case' nên được sử dụng. –

+0

@Dennis: một lý do khiến mọi người sử dụng ngôn ngữ động là vì họ có thể mã * nhanh hơn *. Cho rằng họ đã sẵn sàng để có nguy cơ phân tích/xác minh ít tĩnh tại thời gian biên dịch. Để thực sự được triển khai nhanh hơn, nhiều tập lệnh sẽ không làm phiền với câu lệnh trường hợp trọng lượng nặng. Nếu không, các nhà phát triển của họ sẽ sử dụng một ngôn ngữ tĩnh hơn. – MarcH

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