使用 NCurses 和 C 显示系统信息的简单文本 GUI (TUI)

Simple Text GUI (TUI) Using NCurses and C to Display System Info

我刚刚开始尝试结合 ncurses 和 C 来开发一个非常小的 TUI。 TUI 的目的是用基本的 login/welcome 屏幕迎接用户。目标是显示基本的系统信息,如操作系统、可用内存、IP 地址等。除了只读之外什么都没有。

执行此操作的最佳方法是什么?我正在努力处理的部分是将 shell 命令(如 dflsifconfig 等)与我可以在 ncurses 和 C 中显示或打印的变量连接起来。我知道可以这样做,也可以用字符串调用系统命令,但这看起来有点笨重:

#include <ncurses.h>
#include <stdlib.h>
#include <stdio.h>

int main(void) {
    FILE *pp;

    initscr();
    cbreak();
    if ((pp = popen("df", "r")) != 0) {
        char buffer[BUFSIZ];
        while (fgets(buffer, sizeof(buffer), pp) != 0) {
            addstr(buffer);
        }
        pclose(pp);
    }
    getch();
    return EXIT_SUCCESS;
}

是否有任何方法可以从 C 程序中的命令行中执行命令,然后有选择地访问该命令的输出以供以后显示?或者这些信息通常存储在机器上可解析文件的某个地方?我刚开始尝试以 "TUI" 的方式将 system information/use 拉入命令行,如有任何帮助,我们将不胜感激。提前致谢!

管道的想法既好又简单,其他任何东西都至少缺少 "good and simple" 之一,很可能两者都缺少。但是您的另一个问题是关于某些系统信息的可用性。好吧,这些信息非常分散,具体位置取决于实际使用的操作系统。

对于普通的非专用Linux系统:文件系统是/etc/mtab(详细信息使用statfs()),许多系统信息在[=22] =].如果您需要更多,它会变得复杂。

即使你想构建一个df的简化版本($COREUTILS/src/df.c中的df的原始代码),也已经相当复杂了。而不是仅仅 运行ning df 并从管道读取,你必须做

  • 阅读/etc/mtab并找到挂载点(系统可能没有/etc/mtab,尽管它应该有)
  • 运行 statfs() 在每个挂载点上打印结果

你需要超过 100 行容易出错的 C 代码,即使你跳过所有花哨的东西。并且仅用于打印文件系统。

不,只需从管道读取经过良好测试的旧程序的输出,这是最简单的方法。

编辑:

如果使用管道,则使用完整 shell。这意味着您也可以使用所有其他工具。

为了让测试更简单,这里有一个没有 ncurses 的简化版本(让它变得更复杂 ;-) ),只是为了在命令行下玩。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUF_SIZE 256

// ALL CHECKS OMMITTED!

char *sub_exec(const char *command)
{
  char buf[BUF_SIZE];
  char *ret;
  size_t mem_alloc, mem_needed;

  ret = malloc(4 * BUF_SIZE * sizeof(char));
  // or use calloc or set [=10=] manually
  memset(ret, '[=10=]', 4 * BUF_SIZE);
  // memory allocated
  mem_alloc = 4 * BUF_SIZE;
  // memory needed
  mem_needed = 0;
  // open the pipe read-only
  FILE *out_pipe = popen(command, "r");
  // until end of the output of the pipe (EOF)
  while (!feof(out_pipe)) {
    // read a chunk of the output
    if (fgets(buf, BUF_SIZE, out_pipe) != NULL) {
      mem_needed += BUF_SIZE;
      if (mem_alloc < mem_needed) {
    // no fancy algorithms
    ret = realloc(ret, mem_needed + 4 * BUF_SIZE);
    mem_alloc = mem_needed * 2;
      }
      // and conatenate it to the result
      strncat(ret, buf, BUF_SIZE);
    }
  }
  pclose(out_pipe);
  // You may or may not readjust the memory used
  // ret = realloc(ret, strlen(ret) + 1);
  return ret;
}

int main(int argc, char **argv)
{
  char *str_from_pipe;
  if (argc < 2)
    fprintf(stderr, "Usage: %s command\n", argv[0]);

  str_from_pipe = sub_exec(argv[1]);
  printf("%s\n", str_from_pipe);

  free(str_from_pipe);

  exit(EXIT_SUCCESS);
}

你可以在这里做一些简单的事情,比如

./readpipe "cat win*c | tr -d '5' | perl -0777 -pe 's{/\*.*?\*/}{}gs' | indent -"

(连接所有 C 文件,去除 \rs,去除大部分注释并 运行 通过 indent(1)

df。假设您想要其中包含实际数据的文件系统,而不是 tempfs 或类似的文件系统,所以:

./readpipe "df -P -h -t ext4"

此处打印:

Filesystem      Size  Used Avail Use% Mounted on
/dev/sda2        48G   33G   14G  71% /
/dev/sda3       861G  761G   56G  94% /home

(好像很饱)

您可以直接使用或进一步按摩:

./readpipe "df -h -t ext4 --output=target,fstype,size,used,avail|awk '{if(NR>1)print}'"

打印:

/          ext4   48G   33G   14G
/home      ext4  861G  761G   56G

警告:

./readpipe "df -h -t ext4 --output=target,fstype,size,used,avail|  sed -n '1!p'"

不行,你需要交换那种报价(但并不总是那么简单)

./readpipe 'df -h -t ext4 --output=target,fstype,size,used,avail |  sed -n "1!p"'

为了能够拆分条目,例如:strtok(3) 用单个制表符替换所有空格

./readpipe 'df -h -t ext4 --output=target,fstype,size,used,avail |  sed -n "1!p" | sed -e "s/[ ]\+/\t/g"'

(是的,还有更优雅的方法,但已经足够了)

files/directories 中关于 CPU(s)

的更多有用信息
/sys/devices/system/cpu/cpu*/cpufreq/
/sys/devices/system/cpu/cpu*/cache/

lscpu。有许多有用的 ls* 程序,例如 lspcilsusblskat…不,等等,那是不同的东西,不要忘记 lsblk(列出块设备,包括分区(如果可用)。在 lshw 的帮助下可以获得已安装硬件的完整列表(一些信息需要 root 权限,但它已经相当广泛)并且 uname 是关于 OS 的信息,还有:free 内存消耗,还有很多很多。大多数(如果不是全部)允许某种格式,请参阅相应的联机帮助页以了解详细信息。

如果你告诉我你需要什么,我可以告诉你在哪里可以找到它(他大胆地说;-))。只要在下面评论问,我会添加它。