就如同一些代碼比賽網站一樣,直接上傳代碼就可以在網頁上看到運行結果,go語言官方網站也有著類似功能。如何??有沒有現成的解決方案?
回複內容:
如果需要的是現成的解決方案,這個就不錯:
https://github.com/mattgodbolt/gcc-explorer
效果預覽:
Compiler Explorer
如果是針對傳統使用方法的程式設計語言實現一個的話涉及的內容很雜,包括:
- Web伺服器+Web伺服器與後端程式互動的組件(這個可以用現成的,我用的是nginx+FCGI)
- 後端程式
後端核心就是一個類似調用系統給的類似execl的API執行一下對應編譯工具,用這個API時還得精心處理一下管道,把輸出內容匯出來顯示回網頁。
但是因為這類程式和OJ一樣,是網路上的公用服務而且居然還允許使用者上傳代碼編譯執行,所以問題主要集中在安全處理上,而且安全問題的處理高度依賴作業系統。
以Linux為例,安全方麵包括但不僅包括以下內容:
- 依賴環境構建、沙箱
- 運行身份,包括GID、UID
- 資源限制,包括socket、檔案操作、核心轉儲大小、檔案數、子進程數等等
- syscall限制
- 執行時間限制,包括已耗用時間和CPU時間
- 檔案系統壓力
Windows下是另一堆問題要解決,比Linux複雜得多(也許是我不太會用Windows)。
我認識一人,自己實現了一個類似Haskell的東西,有和Go Playground差不多的線上運行網頁,我問他怎麼那麼快把那麼多東西都搞完了,他說,“整個語言就是用JS實現的,所以有瀏覽器就能運行,不需要後端”,這也是一種思路。
前兩天的課程設計上正好根同學一塊兒設計了一個簡單的線上比賽平台,而且平時也經常到網站上做比賽,就簡單說下它的實現吧。
把代碼提交到網站之後,將其儲存成代碼,在PHP或JSP中有調用系統命令的東西,如PHP中的exec函數。此時你需要一個判題的指令碼,對得到的代碼進行編譯,運行,得到運行資訊之後儲存到資料庫中,如在php中就可以寫一個實現的語句:
exec("./onj $destFile $file", $output, $verdict);
//from onj project - Processfile.php - line 105
這就是調用判題功能,原則上可以用任何語言寫。onj就是用python寫的,對代碼進行編譯,運行和判斷。它需要得到一個比賽題目的標準輸入,將標準輸出重新導向到一個檔案中,然後對標準答案進行對比,可以得出使用者提交的代碼是否能得出正確的結果。
這樣的系統在網上好多了,推薦幾個:
1. ONJ http://sourceforge.net/projects/onj/
php,代碼十分工整,我很喜歡,中文支援不完善。
2.NEUOJ https://github.com/yangzhe1991/neuoj
判題是用python寫的。
3.HUSTOJ http://code.google.com/p/hustoj/
國內好像用的比較多的,我沒用過。
//自己寫的太醜了,就不帖出來了。
這種比賽的網站搞ACM的人相對熟悉,如果有認識的人可以問問。直接以web進程fork的問題是web是輕量級的,並發數大一些很正常。
而編譯和運行則比較重量級,不能並發太多,必須控制。
所以應該有個任務隊列的機制,先後有序的進行。
至於安全,可以另外開一個話題了。應該是直接調用編譯命令,檢查輸出結果吧。
至於安全問題,應該可以用一個權限等級很低的使用者來做這個事。