2016-11-08 87 views
2

在Clojure程序中,你如何從標準中讀出讀取?我想這樣做,或者將標準輸出傳輸到我創建的輸入流。 Clojure中的標準輸出是java.io.PrintWriterClojure可以從現有流程中捕捉標準嗎?

我有一個Samza工作,由Clojure程序開始。還有一個我可以遠程連接的nrepl服務器。連接之後,我需要能夠進入並尾出標準輸出(將作業寫入輸出)。

1)按本SO questionwith-out-str(見here)讓我們暫時結合*out*(到java.io.StringWriter中),讓你執行的代碼寫入到一個字符串。但這並不能讓我進入現有的*out*

2)如果你看一下clojure.java.shell(見here),它得到了JVM的運行和exec是它的過程。從這個過程中,你可以得到它的標準輸出流。但是,這不是我正在尋找的默認標準(*out*)。

3)SO question接近我想要做的。但是,我再次連接到一個現有的流程,並希望終止其標準輸出。

這在Clojure中可能嗎(請參閱here)?有沒有人解決這個問題

+0

在Linux上,您可以從'/ proc/{pid}/fd/1'讀取該文件,該文件是該進程的標準輸出。同樣'/ proc/{pid}/fd/2'是stderr。 –

+2

你的意思是說你想將流程的輸出流入clojure流程,比如'ls | my-clj'並讓my-clj讀取ls的輸出?如果是這樣,只需使用http://stackoverflow.com/questions/18688755/reading-characters-from-stdin –

+0

@AnnThompson不,我正在遠程連接到一個已經運行的進程中的repl。一旦連接,我想*「尾巴」*標準輸出。 – Nutritioustim

回答

1

流程輸出不是一個發佈訂閱模型,所以當一個進程將一個字符放入其輸出緩衝區時,實際上有一個進程會將其從該緩衝區中取出。如果你有一個程序是由shell程序啓動的,如果它讀取它的輸出並將其寫入終端(或者讀取和忽略它),那麼shell會進行處理。如果你在啓動它的進程之後附加你的進程並開始嘗試獲取數據,那麼你最有可能得不到任何東西,因爲父進程會首先得到它。我只是想這從兩個終端:

端子1:

cat 

2號航站樓:

ps -ef | grep cat 
tail -f /proc/24547/fd/2 

端子1:

hello 

2號航站樓: <什麼>

打印到終端1的字符串「hello」,啓動它的過程。

然後說「好吧,如果沒有人讀取輸出,那麼它會在那裏讓我得到」。雖然這聽起來不錯,但它遇到了這些問題,即這些是固定大小的緩衝區,所以只要輸出緩衝區已滿,試圖寫入它的進程就會阻塞(直到有人讀取輸出以解除阻止)它。

一般的解決方法就是管你要尾巴後來到tee命令,該命令的輸出寫入文件它傳遞給任何被閱讀它的過程。

command-to-watch arg1 arg2 | tee logfile.potentially-huge 

儘管如果你走這條路線,你應該在磁盤填滿之前旋轉日誌文件。請確保您清空日誌文件,正是這個命令

echo > logfile.potentially-huge 

,或使用你的程序做出truncate調用文件。簡單地刪除該文件將從日誌目錄中刪除它的名稱而不刪除它,它將靜靜地繼續增長佔用磁盤空間並且新文件將不會有輸出。

這基本上是爲什麼我們建立log4j(90年代)和syslog(80年代)等日誌庫的原因。

如果你仍然想在這個瘋狂的瘋狂,轉到tmux,它可以做任何事情,並改變人們使用文本的方式。嚴肅地說,你應該改變另一個過程創建輸出的方式,以便更容易獲得。