NodeJS 速習チュートリアル

Node.js OSモジュール

1. OSモジュールとは?

Node.js の OSモジュール は、基盤となるオペレーティングシステム(OS)と対話するための強力なユーティリティ群を提供します。
これを利用することで、OSごとの差異を意識せずにシステム関連の情報へアクセスしたり、一般的なOSタスクを実行したりする クロスプラットフォーム な手法が実現します。

1.1 主な機能:

  • システム情報(CPU、メモリ、プラットフォームなど)の取得
  • ユーザーおよびネットワーク情報へのアクセス
  • クロスプラットフォームに対応したファイルパスやディレクトリの操作
  • システムリソースとパフォーマンスの監視
  • OS固有のシグナルやエラーのハンドリング

2. OSモジュールを使い始める

2.1 モジュールのインポート

OSモジュールは Node.js の コアモジュール であるため、追加のインストールは不要です。
CommonJS または ES modules のいずれかの構文でインポートできます。

CommonJS(Node.js のデフォルト)

const os = require('os');

ES Modules(Node.js 14以上、または package.json で "type": "module" を指定)

import os from 'os';
// または特定のメソッドのみをインポート
import { arch, platform, cpus } from 'os';

2.2 基本的な使用例

OSモジュールの代表的なメソッドを使用したクイック例を紹介します。

const os = require('os');

// 基本的なシステム情報
console.log(`OSプラットフォーム: ${os.platform()}`);
console.log(`OSタイプ: ${os.type()}`);
console.log(`OSリリース: ${os.release()}`);
console.log(`CPUアーキテクチャ: ${os.arch()}`);
console.log(`ホスト名: ${os.hostname()}`);

// メモリ情報
const totalMemGB = (os.totalmem() / (1024 * 1024 * 1024)).toFixed(2);
const freeMemGB = (os.freemem() / (1024 * 1024 * 1024)).toFixed(2);
console.log(`メモリ: ${totalMemGB}GB 中 ${freeMemGB}GB の空き`);

// ユーザー情報
const userInfo = os.userInfo();
console.log(`現在のユーザー: ${userInfo.username}`);
console.log(`ホームディレクトリ: ${os.homedir()}`);

3. OSモジュール・リファレンス

注意: OSモジュールのすべてのメソッドは 同期(Synchronous) 処理であり、即座に結果を返します。 パフォーマンスが重視されるアプリケーションでは、os.cpus()os.networkInterfaces() など、頻繁に呼び出される可能性のあるメソッドの結果を キャッシュ することを検討してください。

3.1 システム情報

3.1.1 os.arch()

Node.js バイナリがコンパイルされたOSの CPU アーキテクチャを返します。

const os = require('os');

// CPUアーキテクチャを取得
console.log(`CPUアーキテクチャ: ${os.arch()}`);

// 主な返り値:
// - 'x64' : 64ビットシステム
// - 'arm' : ARMプロセッサ
// - 'arm64' : 64ビットARM
// - 'ia32' : 32ビットx86

3.1.2 os.platform()

オペレーティングシステムのプラットフォームを識別する文字列を返します。

const os = require('os');

// プラットフォーム情報を取得
const platform = os.platform();
console.log(`プラットフォーム: ${platform}`);

// 主な返り値:
// - 'darwin' : macOS
// - 'win32' : Windows (32ビット/64ビット両方)
// - 'linux' : Linux

3.1.3 os.type()

POSIX システムでは uname、Windows では ver コマンドの結果に基づいたOS名を返します。

const os = require('os');

// OSタイプを取得
console.log(`OSタイプ: ${os.type()}`);

// 例:
// - Linux の場合は 'Linux'
// - macOS の場合は 'Darwin'
// - Windows の場合は 'Windows_NT'

3.1.4 os.release()

OSのリリース番号を返します。

const os = require('os');

// OSリリース情報を取得
console.log(`OSリリース: ${os.release()}`);

3.1.5 os.version()

カーネルバージョンを識別する文字列を返します。Windows ではビルド情報も含まれます。

const os = require('os');

// カーネルバージョンを取得
console.log(`カーネルバージョン: ${os.version()}`);

3.2 ユーザーと環境

3.2.1 os.userInfo()

現在の実効ユーザーに関する情報を返します。

const os = require('os');

// 現在のユーザー情報を取得
const user = os.userInfo();
console.log('ユーザー情報:');
console.log(`- ユーザー名: ${user.username}`);
console.log(`- ユーザーID: ${user.uid}`);
console.log(`- グループID: ${user.gid}`);
console.log(`- ホームディレクトリ: ${user.homedir}`);

// Windows の場合、ドメインも取得可能
if (os.platform() === 'win32') {
  console.log(`- ドメイン: ${user.domain || 'N/A'}`);
}

// 注意: user.shell は POSIX プラットフォームでのみ利用可能
if (user.shell) {
  console.log(`- デフォルトシェル: ${user.shell}`);
}

3.2.2 os.homedir()

現在のユーザーのホームディレクトリを返します。

const os = require('os');
const path = require('path');

// ホームディレクトリを取得
const homeDir = os.homedir();
console.log(`ホームディレクトリ: ${homeDir}`);

// 例: ユーザーのホームディレクトリに設定ファイルパスを作成
const configPath = path.join(homeDir, '.myapp', 'config.json');
console.log(`設定ファイルの保存先: ${configPath}`);

3.2.3 os.hostname()

オペレーティングシステムのホスト名を返します。

const os = require('os');

// システムのホスト名を取得
const hostname = os.hostname();
console.log(`ホスト名: ${hostname}`);

3.2.4 os.tmpdir()

OSのデフォルトの一時ファイル用ディレクトリを返します。

const os = require('os');

// システムデフォルトの一時ディレクトリを取得
console.log(`一時ディレクトリ: ${os.tmpdir()}`);

3.3 システムリソース

3.3.1 os.cpus()

各論理 CPU コアに関する情報を含むオブジェクトの配列を返します。

const os = require('os');

// CPU情報を取得
const cpus = os.cpus();
console.log(`CPUコア数: ${cpus.length}`);

// 各CPUコアの情報を表示
cpus.forEach((cpu, index) => {
  console.log(`\nCPUコア ${index + 1}:`);
  console.log(`- モデル: ${cpu.model}`);
  console.log(`- 速度: ${cpu.speed} MHz`);
  console.log('- タイム (ms):', {
    user: cpu.times.user,
    nice: cpu.times.nice,
    sys: cpu.times.sys,
    idle: cpu.times.idle,
    irq: cpu.times.irq
  });
});

// CPU使用率の計算例(2回の計測が必要)
function calculateCpuUsage(prevCpus) {
  const currentCpus = os.cpus();
  const usage = [];

  for (let i = 0; i < currentCpus.length; i++) {
    const current = currentCpus[i];
    const prev = prevCpus ? prevCpus[i] : { times: { user: 0, nice: 0, sys: 0, idle: 0, irq: 0 } };

    const prevIdle = prev.times.idle;
    const idle = current.times.idle - prevIdle;

    let total = 0;
    for (const type in current.times) {
      total += current.times[type] - (prev.times[type] || 0);
    }

    const usagePercent = ((1 - idle / total) * 100).toFixed(1);
    usage.push(parseFloat(usagePercent));
  }

  return {
    perCore: usage,
    average: (usage.reduce((a, b) => a + b, 0) / usage.length).toFixed(1),
    cpus: currentCpus
  };
}

// 計測例
console.log('\nCPU使用率を計算中(1秒程度の負荷シミュレーション後):');
const firstMeasure = os.cpus();
for (let i = 0; i < 1000000000; i++) {} // 負荷シミュレーション
const usage = calculateCpuUsage(firstMeasure);
console.log(`平均CPU使用率: ${usage.average}%`);

3.3.2 os.totalmem() と os.freemem()

それぞれ、システムの全メモリ量と空きメモリ量をバイト単位で返します。

const os = require('os');

// バイトを読みやすい形式に変換するユーティリティ
function formatBytes(bytes, decimals = 2) {
  if (bytes === 0) return '0 Bytes';
  const k = 1024;
  const dm = decimals < 0 ? 0 : decimals;
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}

const totalMem = os.totalmem();
const freeMem = os.freemem();
const usedMem = totalMem - freeMem;

console.log('メモリ情報:');
console.log(`- 全メモリ: ${formatBytes(totalMem)}`);
console.log(`- 空きメモリ: ${formatBytes(freeMem)}`);
console.log(`- 使用中メモリ: ${formatBytes(usedMem)} (${((usedMem / totalMem) * 100).toFixed(2)}%)`);

3.3.3 os.loadavg()

直近 1、5、15 分間の ロードアベレージ(負荷平均) を含む配列を返します。

const os = require('os');

// ロードアベレージを取得
const loadAverages = os.loadavg();
console.log('システムロードアベレージ (1, 5, 15 分):', loadAverages);

// CPUコア数と比較して負荷状態を確認
const cpuCount = os.cpus().length;
const oneMinLoad = loadAverages[0];
console.log(`1分間の負荷平均: ${oneMinLoad.toFixed(2)} (${(oneMinLoad / cpuCount * 100).toFixed(1)}% のコアを占有)`);

3.4 ネットワーク情報

3.4.1 os.networkInterfaces()

ネットワークアドレスが割り当てられたネットワークインターフェースを含むオブジェクトを返します。

const os = require('os');

// ネットワークインターフェース情報を取得
const networkInterfaces = os.networkInterfaces();

console.log('ネットワークインターフェース:');
Object.entries(networkInterfaces).forEach(([name, addresses]) => {
  console.log(`\nインターフェース: ${name}`);
  addresses.forEach((addr) => {
    console.log(`- ファミリ: ${addr.family}`);
    console.log(`  アドレス: ${addr.address}`);
    console.log(`  ネットマスク: ${addr.netmask}`);
    console.log(`  内部通信用 (Internal): ${addr.internal}`);
  });
});

3.4.2 os.uptime()

システムの アップタイム(稼働時間) を秒単位で返します。

const os = require('os');

const uptime = os.uptime();
const days = Math.floor(uptime / (24 * 3600));
console.log(`システム稼働時間: ${days}日と ${Math.floor((uptime % (24 * 3600)) / 3600)}時間`);

3.5 OS定数とユーティリティ

3.5.1 os.constants

エラーコードやプロセスシグナルなど、OS固有の一般的な定数を含むオブジェクトを返します。

const os = require('os');

// シグナル定数の確認
console.log('シグナル定数:', os.constants.signals);

// SIGINT (Ctrl+C) のハンドリング例
process.on('SIGINT', () => {
  console.log('SIGINTを受信しました。クリーンアップを実行します...');
  process.exit(0);
});

3.5.2 os.EOL

現在のOSにおける 改行コード(End-of-Line marker) を返します。

const os = require('os');
const fs = require('fs');

// OSに合わせた改行コードを使用してファイルを作成
const content = `1行目${os.EOL}2行目${os.EOL}3行目`;
fs.writeFileSync('output.txt', content);
console.log('プラットフォームに適した改行コードで書き込みました');

4. ベストプラクティス

4.1 パス操作の正確性

ファイルパスには常に path.join() を使用し、OSごとの区切り文字の違いを吸収しましょう。

// 良い例
const filePath = path.join(os.homedir(), 'app', 'config.json');

// 悪い例 (Windows で動作しません)
const badPath = `${os.homedir()}/app/config.json`;

4.2 os.EOL の活用

ファイルを書き出す際は、クロスプラットフォームの互換性を保つために os.EOL を使用するのが賢明です。

4.3 メモリ制限の考慮

メモリを大量に消費する操作を行う前に、利用可能なメモリをチェックする習慣をつけましょう。

5. 実践的な例

5.1 システム情報ダッシュボード

包括的なシステム情報レポートを作成する例です。

const os = require('os');

function getSystemDashboard() {
  return {
    os: {
      type: os.type(),
      platform: os.platform(),
      release: os.release(),
      uptime: `${Math.floor(os.uptime() / 3600)}時間`
    },
    memory: {
      total: `${(os.totalmem() / 1e9).toFixed(2)} GB`,
      usage: `${((1 - os.freemem() / os.totalmem()) * 100).toFixed(2)}%`
    },
    cpu: {
      model: os.cpus()[0].model,
      cores: os.cpus().length
    }
  };
}

console.log('======= システム情報ダッシュボード =======');
console.table(getSystemDashboard());

5.2 OSに応じた挙動の切り替え

OSごとに設定データの保存場所を切り替える実践的なパターンです。

const os = require('os');
const path = require('path');

function getAppDataPath(appName) {
  const platform = os.platform();
  switch (platform) {
    case 'win32':
      return path.join(process.env.APPDATA || '', appName);
    case 'darwin':
      return path.join(os.homedir(), 'Library', 'Application Support', appName);
    default:
      return path.join(os.homedir(), '.config', appName);
  }
}

console.log(`推奨される設定保存先: ${getAppDataPath('my-cool-app')}`);

6. まとめ

Node.js の OS モジュールは、実行環境に適応する堅牢なアプリケーションを構築するための基盤となります。
このモジュールを使いこなすことで、以下のことが可能になります:

  • CPU、メモリ、ネットワークなどの詳細なリソース監視
  • ユーザーごとのホームディレクトリや一時ディレクトリの適切な取得
  • OS固有の改行コードやシグナルの正しい処理
  • 利用可能な CPU コア数に基づいた並列処理の最適化

OSモジュールを効果的に利用して、どんな環境でも最高のパフォーマンスを発揮する Node.js アプリケーションを開発しましょう。