"fmt"
"log"
"os"
+ "os/signal"
"sort"
"strings"
"sync"
done <- failed
}()
+ hostsLeft := make(map[string]bool)
+ for _, x := range toSync {
+ hostsLeft[x.Name] = true
+ }
+ var hostsLeftMutex sync.Mutex // protects hostsLeft
+
+ // Show unfinished hosts on Ctrl-C
+ sigint := make(chan os.Signal, 1) // buffered for Notify()
+ signal.Notify(sigint, os.Interrupt) // = SIGINT = Ctrl-C
+ go func() {
+ // Running `ssh` processes get killed by SIGINT which is sent
+ // to all processes
+
+ <-sigint
+ log.Print("Received SIGINT, aborting ...")
+
+ // Print all queued events
+ events <- Event{} // poison pill
+ <-done
+ // "races" with <-done in the main function and will hang here
+ // if the other is faster. This is fine because then all hosts
+ // were synced successfully.
+
+ hostsLeftMutex.Lock()
+ var hosts []string
+ for x := range hostsLeft {
+ hosts = append(hosts, x)
+ }
+ sort.Strings(hosts)
+ log.Fatalf("Failed to sync %s", strings.Join(hosts, ", "))
+ }()
+
// Sync all hosts concurrently
var wg sync.WaitGroup
for _, x := range toSync {
}
}
wg.Done()
+
+ hostsLeftMutex.Lock()
+ defer hostsLeftMutex.Unlock()
+ delete(hostsLeft, x.Name)
}()
}