I have an extremely rare error, when implementing a watcher for a remote directory (SFTP) it gives me a syscall error, when trying to execute the Lstat command.
The error is as follows:
golang.org/x/sys/unix.ENOENT (2)
lstat /home/user/directory: no such file or directory
This is the line that gives the error:
_, _, e1 := syscall(funcPC(libc_lstat64_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
The directory path to watch is /home/user/directory, and the implementation is as follows:
SFTP Connection
func StartSFTPConnection() *sftp.Client {
// SFTP connection data
host := os.Getenv("FTP_HOST")
port := os.Getenv("FTP_PORT")
user := os.Getenv("FTP_USER")
pass := os.Getenv("FTP_PASSWORD")
hostKey := getHostKey(host)
if _, err := fmt.Fprintf(os.Stdout, "Connecting to %s ...\n", host); err != nil {
log.Fatal(err)
}
var auths []ssh.AuthMethod
// Try to use $SSH_AUTH_SOCK which contains the path of the unix file socket that the sshd agent uses
// for communication with other processes.
if aconn, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil {
auths = append(auths, ssh.PublicKeysCallback(agent.NewClient(aconn).Signers))
}
// Use password authentication if provided
if pass != "" {
auths = append(auths, ssh.Password(pass))
}
// Initialize client configuration
config := ssh.ClientConfig{
User: user,
Auth: auths,
HostKeyCallback: ssh.FixedHostKey(hostKey),
}
addr := fmt.Sprintf("%s:%s", host, port)
// Connect to server
conn, err := ssh.Dial("tcp", addr, &config)
if err != nil {
if _, err := fmt.Fprintf(os.Stderr, "Failed to connecto to [%s]: %v\n", addr, err); err != nil {
log.Fatal(err)
}
}
// Create new SFTP client
sc, err := sftp.NewClient(conn)
if err != nil {
if _, err := fmt.Fprintf(os.Stderr, "Unable to start SFTP subsystem: %v\n", err); err != nil {
log.Fatal(err)
}
}
return sc
}
Watcher
// FileWatcher checks for new files in a folder
func FileWatcher() (err error) {
var sc = sftp2.StartSFTPConnection()
watcher, _ = fsnotify.NewWatcher()
defer func(watcher *fsnotify.Watcher) {
if err := watcher.Close(); err != nil {
log.Fatal(err)
}
}(watcher)
wk := sc.Walk(os.Getenv("WATCH_DIR"))
for wk.Step() {
if wk.Err() != nil {
continue
}
if err := watchDir(wk.Path(), wk.Stat()); err != nil {
fmt.Println("There are some errors in FTP Watcher.")
}
}
done := make(chan bool)
// watch for changes in folder
go func() {
for {
select {
// watch for events
case event := <-watcher.Events:
fmt.Printf("New file added in `WATCH` path. Event %#v.\n", event.Op)
switch {
case event.Op&fsnotify.Write == fsnotify.Write:
fmt.Printf("Write: %s: %s", event.Op, event.Name)
case event.Op&fsnotify.Create == fsnotify.Create:
fmt.Printf("Create: %s: %s", event.Op, event.Name)
parser.FileParser(event.Name)
case event.Op&fsnotify.Remove == fsnotify.Remove:
fmt.Printf("Remove: %s: %s", event.Op, event.Name)
case event.Op&fsnotify.Rename == fsnotify.Rename:
fmt.Printf("Rename: %s: %s", event.Op, event.Name)
case event.Op&fsnotify.Chmod == fsnotify.Chmod:
fmt.Printf("Chmod: %s: %s", event.Op, event.Name)
}
// watch for errors
case err := <-watcher.Errors:
fmt.Println(err)
}
}
}()
<-done
// return
return nil
}
// watchDir gets run as a walk func, searching for directories to add watchers to
func watchDir(path string, fi os.FileInfo) error {
// since fsnotify can watch all the files in a directory, watchers only need to be added to each nested directory
if fi.Mode().IsDir() {
return watcher.Add(path)
}
return nil
}
What could be wrong? Also, the directory is a normal dir, not a symlink.