我正在尝试保存 Emacs 暂存缓冲区的内容,由于终端无法访问,我无法再访问该缓冲区。
在我的 Linux 机器上,我已经通过 ssh 连接到服务器,并启动了 Emacs。我的 Linux 机器现在已经冻结了,但是我仍然可以看到 Emacs 进程在 ssh 进入的服务器上处于活动状态。
有没有办法让 Emacs 转储/保存其临时内容而无需直接访问?我有两个想法:
- 向进程发送信号,以便 Emacs 转储其核心,然后重新加载核心(然后保存暂存)
- 将击键发送到进程的标准输入,指示 Emacs 进程保存文件,即:via
echo "abd" > /proc/<pid>/fd/0
.我通过打开两个终端进行了尝试,击键出现在目标终端上,但 Emacs 没有捕获它们。
答案1
我很幸运地将 gdb 附加到正在运行的进程中。大量借款来自:如何将终端附加到分离的进程?
写文件
mkfifo /tmp/some_name
gdb -p [pid]
- (在 gdb 内):
call close(0)
- (在 gdb 内):
call open('/tmp/some_name', 0600)
.此时gdb会出现hang住的情况 - (来自外壳):
echo '(write-file "savedresults")' > /tmp/some_name
- (在 GBD 内):
ctrl-d
scrap 的内容被写到文件“savedresults”中。有趣的(write-file "savedresults")
是附加到文件中(不确定为什么)。
Cx CW 名称
mkfifo /tmp/some_name
gdb -p [pid]
- (在 gdb 内):
call close(0)
- (在 gdb 内):
call open('/tmp/some_name', 0600)
.此时gdb会出现hang住的情况 - (从 shell):(
cmd="^X^Wsavedresults"
通过按键序列输入 ^X:CTRL-V CTRL-X,与 ^W 类似” - (来自外壳):
echo "$cmd" > /tmp/some_name
- (在 GBD 内):
ctrl-d
内容写入文件“savedresults”。
答案2
Emacs 服务器
最好的方法是联系Emacs服务器并运行 Emacs Lisp 命令。
emacsclient -e '(with-current-buffer "*scratch*" (write-file "~/scratch.txt"))'
或者您可以将 Emacs 连接到当前终端并在那里执行您想要的任何操作,例如切换到`划痕缓冲区并保存其内容。
emacsclient -nw
不幸的是,您需要显式启动服务器。我建议您将其添加(server-start)
到 init 文件中,因为它非常有用,但如果您还没有这样做,那么它现在对您没有帮助。
将输入发送到 Emacs 的终端
当您运行 时echo "abd" > /proc/$emacs_pid/fd/0
,这会将文本发送到正在运行 Emacs 的终端。将数据写入终端会显示该数据。您无法发送输入到终端:输入就是出现的内容从一个终端。
屏幕
如果您在屏幕或者多路复用器会话,您可以附加到现有会话并继续与程序交互。 screen 和 tmux 还支持以编程方式将输入发送到内部运行的程序。不过,这需要首先运行该程序,所以这次它对您没有帮助。
对于 Emacs,Screen 不会比使用emacsclient
.
核心转储
筛选核心转储是一种选择。Emacs 将缓冲区的内容存储在单个块中,中间有一个间隙(间隙可能包含任意垃圾;如果最后一个操作是删除,则它就是被删除的内容)。
默认情况下,SIGQUIT 信号会导致进程终止并留下核心转储(如果启用)。然而,Emacs 捕获 SIGQUIT(它退出到顶层,这在某些情况下很方便,但对您没有帮助)。所以你需要使用调试器附加到它并使其转储核心。无论如何,这比 SIGQUIT 有好处:它使进程保持运行状态,即使核心转储被禁用也能正常工作。
$ gdb -p $(pidof emacs)
(gdb) gcore
那么你可以筛选核心转储提取数据
将 Emacs 重新连接到新终端
Unix 甚至 Linux 都没有功能可以将程序从一个终端分离并将其附加到另一个终端上。但是,可以将调试器附加到任何程序并使其打开不同的终端。这可能是偶然的:有时它有效,有时它使程序崩溃。有几种工具试图尽可能地做到这一点;看如何否认正在运行的进程并将其关联到新的屏幕外壳?