From 10fcc64b7439a536c24d41d43b1e518dfd81c3bd Mon Sep 17 00:00:00 2001 From: Luke Bakken Date: Sat, 10 Dec 2022 14:20:02 -0800 Subject: [PATCH] Use win32_cmd/2 to run handle.exe because it is great. --- deps/rabbit_common/src/rabbit_misc.erl | 44 ++++++++++--------- .../src/rabbit_mgmt_external_stats.erl | 11 ++--- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/deps/rabbit_common/src/rabbit_misc.erl b/deps/rabbit_common/src/rabbit_misc.erl index bf43ac59af..aadf485ddf 100644 --- a/deps/rabbit_common/src/rabbit_misc.erl +++ b/deps/rabbit_common/src/rabbit_misc.erl @@ -62,7 +62,7 @@ -export([pget/2, pget/3, pupdate/3, pget_or_die/2, pmerge/3, pset/3, plmerge/2]). -export([format_message_queue/2]). -export([append_rpc_all_nodes/4, append_rpc_all_nodes/5]). --export([os_cmd/1, pwsh_cmd/1]). +-export([os_cmd/1, pwsh_cmd/1, win32_cmd/2]). -export([is_os_process_alive/1]). -export([version/0, otp_release/0, platform_and_version/0, otp_system_version/0, rabbitmq_and_erlang_versions/0, which_applications/0]). @@ -1173,7 +1173,7 @@ is_os_process_alive(Pid) -> case os:find_executable("tasklist.exe") of false -> Cmd = format("(Get-Process -Id ~ts).ProcessName", [PidS]), - {ok, Res} = pwsh_cmd(Cmd), + {ok, [Res]} = pwsh_cmd(Cmd), case Res of "erl" -> true; "werl" -> true; @@ -1181,7 +1181,7 @@ is_os_process_alive(Pid) -> end; TasklistExe -> Args = ["/nh", "/fi", "pid eq " ++ PidS], - {ok, Res} = do_win32_cmd(TasklistExe, Args), + {ok, [Res]} = win32_cmd(TasklistExe, Args), match =:= re:run(Res, "erl\\.exe", [{capture, none}]) end end}]). @@ -1472,44 +1472,46 @@ whereis_name(Name) -> %% End copypasta from gen_server2.erl %% ------------------------------------------------------------------------- -%% This will execute a Powershell command that is expected to return a -%% single-line result. Output lines can't exceed 512 bytes. If multiple -%% lines are returned by the command, these functions will return the -%% last line. +%% This will execute a Powershell command without an intervening cmd.exe +%% process. Output lines can't exceed 512 bytes. %% %% Inspired by os:cmd/1 in lib/kernel/src/os.erl do_pwsh_cmd(Command) -> Pwsh = find_powershell(), - A1 = ["-NoLogo", - "-NonInteractive", - "-NoProfile", - "-InputFormat", "Text", - "-OutputFormat", "Text", - "-Command", Command], - do_win32_cmd(Pwsh, A1). + Args = ["-NoLogo", + "-NonInteractive", + "-NoProfile", + "-InputFormat", "Text", + "-OutputFormat", "Text", + "-Command", Command], + win32_cmd(Pwsh, Args). -do_win32_cmd(Exe, Args) -> +win32_cmd(Exe, Args) -> SystemRootDir = os:getenv("SystemRoot", "/"), % Note: 'hide' must be used or this will not work! A0 = [exit_status, stderr_to_stdout, in, hide, {cd, SystemRootDir}, {line, 512}, {arg0, Exe}, {args, Args}], Port = erlang:open_port({spawn_executable, Exe}, A0), MonRef = erlang:monitor(port, Port), - Result = win32_cmd_receive(Port, MonRef, <<>>), + Result = win32_cmd_receive(Port, MonRef, []), true = erlang:demonitor(MonRef, [flush]), Result. -win32_cmd_receive(Port, MonRef, Data0) -> +win32_cmd_receive(Port, MonRef, Acc0) -> receive {Port, {exit_status, 0}} -> win32_cmd_receive_finish(Port, MonRef), - {ok, Data0}; + {ok, lists:reverse(Acc0)}; {Port, {exit_status, Status}} -> win32_cmd_receive_finish(Port, MonRef), {error, {exit_status, Status}}; - {Port, {data, {eol, Data1}}} -> - Data2 = string:trim(Data1), - win32_cmd_receive(Port, MonRef, Data2); + {Port, {data, {eol, Data0}}} -> + Data1 = string:trim(Data0), + Acc1 = case Data1 of + [] -> Acc0; % Note: skip empty lines in output + Data2 -> [Data2 | Acc0] + end, + win32_cmd_receive(Port, MonRef, Acc1); {'DOWN', MonRef, _, _, _} -> flush_exit(Port), {error, nodata} diff --git a/deps/rabbitmq_management_agent/src/rabbit_mgmt_external_stats.erl b/deps/rabbitmq_management_agent/src/rabbit_mgmt_external_stats.erl index 8a2b765f2b..fe25326272 100644 --- a/deps/rabbitmq_management_agent/src/rabbit_mgmt_external_stats.erl +++ b/deps/rabbitmq_management_agent/src/rabbit_mgmt_external_stats.erl @@ -116,19 +116,20 @@ get_used_fd({win32, _}, State0) -> UsedFd = get_used_fd_via_powershell(Pid), {State1, UsedFd}; HandleExe -> - Handle = rabbit_misc:os_cmd("\"" ++ HandleExe ++ "\" /accepteula -s -p " ++ Pid ++ " 2> nul"), - case Handle of + Args = ["/accepteula", "-s", "-p", Pid], + HandleExeOutput = rabbit_misc:win32_cmd(HandleExe, Args), + case HandleExeOutput of [] -> State1 = log_fd_warning_once("Could not execute handle.exe, using powershell to determine handle count", [], State0), UsedFd = get_used_fd_via_powershell(Pid), {State1, UsedFd}; _ -> - case find_files_line(string:tokens(Handle, "\r\n")) of + case find_files_line(HandleExeOutput) of unknown -> State1 = log_fd_warning_once("handle.exe output did not contain " "a line beginning with 'File', using " "powershell to determine used file descriptor " - "count: ~tp", [Handle], State0), + "count: ~tp", [HandleExeOutput], State0), UsedFd = get_used_fd_via_powershell(Pid), {State1, UsedFd}; UsedFd -> @@ -147,7 +148,7 @@ find_files_line([_H | T]) -> get_used_fd_via_powershell(Pid) -> Cmd = "Get-Process -Id " ++ Pid ++ " | Select-Object -ExpandProperty HandleCount", - {ok, Result} = rabbit_misc:pwsh_cmd(Cmd), + {ok, [Result]} = rabbit_misc:pwsh_cmd(Cmd), list_to_integer(Result). -define(SAFE_CALL(Fun, NoProcFailResult),