我正在尝试找到一种方法来检查 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
对我来说没有用,因为我不想知道我是否在会话中,而已经在会话中,这是没有意义的。我想知道服务器是否是alive
或dead
,无论我是否附加到会话。
额外的(仅适用于 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/null
。tmux
如果没有可用的会话,该命令将输出一条错误消息,但我们对该消息不感兴趣。
答案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 的输出,否则您应该使用grep
s -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