duanhuoyao7011 2015-04-02 09:59
浏览 140
已采纳

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

I would like to get the application status of a running application. For example:

# 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

[...]

I see for the moment only one option to accomplish this result: using an external process.

The external process "speak" with the main application through a file (it touch a new file, so the main application "knows" that it must prepare the status report), then when the status report is ready, it send back to the external process (through a file), finally this one print the status to the cli.

But personally I find this solution not so elegant.

Do you have any others ideas to accomplish this? The application is written in Golang, are there maybe any tricks in Go to do this?

  • 写回答

1条回答 默认 最新

  • duanchi5078 2015-04-02 10:16
    关注

    The file system is not the only way to provide input for an application, there are many other ways, e.g. sending data to its standard input, the application may listen on a port for incoming connections or using any other peripherals (like microphone, sensors etc.).

    Since Go has a built-in webserver, it may be convenient to take advantage of it: the Go app can start the webserver (if it doesn't yet use it), and listen on a port for incoming connections, and when requests come, simply send back the status as simple text or in HTML format.

    Here is an example of it:

    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
    ", "jobs waiting in queue", waiting)
        fmt.Fprintf(w, "%-22s : %d
    ", "processing jobs", processing)
        fmt.Fprintf(w, "%-22s : %d
    ", "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.")
        }
    }
    

    The process that wants to get the status of your running app only has to make an HTTP GET request (e.g. wget in linux) to get the status. The above application serves the following status text as the response:

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

    Important note:

    I started the webserver on address "localhost:8081" which means the stats are only available from localhost (the same computer). If your app already uses the webserver, you may use that, but note that if it is reachable from the "outside" so will be your stats. If this is unwanted, you must check if the request (client) is originating from localhost, and if not you can deny serving the request.

    Without an External Process

    The "external process" that queries the status doesn't even have to be external, you can implement it in the application itself.

    Using your example: the application on startup can check if the status command line argument is present, and if so, it will not continue the normal startup process but perform the HTTP GET to get the status of the other running instance of the app, print it to the console and exit right after.

    Here's how you can do it. The modified main() function:

    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.")
        }
    }
    

    And the implementation of 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))
    }
    

    If you provide no arguments (or not the "status" one), the application tries to start normally.

    If you provide the argument "status", it tries to get the status from a running instance. If succeeds, prints the received status. If not, prints that there is no running instance found. Either way, run terminates after that.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘