JavaScriptを有効にしてください

golangでsymlinkを上書きする

 · 

golangでsymlinkを上書きする

Symlink関数で上書きしようとするとエラー

golangにはシンボリック作成関数があるが上書きはできない。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package main

import (
	"fmt"
	"os"
)

func main() {
	var s string = "symlink"
	var t1 string = "target1.txt"
	var t2 string = "target2.txt"

	//target1.txtを作成
	f, err := os.Create(t1)
	if err != nil {
		panic(err)
	}
	f.Close()
	//target2.txtを作成
	f, err = os.Create(t2)
	if err != nil {
		panic(err)
	}
	f.Close()
	//target1.txtに対してシンボリックリンクを作成
	err = os.Symlink(t1, s)
	if err != nil {
		panic(err)
	}
	//シンボリックリンクの内容を読み取る
	sl, err := os.Readlink(s)
	if err != nil {
		panic(err)
	}
	fmt.Println(sl) //出力:target1.txt
	//target2.txtに対してシンボリックリンクを作成
	err = os.Symlink(t2, s)
	if err != nil {
		//これは既に作成済みのためエラーになる
		fmt.Println(err) //出力:symlink target1.txt symlink: file exists
	}
}

golangの関数で上書きする場合は一回シンボリックを削除してから作成する必要がある。

osのコマンドを使っても同じことなので素直に削除して作成する方がいいだろう。

実際に運営しているwebサービスでシンボリックリンクを使ってみた結果

シンボリックリンクで参照先の切替をやっていたが、上書きしてもキャッシュの影響で古いリンクを見に行ってしまう状態が発生していた。
書き換えを行ってから10秒以上経過しても古いリンクが読み取られていた。原因は不明。
その時のログにls -l コマンドを実行した結果を出力すると表示されるシンボリックリンクの参照先は新しいものになっていたが os.Readlink で読みだしたときは古いものになっていたためもはやお手上げ状態だった。
GKE上でNFSを使用して共有のHDDを見に行く環境だったが、どこでキャッシュされているのか原因を掴むことができなかった。
厄介なのが本番環境でたまに発生しているようでローカル環境では再現できなかったところだ。

仕方がないので、Redisの方にキャッシュさせてRedisになければ目的のファイルを検索して参照するようにした。
現在の所こちらは問題なく動いている。

パフォーマンスの観点からも頻繁にシンボリックリンクを更新するような環境なら別の方法を模索した方がいいように思える。

実行環境

1
2
~/$ go version
go version go1.16.5 linux/amd64

スポンサーリンク

共有

もふもふ
著者
もふもふ
プログラマ。汎用系→ゲームエンジニア→Webエンジニア→QAエンジニア