今天在使用Tabby的时候发现了一个比较好玩的插件server-stats,安装后发现一直是loading…的状态。以下是我解决问题的步骤。

一、问题展现

  1. 使用的工具:Tabby V1.0.229
  2. 安装的插件是server-stats。具体安装步骤是 配置 ➡️插件 ➡️server-stats ➡️ 获取 即可安装。安装之后状态栏就一直是loading…的状态。
    在这里插入图片描述

纳闷了,咋回事儿呢。下载源码下来看看。

二、问题解决

下载源码:
git clone https://github.com/kasuganosoras/tabby-server-stats.git

1. 处理问题1,loading… 的问题

文件位置:src/components/bottom-bar.component.ts

原因分析: 这个问题是由于程序在获取服务器数据失败时(例如超时、网络问题或不支持的系统),没有正确地把界面的状态从“加载中”切换回来。这就导致了一旦第一次获取失败,界面就会永久卡在 Loading… 。

修复内容: 我修改了 src/components/bottom-bar.component.ts 文件,增加了一个强制重置逻辑:无论数据获取成功还是失败,都会强制结束加载状态。如果获取失败,界面将显示默认值(0%),而不是一直转圈。

同时,我还顺手修复了一个小问题,让 “Loading…” 这个词现在可以正确支持多语言翻译了。

源码如下:

import { Component, OnInit, OnDestroy, ChangeDetectorRef, NgZone } from '@angular/core'
import { Subscription } from 'rxjs'
import { AppService, ConfigService } from 'tabby-core'
import { StatsService } from '../services/stats.service'
import { CustomMetric } from '../config'

@Component({
    selector: 'server-stats-bottom-bar',
    template: `
        <div class="stats-container" 
             *ngIf="visible"
             [style.background]="styleConfig.background">
            <div class="stat-section" *ngIf="loading">
                <div class="loading-text">Loading...</div>
            </div>
            
    

需要调整的位置如下:

import { Component, OnInit, OnDestroy, ChangeDetectorRef, NgZone } from '@angular/core'
import { Subscription } from 'rxjs'
import { AppService, ConfigService } from 'tabby-core'
import { StatsService } from '../services/stats.service'
import { CustomMetric } from '../config'

@Component({
    selector: 'server-stats-bottom-bar',
    template: `
        <div class="stats-container" 
             *ngIf="visible"
             [style.background]="styleConfig.background">
            <div class="stat-section" *ngIf="loading">
                <div class="loading-text">{{ 'Loading...' | translate }}</div>
            </div>

修改了之后,保存并进行编译。

npm run build

将生成的dist文件放到,Tabby的插件位置重启即可。
我电脑的位置是C:\Users\XXXX\AppData\Roaming\tabby\plugins\node_modules\tabby-server-stats 将dist替换即可。

这就解决了loading…的问题。

2. 状态栏展示cpu、内存、磁盘 都为 0%的问题

没有了loading...的问题后,发现展示的数据不正确。发现是展示的时候对于不同系统兼容性的问题,没有处理。

问题文件1位置:src/components/bottom-bar.component.ts
问题文件2位置:src/services/stats.service.ts

具体的问题分析如下:
1. 出现这个问题大概率是没有识别到显示指标的命令,所以需要找到形成语句的位置,并进行调整。具体找的环节我就不多说了。
2. 找到语句位置调整指标命令,大概率是可以解决问题的。
2.1 src/components/bottom-bar.component.ts

具体的代码调调整是针对src/components/bottom-bar.component.ts 的checkAndFetch()这个方法,位置如下:

在这里插入图片描述

    async checkAndFetch() {
        const isEnabled = this.config.store.plugin?.serverStats?.enabled;
        const displayMode = this.config.store.plugin?.serverStats?.displayMode || 'bottomBar';
        
        if (displayMode !== 'bottomBar') {
            if (this.visible) {
                this.visible = false;
                this.loading = true;
                this.cdr.detectChanges();
            }
            return;
        }

        let activeTab: any = this.app.activeTab

        if (!isEnabled || !activeTab) {
            if (this.visible) {
                this.visible = false;
                this.loading = true;
                this.cdr.detectChanges();
            }
            return;
        }

        if (activeTab['focusedTab']) {
            activeTab = activeTab['focusedTab'];
        }

        const session = activeTab['session'];
        
        if (session) {
            if (!this.visible) {
                this.visible = true;
                this.loading = true;
                this.cdr.detectChanges();
            }
            
            try {
                const data = await this.statsService.fetchStats(session)
                this.loading = false;
                if (data) {
                    this.updateStats(data);
                    this.currentStats = data;
                }
                this.cdr.detectChanges();
                return;
            } catch (e) { 
                this.loading = false;
                this.cdr.detectChanges();
            }
        } else {
            if (this.visible) {
                this.visible = false;
                this.loading = true;
                this.cdr.detectChanges();
            }
        }
    }

调整位置如下:
在这里插入图片描述

2.2 src/services/stats.service.ts :
  1. 调整src/services/stats.service.ts的 StatsService 类中的private baseStatsCommand 变量
    在这里插入图片描述

将原有的代码

// 以后可以在这里扩展更多命令
    private baseStatsCommand = `
    stats=$( (grep 'cpu ' /proc/stat; awk 'NR>2 {r+=$2; t+=$10} END{print r, t}' /proc/net/dev; sleep 1; grep 'cpu ' /proc/stat; awk 'NR>2 {r+=$2; t+=$10} END{print r, t}' /proc/net/dev) | awk 'NR==1 {t1=$2+$3+$4+$5+$6+$7+$8; i1=$5} NR==2 {rx1=$1; tx1=$2} NR==3 {t2=$2+$3+$4+$5+$6+$7+$8; i2=$5} NR==4 {rx2=$1; tx2=$2} END { dt=t2-t1; di=i2-i1; cpu=(dt<=0)?0:(dt-di)/dt*100; rx=rx2-rx1; tx=tx2-tx1; printf "%.1f %.0f %.0f", cpu, rx, tx }' );
    mem=$(free | awk 'NR==2{printf "%.2f", $3*100/$2 }');
    disk=$(df -h / | awk 'NR==2{print $5}' | sed 's/%//');
    echo "TABBY-STATS-START $stats $mem $disk"

改为

private baseStatsCommand = `export LC_ALL=C; PATH=$PATH:/usr/bin:/bin:/usr/sbin:/sbin; OS=$(uname -s 2>/dev/null || echo "Linux"); if [ "$OS" = "Darwin" ]; then cpu=$(ps -A -o %cpu | awk '{s+=$1} END {print s}' 2>/dev/null || echo "0"); mem=$(ps -A -o %mem | awk '{s+=$1} END {print s}' 2>/dev/null || echo "0"); disk=$(df -h / 2>/dev/null | awk 'NR==2{print $5}' | sed 's/%//' || echo "0"); echo "TABBY-STATS-START $cpu 0 0 $mem $disk"; else stats=$( (grep 'cpu ' /proc/stat; awk 'NR>2 {r+=$2; t+=$10} END{print r, t}' /proc/net/dev; sleep 1; grep 'cpu ' /proc/stat; awk 'NR>2 {r+=$2; t+=$10} END{print r, t}' /proc/net/dev) 2>/dev/null | awk 'NR==1 {t1=$2+$3+$4+$5+$6+$7+$8; i1=$5} NR==2 {rx1=$1; tx1=$2} NR==3 {t2=$2+$3+$4+$5+$6+$7+$8; i2=$5} NR==4 {rx2=$1; tx2=$2} END { dt=t2-t1; di=i2-i1; cpu=(dt<=0)?0:(dt-di)/dt*100; rx=rx2-rx1; tx=tx2-tx1; printf "%.1f %.0f %.0f", cpu, rx, tx }' ); mem=$(free 2>/dev/null | awk 'NR==2{printf "%.2f", $3*100/$2 }'); disk=$(df -h / 2>/dev/null | awk 'NR==2{print $5}' | sed 's/%//'); if [ -z "$stats" ]; then stats="0 0 0"; fi; if [ -z "$mem" ]; then mem="0"; fi; if [ -z "$disk" ]; then disk="0"; fi; echo "TABBY-STATS-START $stats $mem $disk"; fi`

注意:这个地方不要换行

并且在src/services/stats.service.ts的第40行 调整

在这里插入图片描述


            // Flatten command to single line to prevent SSH exec issues
            finalCommand = finalCommand.replace(/\n/g, ' ');

            // Wrap in /bin/sh -c to ensure POSIX compatibility (fixes issues with fish shell, etc.)
            finalCommand = `/bin/sh -c '${finalCommand.replace(/'/g, "'\\''")}'`;

调整完成,编译&放入插件。重启Tabby,问题解决。

![[Pasted image 20251218173951.png]]

终于可以开心的使用Tabby啦!!!

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐