Emacs 组织模式 - 如何 运行 shell 具有后台进程的脚本而不挂起 Emacs
Emacs org-mode - How to run shell scripts with backgrounded processes without hanging Emacs
将此添加到 emacs .org 文件中:
#+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
将点(光标)移动到 BEGIN_SRC 块中并使用 C-c C-c(绑定到 org-ctrl-c-ctrl-c
)计算它。
看看会发生什么。 Emacs 坐在那里并挂起。我想让它做的是运行那个命令(在这个简单的例子中是sleep 10
)并继续。
Emacs 以某种方式试图等待脚本创建并挂在那里的所有子进程。我必须按 C-g 才能取回控制权。
这个用例是我想调用一些 GUI 应用程序(xterm 等)并将其 运行 置于后台,但立即将控制权交还给 Emacs。
我该怎么做?请参阅上面我失败的尝试。
编辑:我将问题隔离到最低限度的 Emacs Lisp 代码。评估 *scratch*
(Lisp Interactive) 缓冲区中的以下内容,并查看它挂起 3 秒:
(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"))))
将 sleep 3
更改为 sleep 3000
之类的内容,它将挂起 3000 秒,直到您使用 C-g 将其杀死。
我的 emacs 版本报告:
GNU Emacs 24.4.50.1 (x86_64-unknown-linux-gnu, GTK+ Version 3.4.2) of 2014-09-14 on hungover
这是我能想到的最接近的用法 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
或您的特定用途:
(require 'async)
(async-start
(lambda ()
(shell-command "xterm"))
(lambda (result)
(message-box "%s" result)))
我使用 MELPA 中的 ob-async 来启用异步执行。
.emacs:
(require 'ob-async)
.org:
#+BEGIN_SRC sh :async
sleep 10 && echo 'Done!'
#+END_SRC
我在 mac。对于我的用例,我想使用 links。我在 sh link 的命令中添加了 &
。 &
进程在后台启动:
[[shell:afplay '/path/to/20200523-20123124.m4a' &][sample link]]
我添加了 (setq org-confirm-shell-link-function nil)
b/c 我有数百个小的 m4a 文件要转录...设置不安全但现在没问题。
运行 link(with C-x C-o
)打开一个新组织 shell 输出 window,但我只是忽略它。
干杯! z
我正在使用 emacs lisp start-process
:
例如,打开 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
或在 xterm
的后台启动 java 服务器(在示例表格中)
#+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
将此添加到 emacs .org 文件中:
#+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
将点(光标)移动到 BEGIN_SRC 块中并使用 C-c C-c(绑定到 org-ctrl-c-ctrl-c
)计算它。
看看会发生什么。 Emacs 坐在那里并挂起。我想让它做的是运行那个命令(在这个简单的例子中是sleep 10
)并继续。
Emacs 以某种方式试图等待脚本创建并挂在那里的所有子进程。我必须按 C-g 才能取回控制权。
这个用例是我想调用一些 GUI 应用程序(xterm 等)并将其 运行 置于后台,但立即将控制权交还给 Emacs。
我该怎么做?请参阅上面我失败的尝试。
编辑:我将问题隔离到最低限度的 Emacs Lisp 代码。评估 *scratch*
(Lisp Interactive) 缓冲区中的以下内容,并查看它挂起 3 秒:
(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"))))
将 sleep 3
更改为 sleep 3000
之类的内容,它将挂起 3000 秒,直到您使用 C-g 将其杀死。
我的 emacs 版本报告:
GNU Emacs 24.4.50.1 (x86_64-unknown-linux-gnu, GTK+ Version 3.4.2) of 2014-09-14 on hungover
这是我能想到的最接近的用法 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
或您的特定用途:
(require 'async)
(async-start
(lambda ()
(shell-command "xterm"))
(lambda (result)
(message-box "%s" result)))
我使用 MELPA 中的 ob-async 来启用异步执行。
.emacs:
(require 'ob-async)
.org:
#+BEGIN_SRC sh :async
sleep 10 && echo 'Done!'
#+END_SRC
我在 mac。对于我的用例,我想使用 links。我在 sh link 的命令中添加了 &
。 &
进程在后台启动:
[[shell:afplay '/path/to/20200523-20123124.m4a' &][sample link]]
我添加了 (setq org-confirm-shell-link-function nil)
b/c 我有数百个小的 m4a 文件要转录...设置不安全但现在没问题。
运行 link(with C-x C-o
)打开一个新组织 shell 输出 window,但我只是忽略它。
干杯! z
我正在使用 emacs lisp start-process
:
例如,打开 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
或在 xterm
的后台启动 java 服务器(在示例表格中)#+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