Emacs can access files on any remote server running an ssh or SFTP service, assuming that an ssh client is installed on the host where Emacs runs. I use this extensively, since I run my own personal home servers available over the internet. On those servers, I have files and resources that I access all time, from anywhere.
/ssh:server.example.com:~/myfile.txt
Opening this path in Emacs will automatically open an ssh-connection to server.example.com
and transparently allow editing of myfile.txt
. Emacs uses the TRAMP package (Transparent Remote Access, Multiple Protocols) to provide this functionality.
TRAMP is designed to re-use existing ssh-connections for accessing multiple resources (on the same server). When using a laptop, where network conditions change and the system is frequently suspended, such persistent connections tend to hang for a while after the operating system has resumed operation, which can block Emacs. This is annoying, especially when I’d like to access a remote file immediately, and ssh hasn’t yet detected that its TCP connection has become unusable.
TRAMP provides a convenient function to clean up all existing connections, aptly named tramp-cleanup-all-connections
, which I want to automatically call when the operating system wakes up from a suspended state or if the network changes.
Detecting operating system events on Linux
If running in a typical Linux environment, you can make Emacs listen for DBUS system bus events. Check out my packages nm.el and upower.el for code which reacts to networking and power management events.
For example, to automatically clean up remote connections whenever network connects or re-connects, the following code would work (requires that NetworkManager is used by Linux distro):
(load-file "/path/to/nm.el")
(add-hook 'nm-connected-hook 'tramp-cleanup-all-connections)
(nm-enable)
Or to do the same whenever the machine resumes from suspend:
(load-file "/path/to/upower.el")
(add-hook 'upower-resume-hook 'tramp-cleanup-all-connections)
(upower-enable)
Detecting resume by using system clock
I also use Emacs on Windows sometimes, in a WSL environment where DBUS is not available. But we can still detect if the machine has been resumed in a generic manner, by observing the system clock:
(defvar clock-jump-detector-hook nil
"Functions to run when a system clock jump is detected.")
(defvar clock-jump-detector-threshold (* 5 60)
"Minimum time skip (in seconds) to consider
it a system clock jump. When it is detected that
the system clock jumps with more than this number of seconds, then hooks in `clock-jump-detector-hook'
are run.")
(setq clock-jump-detector-time (current-time))
(defun clock-jump-detector ()
(let ((time-passed (float-time (time-since clock-jump-detector-time))))
(setq clock-jump-detector-time (current-time))
(when (> time-passed clock-jump-detector-threshold)
(message "Clock jump of %f seconds detected, running hooks .." time-passed)
(run-hooks 'clock-jump-detector-hook))))
(run-at-time t 15 'clock-jump-detector)
The code records the current time every 15 seconds, and if a time jump beyond a threshold is detected (a «clock jump»), then all functions in hook-variable clock-jump-detector-hook
are invoked.
By having Emacs listen for operating system events over DBUS and invoking functions in hook-variables, you can make anything happen in a loosely coupled fashion.