2010-02-09 20 views

回答

7

這就是我想到的。

-module(mycmd). 
-export([cmd/2]). 

cmd(Cmd, Args) -> 
    Tag = make_ref(), 
    {Pid, Ref} = erlang:spawn_monitor(fun() -> 
      Rv = cmd_sync(Cmd, Args), 
      exit({Tag, Rv}) 
     end), 
    receive 
     {'DOWN', Ref, process, Pid, {Tag, Data}} -> Data; 
     {'DOWN', Ref, process, Pid, Reason} -> exit(Reason) 
    end. 

cmd_sync(Cmd, Args) -> 
    P = open_port({spawn_executable, os:find_executable(Cmd)}, [ 
      binary, use_stdio, stream, eof, {args, Args}]), 
    cmd_receive(P, []). 

cmd_receive(Port, Acc) -> 
    receive 
     {Port, {data, Data}} -> cmd_receive(Port, [Data|Acc]); 
     {Port, eof}   -> {ok, lists:reverse(Acc)} 
    end. 
0

難道你不能只做os:cmd(string:join(["cmd", "arg1", "arg2"], " "))

+2

這並沒有解決這個問題,即給予os:cmd/1的字符串將被shell處理。這將以系統依賴的方式擴展事物。例如,os:cmd(「echo'Hello'」)會將hello傳遞給沒有單引號的echo命令。很難弄到這樣的東西,這樣程序就會得到和Erlang一樣的參數字符串。你需要一種方法來運行程序,而不需要shell作爲中間人。 – RichardC 2010-02-10 12:49:56

7

現在你可以做open_port({spawn_executable, Command}, [{args, [A1, ..., An]}]),但是在os模塊中沒有方便的包裝。你可以拿os:cmd/1的代碼,並調整它使用spawn_executable。有關更多詳細信息,請查看erlang:open_port/2的文檔。

相關問題