获取正在运行的应用程序的自定义状

时间:2015-04-02 09:59:42

标签: process go status

我想获取正在运行的应用程序的应用程序状态。例如:

# start my app
./my_app

# require status
./my_app status

# it prints information about the application

jobs waiting in queue : 120
processing jobs       : 3414
jobs done             : 300

number of bad request received : 120

[...]

我目前只看到一个选项来完成此结果:使用外部流程。

外部流程"说"主应用程序通过一个文件(touch一个新文件,所以主应用程序"知道它必须准备好状态报告),然后当状态报告准备就绪时,它会发回对于外部进程(通过文件),最后这个将状态打印到cli。

但我个人觉得这个解决方案并不那么优雅。

你有其他想法来实现这个目标吗?该应用程序是用Golang编写的,Go中可能有任何技巧吗?

1 个答案:

答案 0 :(得分:3)

文件系统不是为应用程序提供输入的唯一方法,还有许多其他方法,例如:将数据发送到其标准输入,应用程序可以在端口上侦听传入连接或使用任何其他外围设备(如麦克风,传感器等)。

由于Go有一个内置的web服务器,利用它可能很方便:Go应用程序可以启动web服务器(如果它还没有使用它),并在端口上侦听传入的连接,以及当请求到来时,只需将状态作为简单文本或HTML格式发回。

以下是一个例子:

package main

import (
    "fmt"
    "net/http"
)

var (
    waiting = 120
    processing = 3414
    done = 300
)

func ServeStats(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "%-22s : %d\n", "jobs waiting in queue", waiting)
    fmt.Fprintf(w, "%-22s : %d\n", "processing jobs", processing)
    fmt.Fprintf(w, "%-22s : %d\n", "jobs done", done)
}

func main() {
    http.HandleFunc("/", ServeStats)
    err := http.ListenAndServe("localhost:8081", nil)
    if err != nil {
        fmt.Println("An instance of the application is already running!",
            "Provide the 'status' parameter to see stats.")
    }
}

想要获取正在运行的应用程序状态的进程只需要发出HTTP GET请求(例如linux中的wget)来获取状态。上述应用程序提供以下状态文本作为响应:

jobs waiting in queue  : 120
processing jobs        : 3414
jobs done              : 300

重要提示:

我在地址"localhost:8081"上启动了网络服务器,这意味着只能从localhost(同一台计算机)获取统计信息。如果您的应用已经使用了网络服务器,您可以使用它,但请注意,如果可以从“外部”访问,那么您的统计数据就是如此。如果这是不需要的,您必须检查请求(客户端)是否来自localhost,如果不是,您可以拒绝提供请求。

没有外部流程

查询状态的“外部流程”甚至不必是外部,您可以在应用程序本身中实现它。

使用您的示例:启动时的应用程序可以检查status命令行参数是否存在,如果存在,它将不会继续正常启动过程但执行HTTP GET以获取状态应用程序的另一个正在运行的实例,将其打印到控制台并在之后立即退出。

这是你如何做到的。修改后的main()函数:

func main() {
    if len(os.Args) > 1 && os.Args[1] == "status" {
        getStatus()
        return
    }

    http.HandleFunc("/", ServeStats)
    err := http.ListenAndServe("localhost:8081", nil)
    if err != nil {
        fmt.Println("An instance of the application is already running!",
            "Provide the 'status' parameter to see stats.")
    }
}

getStatus()的实施:

func getStatus() {
    resp, err := http.Get("http://localhost:8081/")
    if err != nil {
        fmt.Println("No running instance found!")
        return
    }

    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("Running instance found but failed to get status!")
        return
    }

    fmt.Println("Status of the running instance:")
    fmt.Println(string(body))
}

如果您不提供参数(或不提供"status"参数),则应用程序会尝试正常启动。

如果您提供参数"status",它会尝试从正在运行的实例中获取状态。如果成功,则打印收到的状态。如果没有,则打印没有找到正在运行的实例。无论哪种方式,运行都会在此之后终止。