7

每隔一段时间,我就必须从我的终端会话中启动一个 GUI 程序来做某事。通常是 Chrome 来显示一些 HTML 文件是一些类似的任务。然而,这些程序到处都会发出警告,写任何东西实际上会变得很荒谬,所以我一直想将stderr/重定向stdout/dev/null.

虽然($PROGRAM &) &>/dev/null看起来不错,但我决定为它创建一个简单的 Bash 函数,这样我就不必每次都重复自己了。

所以现在我的解决方案是这样的:

#
# silly little function
#
gui ()
{
  if [ $# -gt 0 ] ; then
    ($@ &) &>/dev/null
  else
    echo "missing argument"
  fi
}

#
# silly little example
#
alias google-chrome='gui google-chrome'

所以我想知道的是:

  • 有没有办法没有无穷无尽的别名列表仍然很活泼?
  • 是否有不同的策略来实现这一目标?
  • 其他外壳是否提供不同的解决方案?

在提出这些问题时,我想指出您的策略和解决方案可能与我的大相径庭。将输出重定向到 /dev/null 并为其设置别名是我知道的唯一方法,但可能有完全不同的方法更有效。

因此这个问题:-)

4

4 回答 4

2

正如其他人在评论中指出的那样,我认为真正的问题是在命令行上区分 gui 与非 gui 应用程序的方法。因此,我能想到的最简洁的方法是把这部分的脚本:

  #!/bin/bash

  if [ $# -gt 0 ] ; then
    ($@ &) &>/dev/null
  else
    echo "missing argument"
  fi

放入一个名为 的文件gui中,然后chmod +x将其放入您的~/bin/(确保~/bin在您的$PATH)中。现在您可以使用以下命令启动 gui 应用程序:

`gui google-chrome`

在提示上。

或者,您可以执行上述操作,然后使用bind

bind 'RETURN: "\e[1~gui \e[4~\n"'

这将允许您执行以下操作:

google-chrome

在提示符下,它会gui在之前自动附加google-chrome

或者,您可以将上述操作绑定到F12而不是RETURNwith

bind '"\e[24~": "\e[1~gui \e[4~\n"'

将您想要gui与非 gui 启动的内容分开。

更多关于绑定herehere的讨论。

这些替代方案为您提供了摆脱无尽别名的方法;混合:

  • 放入gui你的~/bin/, 和
  • guito的绑定使用F12如上图

似乎是最理想的(尽管很老套)的解决方案。


更新 - @Enno Weichert 的最终解决方案:

四舍五入这个解决方案......

这将处理别名(虽然以某种古怪的方式)和不同的转义编码(以更实用而不是详尽的方式)。

把这个放进去$(HOME)/bin/quiet

#!/bin/bash -i

if [ $# -gt 0 ] ; then
  # Expand if $1 is an alias
  if [ $(alias -p | awk -F "[ =]" '{print $2}' | grep -x $1) > 0 ] ; then
    set -- $(alias $1 | awk -F "['']" '{print $2}') "${@:2}"
  fi
  ($@ &) &>/dev/null
else
  echo "missing argument"
fi

而这在$(HOME)/.inputrc

#
# Bind prepend `quiet ` to [ALT][RETURN]
#
# The condition is of limited use actually but serves to seperate
# TTY instances from Gnome Terminal instances for me.
# There might very well be other VT emulators that ID as `xterm`
# but use totally different escape codes!
#
$if $term=xterm
  "\e\C-j": "\eOHquiet \eOF\n"
$else
  "\e\C-m": "\e[1~quiet \e[4~\n"
$endif
于 2012-11-19T16:08:58.610 回答
0

虽然它是一个丑陋的黑客,但我有时会nohup用于类似的需求。它具有重定向命令输出的副作用,并使程序独立于终端会话。

对于在桌面环境中运行 GUI 程序的情况,资源泄漏的风险很小,因为程序无论如何都会以窗口管理器会话结束。尽管如此,还是应该考虑到这一点。

还可以选择打开另一个终端会话。例如,在 Gnome 中,您可以使用gnome-terminal --comand 'yourapp'.
但这会导致打开许多无用的终端窗口。

于 2012-11-19T14:22:49.867 回答
0

首先,从终端启动 GUI 应用程序是个好主意,因为这样可以减少鼠标的使用。它在选项和参数方面更快,更方便。以浏览器为例。假设您在剪贴板中有 URL,可以粘贴了。只需键入(例如iceIceweasel)并按 Shift-Insert(粘贴)和 Enter。将此与单击图标(可能在菜单中)进行比较,等待窗口加载(如果有启动页面则更糟),然后单击 URL 栏(或按 Ctrl-L),然后按 Ctrl-V.. . 所以我理解你希望这个工作。

但是,我不明白这将如何需要一个“无限”的别名和函数列表。您真的在使用那么多 GUI 应用程序吗?即便如此,别名也是一行 - 对于处理参数可能更实用的函数可能是 1-5 行(稀疏)代码。而且,不要觉得你需要一劳永逸地设置它们 - 当你需要时,一个接一个地设置它们。不久之后,你就会拥有它们。

此外,如果您有一个选项卡式终端,例如 urxvt(有一个 Perl 扩展),您将从“GUI:s”移动到“CLI:s”中受益:下载,有 rtorrent;对于 IRC,irssi;而不是 XEmacs (或emacs), emacs -nw; vlc 有一个用于流式传输音乐的 CLI 接口;对于邮件,Emacs 的 rmail;等等等等!去打猎:)

(我认为唯一可悲的例外是浏览器。Lynx、W3M 等从技术角度来看可能很棒,但这并不总是重要的,因为现代网页是根本就没有在设计时考虑到那些纯文本浏览器。老实说,很多页面在这些浏览器中看起来不太清晰。)

提示:要充分利用选项卡式终端,您需要“关闭”“更改选项卡”快捷键(例如,Alt-J 用于上一个选项卡,Alt-K 用于下一个选项卡,而不是箭头键你到达)。

最后,一种可以绕过这个问题的解决方案,即&在您的~/.xinitrc(包括您的终端仿真器)中将“GUI:s”作为后台进程(使用 )启动。不是很灵活,但非常适合您每次使用计算机时总是使用的东西。

于 2012-11-20T01:14:57.567 回答
0

好的,所以我一直认为一个功能应该足够了。没有别名,没有 bashisms,没有废话。但在我看来,在不影响常规使用(例如扩展和完成)的情况下,唯一的方法是将函数放在命令的末尾。这并不像人们最初想象的那么容易。

首先,我考虑了一个附加到末尾的函数,我会调用它,例如,printf "%b" "\u"为了剪切当前行,插入另一个printf,将其粘贴回去,并在开头加上一两个引号,然后在结束。我不知道如何使这项工作,但我很抱歉。即使我这样做了,由于shell解释escape序列的方式不同,我也不希望这种方法有任何真正的可靠性/可移植性,更不用说它们运行的​​终端仿真器了。也许stty可以提供沿着这些思路前进的方法,但是如果是这样,你不会在这里找到它......现在,无论如何。

我最终改为将当前命令实际复制/proc/{PID}/cmdline到一个变量中,然后(可耻地)完全杀死它,最后按照我的喜好包装它。从好的方面来说,这很容易完成,很快就完成了(尽管我可以想象以任何一种方式争论它的“效率”),并且无论原始输入如何,无论是别名、变量还是函数等。我相信它也是 POSIX 可移植的(虽然我不记得是否需要kill SIGNALS为 POSIX 指定名称),而且绝对不是废话。

另一方面,它的优雅当然还有很多不足之处,虽然它可能不值得担心,但它确实完全浪费了一个PID.,它并不能完全阻止shell 垃圾邮件;也就是说,在我的 shell 中,我启用了后台jobs报告,set因此,当第一次运行时,shell 友好地通知我我刚刚打开并浪费了PID两行。另外,因为我复制../cmdline而不是直接与0文件描述符接口,所以我希望管道;等会出现问题。我可以而且很可能会很快解决这个问题。

我将解决这个问题,也就是说,如果我无法找到一种方法来代替使用,正如我怀疑可以做到的那样,SIGTSTP+SIGCONT首先在子shell 之外暂停进程,然后在重定向子shell 的输出后在一个进程中继续它。由于我尚未发现的原因,这似乎不可靠,但我认为它很有希望。也许nohup和一个trap(实际上rehup是)是需要的,但我也不确定如何将它们放在一起......

Amyway,不用多说,我的半中止,向后的 gui 启动器:

% _G() { ( 
    _gui_cmd="$(tr '\0' ' ' </proc/"$\!"/cmdline )" ; 
    kill -9 "$\!" ; 
    exec eval "${_gui_cmd} &" ) 
    &>/dev/null 2&>1 
}
% google-chrome-beta --disk-cache-dir="/tmp/cache" --disk-cache-size=100000000 &_G                                                   
[1] 2674
[1]  + 2674 killed     google-chrome-beta --disk-cache-dir="/tmp/cache" --disk-cache-   
%

因此,如果尝试进行类似操作,可能会遇到的另一个问题是 shell 假定的扩展顺序。如果没有像我这样的技巧,在前面的命令将它作为参数之前,你肯定会遇到一些严重的困难来扩展你的函数。我相信我已经通过简单地将我的_G函数调用附加到原始命令的&背景指令上来防止这种情况发生而没有不必要的冗余。只需添加&_G到您希望运行的命令的末尾,祝您好运。

-麦克风

PS 好的,所以写最后一句话让我想到可以用tee.

于 2013-11-21T21:26:12.990 回答