2016-01-22 81 views
3

我正在構建一個使用Java來允許用戶在Linux上運行shell命令的CFML應用程序。輸入的命令通過-c選項傳遞給bash。要使bash擴展別名,我使用-i選項以交互模式運行。以下行可以從CommandBox REPL進行測試,以重複的行爲:我可以在沒有掛起主進程的情況下以Java的交互模式運行bash嗎?

CWD = createObject('java', 'java.io.File').init('/my/working/dir') 
process = createObject('java', 'java.lang.Runtime').getRuntime().exec(['bash','-i','-c','ll'], javaCast('null', ''), CWD) 

此執行和ll命令的輸出可以經由process.getInputStream()被訪問,但是它也中止主java程序,我的CFML發動機是跑進去,把我扔在我的外殼裏。

[1]+ Stopped     myBinary 
[[email protected]]# 

然後我必須運行fg開始備份。我知道這與在交互模式下運行bash有關,但是如何避免此行爲?

我也嘗試通過使用選項-O expand_aliases或運行shopt -s expand_aliases來擴展別名,但這兩者都沒有任何影響。

+0

你可以試試['ProcessBuilder'](https://docs.oracle.com/javase/8/docs/api/java/lang/ProcessBuilder.html)。 –

+0

是的,我意識到這一點,但盧西CF引擎有一些不錯的實用程序圍繞runtime.exec構建,它處理併發捕獲錯誤和輸出流等,這真是太好了。我想讓它按原樣運行,但請始終認爲我只是在某處丟失了一些簡單的選項。 –

+0

我發現一個黑客添加「&&退出」到最後。我會再提供幾天,如果沒有人能回答,我會將其作爲解決方案發布。 –

回答

1

我從來沒有真正弄清楚這個「爲什麼」,但我發現了一些解決方法,至少讓我通過使用別名擴展的Runtime.exec()運行用戶輸入的bash命令,所以我會在這裏分享它們爲他人。如果有人有更好的答案,請添加它。

我發現的最徹底的方法是用set +m;運行命令之前設置+m選項來禁用作業控制(監控模式):

process = createObject('java', 'java.lang.Runtime').getRuntime().exec([ 'bash','-i','-c', 'set +m; ll' ], javaCast('null', ''), CWD); 

唯一的缺點是,與bash工作,但沒」 t與zsh工作,我的幾個用戶喜歡在他們的Mac上使用。

我最終什麼事做了添加&& exit的命令退出,像這樣的外殼:

process = createObject('java', 'java.lang.Runtime').getRuntime().exec([ 'bash','-i','-c', 'll && exit'], javaCast('null', ''), CWD); 

這跑,而無需把整個Java進程進入後臺模式,但我發現兩個側面影響至今:

  1. 「exit」一詞被附加到標準錯誤。
  2. 某些命令如git pull輸出標準錯誤文本bash: no job control in this shell
+0

非常好奇,「爲什麼」的答案是。顯然你不能/不想使用SSH ......但爲什麼? –

+0

那麼,我正在運行CFML(Java)應用程序運行的同一臺機器上的進程。我不知道爲什麼我想使用SSH。 –

+0

我不懷疑你需要使用CFML。我只是想知道你的場景是什麼,你需要允許用戶通過cfml運行命令,而通常情況下只需要給用戶SSH訪問。 我完全理解你對cfml的這種想法我只是好奇它的用途,因爲它可能對未來有用。 –

相關問題