os_mon does not work for Linux

Miguel Barreiro Paz enano@REDACTED
Tue May 8 19:39:52 CEST 2001


	Hi,

> >os_mon is not working for Linux.
> >This applies for both os_mon-1.3.8 and os_mon-1.3.8.1
> >I haven't checked the other versions.
> 
> I believe os_mon support for different platforms is implemented on a
> per-need basis. Perhaps it's time for Linux now? A good Open Source
> programming exercise...  ;)

	Here are the necessary patches. memsup, disksup and cpu_sup are
ported, os_sup isn't (it isn't too documented either, and I haven't ever
used it). It all seems to work correctly here under debian 2.2
(potato). No external ports, it parses /proc info instead.

--- ../../os_mon_ORIX/src/cpu_sup.erl	Mon Sep 20 23:11:36 1999
+++ cpu_sup.erl	Tue May  8 19:21:59 2001
@@ -15,9 +15,11 @@
 %% 
 %%     $Id$
 %%
+%% 20010508 <enano@REDACTED> linux support added 
+%%
 -module(cpu_sup).
 
-%%% Purpose : Obtain cpu statistics on Solaris 2
+%%% Purpose : Obtain cpu statistics on Solaris 2 or Linux
 
 -export([nprocs/0,avg1/0,avg5/0,avg15/0,ping/0]).
 
@@ -66,12 +68,17 @@
 %%          {stop, Reason}
 %%----------------------------------------------------------------------
 init([]) ->
-    Prog = code:priv_dir(?APPLICATION) ++ ?PORT_PROG,
-    Port = open_port({spawn,Prog},[stream]),
-    if port(Port) ->
-	    {ok, #state{port=Port}};
-       true ->
-	    {stop, {port_prog_not_available,Port}}
+    case os:type() of
+	{unix,sunos} ->
+	    Prog = code:priv_dir(?APPLICATION) ++ ?PORT_PROG,
+	    Port = open_port({spawn,Prog},[stream]),
+	    if port(Port) ->
+		    {ok, #state{port=Port}};
+	       true ->
+		    {stop, {port_prog_not_available,Port}}
+	    end;
+	{unix,linux} ->
+	    {ok,#state{port=not_used}}
     end.
 
 %%----------------------------------------------------------------------
@@ -84,8 +91,13 @@
 %%          {stop, Reason, Reply, State}     (terminate/2 is called)
 %%----------------------------------------------------------------------
 handle_call(?quit, From, State) ->
-    State#state.port ! {self(), {command, ?quit}},
-    State#state.port ! {self(), close},
+    case os:type() of
+	{unix,sunos} ->
+	    State#state.port ! {self(), {command, ?quit}},
+	    State#state.port ! {self(), close};
+	_ ->
+	    ok
+    end,
     {stop, shutdown, ok, State};
 handle_call(Request, From, State) ->
     Reply = get_measurement(Request,State#state.port),
@@ -124,11 +136,30 @@
 %%%----------------------------------------------------------------------
 
 get_measurement(Request,Port) ->
-    Port ! {self(), {command, Request}},
-    receive
-	{Port,{data,[D3,D2,D1,D0]}} ->
-	    (D3 bsl 24) bor (D2 bsl 16) bor (D1 bsl 8) bor D0
+    case os:type() of
+	{unix,sunos} ->
+	    Port ! {self(), {command, Request}},
+	    receive
+		{Port,{data,[D3,D2,D1,D0]}} ->
+		    (D3 bsl 24) bor (D2 bsl 16) bor (D1 bsl 8) bor D0
+	    end;
+	{unix,linux} ->
+	    {ok,F}=file:open("/proc/loadavg",[read,raw]),
+	    {ok,D} = file:read(F,24),
+	    {ok,[Load1,Load5,Load15,PRun,PTotal],_}=io_lib:fread("~f ~f ~f ~d/~d", D),
+	    case Request of
+		?avg1 ->  sunify(Load1);
+		?avg5  -> sunify(Load5);
+		?avg15  -> sunify(Load15);
+		?ping -> 4711; % Guys, it would be nice to document it somewhere ;)
+		?nprocs -> PTotal
+	    end
+
     end.
+
+sunify(Val)  ->
+    round(Val*256). % Note that Solaris and Linux load averages are 
+		    % measured quite differently anyway
 
 %%%----------------------------------------------------------------------
 
--- ../../os_mon_ORIX/src/disksup.erl	Thu Sep 14 12:27:36 2000
+++ disksup.erl	Tue May  8 19:21:56 2001
@@ -15,6 +15,8 @@
 %% 
 %%     $Id$
 %%
+%% 20010508 <enano@REDACTED> linux support added 
+%%
 -module(disksup). 
 
 -export([start_link/0, get_disk_data/0, get_check_interval/0,
@@ -79,7 +81,7 @@
     Result = os_mon_sysinfo:get_disk_info(),
     check_disks_win32(Result, State#state.threshold);
 check_disk_space(State) when State#state.os == {unix, solaris} ->
-    Result = os:cmd("/usr/bin/df -lk"),
+    Result = os:cmd("/bin/df -lk"),
     check_disks_solaris(skip_to_eol(Result), State#state.threshold);
 check_disk_space(State) when State#state.os == {unix, sunos4} ->
     Result = os:cmd("df"),
@@ -156,6 +158,9 @@
 
 get_os() ->
     case os:type() of
+	{unix, linux} ->
+	    {unix, solaris}; % This is a fake, but Solaris and Linux are similar
+			     % enough by the grace of POSIX. It works.
 	{unix, sunos} ->
 	    case os:version() of
 		{5,_,_} -> {unix, solaris};
--- ../../os_mon_ORIX/src/memsup.erl	Mon Sep 20 23:05:26 1999
+++ memsup.erl	Tue May  8 19:22:50 2001
@@ -15,6 +15,8 @@
 %% 
 %%     $Id$
 %%
+%% 20010508 <enano@REDACTED> linux support added 
+%%
 -module(memsup). 
 -export([start_link/0, get_memory_data/0, get_check_interval/0,
 	 get_sysmem_high_watermark/0, get_procmem_high_watermark/0,
@@ -62,6 +64,7 @@
     process_flag(priority, low),
     PortResult = case OsType of
 		     {win32,_} ->{ok,not_used};
+		     {unix,linux} -> {ok,not_used};
 		     _ -> start_portprogram()
 		 end,
     case PortResult of
@@ -69,6 +72,8 @@
 	    Reply = case OsType of
 			{win32,_} ->
 			    get_memory_usage_win32(Port);
+			{unix,linux} ->
+			    get_memory_usage_linux(Port);
 			_ ->
 			    get_memory_usage(Port)
 		    end,
@@ -109,6 +114,8 @@
     MemUsage = case os:type() of
 		   {win32,_} ->
 		       get_memory_usage_win32(State#state.port);
+		   {unix,linux} ->
+		       get_memory_usage_linux(State#state.port);
 		   _ ->
 		       get_memory_usage(State#state.port)
 	       end,
@@ -190,6 +197,17 @@
     end.
 
 %%-----------------------------------------------------------------
+%% get_memory_usage_linux(_Port)
+%%-----------------------------------------------------------------
+get_memory_usage_linux(_) ->
+    {ok,F}=file:open("/proc/meminfo",[read,raw]),
+    {ok,D}=file:read(F,1024),
+    {ok,[_Headers,MemInfo,Swap,MemTotal,MemFree,MemShared,Buffers,Cached,SwTot,SwFree,_]} = 
+	regexp:split(D,"\n"),
+    {ok,[_,NMemTotal,NMemUsed],_}=io_lib:fread("~s ~d ~d",MemInfo),
+    {ok,{NMemUsed,NMemTotal}}.
+
+%%-----------------------------------------------------------------
 %% Func: get_memory_usage(Port)
 %% Purpose: Function which finds out how much memory is in use by
 %%          using the external portprogram.
@@ -262,6 +280,10 @@
 		_ ->
 		    {error, port_terminated}
 	    end;
+	{unix,linux} ->
+	    {ok,{Alloced,Tot}} = get_memory_usage_linux([]),
+	    [{total_memory,Tot},{free_memory, Tot-Alloced},
+	     {system_total_memory,Tot}]; % correct unless setrlimit() set
 	_ -> 
 	    Port ! {self(), {command, [?SYSTEM_MEM_SHOW]}},
 	    collect_sysmem(Port)
--- ../../os_mon_ORIX/src/os_mon.erl	Mon Sep 20 23:05:51 1999
+++ os_mon.erl	Tue May  8 19:22:30 2001
@@ -15,6 +15,8 @@
 %% 
 %%     $Id$
 %%
+%% 20010508 <enano@REDACTED> linux support added 
+%%
 -module(os_mon).
 
 -behaviour(supervisor).
@@ -57,6 +59,11 @@
 			start_memsup(),
 			[],
 			[]};
+		  {unix,linux} ->
+		      {start_disksup(),
+		      start_memsup(),
+		       start_cpu_sup(),
+		      []};
 		  _ -> {start_disksup(),
 			start_memsup(),
 			start_cpu_sup(),





More information about the erlang-questions mailing list