Emacs org-mode - How to run shell scripts with background processes without hanging Emacs

Add this to your 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 point (cursor) to the BEGIN_SRC block and evaluate it with Cc Cc (anchored to org-ctrl-c-ctrl-c

).

See what happens. Emacs sits there and hangs. What I want to do is run this command ( sleep 10

in this trivial example) and continue.

Somehow Emacs tries to wait in all the subprocesses that the script creates and hangs. I need to hit Cg to get control.

In this case, I want to call some GUI application (xterm, etc.) and run it in the background, but go back to Emacs right away.

How can i do this? See my failed attempts above.

EDIT : I've highlighted the problem down to the minimal Emacs Lisp code. Evaluate the following inside the buffer *scratch*

(Lisp Interactive) and see it hang for 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 sleep 3

to something like sleep 3000

and it will hang for 3000 seconds until you kill it with Cg.

My emacs version releases:

GNU Emacs 24.4.50.1 (x86_64-unknown-linux-gnu, GTK+ Version 3.4.2) of 2014-09-14 on hungover

      

+3


source to share


2 answers


I am using ob-async from MELPA to enable asynchronous executions.

.emacs:

(require 'ob-async)

      



.org:

#+BEGIN_SRC sh :async
sleep 10 && echo 'Done!'
#+END_SRC

      

+1


source


Here is the closest I can think of 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 specific use:

(require 'async)

(async-start
 (lambda ()
   (shell-command "xterm"))
 (lambda (result)
   (message-box "%s" result)))

      

+2


source







All Articles