From fb8f1f1b53f57744c86e60ee6b02d8d86d298fdf Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 23 Mar 2016 19:14:42 +0100 Subject: ssh: experimental ssh_info extended --- lib/ssh/src/ssh_info.erl | 288 ++++++++++++++++++++++++++++------------------- 1 file changed, 173 insertions(+), 115 deletions(-) (limited to 'lib/ssh') diff --git a/lib/ssh/src/ssh_info.erl b/lib/ssh/src/ssh_info.erl index 2dfc55cd92..67130d5eac 100644 --- a/lib/ssh/src/ssh_info.erl +++ b/lib/ssh/src/ssh_info.erl @@ -31,134 +31,168 @@ collect_pids/0 ]). +-include("ssh_connect.hrl"). + print() -> - print(user). + io:format("~s", [string()]). +print(File) when is_list(File) -> + {ok,D} = file:open(File, write), + print(D), + file:close(D); print(D) -> + io:format(D, "~s", [string()]). + +string() -> try supervisor:which_children(ssh_sup) of _ -> - io__nl(D), - print_general(D), - io__nl(D), - underline(D, "Client part", $=), - print_clients(D), - io__nl(D), - underline(D, "Server part", $=), - print_servers(D), - io__nl(D), - underline(D, "Supervisors", $=), - walk_sups(D, ssh_sup), - io__nl(D) + [io_lib:nl(), + print_general(), + io_lib:nl(), + underline("Client part", $=), + print_clients(), + io_lib:nl(), + underline("Server part", $=), + print_servers(), + io_lib:nl(), + underline("Supervisors", $=), + walk_sups(ssh_sup), + io_lib:nl()] catch _:_ -> - io__format(D,"Ssh not found~n",[]) + io_lib:format("Ssh not found~n",[]) end. -string() -> - Pid = spawn(fun init/0), - print(Pid), - Pid ! {get,self()}, - receive - {result,R} -> R - end. - -%%%================================================================ -print_general(D) -> - {_Name, Slogan, Ver} = lists:keyfind(ssh,1,application:which_applications()), - underline(D, io_lib:format("~s ~s", [Slogan, Ver]), $=), - io__format(D, 'This printout is generated ~s. ~n',[datetime()]). %%%================================================================ -define(INDENT, " "). -print_clients(D) -> - PrintClient = fun(X) -> print_client(D,X) end, +print_general() -> + {_Name, Slogan, Ver} = lists:keyfind(ssh,1,application:which_applications()), + [underline(io_lib:format("~s ~s", [Slogan, Ver]), $=), + io_lib:format('This printout is generated ~s. ~n',[datetime()]) + ]. + +print_clients() -> try - lists:foreach(PrintClient, supervisor:which_children(sshc_sup)) + lists:map(fun print_client/1, + supervisor:which_children(sshc_sup)) catch C:E -> - io__format(D, '***FAILED: ~p:~p~n',[C,E]) + io_lib:format('***print_clients FAILED: ~p:~p~n',[C,E]) end. -print_client(D, {undefined,Pid,supervisor,[ssh_connection_handler]}) -> +print_client({undefined,Pid,supervisor,[ssh_connection_handler]}) -> {{Local,Remote},_Str} = ssh_connection_handler:get_print_info(Pid), - io__format(D, ?INDENT"Local: ~s Remote: ~s ConnectionRef = ~p~n",[fmt_host_port(Local),fmt_host_port(Remote),Pid]); -print_client(D, Other) -> - io__format(D, " [[Other 1: ~p]]~n",[Other]). + [io_lib:format(?INDENT"Local: ~s Remote: ~s ConnectionRef = ~p~n", + [fmt_host_port(Local), fmt_host_port(Remote), Pid]), + case channels(Pid) of + {ok,Channels=[_|_]} -> + [print_ch(ChPid) || #channel{user=ChPid} <- Channels]; + _ -> + io_lib:format(?INDENT?INDENT?INDENT"No channels~n",[]) + end]; + +print_client(Other) -> + io_lib:format(" [[Other 1: ~p]]~n",[Other]). %%%================================================================ -print_servers(D) -> - PrintServer = fun(X) -> print_server(D,X) end, +print_servers() -> try - lists:foreach(PrintServer, supervisor:which_children(sshd_sup)) + lists:map(fun print_server/1, + supervisor:which_children(sshd_sup)) catch C:E -> - io__format(D, '***FAILED: ~p:~p~n',[C,E]) + io_lib:format('***print_servers FAILED: ~p:~p~n',[C,E]) end. -print_server(D, {{server,ssh_system_sup,LocalHost,LocalPort,Profile},Pid,supervisor,[ssh_system_sup]}) when is_pid(Pid) -> - io__format(D, ?INDENT"Listen: ~s (~p children) Profile ~p~n",[fmt_host_port({LocalHost,LocalPort}), - ssh_acceptor:number_of_connections(Pid), - Profile]), - PrintSystemSup = fun(X) -> print_system_sup(D,X) end, - lists:foreach(PrintSystemSup, supervisor:which_children(Pid)). +print_server({{server,ssh_system_sup,LocalHost,LocalPort,Profile},Pid,supervisor,[ssh_system_sup]}) when is_pid(Pid) -> + Children = supervisor:which_children(Pid), + [io_lib:format(?INDENT"Listen: ~s (~p children) Profile ~p",[fmt_host_port({LocalHost,LocalPort}), + ssh_acceptor:number_of_connections(Pid), + Profile]), + case [AccPid + || {{ssh_acceptor_sup,_LocalHost,_LocalPort,_Profile}, AccPid, supervisor, [ssh_acceptor_sup]} + <- Children] of + AcceptorPids = [_|_] -> + [io_lib:format(" [Acceptor Pid", []), + [io_lib:format(" ~p",[AccPid]) || AccPid <- AcceptorPids], + io_lib:format("]~n", []) + ]; + [] -> + io_lib:nl() + end, + lists:map(fun print_system_sup/1, + supervisor:which_children(Pid)) + ]. + + +print_system_sup({Ref,Pid,supervisor,[ssh_subsystem_sup]}) when is_reference(Ref), + is_pid(Pid) -> + lists:map(fun print_channels/1, + supervisor:which_children(Pid)); +print_system_sup({{ssh_acceptor_sup,_LocalHost,_LocalPort,_Profile}, Pid, supervisor, [ssh_acceptor_sup]}) when is_pid(Pid) -> + []. -print_system_sup(D, {Ref,Pid,supervisor,[ssh_subsystem_sup]}) when is_reference(Ref), - is_pid(Pid) -> - PrintChannels = fun(X) -> print_channels(D,X) end, - lists:foreach(PrintChannels, supervisor:which_children(Pid)); -print_system_sup(D, {{ssh_acceptor_sup,_LocalHost,_LocalPort,_Profile}, Pid, supervisor, [ssh_acceptor_sup]}) when is_pid(Pid) -> - io__format(D, ?INDENT?INDENT"[Acceptor Pid ~p]~n",[Pid]). -print_channels(D, {{server,ssh_channel_sup,_,_},Pid,supervisor,[ssh_channel_sup]}) when is_pid(Pid) -> +print_channels({{server,ssh_channel_sup,_,_},Pid,supervisor,[ssh_channel_sup]}) when is_pid(Pid) -> Children = supervisor:which_children(Pid), ChannelPids = [P || {R,P,worker,[ssh_channel]} <- Children, is_pid(P), is_reference(R)], case ChannelPids of - [] -> io__format(D, ?INDENT?INDENT"No channels~n",[]); + [] -> io_lib:format(?INDENT?INDENT"No channels~n",[]); [Ch1Pid|_] -> {{ConnManager,_}, _Str} = ssh_channel:get_print_info(Ch1Pid), {{_,Remote},_} = ssh_connection_handler:get_print_info(ConnManager), - io__format(D, ?INDENT?INDENT"Remote: ~s ConnectionRef = ~p~n",[fmt_host_port(Remote),ConnManager]), - lists:foreach(fun(P) -> print_ch(D,P) end, ChannelPids) + [io_lib:format(?INDENT?INDENT"Remote: ~s ConnectionRef = ~p~n",[fmt_host_port(Remote),ConnManager]), + lists:map(fun print_ch/1, ChannelPids) + ] end; -print_channels(_D, {{server,ssh_connection_sup,_,_},Pid,supervisor,[ssh_connection_sup]}) when is_pid(Pid) -> - ok. % The supervisor of the connections socket owning process - -print_ch(D, Pid) -> - {{ConnManager,ChannelID}, Str} = ssh_channel:get_print_info(Pid), - {_LocalRemote,StrM} = ssh_connection_handler:get_print_info(ConnManager), - io__format(D, ?INDENT?INDENT?INDENT"ch ~p: ~s ~s~n",[ChannelID, StrM, Str]). - +print_channels({{server,ssh_connection_sup,_,_},Pid,supervisor,[ssh_connection_sup]}) when is_pid(Pid) -> + []. % The supervisor of the connections socket owning process + +print_ch(Pid) -> + try + {{ConnManager,ChannelID}, Str} = ssh_channel:get_print_info(Pid), + {_LocalRemote,StrM} = ssh_connection_handler:get_print_info(ConnManager), + io_lib:format(?INDENT?INDENT?INDENT"ch ~p ~p: ~s ~s~n",[ChannelID, Pid, StrM, Str]) + catch + C:E -> + io_lib:format('****print_ch FAILED for ChanPid ~p: ~p:~p~n',[Pid, C, E]) + end. + + %%%================================================================ -define(inc(N), (N+4)). -walk_sups(D, StartPid) -> - io__format(D, "Start at ~p, ~s.~n",[StartPid,dead_or_alive(StartPid)]), - walk_sups(D, children(StartPid), _Indent=?inc(0)). - -walk_sups(D, [H={_,Pid,_,_}|T], Indent) -> - indent(D, Indent), io__format(D, '~200p ~p is ~s~n',[H,Pid,dead_or_alive(Pid)]), - case H of - {_,_,supervisor,[ssh_connection_handler]} -> ok; - {_,Pid,supervisor,_} -> walk_sups(D, children(Pid), ?inc(Indent)); - _ -> ok - end, - walk_sups(D, T, Indent); -walk_sups(_D, [], _) -> - ok. +walk_sups(StartPid) -> + io_lib:format("Start at ~p, ~s.~n",[StartPid,dead_or_alive(StartPid)]), + walk_sups(children(StartPid), _Indent=?inc(0)). + +walk_sups([H={_,Pid,_,_}|T], Indent) -> + [indent(Indent), + io_lib:format('~200p ~p is ~s~n',[H,Pid,dead_or_alive(Pid)]), + case H of + {_,_,supervisor,[ssh_connection_handler]} -> ""; + {_,Pid,supervisor,_} -> walk_sups(children(Pid), ?inc(Indent)); + _ -> "" + end, + walk_sups(T, Indent) + ]; +walk_sups([], _) -> + "". dead_or_alive(Name) when is_atom(Name) -> case whereis(Name) of - undefined -> + undefined -> "**UNDEFINED**"; - Pid -> + Pid -> dead_or_alive(Pid) end; dead_or_alive(Pid) when is_pid(Pid) -> @@ -167,7 +201,8 @@ dead_or_alive(Pid) when is_pid(Pid) -> _ -> "alive" end. -indent(D, I) -> io__format(D,'~*c',[I,$ ]). +indent(I) -> io_lib:format('~*c',[I,$ ]). + children(Pid) -> Parent = self(), @@ -178,20 +213,39 @@ children(Pid) -> {Helper,L} when is_list(L) -> L after - 2000 -> + 2000 -> catch exit(Helper, kill), [] end. +is_connection_handler(Pid) -> + try + {ssh_connection_handler,init,_} = + proplists:get_value( + '$initial_call', + proplists:get_value( + dictionary, + process_info(Pid, [dictionary]))) + of + _ -> true + + catch + _:_ -> + false + end. + +channels(Pid) -> + case is_connection_handler(Pid) of + true -> + ssh_connection_handler:info(Pid,all); + false -> + false + end. + %%%================================================================ -underline(D, Str, LineChar) -> - Len = lists:flatlength(Str), - io__format(D, '~s~n',[Str]), - line(D,Len,LineChar). +underline(Str, LineChar) -> + io_lib:format('~s~n~*c~n',[Str, lists:flatlength(Str), LineChar]). -line(D, Len, Char) -> - io__format(D, '~*c~n', [Len,Char]). - datetime() -> {{YYYY,MM,DD}, {H,M,S}} = calendar:now_to_universal_time(erlang:timestamp()), @@ -201,29 +255,10 @@ datetime() -> fmt_host_port({{A,B,C,D},Port}) -> io_lib:format('~p.~p.~p.~p:~p',[A,B,C,D,Port]); fmt_host_port({Host,Port}) -> io_lib:format('~s:~p',[Host,Port]). -%%%################################################################ - -io__nl(D) when is_atom(D) -> io:nl(D); -io__nl(P) when is_pid(P) -> P ! {string,io_lib:nl()}. - -io__format(D, Fmt, Args) when is_atom(D) -> io:format(D, Fmt, Args); -io__format(P, Fmt, Args) when is_pid(P) -> P ! {string,io_lib:format(Fmt, Args)}. - - -init() -> loop([]). - -loop(Acc) -> - receive - {string,Str} -> - loop([Str|Acc]); - {get,Who} -> - Who ! {result,lists:flatten(lists:reverse(Acc))} - end. - %%%################################################################ collect_pids() -> collect_pids(ssh_sup). -collect_pids(P) -> +collect_pids(P) -> Collector = pcollect_pids(P, spawn(fun init_collector/0)), Collector ! {get_values,self()}, receive @@ -231,7 +266,7 @@ collect_pids(P) -> Values end. -%%%---------------- +%%%---------------- pcollect_pids(undefined, Collector) -> Collector; @@ -249,17 +284,43 @@ pcollect_pids(Pid, Collector) when is_pid(Pid) -> end), Collector; -pcollect_pids({_,Pid,supervisor,_}, Collector) when is_pid(Pid) -> +pcollect_pids({Ref,Pid,supervisor,_}, Collector) when is_pid(Pid), + is_reference(Ref) -> pcollect_pids(Pid, Collector); -pcollect_pids({_,Pid,worker,_}, Collector) when is_pid(Pid) -> +pcollect_pids({sshc_sup,Pid,supervisor,_}, Collector) when is_pid(Pid) -> + pcollect_pids(Pid, Collector); + +pcollect_pids({sshd_sup,Pid,supervisor,_}, Collector) when is_pid(Pid) -> + pcollect_pids(Pid, Collector); + +pcollect_pids({{ssh_acceptor_sup,_,_,_},Pid,supervisor,_}, Collector) when is_pid(Pid) -> + pcollect_pids(Pid, Collector); + +pcollect_pids({{server,_,_,_},Pid,supervisor,_}, Collector) when is_pid(Pid) -> + pcollect_pids(Pid, Collector); + +pcollect_pids({{server,_,_,_,_},Pid,supervisor,_}, Collector) when is_pid(Pid) -> + pcollect_pids(Pid, Collector); + +pcollect_pids({undefined,Pid,supervisor,[ssh_connection_handler]}, Collector) -> + Collector ! {value,Pid,Pid}, + case channels(Pid) of + {ok,L} -> + [Collector!{value,P,P} || #channel{user=P} <- L]; + _ -> + ok + end, + Collector; + +pcollect_pids({_,Pid,_,_}, Collector) when is_pid(Pid) -> Collector ! {value,Pid,Pid}, Collector; pcollect_pids(_, Collector) -> Collector. -%%%---------------- +%%%---------------- init_collector() -> loop_collector([],[]). @@ -273,6 +334,3 @@ loop_collector(Expects, Values) -> %% Values=/=[] -> From ! {values,Values} end. - - - -- cgit v1.2.3