`os` モジュールと `process` モジュール:システム情報とプロセス制御
アリスは、数十台のサーバーの管理を担当するDevOpsエンジニアです。新しいアプリケーションをデプロイするたびに、サーバーに手動でログインしてCPUコア数、利用可能なメモリ、OSのバージョンを確認し、環境変数に基づいて設定を切り替える必要があります。ある日の午前3時、緊急のデプロイ中に、手動での確認作業でメモリ不足の問題を見逃してしまい、デプロイが失敗してしまいました。そこで彼女は、ワンクリックでサーバーのリソース情報や環境情報を取得できる自動検出スクリプトをNode.jsで作成し、今後のデプロイが円滑に行われるようにすることにしました。
1. 学習内容
osモジュールの主要なメソッド:CPU、メモリ、ホスト名、プラットフォームなどの情報を取得するprocessモジュールの主要な属性:argv、env、exit、cwdなど。- 標準ストリーム操作:stdin / stdout / stderr
process.nextTick()の実行時とその目的- 環境変数の管理:.env ファイルと dotenv ライブラリ
- クロスプラットフォームのCLIツールを構築するための実践的なヒント
2. os モジュール:システム情報の収集
(1) CPUおよびメモリの情報
os.cpus() は CPU コアの詳細情報を配列として返します。os.totalmem() と os.freemem() は、それぞれ総メモリ容量と使用可能メモリ容量を(バイト単位で)返します。
▶ 例:サーバーのCPUとメモリの確認
const os = require('os');
const cpus = os.cpus();
console.log(`CPU Number of cores: ${cpus.length}`);
console.log(`CPU Model: ${cpus[0].model}`);
const totalMem = os.totalmem();
const freeMem = os.freemem();
const usedPercent = ((totalMem - freeMem) / totalMem * 100).toFixed(1);
console.log(`Total Memory: ${(totalMem / 1024 / 1024 / 1024).toFixed(2)} GB`);
console.log(`Available memory: ${(freeMem / 1024 / 1024 / 1024).toFixed(2)} GB`);
console.log(`Memory Usage: ${usedPercent}%`);
CPU Number of cores: 8
CPU Model: Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz
Total Memory: 15.88 GB
Available memory: 6.23 GB
Memory Usage: 60.7%
(2) オペレーティングシステムの識別子
os.platform() はプラットフォーム識別子(例:win32、linux、darwin)を返します。os.type() はオペレーティングシステムの名前を返し、os.arch() は CPU アーキテクチャを返し、os.hostname() はホスト名を返します。
▶ 例:オペレーティングシステムの情報の取得
const os = require('os');
console.log(`Platform: ${os.platform()}`);
console.log(`System Type: ${os.type()}`);
console.log(`CPU Architecture: ${os.arch()}`);
console.log(`Hostname: ${os.hostname()}`);
console.log(`System Version: ${os.version()}`);
Platform: linux
System Type: Linux
CPU Architecture: x64
Hostname: web-server-01
System Version: #1 SMP Thu Jan 1 00:00:00 UTC 2026
(3) ユーザーおよびディレクトリ情報
os.userInfo() は現在のユーザー情報を返します。os.homedir() はユーザーのホームディレクトリを返します。os.tmpdir() は一時ファイルディレクトリを返します。
▶ 例:ユーザーおよびディレクトリ情報の取得
const os = require('os');
const userInfo = os.userInfo();
console.log(`Username: ${userInfo.username}`);
console.log(`Home Directory: ${os.homedir()}`);
console.log(`Shell: ${userInfo.shell}`);
console.log(`Temporary Directory: ${os.tmpdir()}`);
Username: alice
Home Directory: /home/alice
Shell: /bin/bash
Temporary Directory: /tmp
(4) ネットワークインターフェース情報
os.networkInterfaces() すべてのネットワークインターフェースに関する詳細情報(IPアドレス、MACアドレス、アドレスファミリーなど)を返します。
▶ 例:ネットワークインターフェースの表示
const os = require('os');
const interfaces = os.networkInterfaces();
for (const [name, addrs] of Object.entries(interfaces)) {
for (const addr of addrs) {
if (addr.family === 'IPv4' && !addr.internal) {
console.log(`${name}: ${addr.address} (${addr.family})`);
}
}
}
eth0: 192.168.1.100 (IPv4)
wlan0: 10.0.0.5 (IPv4)
(5) 一般的なOSメソッドのクイックリファレンス
| メソッド | 戻り値の型 | 目的 |
|---|---|---|
os.cpus() |
object[] |
CPUコア情報配列 |
os.totalmem() |
number |
総メモリ(バイト) |
os.freemem() |
number |
使用可能メモリ (バイト) |
os.platform() |
string |
プラットフォーム識別子 (win32/linux/darwin) |
os.type() |
string |
オペレーティングシステムの名称 |
os.arch() |
string |
CPUアーキテクチャ (x64/arm64) |
os.hostname() |
string |
ホスト名 |
os.userInfo() |
object |
現在のユーザー情報 |
os.homedir() |
string |
ユーザーのホームディレクトリのパス |
os.tmpdir() |
string |
一時ファイルのディレクトリパス |
os.networkInterfaces() |
object |
ネットワークインターフェース情報 |
os.uptime() |
number |
システムの稼働時間(秒) |
os.loadavg() |
number[] |
平均システム負荷(1分/5分/15分) |
os.EOL |
string |
改行定数 |
os.devNull |
string |
デバイスパスが空です |
3. process モジュール:プロセス制御
(1) コマンドライン引数 process.argv
process.argv は配列です。argv[0] は Node.js 実行ファイルへのパス、argv[1] は実行されるスクリプトへのパスであり、その後の要素は渡されたコマンドライン引数です。
flowchart TD
A["Command-Line Input<br/>node app.js --env prod --port 3000"] --> B["process.argv Array"]
B --> C["argv[0]: Node.js Path<br/>/usr/local/bin/node"]
B --> D["argv[1]: Script Path<br/>/home/alice/app.js"]
B --> E["argv[2]: --env"]
B --> F["argv[3]: prod"]
B --> G["argv[4]: --port"]
B --> H["argv[5]: 3000"]
E --> I["Parameter Parsing Logic"]
G --> I
I --> J["{ env: 'prod', port: '3000' }"]
▶ 例:コマンドライン引数の解析
function parseArgs(argv) {
const args = {};
for (let i = 2; i < argv.length; i++) {
if (argv[i].startsWith('--')) {
const key = argv[i].slice(2);
const value = argv[i + 1] && !argv[i + 1].startsWith('--')
? argv[++i]
: true;
args[key] = value;
}
}
return args;
}
const config = parseArgs(process.argv);
console.log(config);
node cli.js --env production --port 8080 --verbose
{ env: 'production', port: '8080', verbose: true }
(2) process.env 環境変数
process.env すべての環境変数のキーと値のペアが含まれており、デプロイスクリプトが実行環境を判別するための中心的な基盤となります。
▶ 例:環境変数の読み取りと設定
console.log(`NODE_ENV: ${process.env.NODE_ENV || 'development'}`);
console.log(`PATH: ${process.env.PATH}`);
process.env.APP_MODE = 'production';
console.log(`APP_MODE: ${process.env.APP_MODE}`);
NODE_ENV: development
PATH: /usr/local/bin:/usr/bin:/bin
APP_MODE: production
(3) プロセスの終了と作業ディレクトリ
process.exit(code) プロセスを終了します(0は成功、0以外の場合は失敗を示します)、process.cwd() 現在の作業ディレクトリに戻ります。
▶ 例:条件付き終了とディレクトリチェック
const requiredEnv = ['DATABASE_URL', 'APP_SECRET'];
const missing = requiredEnv.filter(key => !process.env[key]);
if (missing.length > 0) {
console.error(`Missing required environment variables: ${missing.join(', ')}`);
process.exit(1);
}
console.log(`Working Directory: ${process.cwd()}`);
console.log(`Process ID: ${process.pid}`);
console.log(`Runtime: ${process.uptime().toFixed(0)} seconds`);
Missing required environment variables: DATABASE_URL, APP_SECRET
(4) 標準ストリーム:stdin / stdout / stderr
process.stdout と process.stderr は書き込み可能なストリームであるのに対し、process.stdin は端末とのやり取りに使用される読み取り専用のストリームです。
▶ 例:標準入力と標準出力の使用
process.stdout.write('Please enter your name: ');
process.stdin.once('data', (data) => {
const name = data.toString().trim();
process.stdout.write(`Hello, ${name}!\n`);
process.exit(0);
});
Please enter your name: Alice
Hello, Alice!
(5) process.nextTick()
process.nextTick() コールバックをマイクロタスクキューに追加します。コールバックは、現在の処理が完了した後、I/O イベントが発生する前に実行されます。これは、非同期処理が期待される順序で進行するようにするために、よく使用されます。
▶ 例:nextTickの実行順序
console.log('1 - Synchronize Code');
process.nextTick(() => {
console.log('3 - nextTick callback');
});
console.log('2 - Synchronize Code');
setImmediate(() => {
console.log('5 - setImmediate');
});
Promise.resolve().then(() => {
console.log('4 - Promise then');
});
1 - Synchronize Code
2 - Synchronize Code
3 - nextTick callback
4 - Promise then
5 - setImmediate
(6) 一般的なプロセス特性および手法のクイックリファレンス
| プロパティ/メソッド | 型 | 目的 |
|---|---|---|
process.argv |
string[] |
コマンドライン引数の配列 |
process.env |
object |
Environment Variable Object |
process.exit(code) |
方法 | プロセスの終了 |
process.cwd() |
コマンド | 現在の作業ディレクトリに戻る |
process.pid |
number |
現在のプロセスID |
process.uptime() |
手法 | 処理時間 (秒) |
process.stdin |
ReadStream |
標準入力ストリーム |
process.stdout |
WriteStream |
標準出力ストリーム |
process.stderr |
WriteStream |
標準エラーストリーム |
process.nextTick(cb) |
手法 | マイクロタスクのスケジューリング |
process.platform |
string |
動作プラットフォーム |
process.version string Node.jsのバージョン |
||
process.versions |
object |
コンポーネントのバージョン情報 |
process.kill(pid) |
メソッド | プロセスにシグナルを送信する |
process.title |
string |
プロセスタイトル |
4. クロスプラットフォームの定数とパスの取り扱い
(1) 改行とパス区切り文字
改行やパス区切り文字はオペレーティングシステムによって異なるため、これらをハードコーディングすると、クロスプラットフォームの問題を引き起こす可能性があります。
▶ 例:os.EOL と os.sep の使用
const os = require('os');
const path = require('path');
const lines = ['First line', 'Second line', 'Third line'].join(os.EOL);
console.log('Escaping Line Breaks:', JSON.stringify(os.EOL));
console.log('Path separator:', os.sep);
console.log('path.join Results:', path.join('src', 'utils', 'index.js'));
Escaping Line Breaks: "\n"
Path separator: /
path.join Results: src/utils/index.js
(2) クロスプラットフォームのパスと改行定数の比較
| 定数 | Windows の値 | POSIX の値 | 用途 |
|---|---|---|---|
os.EOL |
\r\n |
\n |
行末 |
os.sep |
\ |
/ |
パス区切り文字 |
path.sep \ / パス区切り文字(パスモジュール) |
|||
os.devNull |
nul |
/dev/null |
デバイスパスが空です |
path.delimiter |
; |
: |
PATH 環境変数の区切り文字 |
5. 環境変数の管理:.env と dotenv
(1) dotenv ライブラリの基本的な使い方
dotenv ファイルから .env ファイルへ環境変数を読み込むことは、プロジェクト構成を管理するための業界標準の手法です。
▶ 例:dotenv を使用して .env ファイルを読み込む
.env ファイルを作成します:
NODE_ENV=production
DATABASE_URL=postgresql://db.example.com:5432/myapp
APP_SECRET=my-super-secret-key
APP_PORT=3000
コードを読み込みます:
require('dotenv').config();
console.log(`Environment: ${process.env.NODE_ENV}`);
console.log(`Database: ${process.env.DATABASE_URL}`);
console.log(`Port: ${process.env.APP_PORT}`);
Environment: production
Database: postgresql://db.example.com:5432/myapp
Port: 3000
(2) 環境変数の設定方法の比較
| メソッド | 適用範囲 | 永続性 | ユースケース |
|---|---|---|---|
シェルの一時設定 (export KEY=val) |
現在のターミナルセッション | セッション終了時に消える | 一時的なデバッグ |
.env ファイル + dotenv |
現在の Node プロセス | ファイルの永続化 | プロジェクト開発 |
| システム環境変数 | グローバル(ユーザー/システム) | 永続的 | サーバーへの展開 |
| Docker ENV / env-file | コンテナ内部 | コンテナのライフサイクル | コンテナ化されたデプロイ |
| CI/CDプラットフォームの設定 | CI/CDパイプライン | パイプライン内 | 継続的インテグレーション |
(3) 環境変数の安全な読み取り
▶ 例:検証付きで環境変数を読み込む
function getEnv(key, options = {}) {
const value = process.env[key];
if (value === undefined) {
if (options.required) {
throw new Error(`Environment Variables ${key} It is necessary`);
}
return options.default ?? null;
}
if (options.type === 'number') {
const num = Number(value);
if (isNaN(num)) throw new Error(`Environment Variables ${key} It must be a number`);
return num;
}
if (options.type === 'boolean') {
return value === 'true' || value === '1';
}
return value;
}
const port = getEnv('APP_PORT', { default: 3000, type: 'number' });
const debug = getEnv('DEBUG', { default: false, type: 'boolean' });
const dbUrl = getEnv('DATABASE_URL', { required: true });
6. 包括的な例:システム診断 CLI ツール
完全なCLIツールを構築する:OS・メモリ・CPUを検出 → 環境変数を読み込む → 出力レポートをフォーマットする。
▶ 例:syscheck.js
const os = require('os');
function parseArgs(argv) {
const args = {};
for (let i = 2; i < argv.length; i++) {
if (argv[i].startsWith('--')) {
const key = argv[i].slice(2);
const value = argv[i + 1] && !argv[i + 1].startsWith('--')
? argv[++i] : true;
args[key] = value;
}
}
return args;
}
function formatBytes(bytes) {
const units = ['B', 'KB', 'MB', 'GB'];
let i = 0;
let size = bytes;
while (size >= 1024 && i < units.length - 1) {
size /= 1024;
i++;
}
return `${size.toFixed(2)} ${units[i]}`;
}
function getSystemInfo() {
const cpus = os.cpus();
const totalMem = os.totalmem();
const freeMem = os.freemem();
return {
hostname: os.hostname(),
platform: os.platform(),
arch: os.arch(),
osType: os.type(),
cpuModel: cpus[0].model,
cpuCores: cpus.length,
totalMemory: formatBytes(totalMem),
freeMemory: formatBytes(freeMem),
memUsage: ((totalMem - freeMem) / totalMem * 100).toFixed(1) + '%',
uptime: (os.uptime() / 3600).toFixed(1) + ' hours'
};
}
function getEnvInfo(keys) {
const result = {};
for (const key of keys) {
result[key] = process.env[key] || '(Not set)';
}
return result;
}
function printReport(sys, env) {
const sep = '='.repeat(48);
console.log(`\n${sep}`);
console.log(' System Diagnostic Report');
console.log(`${sep}`);
console.log(` Hostname : ${sys.hostname}`);
console.log(` Platform : ${sys.platform} / ${sys.arch}`);
console.log(` Operating System : ${sys.osType}`);
console.log(` CPU : ${sys.cpuModel}`);
console.log(` CPU Number of cores : ${sys.cpuCores}`);
console.log(` Total Memory : ${sys.totalMemory}`);
console.log(` Available memory : ${sys.freeMemory}`);
console.log(` Memory Usage : ${sys.memUsage}`);
console.log(` Runtime : ${sys.uptime}`);
console.log(`${sep}`);
console.log(' Environment Variables');
console.log('-'.repeat(48));
for (const [key, val] of Object.entries(env)) {
console.log(` ${key.padEnd(20)} : ${val}`);
}
console.log(`${sep}\n`);
}
const args = parseArgs(process.argv);
const envKeys = args.envKeys
? args.envKeys.split(',')
: ['NODE_ENV', 'HOME', 'PATH', 'SHELL'];
const sys = getSystemInfo();
const env = getEnvInfo(envKeys);
printReport(sys, env);
node syscheck.js --envKeys NODE_ENV,APP_PORT,DATABASE_URL
================================================
System Diagnostic Report
================================================
Hostname : web-server-01
Platform : linux / x64
Operating System : Linux
CPU : Intel(R) Xeon(R) CPU E5-2680 v4
CPU Number of cores : 8
Total Memory : 15.88 GB
Available memory : 6.23 GB
Memory Usage : 60.7%
Runtime : 72.5 hours
================================================
Environment Variables
------------------------------------------------
NODE_ENV : production
APP_PORT : (Not set)
DATABASE_URL : (Not set)
================================================
❓ よくある質問
os.freemem() はどのような単位で値を返しますか?process.stdin 読み取りストリームを data イベントリスナーと組み合わせて使用するか、readline モジュールが提供する行単位の読み取りインターフェースを使用できます。readline は、対話型の Q&A シナリオに適しています。process.exit() は注意して使用すべきなのでしょうか?process.exit() は、保留中のすべてのコールバック、I/O 操作、およびクリーンアップ処理をスキップしてプロセスを即座に終了させるため、データの損失やリソースの解放漏れにつながる可能性があります。イベントループが自然に終了するようにすることを優先すべきです。process.nextTick() と setImmediate() の違いは何ですか?nextTick コールバックはマイクロタスクキューにあり、現在の操作の直後に実行され、すべての I/O 操作よりも優先されます。setImmediateはマクロタスクキューにあり、I/Oイベントループフェーズ中に実行されます。なお、nextTickの方が優先度が高くなります。config({ path: 'custom/path' }) を使用してパスを指定することもできます。機密情報が漏洩しないよう、必ず .env を .gitignore に追加してください。📖 まとめ
osモジュールは、CPU、メモリ、プラットフォーム、ネットワークインターフェース、ユーザー情報など、システムレベルの情報を提供します。- process.argv parses the command-line arguments; argv[0] is the Node path, and argv[1] is the script path
process.envは環境変数を管理します。dotenvライブラリは、.envファイルから設定を読み込みます- クリーンアップ処理が省略されないよう、
process.exit()の使用には注意が必要です。 process.nextTick()はマイクロタスクであり、setImmediateおよびPromiseよりも優先されます。- クロスプラットフォーム間の違いに対処するために、os.EOL、os.sep、および path.join を使用する
📝 練習問題
- 現在のシステムのCPUコア数、総メモリ容量(GB)、空きメモリ容量(GB)、およびメモリ使用率(%)を出力するスクリプトを作成してください。
process.argvを使用して、--add、--sub、--mulの 3 つの演算をサポートする、簡単なコマンドライン電卓を実装してください。- データベースの接続情報を保存するための .env ファイルを作成し、dotenv を使用して読み込み、スクリプト内で安全に読み込む(デフォルト値を指定する)
- 現在のプラットフォームが Windows であるかどうかを確認する関数を実装してください。Windows の場合は改行文字
\r\nを使用し、そうでない場合は\nを使用してください。 - メモリ使用量を監視し、90%を超えた場合にstderrに警告メッセージを出力するスクリプトを作成してください。



