用Clojure查看Windows系统内存使用情况

用Clojure查看Windows系统内存使用情况

4GB内存的机器, 现在基本上常常不够用. 所以经常需要看一眼内存使用情况. 通常的办法当然是任务管理器, 但是现在觉得十分麻烦. 不过Emacs和Clojure REPL倒是一直开着的, 如果能够直接在REPL里面显示这个信息就方便的多.

第一步从命令行获取内存使用情况

Windows中有下面两条命令能够达到我们的要求

 
wmic OS get FreePhysicalMemory
wmic ComputerSystem get TotalPhysicalMemory
 

一个输出可用内存数量, 单位是kb, 一个是列出全部物理内存数量单位是字节.

从Clojure中调用外部命令

这个我们之前的文章讲过怎么从Clojure中调用外部命令, 现贴在这里

 
(defn shell-inner [cmd arg waitfn] 
  (let [
         p (.exec (Runtime/getRuntime) (str cmd " " arg))
         ip (.getInputStream p)
         ipr ( java.io.InputStreamReader. ip)
         br (java.io.BufferedReader. ipr)
 
         ip-error (.getErrorStream p)
         ipr-error ( java.io.InputStreamReader. ip-error)
         br-error (java.io.BufferedReader. ipr-error)
       ]
 
    (let [ return-output 
      (loop [str (.readLine br) output []]
        (if (nil? str)
          output
          (recur (.readLine br) (conj output str))
        )
      )
        ]
 
      ;; consume error stream to prevent process from hanging
      (loop [str (.readLine br-error)]        
        (if (nil? str)
          (do (waitfn p) "")
          (recur (.readLine br-error))
        )
      )
      return-output
    )
  )
)
 
(defn shell [cmd arg]
  (shell-inner cmd arg (fn [p] (.waitFor p)))
)
 

调用命令方法如下

 
(shell "wmic" "OS get FreePhysicalMemory")
(shell "wmic" "ComputerSystem get TotalPhysicalMemory")
 

转换为易读的格式

我需要的是以GB为单位, 保留一位小数的格式. 首先把命令的输出结果当中的数字提取为浮点数

 
(Float/parseFloat (clojure.string/trim (nth (shell "wmic" "OS get FreePhysicalMemory") 2)))
(Float/parseFloat (clojure.string/trim (nth (shell "wmic" "ComputerSystem get TotalPhysicalMemory") 2)))
 

下面是两个简单的kb转gb, 字节转gb的函数

 
(defn kb-to-gb [bytes] (/ bytes (* 1024.0 1024.0 )))
 
(defn byte-to-gb [bytes] (/ bytes (* 1024.0 1024.0 1024.0)))
 

保留一位小数用String的静态方法format

 
(java.lang.String/format "%.1f" (into-array  [(kb-to-gb free-mem-f)]))
 

注意从Clojure中调用Java的可变参数方法的语法. 传参要传一个数组.

最终结果

综合以上, 我们可以写一个mem函数

 
 
(defn kb-to-gb [bytes] (/ bytes (* 1024.0 1024.0 )))
 
(defn byte-to-gb [bytes] (/ bytes (* 1024.0 1024.0 1024.0)))
 
(defn mem []
  (let [free-mem-f (Float/parseFloat (clojure.string/trim (nth (shell "wmic" "OS get FreePhysicalMemory") 2)))
        totoal-mem-f (Float/parseFloat (clojure.string/trim (nth (shell "wmic" "ComputerSystem get TotalPhysicalMemory") 2)))
        used-mem-f (- totoal-mem-f (* free-mem-f 1024.0))
        free-mem (java.lang.String/format "%.1f" (into-array  [(kb-to-gb free-mem-f)]))
        total-mem (java.lang.String/format "%.1f" (into-array [(byte-to-gb totoal-mem-f)]))
        used-mem (java.lang.String/format "%.1f" (into-array [(byte-to-gb used-mem-f)]))
       ]
    ;;(str "已用: " used-mem "GB / 全部: " total-mem "GB / 可用: " free-mem "GB")
    (str  used-mem "GB / " total-mem "GB / " free-mem "GB")
  )
)
 

下面是运行效果.

 clojure physical memory information