aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorHans Nilsson <hans@erlang.org>2016-03-23 19:14:42 +0100
committerHans Nilsson <hans@erlang.org>2016-03-29 15:51:12 +0200
commitfb8f1f1b53f57744c86e60ee6b02d8d86d298fdf (patch)
treea6db2e75d7bf4d1d61735b309fd6469af1663aee /lib
parent9be7db7401d3e107f6f63cb02117d1ffa1db1311 (diff)
downloadotp-fb8f1f1b53f57744c86e60ee6b02d8d86d298fdf.tar.gz
otp-fb8f1f1b53f57744c86e60ee6b02d8d86d298fdf.tar.bz2
otp-fb8f1f1b53f57744c86e60ee6b02d8d86d298fdf.zip
ssh: experimental ssh_info extended
Diffstat (limited to 'lib')
-rw-r--r--lib/ssh/src/ssh_info.erl288
1 files changed, 173 insertions, 115 deletions
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()),
@@ -202,28 +256,9 @@ 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.
-
-
-