欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

讓go程序以后臺進(jìn)程或daemon方式運(yùn)行方法探究

 更新時間:2024年01月25日 11:03:52   作者:磊豐 Go語言圈  
本文探討了如何通過Go代碼實(shí)現(xiàn)在后臺運(yùn)行的程序,最近我用Go語言開發(fā)了一個WebSocket服務(wù),我希望它能在后臺運(yùn)行,并在異常退出時自動重新啟動,我的整體思路是將程序轉(zhuǎn)為后臺進(jìn)程,也就是守護(hù)進(jìn)程(daemon)

引言

本文探討了如何通過Go代碼實(shí)現(xiàn)在后臺運(yùn)行的程序。最近我用Go語言開發(fā)了一個WebSocket服務(wù),我希望它能在后臺運(yùn)行,并在異常退出時自動重新啟動。我的整體思路是將程序轉(zhuǎn)為后臺進(jìn)程,也就是守護(hù)進(jìn)程(daemon)。它不處理具體的業(yè)務(wù)邏輯,而是再次使用相同的參數(shù)調(diào)用自身,啟動一個子進(jìn)程來處理業(yè)務(wù)邏輯。守護(hù)進(jìn)程監(jiān)視子進(jìn)程的狀態(tài),如果子進(jìn)程退出,則再次啟動一個新的子進(jìn)程。這樣就能保證在服務(wù)異常終止時及時重啟。

我在網(wǎng)上找到了一個開源庫,github.com/sevlyar/go-daemon,它很方便地實(shí)現(xiàn)了在后臺啟動一個新的進(jìn)程,但如果后臺進(jìn)程再次嘗試作為另一個后臺進(jìn)程啟動,會出現(xiàn)錯誤。

后來我閱讀了源代碼才發(fā)現(xiàn):為了區(qū)分當(dāng)前進(jìn)程是父進(jìn)程還是子進(jìn)程,作者巧妙地設(shè)計(jì)了一個環(huán)境變量標(biāo)識。正是因?yàn)檫@種識別策略,該庫只能啟動一次自身作為后臺進(jìn)程,無法連續(xù)啟動自身為后臺進(jìn)程。

不過,這種使用環(huán)境變量來區(qū)分進(jìn)程身份的思路給我啟發(fā)很大?;谶@個想法,我通過延伸和優(yōu)化,最終實(shí)現(xiàn)了在保持參數(shù)不變的情況下連續(xù)啟動自身為后臺進(jìn)程。我對作者表示敬意。

此外,我還找到了一些其他的庫,它們的思路有所不同,主要通過添加特殊參數(shù)來標(biāo)記進(jìn)程身份。但是,這些方法并沒有完美地解決讓進(jìn)程啟動自身的問題,令我有些遺憾。

最終,我決定自己實(shí)現(xiàn)一個庫來解決我的項(xiàng)目需求,并希望它是一個通用的庫,可以快速方便地將用Go語言編寫的服務(wù)程序轉(zhuǎn)為后臺運(yùn)行或守護(hù)進(jìn)程模式運(yùn)行。本文總結(jié)了我在這次探索中的經(jīng)驗(yàn)和收獲。

后臺運(yùn)行和守護(hù)進(jìn)程區(qū)別

首先,讓我們區(qū)分一下兩個概念:后臺運(yùn)行和守護(hù)進(jìn)程。平常交流時,我們可能不太區(qū)分或區(qū)分不夠清晰。在本文中,我想明確如下定義:

后臺運(yùn)行:指進(jìn)程在操作系統(tǒng)中以非顯示方式運(yùn)行,沒有與任何命令行終端或程序界面相關(guān)聯(lián)。這種方式下運(yùn)行的進(jìn)程稱為后臺進(jìn)程,比如沒有與任何終端相關(guān)聯(lián)的命令行程序進(jìn)程。

守護(hù)進(jìn)程:也稱為守護(hù)進(jìn)程,它首先以后臺運(yùn)行方式啟動,然后還有額外的職責(zé)。在本文中,我的定義是守護(hù)進(jìn)程可以監(jiān)視Go服務(wù)程序進(jìn)程的狀態(tài),如果異常退出,可以自動重新啟動。這樣守護(hù)進(jìn)程可以確保服務(wù)程序一直在后臺運(yùn)行,即使它在某些情況下崩潰或意外終止。

接下來,我將介紹如何使用Go代碼來實(shí)現(xiàn)在后臺運(yùn)行的程序,并將其轉(zhuǎn)化為一個守護(hù)進(jìn)程。

后臺運(yùn)行程序

要將Go程序在后臺運(yùn)行,可以使用一些操作系統(tǒng)級別的方法。以下是一種簡單的方法:

package main
import (
    "fmt"
    "os"
    "os/exec"
    "syscall"
)
func main() {
    if os.Getppid() != 1 {
        cmd := exec.Command(os.Args[0])
        cmd.Start()
        fmt.Println("Background process ID:", cmd.Process.Pid)
        os.Exit(0)
    }
    // 在這里寫入具體的業(yè)務(wù)邏輯代碼
    fmt.Println("Running in background...")
    select {}
}

在上面的代碼中,我們首先使用os.Getppid()函數(shù)獲取當(dāng)前進(jìn)程的父進(jìn)程ID。如果父進(jìn)程不是1,說明當(dāng)前進(jìn)程不是守護(hù)進(jìn)程,而是從終端啟動的。在這種情況下,我們創(chuàng)建一個新的命令,使用相同的參數(shù)再次啟動程序,并在后臺運(yùn)行。我們打印出新進(jìn)程的PID,并退出初始進(jìn)程。

如果進(jìn)程的父進(jìn)程是1,那么說明當(dāng)前進(jìn)程已經(jīng)是守護(hù)進(jìn)程了,我們可以在此處寫入具體的業(yè)務(wù)邏輯代碼。

使用這種方法,我們可以確保程序在后臺運(yùn)行,而且還可以檢查是否已經(jīng)啟動了一個后臺進(jìn)程。

守護(hù)進(jìn)程

將程序轉(zhuǎn)化為守護(hù)進(jìn)程需要額外的步驟,我們需要創(chuàng)建一個監(jiān)聽子進(jìn)程狀態(tài)的循環(huán),并在子進(jìn)程異常退出時重新啟動它。以下是一個簡單的守護(hù)進(jìn)程實(shí)現(xiàn):

package main
import (
    "fmt"
    "os"
    "os/exec"
    "syscall"
)
func main() {
    if os.Getppid() != 1 {
        cmd := exec.Command(os.Args[0])
        cmd.Start()
        fmt.Println("Background process ID:", cmd.Process.Pid)
        os.Exit(0)
    }
    // 在這里寫入具體的業(yè)務(wù)邏輯代碼
    fmt.Println("Running in background...")
    for {
        cmd := exec.Command(os.Args[0])
        cmd.Start()
        exitCh := make(chan error)
        go func() {
            exitCh <- cmd.Wait()
        }()
        err := <-exitCh
        if err != nil {
            fmt.Println("Process exited with error:", err)
        } else {
            fmt.Println("Process exited successfully")
        }
        select {
        case <-exitCh:
        default:
        }
    }
}

在上面的代碼中,我們添加了一個循環(huán),用于監(jiān)聽子進(jìn)程的狀態(tài)。在每次子進(jìn)程退出之后,我們使用相同的參數(shù)再次啟動守護(hù)進(jìn)程,并重新開始監(jiān)聽。這樣就可以確保服務(wù)程序在異常退出時能夠自動重新啟動。

這只是一個簡單的守護(hù)進(jìn)程實(shí)現(xiàn),你可以根據(jù)自己的需求進(jìn)行擴(kuò)展和優(yōu)化。

以上就是讓go程序以后臺進(jìn)程或daemon方式運(yùn)行方法探究的詳細(xì)內(nèi)容,更多關(guān)于go以后臺進(jìn)程daemon方式運(yùn)行的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Go創(chuàng)建Grpc鏈接池實(shí)現(xiàn)過程詳解

    Go創(chuàng)建Grpc鏈接池實(shí)現(xiàn)過程詳解

    這篇文章主要為大家介紹了Go創(chuàng)建Grpc鏈接池實(shí)現(xiàn)過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • golang 實(shí)現(xiàn)兩個結(jié)構(gòu)體復(fù)制字段

    golang 實(shí)現(xiàn)兩個結(jié)構(gòu)體復(fù)制字段

    這篇文章主要介紹了golang 實(shí)現(xiàn)兩個結(jié)構(gòu)體復(fù)制字段,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • Golang中如何實(shí)現(xiàn)枚舉詳析

    Golang中如何實(shí)現(xiàn)枚舉詳析

    舉就是將數(shù)據(jù)值一一列出來,枚舉可以用來表示一些固定的值,枚舉是常量組成的,下面這篇文章主要給大家介紹了關(guān)于Golang中如何實(shí)現(xiàn)枚舉的相關(guān)資料,需要的朋友可以參考下
    2022-07-07
  • go語言實(shí)現(xiàn)并發(fā)網(wǎng)絡(luò)爬蟲的示例代碼

    go語言實(shí)現(xiàn)并發(fā)網(wǎng)絡(luò)爬蟲的示例代碼

    本文主要介紹了go語言實(shí)現(xiàn)并發(fā)網(wǎng)絡(luò)爬蟲的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • Go1.20最新資訊go?arena手動管理內(nèi)存鴿了

    Go1.20最新資訊go?arena手動管理內(nèi)存鴿了

    由于過于繁雜,Go?核心團(tuán)隊(duì)成員@Ian?Lance?Taylor,也表態(tài):目前尚未做出任何決定,也不可能在短期內(nèi)做出任何決定,可以認(rèn)為這個提案基本鴿了,今天這篇文章就是給大家同步目前的情況
    2023-11-11
  • Go語言sync.Map詳解及使用場景

    Go語言sync.Map詳解及使用場景

    Go語言中的sync.Map是一個高效的并發(fā)安全映射結(jié)構(gòu),適用于高并發(fā)讀多寫少的場景,它通過讀寫分離、無鎖讀取路徑、寫入時的鎖保護(hù)等機(jī)制,提高了讀取性能并減少了鎖競爭,sync.Map不需要手動管理鎖,降低了編程復(fù)雜性,適合需要簡單并發(fā)訪問的場合
    2024-10-10
  • GoFrame框架gset交差并補(bǔ)集使用實(shí)例

    GoFrame框架gset交差并補(bǔ)集使用實(shí)例

    這篇文章主要為大家介紹了GoFrame框架gset交差并補(bǔ)集使用實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • Go語言中defer使用的陷阱小結(jié)

    Go語言中defer使用的陷阱小結(jié)

    本文主要介紹了Go語言中defer使用的陷阱小結(jié),分別是defer語句不可以在return語句之后,defer語句執(zhí)行的匿名函數(shù),匿名函數(shù)的參數(shù)會被預(yù)先處理,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01
  • Go語言實(shí)現(xiàn)lru淘汰策略和超時過期

    Go語言實(shí)現(xiàn)lru淘汰策略和超時過期

    緩存的大小是有限的,當(dāng)添加數(shù)據(jù)發(fā)現(xiàn)剩余緩存不夠時,需要淘汰緩存中的部分?jǐn)?shù)據(jù),本文主要介紹了Go語言實(shí)現(xiàn)lru淘汰策略和超時過期,感興趣的可以了解一下
    2024-02-02
  • 解決go 生成的exe不在bin文件夾里的問題

    解決go 生成的exe不在bin文件夾里的問題

    這篇文章主要介紹了解決go 生成的exe不在bin文件夾里的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12

最新評論