当没有 tmux 服务器运行时,我无法 grep tmux ls 输出

当没有 tmux 服务器运行时,我无法 grep tmux ls 输出

我正在尝试找到一种方法来检查 tmux 服务器是否正在运行,以便使用该信息更新我的 zsh 提示符。

当 tmux 服务器处于活动状态时

> tmux ls
0: 1 windows (created Sat Jul 10 13:47:36 2021) (attached)

这样我就可以 grep 输出,对吗?

grep 输出:

> tmux ls | grep -i "windows"
0: 1 windows (created Sat Jul 10 13:47:36 2021)

windows是彩色的red(对我来说),或者你终端中的任何颜色,所以命令有效。

我选择这个词是windows因为这个词总是出现在tmux ls输出中。

现在检查服务器是否离线

杀死 tmux 服务器后:

tmux kill-server

现在我使用以下命令检查服务器是否处于活动状态tmux ls

> tmux ls
no server running on /tmp/tmux-1000/default

正常输出,符合预期。

grep当 tmux 服务器死机时,似乎会失败;检查一下这个奇怪的事情:

> tmux ls | grep -i "windows"
no server running on /tmp/tmux-1000/default

exit code该命令的:

> echo $?
1

意思是 grepfailed来抓取输出。

另一个测试用例显示出奇怪的情况

> tmux ls > file.txt
no server running on /tmp/tmux-1000/default

无论您运行什么,它总是打印no server ... bla bla在屏幕上。

捕获文件时:

> cat file.txt

空空如也

如何检查 tmux 服务器是否正在运行,以便使用该信息更新我的 zsh 提示符?

注意:变量$TMUX对我来说没有用,因为我不想知道我是否在会话中,而已经在会话中,这是没有意义的。我想知道服务器是否是alivedead,无论我是否附加到会话。

额外的(仅适用于 zsh 用户)

如果你想将 tmux 服务器状态放入 zsh 提示符中,这就是我得到的: 在此输入图像描述

要得到这个,只需将这些行添加到您的.zshrc

function update_prompt_and_venv () {
  if tmux ls &> /dev/null; then
      tmux_server="%{$terminfo[bold]$fg[black]%}(%{$terminfo[bold]$fg[green]%}tmux%{$terminfo[bold]$fg[black]%}) "
  fi
  PROMPT="
$tmux_server ... $your_cwd
> "
}
precmd_functions+=(update_prompt_and_venv)

内容:

  • 每次在终端中按 Enter 键时都会调用的函数
  • 具有 tmux 服务器状态的变量
  • 函数中更新的提示
  • 确保添加该函数,precmd_functions以便在每个输入命令之前调用

当您关闭服务器后按 Enter 键时,您将立即看到更新

答案1

您的困惑来自于这样一个事实tmux:像所有其他实用程序一样,将错误消息和其他诊断消息写入标准错误流而不是到标准输出流。通过>重定向,您仅重定向标准输出流,而不重定向错误消息。同样,当您通过管道传输命令的输出时,您仅通过管道传输标准输出流,而不是错误消息。这是设计使然。

但是,您在这里不需要做grep任何事情,而是可以依靠调查tmux其本身的退出状态。

有一个has-session子命令的tmux存在只是为了告诉您会话是否存在(或者是否存在具体的会话存在):

has-session[ -t target-session]
(别名:has

如果指定的会话不存在,则报告错误并以 1 退出。如果存在,则以 0 退出。

这意味着您可以使用

if tmux has-session 2>/dev/null; then
    echo session exists
else
    echo no sessions
fi

这依赖于调查特定字符串的存在状态,tmux has-session并且不需要解析命令的输出。

我们将错误流重定向到/dev/null使用 来丢弃它2>/dev/nulltmux如果没有可用的会话,该命令将输出一条错误消息,但我们对该消息不感兴趣。

答案2

tmux ls | grep -i "windows"管道的标准输出tmux ls进入grep.该no server running on /tmp/tmux-1000/default消息正在打印到标准错误,不是标准输出。

要 grep stdout 和 stderr,您必须将 stderr 重定向到与 stdout 相同的位置。例如:

tmux ls 2>&1 | grep -i "windows"

或者只是将 stderr 重定向到/dev/null

tmux ls 2>/dev/null | grep -i "windows"

顺便说一句,除非您确实需要显示 grep 的输出,否则您应该使用greps -q(或--quiet, --silent)选项并检查 grep 的退出代码。例如

tmux ls 2>/dev/null | grep -i -q "windows"

if [ $? -eq 0 ] ; then
  echo "tmux is running for $USER"
else
  echo "tmux is not running for $USER"
fi

答案3

在unix中,当一个程序启动时,它有3个文件无句柄打开:STDIN STDOUT SDERR

重定向|通常将 STDOUT 从第一个程序发送到第二个程序的 STDIN。像“没有服务器正在运行”这样的错误会转到 STDERR,它通常最终出现在终端上,而不是在管道或其他重定向中。

如果你想同时捕获STDOUT和STDERR,你需要做更多的事情。在 bash、zsh 和较新的 shell 中,这可以工作:

tmux ls |& grep...

在较旧的 shell(和当前的 shell)中,您需要执行以下操作:

tmux ls 2>&1 | grep...

这告诉 shell 在 STDOUT 上创建管道,然后在运行第一个命令之前将 STDERR 文件句柄 (2) 替换为 STDOUT (1) 文件句柄的副本。请注意2>&1和的顺序|在这里很重要。

不涉及 grep 的一个可能更简单的替代方案是只运行tmux ls然后检查输出$?是否有错误。尽管这无法区分其他 tmux 错误。例如

if ! tmux ls
then
    # do this when tmux errors
fi

相关内容