Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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?

share|improve this question
add comment

2 Answers 2

up vote 1 down vote accepted

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
share|improve this answer
    
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 Dec 17 '10 at 13:07
    
I didn't need to sudo, so I don't think so. –  Trey Jackson Dec 17 '10 at 17:23
    
@Deditos: On Solaris, use truss (strace is the equivalent command on Linux). –  Gilles Dec 17 '10 at 19:06
    
Thanks, that worked. And well spotted that the workstation is Solaris, I hadn't mentioned it! –  Deditos Dec 17 '10 at 19:40
add comment

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.
share|improve this answer
    
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 Dec 17 '10 at 13:00
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.