2010-10-13 71 views
8

我正在尋找處理一個shell腳本來確定的一種方式:確定shell腳本的函數和文件依賴關係?

  1. 哪些命令,腳本或函數調用的腳本。
  2. 腳本(r或w)訪問哪些文件。

它不需要通過依賴遞減,只需列出它直接運行的內容即可。我可以自己寫一些能夠做到這一點的東西,但一定是在...之前完成的,我只是沒有找到它。

+0

有趣的問題 - 非平凡回答。考慮跟蹤'sh -x'的輸出(但是它只顯示你執行的命令,而不是那些沒有執行的命令) – 2010-10-13 19:27:17

回答

1

這將是我目前開發的Loker項目的一項功能。目前,解析器已基本完成,您可以在其上實現一個合理的近似值。但是,一般來說,這項任務非常複雜,因爲命令的名稱可能來自可變擴展,字段分割等。

如果您描述了什麼是您需要的,以及您要解析的是哪種腳本將能夠說出Loker現在可以滿足您的多少需求。

作爲替代選項,某些版本的bash有--rpm-requires選項,它也有類似的功能。

+0

非常有趣,當我有時間的時候,我會更好地看看Loker,正確解析文件和可執行文件的代碼確實是非常複雜的......我想通過使用UNIX來運行代碼來跟蹤文件訪問可能是一種方法,我對這個事情一無所知......因此,這個幻想。 – mathtick 2010-10-14 18:55:27

+0

@mathtick「I幻想這可能是通過使用UNIX來運行代碼來跟蹤文件訪問的方式。「這是絕對可能的,使用'strace'來解決這個問題是你需要真正運行代碼(動態vs靜態分析),你不會看到所有可能的命令/文件 - 只有那些在執行/訪問期間這個特殊的運行 – 2010-10-14 19:40:03

+0

謝謝,這看起來是一個很好的起點,ptree和pfiles的組合也許是動態分析的一個有用的起點,測試所有的情況(而不僅僅是那些碰巧運行在特定實例)對於我現在看到的代碼來說非常重要 – mathtick 2010-10-15 14:46:10

5

您可以使用'strace'來運行腳本並查看腳本及其子進程的所有內容,包括查找和打開文件。例如:

$ 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) --- 
$ 

我修剪了很多其他活動(開放系統庫;查找語言環境數據等等)。查看「man strace」以瞭解選項的含義。 -f,-o和-e是我經常使用的。

+0

這對於顯示腳本的執行路徑很有幫助,但理想情況下OP的問題的解決方案也會顯示未執行的路徑(類似於怎麼'bash -n'在整個腳本中檢查語法) – 2010-11-10 03:48:51

+0

是的,這對我來說有點問題......有很多例外情況發送腳本來訪問不同的文件, d令人難以置信。我的主要策略是使用strace並減少輸出,以便我可以運行差異來查看事情何時發生急劇變化。 – mathtick 2010-11-10 15:08:23

0

你只是不能用這樣一種動態語言來做到這一點,你的靜態分析工具將不可靠,並會錯過一些依賴關係。考慮下面的代碼:

#!/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" 

這不是一個複雜的例子;我最近通過參數向生產環境中添加了更詳細的版本。

如果你真的需要靜態分析,那麼你不應該使用在首位動態語言,他們只是彼此不兼容。對於函數作爲參數傳遞的其他函數式語言也是如此:靜態分析實際上不能預測參數的值。

即使在像Java這樣非常靜態和簡單的語言中,如果您努力嘗試並使用反射,仍然可以躲避靜態分析。然而,由於反射設計繁瑣且不被廣泛使用,因此對Java的分析在實踐中非常有用:請參閱Eclipse等。

+0

的確,你想要一個分析工具來處理你所顯示的代碼,但這不是一個好的設計。爲了可維護性等,應該使用'case'語句。 – 2010-11-11 01:06:31

+0

@Dennis:人們使用動態語言的一個原因是因爲他們可以更快地編碼*。爲此,他們準備在編譯時承擔較少的靜態分析/驗證風險。要實際執行得更快,許多腳本不會受到重量級的病例陳述的困擾。否則,他們的開發人員會使用更靜態的語言。 – MarcH 2010-11-11 09:33:14