gnome-terminal - 执行具有暂停功能的命令

gnome-terminal - 执行具有暂停功能的命令

我有一个应用程序启动器,它使用 -- 选项在 gnome-terminal 内执行命令,但是每当我进入终端并尝试 crtl-z 尝试挂起该命令并将其移动到后台时,什么也没有发生。我的搜索发现了一堆关于在 bash 中启动交互式 shell 的帖子,但我在那里尝试过的任何方法都不起作用。有没有办法启动 gnome-terminal 并执行命令,使我能够暂停命令并稍后显示提示?

答案1

bash_in_gnome_terminal(){
    local IFS
    printf -v cmd %q ". ~/.bashrc; set -m; $*"
    gnome-terminal -- bash -c "bash --rcfile <(echo $cmd)"
}

bash_in_gnome_terminal tail -f ~/.xsession-errors
bash_in_gnome_terminal 'grep -r pattern dir | less'

该解决方案很复杂(而且很严重!),因为该gnome-terminal命令实际上调​​用“终端服务器”来生成终端实例,并且您无法将文件描述符传递给在其中运行的进程。

对于其他终端,如xterm或 ,mlterm解决方案更简单、更实用:

bash_in_xterm(){
    local IFS
    xterm -e bash --rcfile <(printf '. ~/.bashrc; set -m; %s\n' "$*")
}

vi +'cmd'另外,如果 bash 可以选择在交互式 shell(如)之前运行一些命令,而无需像 那样的拼凑,那就太好了--rcfile <(...)。也许它甚至有——但我无法弄清楚;-)

set -m是必需的,因为 bash 使用以下命令获取初始化文件监控模式关闭^Z,即没有作业控制和使用、fgbg等的可能性。


如果您希望在启动的命令退出时退出 shell 并关闭终端,可以像这样修改该函数[假设是最新版本的 bash]:

bash_in_gnome_terminal(){
    local IFS
    set -- 'sigchld(){ local j="\j"; ((${j@P})) || exit; }; trap sigchld CHLD;' "$@"
    printf -v cmd %q ". ~/.bashrc; set -m; $*"
    gnome-terminal -- bash -c "bash --rcfile <(echo $cmd)"
}

${var@P}表单扩展了 中的任何提示转义var,并且\j提示转义扩展为作业数量。如果没有更多的作业,从陷阱调用的命令将退出shell j="\j"; ((${j@P})) || exitCHLD

在不支持${var@P}扩展形式的旧版本 bash 中,必须使用更笨重的 kludge:

set -- 'sigchld(){ trap - CHLD; test "$(jobs -p)" || exit; trap sigchld CHLD; }; trap sigchld CHLD;' "$@"

这里CHLD必须禁用陷阱然后重新启用,否则$(jobs -p)命令替换将递归地触发它。


整个事情可以做成一个独立的脚本而不是函数:

#! /bin/bash

# uncomment and edit the following line accordingly
# set -- <fixed command and arguments> "$@"

# this only works in bash >= 4.4
# set -- 'sigchld(){ local j="\j"; ((${j@P})) || exit; }; trap sigchld CHLD;' "$@"
set -- 'sigchld(){ trap - CHLD; test "$(jobs -p)" || exit; trap sigchld CHLD; }; trap sigchld CHLD;' "$@"

printf -v cmd %q ". ~/.bashrc; set -m; $*"
gnome-terminal -- bash -c "bash --rcfile <(echo $cmd)"

相关内容