• port 执行命令的封装和参数详解


    下面代码摘自rebar_utils.erl

    -module(tt7).
    %-export([start/0]).
    -compile(export_all).
    
    -define(FAIL, abort()).
    -define(ABORT(Str, Args), abort(Str, Args)).
    
    -define(CONSOLE(Str, Args), io:format(Str, Args)).
    
    -define(DEBUG(Str, Args), io:format("debug :" ++ Str, Args)).
    -define(INFO(Str, Args), io:format("info :" ++ Str, Args)).
    -define(WARN(Str, Args), io:format("warn :" ++ Str, Args)).
    -define(ERROR(Str, Args), io:format("standard_error error :" ++ Str, Args)).
    
    -define(FMT(Str, Args), lists:flatten(io_lib:format(Str, Args))).
    
    sh(Command0, Options0) ->
        ?INFO("sh info:
    	cwd: ~p
    	cmd: ~s
    ", [file:get_cwd(), Command0]),
        ?DEBUG("	opts: ~p
    ", [Options0]),
    
        DefaultOptions = [{use_stdout, false}, abort_on_error], %% use_stdout表示是否输出cmd执行结果 abort_on_error表示错误时候退出
        Options = [expand_sh_flag(V)
                   || V <- proplists:compact(Options0 ++ DefaultOptions)],
    
        ErrorHandler = proplists:get_value(error_handler, Options),
        OutputHandler = proplists:get_value(output_handler, Options),
    
    %    Command = patch_on_windows(Command0, proplists:get_value(env, Options, [])),
        Command = Command0,
        PortSettings = proplists:get_all_values(port_settings, Options) ++
            [exit_status, {line, 16384}, use_stdio, stderr_to_stdout, hide],  %%open_port的一些常用参数
        ?DEBUG("Port Cmd: ~p
    Port Opts: ~p
    ", [Command, PortSettings]),
        Port = open_port({spawn, Command}, PortSettings),
    
        case sh_loop(Port, OutputHandler, []) of
            {ok, _Output} = Ok ->
                Ok;
            {error, {_Rc, _Output}=Err} ->
                ErrorHandler(Command, Err)
        end.
    
    sh_loop(Port, Fun, Acc) ->         %%接受port执行结果
        receive
            {Port, {data, {eol, Line}}} ->
                sh_loop(Port, Fun, Fun(Line ++ "
    ", Acc));
            {Port, {data, {noeol, Line}}} ->
                sh_loop(Port, Fun, Fun(Line, Acc));
            {Port, {exit_status, 0}} ->
                {ok, lists:flatten(lists:reverse(Acc))};
            {Port, {exit_status, Rc}} ->
                {error, {Rc, lists:flatten(lists:reverse(Acc))}}
        end.
    
    %%处理return_on_error、abort_on_error、use_stdout、cd、env这几个参数的结果
    expand_sh_flag(return_on_error)
    -> {error_handler, fun(_Command, Err) -> {error, Err} end}; expand_sh_flag({abort_on_error, Message}) -> {error_handler, log_msg_and_abort(Message)}; expand_sh_flag(abort_on_error) -> {error_handler, fun log_and_abort/2}; expand_sh_flag(use_stdout) -> {output_handler, fun(Line, Acc) -> ?CONSOLE("~s", [Line]), [Line | Acc] end}; expand_sh_flag({use_stdout, false}) -> {output_handler, fun(Line, Acc) -> [Line | Acc] end}; expand_sh_flag({cd, _CdArg} = Cd) -> {port_settings, Cd}; expand_sh_flag({env, _EnvArg} = Env) -> {port_settings, Env}. log_msg_and_abort(Message) -> fun(_Command, {_Rc, _Output}) -> ?ABORT(Message, []) end. log_and_abort(Command, {Rc, Output}) -> ?ABORT("sh(~s)~n" "failed with return code ~w and the following output:~n" "~s~n", [Command, Rc, Output]). abort() -> throw(execute_abort). abort(String, Args) -> ?ERROR(String, Args), abort().

    这样就能用port方法执行一些shell命令

    执行如下

     1 11> tt7:sh("/bin/echo this is a $name", [{env,[{"name", "tanwen"}]}]).
     2 info :sh info:
     3         cwd: {ok,"/home/erlang/fortest"}
     4         cmd: /bin/echo this is a $name
     5 debug : opts: [{env,[{"name","tanwen"}]}]
     6 debug :Port Cmd: "/bin/echo this is a $name"
     7 Port Opts: [{env,[{"name","tanwen"}]},
     8             exit_status,
     9             {line,16384},
    10             use_stdio,stderr_to_stdout,hide]    
    11 {ok,"this is a tanwen
    "}    %%没有输出默认的cmd结果,这个是port的打印

     去掉调试,修改DefaultOptions = [{use_stdout, true}, abort_on_error]

    1 13> tt7:sh("/bin/echo this is a $name", [{env,[{"name", "tanwen"}]}]).
    2 this is a tanwen          %%这个是{use_stdout, true}的输出
    3 {ok,"this is a tanwen
    "}
  • 相关阅读:
    位置定位 api
    代理相关
    手机网页 右边的空白区
    sip介绍
    测试浏览器对html5支持
    sencha touch
    PC上的手机模拟器大全(安卓/苹果/黑莓/塞班/微软)
    测试视频
    android 环境配置 与 运行错误
    android 一年过期
  • 原文地址:https://www.cnblogs.com/tudou008/p/5278489.html
Copyright © 2020-2023  润新知