プログラムが動作中に再度呼ばれると色々良くないので禁止してみます
やり方としてはプロセスの起動状態を見るとかあるのですが
今回はロックファイルを作って排他が掛かっていたら
エラーで抜けるという方法です
golang実装
lockgo.go
package main
import (
"fmt"
"io/ioutil"
"os"
"syscall"
)
func main() {
fmt.Println("ready")
lockfile := "lock"
if _, err := os.Stat(lockfile); err != nil {
fmt.Println("make lockfile")
ioutil.WriteFile(lockfile, []byte(""), 0644)
}
fd, _ := syscall.Open("lock", syscall.O_RDONLY, 0000)
defer syscall.Close(fd)
if err := syscall.Flock(fd, syscall.LOCK_EX|syscall.LOCK_NB); err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println("running")
for {
}
}
Perl実装
lockpl.pl
#!/usr/bin/perl
use strict;
use warnings;
use Fcntl qw/ :flock /;
main();
sub main {
print "ready\n";
my $lockfile = "lock";
unless (-f $lockfile) {
print "make lockfile\n";
open my $fh, ">", $lockfile;
close $fh;
}
open my $fd, "<", "lock";
flock($fd, LOCK_EX | LOCK_NB ) or die $!;
print "running\n";
while (1) {
}
}
動作確認
動作は同じなのでそれぞれの実装を起動してみます。
なんかPerlのエラーは日本語になってるけど気にしない。
go_main_lock
$ go run lockgo.go &
ready
make lockfile
running
$ perl lockpl.pl
ready
リソースが一時的に利用できません at lockpl.pl line 19.
$ fg
Ctrl + c
pl_main_lock
$ perl lockpl.pl &
ready
running
$ go run lockgo.go
ready
resource temporarily unavailable
exit status 1
蛇足
Windowsへのクロスコンパイルは通りませんでした。
flock無いんですね。。
$ GOOS=windows GOARCH=amd64 go build lockgo.go
# command-line-arguments
./lockgo.go:23: undefined: syscall.Flock
./lockgo.go:23: undefined: syscall.LOCK_EX
./lockgo.go:23: undefined: syscall.LOCK_NB
参考
Man page of FLOCK
http://linuxjm.osdn.jp/html/LDP_man-pages/man2/flock.2.html
Go言語: ファイルの存在をちゃんとチェックする実装? - Qiita
http://qiita.com/suin/items/b9c0f92851454dc6d461
Golang Flock
https://gist.github.com/ericchiang/ce0fdcac5659d0a80b38
import "C"でもできる?