在终端的特定位置显示后台进程的标准输出


8

每次打开新终端或进行新登录时,我都有一条命令运行。

该程序产生的输出(彩色)应放在命令提示符之前。运行可能需要几秒钟,这将阻止我在此之前使用终端(除非在后台运行)。

鉴于zsh具有一些重绘终端而又不破坏现有文本的高级方法,我想知道如何以一种无需使用它就可以等待的方式运行此命令,但是我可以使用终端完成后,将打印输出,就好像它不是首先放在后台一样。

实际上,我希望可以做些什么:

Command output:
... (running on background)
me@computer: somecommand
me@computer: someothercommand

命令完成后,我将得到:

Command output:
 * Output foo
 * Multiple lines bar
 * and some yada
me@computer: somecommand
me@computer: someothercommand

我尝试在开始时将进程置于后台,但随后无法清晰显示输出。我得到类似的东西:

Command output:
[2] 32207
me@computer: somecommand
me@computer: someother * Output foo
 * Multiple lines bar
 * and some yada
[2]  + done       command
me@computer: someothercommand

那么,这可能吗?如果不使用zsh,是否有解决方案可以做到?

欢迎任何指针或信息。


如果程序直接在终端中运行,则是不可能的,因为只有一个光标位置,并且zsh和程序将争夺它。您可以执行以下操作zpty:在zsh创建的终端中运行命令,并在zsh的控制下将其输出中继到实际终端。
吉尔(Gilles)'所以

@Gilles您能详细说明一下zpty吗?我知道,没有游标之间的某种竞争,就不可能有两个程序写入同一终端。我的问题来自zsh在某些配置中已经重写了提示的事实。显然,该程序必须写入一些临时的内存缓冲区,然后在命令完成后将其“打印”到特定位置。后者全部由zsh控制。
2011年

@吉尔斯:也许这值得一个真正的答案?
斯特凡希门尼斯

@StéphaneGimenez当然可以。没有一些研究,我不知道该怎么做,而且我现在没有时间进行这项研究。
吉尔(Gilles)'所以

一个想法是screen使用启动脚本来做到这一点,该脚本拆分屏幕并在上部运行长运行程序,在下部运行普通命令行。
vasquez 2012年

Answers:


5

如果您愿意接受当前提示行上方的输出,这是一个简单的解决方案。

TRAPUSR1 () { zle -I; unfunction TRAPUSR1 }  # invalidate prompt on signal USR1

bufferout () {
    local buffer
    while read -r line; do                   # buffer lines from stdin
        buffer="$buffer$line\n"
    done
    print -rn -- $terminfo[dl1]              # delete current line
    print -rn -- $terminfo[cr]               # move cursor to BOL
    printf "$buffer"                         # print buffer
    kill -USR1 $$                            # send USR1 when we're done
}

unsetopt monitor                             # don't monitor this job
./testout |& bufferout & disown              # bg and disown to suppress notification
setopt monitor                               # restore job monitoring

作业完成后,将删除当前提示和输入缓冲区,stdoutstderr打印命令的全部和内容。

可能会比使用该zsh/curses模块花更多的钱,但是我怀疑它是否会提供足以值得付出努力的显着优势。


这可行。但是,要防止外壳程序在发送到后台时打印进程pid并在完成时显示“完成”消息有多困难?(我的意思是暂时停用该功能)。另外,在将输出放到终端上之前,清除现有的提示行有多难?
Unode 2012年

我认为我可能还有其他一些提示重写配置与初始提示的删除发生冲突。命令完成后,我的就不会消失。当发送到后台时,我仍然仍然获得进程的PID,但是“完成”行消失了。无论如何,我都接受您的回答,因为它与我的初衷非常接近。谢谢。
Unode 2012年

我正在使用xterm并启用了VCS模块,并对提示进行了一些其他自定义。我没有尝试过,但是我很确定它与此有关。一段时间前,我尝试使用类似于此模式的vi模式通知程序(stackoverflow.com/a/3791786/125801),并且在激活时我丢失了一些自定义提示行为。没什么大不了的,目前我对解决方案感到满意。这些天之一,我将尝试清除提示,并检查PID是否仍然显示。
2012年

Zsh-4.3.10,在几乎禁用了所有自定义功能之后,我现在不再得到提示(即,它已被正确删除),但是我仍然在后台获得进程的PID,例如[1] 27911 27912单行和第一行。终奌站。
2012年

我可以再次投票吗?:)现在太完美了!谢谢你
Unode 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.