1

I have several instances of Emacs (v21.2.1) running on a remote workstation, one of which I would like to kill via ssh. I can get the PIDs of each instance (using pgrep emacs, say) while ssh'd into the workstation, but I don't know how to determine which of those processes has a particular file open.

lsof doesn't return any information that's obviously useful, presumably because Emacs doesn't keep the files open while they are being edited in a buffer. Maybe it's possible to export the existing Emacs windows to my current location, but I don't know how I would go about that.

Am I foolish in thinking this is even possible?

2 Answers 2

1

Use strace to see what files it has open (it does keep things open, or at least is often checking on the files). This should give you a list of everything that the process is looking at, obviously you'll have to parse it somewhat and filter out duplicates (and substitute the proper pid):

strace -p1337 -e trace=file

It generates output like this:

unlink("/tmp/emacsBYJwbf")              = 0
stat("/home/tjackson/.jabber-avatars", {st_mode=S_IFDIR|0755, st_size=16384, ...}) = 0
stat("/home/tjackson/.jabber-avatars/e7e63a04ac20783855bc31ab8fcfb7bc23a39036.jpg", {st_mode=S_IFREG|0644, st_size=2556, ...}) = 0
stat("/lab_scratch/mymachine/work/path/to/some/file.cxx", {st_mode=S_IFREG|0644, st_size=45772, ...}) = 0
open("/lab_scratch/mymachine/work/path/to/some/file.cxx", O_RDONLY) = 10
stat("/lab_scratch/mymachine/work/path/to/some/file.cxx", {st_mode=S_IFREG|0644, st_size=45772, ...}) = 0
stat("/lab_scratch/mymachine/work/some/other/path/different/header_file.h", {st_mode=S_IFREG|0644, st_size=92260, ...}) = 0
open("/lab_scratch/mymachine/work/some/other/path/different/header_file.h", O_RDONLY) = 10
stat("/lab_scratch/mymachine/work/some/other/path/different/header_file.h", {st_mode=S_IFREG|0644, st_size=92260, ...}) = 0
stat("/home/tjackson/News/drafts/drafts/272", 0x7fbfffd400) = -1 ENOENT (No such file or directory)
stat("/scratch2/complex/tmp/output.log", {st_mode=S_IFREG|0644, st_size=378306, ...}) = 0
open("/scratch2/complex/tmp/output.log", O_RDONLY) = 10
stat("/scratch2/complex/tmp/output.log", {st_mode=S_IFREG|0644, st_size=378306, ...}) = 0
stat("/home/tjackson/.diary", {st_mode=S_IFREG|0644, st_size=72457, ...}) = 0
open("/home/tjackson/.diary", O_RDONLY) = 10
stat("/home/tjackson/.diary", {st_mode=S_IFREG|0644, st_size=72457, ...}) = 0
stat("/home/tjackson/News/drafts/drafts/271", 0x7fbfffd400) = -1 ENOENT (No such file or directory)
stat("/home/tjackson/News/drafts/drafts/273", 0x7fbfffd400) = -1 ENOENT (No such file or directory)
stat("/home/tjackson/personal/.newsrc-dribble", 0x7fbfffd400) = -1 ENOENT (No such file or directory)
stat("/lab_scratch/mymachine/work/sandbox/TAGS", {st_mode=S_IFREG|0644, st_size=2578671, ...}) = 0
open("/lab_scratch/mymachine/work/sandbox/TAGS", O_RDONLY) = 10
stat("/lab_scratch/mymachine/work/sandbox/TAGS", {st_mode=S_IFREG|0644, st_size=2578671, ...}) = 0
4
  • That looks like it would do the job, but my strace just returns the error Unable to open /dev/log no matter what arguments I pass. Do I need SU privileges to run strace?
    – Deditos
    Commented Dec 17, 2010 at 13:07
  • I didn't need to sudo, so I don't think so. Commented Dec 17, 2010 at 17:23
  • @Deditos: On Solaris, use truss (strace is the equivalent command on Linux). Commented Dec 17, 2010 at 19:06
  • Thanks, that worked. And well spotted that the workstation is Solaris, I hadn't mentioned it!
    – Deditos
    Commented Dec 17, 2010 at 19:40
0

If you're running Gnuserv (a GNU Emacs port of the XEmacs server), or if you were running the included emacsserver on GNU Emacs ≥23, you can run arbitrary Lisp commands in a running instance of Emacs.

gnuclient -r /tmp/gsrvdir1234/gsrv -batch -eval '(buffer-list)'
emacsclient -r /tmp/emacs1234/server -e '(buffer-list)'  # Emacs ≥23 only

Otherwise I can only think of two highly hackish ways.

  • Search through the memory of the Emacs instance for the file name. On Linux, the process's mapped memory is in /proc/$pid/mem, but you can only read the pages that are actually mapped, as readable through /proc/$pid/maps. I don't know of an existing program for that.
  • Open a file containing a vulnerable local variable declaration, i.e., one that allows execution of arbitrary Lisp code. Emacs 21 still treated local variables as safe unless indicated otherwise, so there surely were variables that should have been declared as risky but weren't. I don't know any example though.
1
  • Ah, it crossed my mind that something like that client/Lisp might be possible, but I didn't know how. Unfortunately, emacs isn't running in server mode so those *client options aren't goers. Useful to know though.
    – Deditos
    Commented Dec 17, 2010 at 13:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .