Add this to an emacs .org file:
#+BEGIN_SRC sh :results verbatim
#!/bin/bash
exec 2>&1 # <-- Because Emacs treats stderr output as an error and doesn't show it in the RESULT
echo before
# This nohup should just run in the background and continue to exit
# the script, but emacs hangs and waits on it anyhow:
nohup sleep 10 &
# Failed attempts at working around the hang are:
# setsid nohup sleep 10 &
# nohup sleep 10 </dev/null &
# Do see /tmp/ps.out being updated here so the hang is in Emacs:
ps -ef --forest --cols=10000 >/tmp/ps.out
echo after
exit 0
#+END_SRC
Move the point (cursor) into the BEGIN_SRC block and evaluate it using C-c C-c (which is bound to org-ctrl-c-ctrl-c
).
Watch what happens. Emacs sits there and hangs. What I want it to do is run that command (sleep 10
in this trivial example) and continue on.
Somehow Emacs is trying to wait on all subprocesses that the script creates and hangs there. I have to hit C-g to get control back.
The use case for this is that I want to invoke some GUI application (xterm, etc.) and have it run in the background but give control immediately back to Emacs.
How can I do that? See my failed attempts above.
EDIT: I isolated the issue to the bare minimum Emacs Lisp code. Evaluate the following inside your *scratch*
(Lisp Interactive) buffer and see that it hangs for the 3 seconds:
(let ((shell-file-name "/bin/bash")
(input-file "/tmp/tmpscript.sh")
(error-file "/tmp/tmperror")
(shell-command-switch "-c")
(command "sh")
exit-status)
(with-temp-file input-file
(insert "#!/bin/bash") (newline)
(insert "nohup sleep 3 &") (newline)
(insert "exit 0") (newline))
(setq exit-status
(apply 'call-process "/bin/bash"
input-file
(list t error-file)
nil
(list "-c" "sh"))))
Change the sleep 3
to something like sleep 3000
and it will hang for 3000 seconds until you kill it with C-g.
My emacs version reports:
GNU Emacs 24.4.50.1 (x86_64-unknown-linux-gnu, GTK+ Version 3.4.2) of 2014-09-14 on hungover
I use ob-async from MELPA to enable asynchronous executions.
.emacs:
(require 'ob-async)
.org:
#+BEGIN_SRC sh :async
sleep 10 && echo 'Done!'
#+END_SRC
I am using emacs lisp start-process
:
For example, to open libreoffice calc sheet
#+BEGIN_SRC elisp :noweb yes :results output :eval no-export :exports none
(start-process "server" "buf-server" "libreoffice" "calc.ods")
#+END_SRC
or to launch a java server (in the example tabula) in the background in xterm
#+BEGIN_SRC elisp :noweb yes :results output :eval no-export :exports none
(start-process "server" "buf-server" "xterm" "-T" "TABULA" "-hold" "-e" "bash" "-c" "java -Dfile.encoding=utf-8 -Xms256M -Xmx1024M -jar ~/java/tabula.jar")
#+END_SRC
Here is the closest I can think of using https://github.com/jwiegley/emacs-async
* Run shell command asynchronously
#+BEGIN_SRC sh :tangle some_cmd.sh :tangle-mode (identity #o755) :shebang #!/bin/bash
sleep 10
touch async-file
echo "done"
#+END_SRC
#+RESULTS:
#+BEGIN_SRC emacs-lisp
(require 'async)
(org-babel-tangle)
(async-start
(lambda ()
(shell-command (expand-file-name "some_cmd.sh")))
(lambda (result)
(message-box "%s" result)))
#+END_SRC
#+RESULTS:
: #<process emacs>
#+BEGIN_SRC sh
ls async-file
#+END_SRC
or for your particular use:
(require 'async)
(async-start
(lambda ()
(shell-command "xterm"))
(lambda (result)
(message-box "%s" result)))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With