How to gracefully shutdown emacs daemon? [closed] - emacs

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 6 years ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
Improve this question
On login to Ubuntu, I start an Emacs (version 23) daemon using Ubuntu's Startup programs. I then start Emacs clients whenever I need to edit something. When I logoff from Ubuntu, it says Emacs is still running, of course. I need to attach a script somewhere to tell Gnome to shutdown emacs when I logoff/shutdown.
1) What should the script look like? "kill-emacs" doesn't seem to work.
2) Where should I put this script? There's nothing in the startup programs (System->Sessions menu) panel that looks useful. I'd prefer something that works in the user's account, rather than hacking the PostSession script or something else with root access.

ShreevatsaR is right, the answer is kill-emacs or save-buffers-kill-emacs, both of which are interactive, and so can be run from within Emacs with M-x save-buffers-kill-emacs. This is probably the best way to do it, since you will get to save modified files.
Another alternative is to make a shell file like this:
#!/bin/bash
emacsclient -e "(kill-emacs)"
Which you can run from wherever you like (menu icon, panel, etc).

This linuxquestions.org page has a Python script that can be run during login that listens for the 'save yourself' event that Gnome emits during shutdown. You could modify that to do the:
emacsclient -e '(save-buffers-kill-emacs)'
Official docs: https://www.emacswiki.org/emacs/EmacsAsDaemon#toc8

Another addendum to ShreevatsaR: the python script works like a charm, but I'd suggest using
emacsclient -e '(let ((last-nonmenu-event nil))(save-buffers-kill-emacs))'
as command. Setting last-nonmenu-event to nil forces emacs into mouse-mode, so you get "nice" dialog boxes instead of prompts in the minibuffer.
Or even more fancy (somewhere in your emacs config):
(defun shutdown-emacs-server () (interactive)
(when (not (eq window-system 'x))
(message "Initializing x windows system.")
(x-initialize-window-system)
(when (not x-display-name) (setq x-display-name (getenv "DISPLAY")))
(select-frame (make-frame-on-display display '((window-system . x))))
)
(let ((last-nonmenu-event nil)(window-system "x"))(save-buffers-kill-emacs)))
and then:
emacsclient -e '(shutdown-emacs-server)'

If you use systemd you may be interested in this unit file that lets you manage an Emacs server gracefully from within your console/remote system:
[Unit]
Description=Emacs: the extensible, self-documenting text editor
[Service]
Type=forking
ExecStart=/usr/bin/emacs --daemon
ExecStop=/usr/bin/emacsclient --eval "(kill-emacs)"
Restart=always
# Remove the limit in startup timeout, since emacs
# cloning and building all packages can take time
TimeoutStartSec=0
[Install]
WantedBy=default.target
(it kills the daemon in the same way folks already suggested above.)
You could put and name the unit file like ~/.config/systemd/user/emacs.service so it's bind to your user instead running it as root; to manage it:
$ systemctl --user {enable,disable,start,restart,stop} emacs.service
Please note: I took this note from somewhere else, can't remember where though.

I think that using a script in /etc/init.d is a cleaner solution.
Check here for more details
http://www.emacswiki.org/emacs/EmacsAsDaemon

the answer from willert contains a small bug. it must look like
(defun shutdown-emacs-server () (interactive)
(when (not (eq window-system 'x))
(message "Initializing x windows system.")
(x-initialize-window-system)
(when (not x-display-name) (setq x-display-name (getenv "DISPLAY")))
(select-frame (make-frame-on-display x-display-name '((window-system . x))))
)
(let ((last-nonmenu-event nil)(window-system "x"))(save-buffers-kill-emacs)))

you can put emacsclient -e "(kill-emacs)" in GDM's PostSession directory or directly in the Default script:
/etc/gdm/PostSession/Default
see also GDM documentation.

Perhaps the most general solution would be to put a script in the system PostSession directory that runs every executable script in ~/.logout-d, or something similar. Then you can put whatever scripts you like in ~/.logout-d, and they will be run on logout.
The script might be as simple as run-parts ~/.logout.d.
Note: Untested, though I do use a startup script that does run-parts ~/.autostart.d, and that's been working fine forever.
Edit: Of course, it would be just as easy to modify the above python script to execute that same command, but I personally don't like the idea of loading a script for my entire session just to run commands on logout.

Just open some terminal and pkill -TERM emacs

Related

emacs to automatically rsync?

This was discussed in a emacs StackExchange Discussion where Howard Abrams and gavinb mentioned something that could work. However, I am such a newbie to emacs, and not a programmer at all, that I have no idea of how to get his code to work in my emacs editor. I have started to use org-mode and have used the "easy customization" mode to change things in "[-]-\ Group Org", but I don't know enough to know what to do with it to implement a complete solution.
I assume that the gist code of Mr. Abrams works to run one script named ".on-save" that lives in the same directory as the file that is being saved. And that this code runs the .on-save script and passes the saved file's name to that script to process. At that point I get lost in how to get a rsync script to process the saved file's name.
Would I put the code that Mr. Abrams mentions in my ~.emacs file?
Alternatively do I use "easy customization" to run Mr. Abrams code?
If I managed to run/install the code, how would my rsync script look to make use of his code to pass the file name of the file being saved to the rsync script for processing.
Thanks.
Aaron
So I bound Alt-F11 to trigger a shell script ".rsync-org-mode.sh".
In my .emacs file I put the following:
(defvar script-name "~/.rsync-org-mode.sh")
(defun call-my-script-with-word ()
(interactive)
(shell-command
(concat script-name
" "
(thing-at-point 'word))))
(global-set-key (kbd "M-<f11>") 'call-my-script-with-word)
The shell script:
#!/bin/bash
rsync -avh --delete ~/My-Org-Directory/ /My-Backup-Org-Directory/
I saved the script as ~/.rsync-org-mode.sh and made it executable with chmod+ It rsync's my entire org-mode directory.
To use it I periodically save to backup using Alt-F11. I did not want it to be automatic for fear that it would automatically sync a bad copy.
Very very low tech, but it is adequate for my needs, and it will sync the directories. Lawlist's solution in the post he referenced is great, and more comprehensive, but since I fuse mount my only sftp directory prior to each emacs session, it was more than I really needed.

start emacsclient within emacs (like magit does)

I am looking for ways to start emacs within shell-mode, and I want the client to connect to the enclosing emacs instance so I don't need to switch to the instance running the server to edit the file.
I sense it is doable because magit is already doing something like this: the commit message is edited by emacsclient, and always opened in the enclosing instance. I don't even need to start the server explicitly!
My primary usage is to do git commit from shell-mode. I can't rely on magit because I have to use some customized git version with special command. Anyway I think it would be cool thing to do.
UPDATE:
I found the magit function magit-with-emacsclient that does the trick here:
https://github.com/magit/magit/blob/master/magit.el#L1979
Any help to turn the function into a shell script that can act as the default editor of git will be greatly appreciated! I will also try and post the code if I can make it work.
UPDATE 2:
Here is my solution. It requires start the server beforehand with pid in the socket name and then set your $EDITOR to be emacsclient connecting to that server.
Put this in your init.el
; start a server with a pid
(require 'server)
(defun server-start-pid ()
(interactive)
(when (server-running-p server-name)
(setq server-name (format "server%s" (emacs-pid)))
(when (server-running-p server-name)
(server-force-delete server-name)))
(server-start))
and run server-start-pid before you launch the editor in your shell-mode.
put this script emacsclient-pid in your PATH. It recursively find the parent process until it finds the emacs instance and invoke emacsclient on the right socket:
#! /usr/bin/python
import os, sys
import psutil
def get_pid(name):
pid = os.getppid()
while True:
proc = psutil.Process(pid)
if name in proc.name():
break
pid = proc.ppid()
return pid
if __name__ == '__main__':
pid = get_pid("emacs")
# pass the argument to emacsclient
args = ' '.join(sys.argv[1:])
cmd = "emacsclient -s server{pid} {args}".format(**globals())
print cmd
os.system(cmd)
And put this in your .bashrc
if [[ $EMACS"x" == tx || $TERM"x" == dumbx ]]; then
export PAGER=/bin/cat
export EDITOR='emacsclient-pid'
else
export PAGER=/usr/bin/less
export EDITOR='emacs -q -nw'
fi
I have split the code responsible for client-server interaction into a separate library with-editor. It's part of git-modes' next branch. Magit will start using that once I merge its next branch into master. You should study that instead of the old implementation in magit itself, because it puts all things related to this in one place and because it is also improved in many ways. E.g. it also works when using tramp.
with-editors can be used by other packages besides magit. That's one of the reasons why I have split it into a separate library/package. But I have not yet implemented the parts not actually needed by magit. E.g. the functionality it provides could also be used with shell-command, see https://github.com/magit/git-modes/pull/96.
Something similar would probably work for shell-mode too. From a very quick look I think the function that would need to be advices in this case is comint-exec. I will probably not work on this soon, but eventually I will get back to this. Meanwhile have a look at that library yourself. Understanding what it does won't be easy without good knowledge of elisp and how emacs handles child processes, though. The only advice I can give you here is to also read the issues that concern with-editor in the magit/git-modes repository on github.
Ps. Translating this to a shell script won't work, because certain things have to happen in Emacs before the child process is started, like starting the server.

Emacsclient called by applescript can't find emacs server socket

The shell command
emacsclient -n -e '(make-remember-frame)'
works.
But the applescript
do shell script "emacsclient -n -e '(make-remember-frame)'"
just returns
emacsclient: can't find socket; have you started the server?
To start the server in Emacs, type \"M-x server-start\".
emacsclient: No socket or alternate editor. Please use:
--socket-name
--server-file (or environment variable EMACS_SERVER_FILE)
--alternate-editor (or environment variable ALTERNATE_EDITOR)
I rarely use this, but it has worked successfully in the past for various purposes. Perhaps you can modify it to suit your needs. The init.el or .emacs file must have (server-start) inside in order to make everything work. I have lots of stuff that loads when Emacs is activated for the first time, so I need a 5 second delay before emacsclient is called -- you can adjust the delay downward if your Emacs loads faster. If Emacs is already running, there is no need for a delay. You can comment out the verbal messages generated by say -- I used them this morning to test the conditions and make a minor adjustment to the script. The script contains a command-line example on line 4, which calls two Emacs functions. Of course, the path to your Emacs and emacsclient will need to be adjusted to wherever you have installed them on your computer.
# `(server-start)` must be inside `init.el` or `.emacs` file.
# This script can be used in the terimal: osascript path-to-script arguments
# Terminal Example:
# osascript /Users/HOME/.0.data/.0.emacs/.emacsclient.applescript "-e '(progn (dired \"/Applications\") (message \"Hello-World\!\"))'"
on run argv
set arg to item 1 of argv
set emacs to application "Emacs"
set appIsRunning to emacs is running
if appIsRunning then
say "Emacs is already running."
do shell script "/Users/HOME/.0.data/.0.emacs/Emacs_06_01_2014.app/Contents/MacOS/bin/emacsclient " & arg
else
tell application "/Users/HOME/.0.data/.0.emacs/Emacs_06_01_2014.app/Contents/MacOS/Emacs" to activate
say "Please wait five seconds for Emacs to load."
delay 5
do shell script "/Users/HOME/.0.data/.0.emacs/Emacs_06_01_2014.app/Contents/MacOS/bin/emacsclient " & arg
end if
end run

How can I write to standard output in Emacs

I am trying to debug an Emacs program performance wise. In particular, I suffer an extremely long startup time (~5' compared to ~1' for a bare Emacs) on a remote connection via WLAN, cellphone etc. In this context, any message written is no help, for the display is not refreshed at all.
What I would like to do is to write onto the "standard output" of the Linux process. I am aware of the --batch mode but this is no help to me because I want to use Emacs interactively.
So how can I write messages out to the Linux-standard output (as opposed to the Emacs standard output)?
You can output to standard error like this:
(print "hello world" #'external-debugging-output)
or
(princ "hello world" #'external-debugging-output)
This can buffer, so be careful.It's not possible to output to standard out at the moment. I'm going to add that, I think!
Start emacs as a daemon (emacs --daemon) and any messages during the start-up sequence will be sent to stdout or stderr, as described by lunaryorn.
Connect to the server with emacsclient
The simplest way to kill the server is M-x kill-emacs RET
For details see C-hig (emacs) Emacs Server RET
Works for me in centos 6.8 (GNU Emacs 23.1.1):
(append-to-file "here I come to save the day\n" nil "/dev/stdout")
Try also using "/dev/tty" in place of "/dev/stdout":
Unclear from question if you intend to redirect "emacs -nw" stdout to a file and monitor that file externally (then use "/dev/stdout"); or are ok with writing to "/dev/tty" thus polluting the self-same tty of the main "emacs -nw" display.
If starting a GUI version of emacs, in such a way it may lose attachment to originating tty, can abuse environment variables to communicate an originating shell's tty to elisp.
This works for me using Aquamacs in Mac OS X. Launching from a bash shell:
$ MY_TTY=$(tty) open /Applications/Aquamacs\ Emacs.app &
then in emacs:
(append-to-file "here I come to save the day\n" nil (getenv "MY_TTY"))

Emacs: Tramp doesn't work

I tried to open a remote file via Emacs via Tramp.
(require 'tramp)
(setq tramp-default-method "ssh")
I get a message from Emacs
Tramp: Waiting for prompts from remote shell
Emacs hung and did not respond to any action after that
Emacs was installed on Windows; the remote file was on a Linux machine.
If the account you're connecting to uses some weird fancy shell prompt, then there is a good chance that this is what makes tramp trip.
Log in as root, then enter
PS1="> "
(that's a normal, standard shell (ZSH, BASH, younameit) prompt, one that tramp will understand)
then switch to the user account, and launch emacs -q (to make sure that your .emacs is not causing this mess) and try to C-x C-f /sudo:root#localhost:/etc/hosts and see what's what.
You can (not recommended) also customize the regexp that defines what tramp expects :
M-x customize-variable RET tramp-terminal-prompt-regexp
My approach :
Make sure the variable tramp-terminal-type is set to "dumb"
M-x customize-variable RET tramp-terminal-type
Test that in your .*shrc and serve the correct prompt :
case "$TERM" in
"dumb")
PS1="> "
;;
xterm*|rxvt*|eterm*|screen*)
PS1="my fancy multi-line \n prompt > "
;;
*)
PS1="> "
;;
esac
Your Windows ssh client is the key here, and the 'ssh' Tramp method is almost certainly wrong.
If you're using Cygwin, then you need to use the 'sshx' method, and you probably need to use ssh-agent to handle authentication. Details are here:
Using tramp with EmacsW32 and cygwin, possible?
I imagine the same applies to any stand-alone ssh client which does not require a full Cygwin installation, but does use the Cygwin DLLs. (I mention this, because I'm pretty sure I remember seeing such a thing.)
If you're using PuTTY then you want the 'plink' method, as Alex Ott pointed out. If the Wiki doesn't suffice, a search here will probably turn up solutions for configuring that approach.
Other alternatives I can suggest are:
Use the Cygwin-native Emacs. That will be slower than NTEmacs, but Tramp seems to work well with the 'ssh' method, and password-prompting works as well.
Host a Linux VM on your Windows box, and run Emacs on that. That's a fairly large hoop to jump through, but it's my preferred way of using Tramp when working in Windows.
Well, this is a defect of tramp.
The real solution is to prevent loading .bashrc when tramp is used. (because now it is PS1, but it can be PATH, or any other thing that your .bashrc will do that will displease tramp...).
This can be done by asking ssh to set an environment variable, and testing it in .bashrc:
Add this to ~/.emacs:
(require 'tramp-sh nil t)
(setf tramp-ssh-controlmaster-options (concat "-o SendEnv TRAMP=yes " tramp-ssh-controlmaster-options))
and that at the beginning of ~/.bashrc:
if [ ! -z ${TRAMP-x} ] ; then
return
fi
Another default of tramp is that it doesn't have a variable to pass random arguments to the ssh command, we have to piggy-back on tramp-ssh-controlmaster-options.
Had you checked Emacs wiki for solution? ssh is in PATH? It's also recommended to use plink on MS Windows - see section "Inline methods" in Tramp documentation
If the problem is your fancy custom prompt in the remote shell, an easy workaround is to add to your .bashrc or equivalent:
if [[ $TERM == "dumb" ]]; then
export PS1="$ "
fi
After you define your PS1.
Note: the credit goes to ChasingLogic as this is their suggestion in this thread.
By the way -- if You need tramp to sudo -- You can actually sudo without tramp using sudoedit.
Currently I'm using this bash function:
erf () { SUDO_EDITOR="emacsclient -a emacs" sudoedit $#; }