如何使用 NodeJs 编写自动化脚本来提醒我们准时下班 🤪🤪🤪

1,544 阅读5分钟

有这样的一个场景,本人是在一家 AI 公司,有一台机器是公用的,可能经常有被人使用的可能,但是我想在空闲的时候使用,那么就有了这样的一个自动化脚,本,通过命令来连接主机,并通过查询显存用量,如果有的话就在桌面上发送通知。

ssh 和 node-ssh

SSH(Secure Shell)是一个加密的网络协议,用于在不安全的网络上安全地执行远程命令和管理系统。SSH 最常见的用途是通过加密的连接远程登录计算机,但它也可以用于传输文件、隧道其他协议、以及执行其他网络服务。

SSH 在工作时,通常涉及三个步骤:

  1. 建立连接:客户端和服务器通过 SSH 协议建立一个加密连接。

  2. 身份验证:客户端向服务器提供凭据(如用户名、密码、或公钥),服务器验证这些凭据后,允许访问。

  3. 数据传输:所有的数据(命令、输出、文件等)都通过加密通道传输,保证数据的机密性和完整性。

它最常用的 SSH 命令主要有以下这些:

  1. ssh username@hostname:远程登录到指定的主机。

  2. scp file.txt username@hostname:/remote/directory/:将文件复制到远程服务器。

  3. ssh -L 8080:localhost:80 username@hostname:将本地的 8080 端口转发到远程主机的 80 端口。

而 node-ssh 是一个用于 Node.js 的库,封装了 SSH 协议的功能,使得开发者可以通过 JavaScript 或 TypeScript 代码在 Node.js 应用程序中实现 SSH 功能。node-ssh 库的底层使用了流行的 ssh2 库,并提供了更易用的 API。

下面是一个基本的使用案例:

const { NodeSSH } = require("node-ssh");
const ssh = new NodeSSH();

ssh
  .connect({
    host: "127.0.0.1",
    username: "moment",
    password: "moment",
  })
  .then(() => {
    // 执行远程命令
    ssh.execCommand("uptime").then((result) => {
      console.log("STDOUT: " + result.stdout);
      console.log("STDERR: " + result.stderr);
    });

    // 上传文件
    ssh
      .putFile("local-path.txt", "/remote-path.txt")
      .then(() => {
        console.log("文件上传成功");
      })
      .catch((err) => {
        console.error("文件上传失败:", err);
      });

    // 下载文件
    ssh
      .getFile("local-path.txt", "/remote-path.txt")
      .then(() => {
        console.log("文件下载成功");
      })
      .catch((err) => {
        console.error("文件下载失败:", err);
      });
  })
  .catch((err) => {
    console.error("SSH连接失败:", err);
  });

如何在电脑上发送通知

在 nodejs 中有一个 node-notifier 包,它能够在桌面上发送通知,是因为它借用了操作系统原生的通知系统或工具,并在不同平台上通过这些工具来实现通知功能。这样,node-notifier 可以在 macOS、Windows 和 Linux 等不同操作系统上都实现相同的效果,同时屏蔽了各平台之间的差异,使得开发者可以使用统一的 API 来发送桌面通知。

以下是一个简单的使用示例:

const notifier = require("node-notifier");

// 基本通知
notifier.notify({
  title: "下班辣下班辣",
  message: "还不下班,都什么时候了",
  sound: true, // 可选:播放通知声音
  wait: true, // 可选:等待用户响应
});

最终效果如图所示:

20240823112852

最终实现

首先我们先来上完整的代码,但是隐藏了关键信息:

const { NodeSSH } = require("node-ssh");
const cron = require("node-cron");
const notifier = require("node-notifier");

const ssh = new NodeSSH();

const remoteHost = ""; // 远程机器的IP地址
const remoteUser = ""; // SSH用户名
const remotePassword = ""; // SSH密码
const remotePort = 6667; // SSH端口

async function checkGpuMemory() {
  try {
    await ssh.connect({
      host: remoteHost,
      port: remotePort,
      username: remoteUser,
      password: remotePassword,
    });
    console.log("SSH连接成功");

    // 执行nvidia-smi命令来检查显存总量和使用情况
    const result = await ssh.execCommand(
      "nvidia-smi --query-gpu=memory.total,memory.used,memory.free --format=csv,noheader,nounits"
    );
    if (result.stderr) {
      console.error("Error executing command:", result.stderr);
      return;
    }

    const lines = result.stdout
      .split("\n")
      .filter((line) => line.trim() !== "");
    const gpuInfo = lines.map((line) => {
      const [total, used, free] = line
        .split(",")
        .map((value) => parseInt(value.trim()));
      return { total, used, free };
    });

    console.log("GPU显存信息:", gpuInfo);

    gpuInfo.forEach((gpu, index) => {
      console.log(
        `GPU ${index}: 总显存 ${gpu.total} MiB, 已使用 ${gpu.used} MiB, 空闲 ${gpu.free} MiB`
      );

      if (gpu.used <= 10) {
        showNotification(index, gpu.used, gpu.total, gpu.free);
      }
    });
  } catch (err) {
    console.error("SSH连接失败:", err);
  } finally {
    ssh.dispose();
  }
}

function showNotification(gpuIndex, used, total, free) {
  notifier.notify({
    title: `GPU ${gpuIndex} 显存空闲`,
    message: `GPU ${gpuIndex} 当前显存空闲情况: 总显存 ${total} MiB, 已使用 ${used} MiB, 空闲 ${free} MiB`,
    sound: true, // 播放提示音
    wait: true, // 用户点击通知时才消失
  });
}

// 每隔1分钟检查一次显存使用情况
cron.schedule("* * * * *", checkGpuMemory);

console.log("显存监测脚本已启动,每分钟检查一次显存使用情况");

最终执行效果如下图所示:

20240823113236

这段代码的作用是通过 SSH 连接到远程服务器,每分钟检查一次服务器上每块 GPU 的显存使用情况,并在显存使用较低时通过桌面通知提醒用户。

首先,代码使用 node-ssh 模块建立与远程服务器的 SSH 连接,通过 nvidia-smi 命令获取 GPU 的显存信息,包括总显存、已使用显存和空闲显存。然后,它将命令的输出解析成每块 GPU 的显存数据,并检查每块 GPU 的已使用显存。如果某块 GPU 的已使用显存小于或等于 10 MiB,代码会通过 node-notifier 模块发送桌面通知,提醒用户该 GPU 几乎处于空闲状态。

代码使用 node-cron 模块设置了一个定时任务,每分钟执行一次 checkGpuMemory 函数,以定期监控 GPU 的显存使用情况。如果连接失败或者命令执行出错,代码会在控制台输出相应的错误信息。

总结

借助 nodejs,它能够与操作系统交互,我们可以编写一些自动化脚本来帮助我们完成日常需求。

最后分享两个我的两个开源项目,它们分别是:

这两个项目都会一直维护的,如果你想参与或者交流学习,可以加我微信 yunmz777 如果你也喜欢,欢迎 star 🚗🚗🚗

文章推荐 自从用了 GPT4o,原来要 20 分钟写完的组件,我 5 分钟就能写完成了