Go語言是一門強大的編程語言,但在處理文件操作時可能會遇到一些問題。特別是當程序A打開一個文件時,程序B可能會嘗試對該文件進行歸檔或刪除,這可能導致程序A出現錯誤。php小編西瓜在這里給出一些方法,幫助您在Go語言中防止程序B對程序A當前打開的文件進行操作,確保程序的穩定運行。下面是一些解決方案:
問題內容
編程語言:使用最新版本
我正在開發一個程序 A,它需要將日志文件歸檔到一個目錄中,不包括由程序 B 打開的日志文件,該程序使用它來進行日志記錄。打開的文件將在特定持續時間(例如 24 小時)后關閉,然后可用于存檔。顯然,兩個程序都是獨立運行的。
當前的實現不會檢查程序 B 中的文件是否打開,因為我最近發現它正在歸檔打開的日志文件,我認為它不會這樣做;基本上,它將文件復制到存檔并刪除它。
在嘗試歸檔文件之前檢查文件當前是否已被另一個 Go 程序打開的可靠方法是什么?
我已經編寫了歸檔器,但我不會將其發布在這里,因為沒有與問題無關的代碼,因此我只添加執行歸檔和刪除的代碼。
我嘗試過使用 Open 和 OpenFile 函數,但沒有成功。
func zipFile(filename string) error { file, err := os.Open(filename) if err != nil { return err } defer func(file *os.File) { err = file.Close() if err != nil { fmt.Println(err) } }(file) fileInfo, err := file.Stat() if err != nil { return err } archiveFile, err := os.Create(fmt.Sprintf("%s.zip", filename)) if err != nil { return err } defer func(archiveFile *os.File) { err = archiveFile.Close() if err != nil { fmt.Println(err) } }(archiveFile) zipWriter := zip.NewWriter(archiveFile) if err != nil { return err } defer func(zipWriter *zip.Writer) { err = zipWriter.Close() if err != nil { fmt.Println(err) } }(zipWriter) writer, err := zipWriter.Create(fileInfo.Name()) if err != nil { return err } _, err = io.Copy(writer, file) if err != nil { return err } err = os.Remove(filename) if err != nil { return err } fmt.Println(fmt.Sprintf("file %s was zipped", fileInfo.Name())) return nil }
登錄后復制
解決方法
無論進程如何,了解某個文件是否被另一個進程打開的問題都非常依賴于底層操作系統。因此,沒有通用的跨平臺方法來回答這個問題。對于 *NIX 系統(Unix、Linux、macOS),回答問題的最佳方法是使用核心 util lsof
(“列出打開的文件”)。
在 macOS 上,看起來像這樣:
package main import ( "fmt" "os/exec" "strings" ) func main() { out, _ := exec.Command("lsof").Output() for _, line := range strings.Split(string(out), "\n") { // Skip anything that's not a regular file if !strings.Contains(line, "REG") { continue } fields := strings.Fields(line) // The macOS lsof command has the filename in the ninth field fmt.Println(fields[8]) } }
登錄后復制
或者,您可以找到一個對此進行抽象的庫,例如:https://github.com/車輪綜合體/lsof
有關 lsof
的更多信息:https://www.php.cn/link/fa2246fa0fdf0d3e270c86767b77ba1b