Last active
May 30, 2017 08:30
-
-
Save vodrazka/b6fbf0f6dfc51e5a15e972bef0e2507b to your computer and use it in GitHub Desktop.
Watch for changes in local directory, if file is created start watching it. If file is not busy by other pids (except this programs process and fuser child process) fire given command with that new file as first argument.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"log" | |
"github.com/howeyc/fsnotify" | |
"path/filepath" | |
"os" | |
"flag" | |
"os/exec" | |
"fmt" | |
"bytes" | |
"strconv" | |
"strings" | |
"time" | |
) | |
var fireCommand string | |
var intervalDuration time.Duration | |
func main() { | |
initFlags() | |
watcher, err := fsnotify.NewWatcher() | |
if err != nil { | |
log.Fatal(err) | |
} | |
done := make(chan bool) | |
dir, _ := filepath.Abs(filepath.Dir(os.Args[0])) | |
_, err = exec.LookPath("fuser") | |
if err != nil { | |
log.Fatal(err, "fuser cannot be found. Export? Install? Access rights?") | |
} | |
// Process events | |
go func() { | |
for { | |
select { | |
case ev := <-watcher.Event: | |
if ev.IsCreate() { | |
if !strings.HasSuffix(ev.Name, ".ignore") { | |
log.Println("event:", ev) | |
fullFilePath := dir + "/" + ev.Name | |
log.Println("Started to watching file:", fullFilePath) | |
go watchFile(fullFilePath) | |
} | |
} | |
case err := <-watcher.Error: | |
log.Println("error:", err) | |
} | |
} | |
}() | |
err = watcher.Watch(".") | |
if err != nil { | |
log.Fatal(err) | |
} | |
// Hang so program doesn't exit | |
<-done | |
watcher.Close() | |
} | |
func watchFile(file string) { | |
if isFileFree(file) { | |
log.Printf("File is free: %s\n", file) | |
fmt.Printf("Running: %s %s\n", fireCommand, file) | |
cmd := exec.Command(fireCommand, file) | |
var out bytes.Buffer | |
cmd.Stdout = &out | |
err := cmd.Run() | |
fmt.Print(out.String()) | |
if err != nil { | |
log.Fatal(err) | |
} | |
} | |
} | |
func isFileFree(file string) bool { | |
pid := os.Getpid() | |
ownPid := strconv.Itoa(pid) | |
cmd := exec.Command("fuser", file) | |
//cmd.Stdin = strings.NewReader("some input") | |
var out bytes.Buffer | |
cmd.Stdout = &out | |
err := cmd.Run() | |
if err != nil { | |
log.Print("fuser err:", err) | |
} | |
//log.Printf("Own pid: %s\n", ownPid) | |
fuserPid := strconv.Itoa(cmd.Process.Pid) | |
//log.Printf("Child fuser pid: %s\n", fuserPid) | |
output := out.String() | |
//log.Printf("fuser output original:(%s)", output) | |
output = strings.Replace(output, ownPid, "", 1) | |
output = strings.Replace(output, fuserPid, "", 1) | |
output = strings.Trim(output, " ") | |
if len(output) == 0 { | |
return true | |
} else { | |
log.Printf("File %s locked by pid(s) %s\n", file, output) | |
time.Sleep(intervalDuration) | |
return isFileFree(file) | |
} | |
} | |
func initFlags() { | |
flag.StringVar(&fireCommand, "c", "", "Command which will be fired when a new file gets created "+ | |
"(file checked with fuser until free). The new file will be passed as 1st arg to that command.") | |
flag.DurationVar(&intervalDuration, "n", 5*time.Second, "Interval for checking on a locked file.") | |
flag.Parse() | |
if fireCommand == "" { | |
log.Fatal("Fire command not provided") | |
} else { | |
fmt.Printf("Fire command: %v \n", fireCommand) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment