Skip to content

Instantly share code, notes, and snippets.

@jtpaasch
Created July 9, 2018 21:08
Show Gist options
  • Select an option

  • Save jtpaasch/07b81a42ae7b6240938b7dff214103f7 to your computer and use it in GitHub Desktop.

Select an option

Save jtpaasch/07b81a42ae7b6240938b7dff214103f7 to your computer and use it in GitHub Desktop.
A simple template for parsing /proc/[pid]/stat files (OCaml).
(* CLI =============================== *)
let pid_value = ref (-1)
let get_pid () = !pid_value
let check () =
match get_pid () with
| (-1) ->
Printf.printf "Error. Please provide a PID.\n%!";
exit 1
| _ -> ()
let set_pid arg =
match int_of_string_opt arg with
| None ->
Printf.printf "Error. Argument '%s' is not an integer.\n%!" arg;
exit 1
| Some n -> pid_value := n
let cli () =
Arg.parse [] set_pid "Parse the /proc/[pid]/stat for a PID.";
check ()
(* FILES ============================ *)
exception NoSuchFile of string
exception CouldNotRead of string
let open_in_exn f msg =
try open_in f
with Sys_error e ->
raise (NoSuchFile msg)
let read_to_end b c =
try
while true do
Buffer.add_channel b c 1
done
with End_of_file -> ()
let all_to_string ic =
let buf = Buffer.create 32 in
read_to_end buf ic;
Buffer.contents buf
let read f err_msg =
let ic = open_in_exn f err_msg in
all_to_string ic
(* PARSE ============================ *)
exception NotAnInt of string
exception NoSuchDatum of string
let get_page_size =
let size_in_bytes = Unix.open_process_in "getconf PAGE_SIZE"
|> input_line
|> int_of_string in
size_in_bytes / 1024
let to_int_exn s =
try
int_of_string s
with e ->
let msg = Printf.sprintf "Cannot convert '%s' to an int." s in
raise (NotAnInt msg)
let get_elem_exn data idx msg =
try
List.nth data idx
with e ->
raise (NoSuchDatum msg)
let parse_pid data idx =
let err = Printf.sprintf
"Can't find PID at index '%d' in /proc/[pid]/stat file." idx in
let datum = get_elem_exn data idx err in
let result = to_int_exn datum in
Printf.sprintf "PID: %d" result
let parse_rss data idx pagesize =
let err = Printf.sprintf
"Can't find RSS at index '%d' in /proc/[pid]/stat file." idx in
let datum = get_elem_exn data idx err in
let pages = to_int_exn datum in
let result = pages * pagesize in
Printf.sprintf "RSS: %dK" result
let get_stats src =
let pagesize = get_page_size in
let data = String.split_on_char ' ' src in
[
parse_pid data 0;
parse_rss data 23 pagesize;
]
(* MAIN ============================ *)
let main () =
cli ();
let pid = get_pid () in
let stat_file = Printf.sprintf "/proc/%d/stat" pid in
Printf.printf "Stats for PID: %d\n%!" pid;
let err_msg = Printf.sprintf "No such PID: %d" pid in
let data = read stat_file err_msg in
Printf.printf "Data:\n%s\n%!" data;
let stats = get_stats data in
List.iter (Printf.printf "%s\n%!") stats
let handle_errors f () =
Printexc.register_printer
(function
| NoSuchFile msg -> Some msg
| CouldNotRead msg -> Some msg
| NotAnInt msg -> Some msg
| NoSuchDatum msg -> Some msg
| _ -> None
);
try
Unix.handle_unix_error f ()
with e ->
let msg = Printexc.to_string e in
Printf.printf "Error. %s\n%!" msg;
exit 1
let () = handle_errors main ()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment