2022年5月28日土曜日

Windows Serverの設定情報を一括取得するスクリプト

先日、Linuxの設定情報を1つのテキストファイルに出力するスクリプトを作成した。

Linuxに引き続き、今回はWindows Serverの設定情報を1つのテキストファイルに出力し、一括取得するスクリプトを作ってみた。このスクリプトを使うことで、Windows Serverの設定に関しても、ネットワーク機器のように設定変更時の差分をdiffツールにて比較をできるようにする。

環境

本スクリプトの動作確認をしたOSは以下の通り。

  • OS : Windows Server 2022 または 2019
  • 実行シェル : PowerShell 5.1

Windows Server設定項目一覧

本スクリプトで取得する設定項目は以下となる。

取得設定項目 取得設定内容
ホスト名・OSバージョン情報 OSのバージョン、カーネル番号、稼働時間など
ハードウェア情報 CPUのコアやソケット数、メモリ容量、PCIデバイス一覧
OS基本設定 Get-ComputerInfoで取得できる情報取得とページングファイルのサイズ設定
ネットワーク設定 各種ネットワーク関連設定。DNSやhostsファイルの設定を含む
ディスク設定 各種ディスク情報
光学ドライブ設定 CD/DVDドライブ情報
ユーザ・グループ設定 ローカルユーザー一覧、ローカルグループ一覧
リモートデスクトップ設定 リモートデスクトップに関する設定
時刻設定 タイムゾーン設定、時刻同期 (w32tm) に関する設定
OS言語設定 使用している言語
サービス設定 サービス一覧
役割・機能 Windowsの役割・機能の一覧
更新プログラム 適用済み更新プログラムの一覧
インストールソフトウェア インストールソフトウェア一覧
PowerShellモジュール インストール済みPowerShellモジュールの一覧
イベントビューアー イベントビューアーの設定情報。セキュリティイベントログの設定情報取得の際は管理者で実行が必要
Windows Defenderファイアウォール Windows Defenderファイアウォールの設定・ルール一覧

上記は一般的なWindows Serverの設定項目となっている。追加した役割・機能に応じて、適宜情報取得コマンドを追加するといったカスタマイズが必要となる。

スクリプト

今回作成したスクリプトはGitHubに置いてあるので、そちらを参照いただきたい。

スクリプトには以下の関数を用意しており、効率よく設定値を取得できるようにしている。以下に関数の動作概要を記載する。

関数名 内容
show_title 取得対象の設定項目のタイトルを表示
get_command コマンドを実行して、その結果を取得
get_command_bat コマンドを実行して、その結果を取得(コマンドプロンプト用)
get_config 設定ファイルからコメント(#から始まる行)及び空行を削除して内容を取得

使い方

任意のディレクトリに配置したのち、PowerShellを「管理者として実行」で開き、配置ディレクトリに移動する。あとは以下の通り実行すれば情報取得が開始する。実行時間は環境にもよるが、10秒程度もあれば終了する。

PS> .\get_windows_config.ps1

なお本スクリプトは、PowerShellを「管理者として実行」せずとも、Administrators権限があればほとんどの情報取得には成功するよう作ってある。
※セキュリティイベントログの設定情報のみ取得に失敗する。

同じディレクトリ内に以下のファイル名でログが出力される。

[ホスト名]_config_[yyyyMMdd-HHmmss].log

情報取得結果のサンプル

以下に取得とした設定情報を例として記載する。
Start-Transcriptのヘッダーは省略している。

コマンドによる情報取得の場合は(command)# [実行コマンド]または(command_bat)# [実行コマンド]、設定ファイルの情報取得の場合は(config)# [ファイルのフルパス]と表示することで、どのように情報取得をしたかわかるようにしている。

################################
ホスト名・OSバージョン情報
################################

(command_bat)# cmd /C 'hostname'
WIN-K7OLL2H57TT

(command_bat)# cmd /C 'whoami.exe /user'

USER INFORMATION
----------------

User Name     SID
============================= =============================================
win-k7oll2h57tt\administrator S-1-5-21-3230081072-2687372604-3793060616-500


(command)# Get-WmiObject Win32_OperatingSystem | Select-Object Caption, OSArchitecture, Version, CodeSet, CountryCode, LastBootUpTime

Caption                                           OSArchitecture Version    CodeSet CountryCode LastBootUpTime
-------                                           -------------- -------    ------- ----------- --------------
Microsoft Windows Server 2022 Standard Evaluation 64 ビット         10.0.20348 932     81          20220516063525.500000+540

~(中略)~

################################
ディスク設定
################################

(command)# Get-Disk

Number Friendly Name       Serial Number                    HealthStatus OperationalStatus Total Size Partition Style
------ -------------       -------------                    ------------ ----------------- ---------- ---------------
0      VMware Virtual disk 6000c29703b80e9e48cca37b8d165c0b Healthy      Online                 80 GB GPT


(command)# Get-WmiObject Win32_DiskDrive | Select-Object Index, DeviceID, Model, @{N='SizeGB'; E={[Math]::Round($_.Size/1GB, 2)}}, Partitions | sort Index

Index DeviceID           Model                                SizeGB Partitions
----- --------           -----                                ------ ----------
    0 \\.\PHYSICALDRIVE0 VMware Virtual disk SCSI Disk Device     80          3


(command)# Get-WmiObject Win32_DiskPartition | Select-Object DiskIndex, Index, Name, BlockSize, Bootable, @{N='SizeGB'; E={[Math]::Round($_.Size/1GB, 2)}}, Type, Description | sort DiskIndex, Index

DiskIndex Index Name                BlockSize Bootable SizeGB Type            Description
--------- ----- ----                --------- -------- ------ ----            -----------
        0     0 ディスク #0, パーティション #0       512     True    0.1 GPT: System     GPT: システム
        0     1 ディスク #0, パーティション #1       512    False   79.3 GPT: Basic Data GPT: ベーシック データ
        0     2 ディスク #0, パーティション #2       512    False   0.58 GPT: Unknown    GPT: 不明

~(以下略)~

以上。

2022年5月22日日曜日

Linuxの設定情報を一括取得するスクリプト

ネットワーク機器などの設定値はshow runなどコマンド実行結果をテキストファイルとして残すことで、変更作業を行った前後のファイルでdiffツールによる比較を行うことができる。

OSの設定については、設定内容が多岐にわたるため、なかなかテキストファイルに残すといったことは難しく、都度コマンドを実行して情報を取得するというパターンが多い。
※Red Hat系のLinuxであれば、ログの取得ツールとしてsosreportがある。こちらは必要な設定やファイルを1つの圧縮ファイルにまとめるものとなり、設定の比較という観点では使いづらい。

そこで今回は、Red Hat系のLinuxの設定情報を1つのテキストファイルに出力し、一括取得するスクリプトを作ってみた。このスクリプトを使うことで、OSの設定に関しても、ネットワーク機器のように設定変更時の差分をdiffツールにて比較できるようにする。

環境

本スクリプトの動作確認をしたOSは以下の通り。Red Hat系のLinuxディストリビューションであるCentOS、AlmaLinux、Rocky Linuxでも動作するはずだ。

  • OS : Red Hat Enterprise Linux 8 または 7
  • 実行シェル : Bash

Linux設定項目一覧

本スクリプトで取得する設定項目は以下となる。

取得設定項目 取得設定内容
ホスト名・OSバージョン情報 OSのバージョン、カーネル番号、稼働時間など
ハードウェア情報 CPUのコアやソケット数、メモリ容量、PCIデバイス一覧
インストール設定 インストール時の設定 (/root/anaconda-ks.cfg)
OS基本設定 grubkdump、SELinuxの設定
カーネルパラメータ カーネルパラメータとシステムリソース制限(ulimit)設定
ネットワーク設定 各種ネットワーク関連設定。DNSやhostsファイルの設定を含む
ディスク設定 各種ディスク情報、LVM関連設定、fstabの設定
ユーザ・グループ設定 ユーザー一覧、グループ一覧、sudoの設定
sshd設定 sshdに関する設定
時刻設定 時刻同期 (Chrony) に関する設定
OS言語設定 使用している言語とインストール済み言語
サービス設定 systemdのサービス一覧
パッケージ設定 yumdnfの設定、インストールされているrpm一覧
rsyslog設定 rsyslogに関する設定
logrotate設定 logrotateに関する設定
Postfix設定 Postfixに関する設定
Dovecot設定 Dovecotに関する設定
Squid設定 Squidに関する設定
Unbound設定 Unboundに関する設定
Apache (httpd) 設定 Apache (httpd) に関する設定
Zabbix Agent設定 Zabbix Agentに関する設定

PostfixやDovecotなどのソフトウェアについては、パッケージのインストール有無によって設定値の取得判断をする。これ以外にもインストールしているソフトウェアがある場合は、適宜追加するといったカスタマイズが必要となる。

スクリプト

今回作成したスクリプトはGitHubに置いてあるので、そちらを参照いただきたい。

スクリプトには以下の関数を用意しており、効率よく設定値を取得できるようにしている。以下に関数の動作概要を記載する。

関数名 内容
show_title 取得対象の設定項目のタイトルを表示
get_command コマンドを実行して、その結果を取得
get_config 設定ファイルからコメント(#から始まる行)及び空行を削除して内容を取得
get_config_files ディレクトリを指定し、その中のファイル及びシンボリックリンクの内容を取得
check_install_package パッケージのインストール状況を確認

使い方

任意のディレクトリに配置しroot権限にて以下の通り実行する。実行時間は環境にもよるが、10秒程度もあれば終了する。

# chmod +x get_linux_config.sh
# ./get_linux_config.sh

同じディレクトリ内に以下のファイル名でログが出力される。

[ホスト名]_config_[yyyyMMdd-HHmmss].log

情報取得結果のサンプル

以下に取得とした設定情報を例として記載する。コマンドによる情報取得の場合は(command)# [実行コマンド]、設定ファイルの情報取得の場合は(config)# [ファイルのフルパス]と表示することで、どのように情報取得をしたかわかるようにしている。

################################
情報取得開始 2022/05/22 11:55:25
################################

################################
ホスト名・OSバージョン情報
################################

(command)# uname -n
rhel8

(command)# uname -a
Linux rhel8 4.18.0-240.el8.x86_64 #1 SMP Wed Sep 23 05:13:10 EDT 2020 x86_64 x86_64 x86_64 GNU/Linux

(config)# /etc/redhat-release
Red Hat Enterprise Linux release 8.3 (Ootpa)

(command)# uptime
 11:55:25 up 63 days, 20:09,  1 user,  load average: 0.00, 0.00, 0.00

~(中略)~

################################
ディスク設定
################################

(command)# ls -l /dev/?da*
brw-rw---- 1 root disk 8, 0  5月 22 10:51 /dev/sda
brw-rw---- 1 root disk 8, 1  5月 22 10:51 /dev/sda1
brw-rw---- 1 root disk 8, 2  5月 22 10:51 /dev/sda2
brw-rw---- 1 root disk 8, 3  5月 22 10:51 /dev/sda3

(command)# ls -l /dev/mapper/*
crw------- 1 root root 10, 236  3月 19 15:46 /dev/mapper/control
lrwxrwxrwx 1 root root       7  3月 19 15:46 /dev/mapper/rhel-root -> ../dm-0
lrwxrwxrwx 1 root root       7  3月 19 15:46 /dev/mapper/rhel-swap -> ../dm-1

(command)# fdisk -l
ディスク /dev/sda: 16 GiB, 17179869184 バイト, 33554432 セクタ
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
ディスクラベルのタイプ: gpt
ディスク識別子: A18174EE-DDA9-4DD9-8999-D1225E510848

デバイス   開始位置 終了位置   セクタ サイズ タイプ
/dev/sda1      2048  1230847  1228800   600M EFI システム
/dev/sda2   1230848  3327999  2097152     1G Linux ファイルシステム
/dev/sda3   3328000 33552383 30224384  14.4G Linux LVM

~(以下略)~

以上。

2022年5月14日土曜日

サービス監視スクリプト (Windows版)

サーバーのプロセス監視 (Windowsの場合はサービス監視) は、監視ソフトウェア(ZabbixやJP1など)を使えば当たり前のように実現できる。ただし、環境やライセンスの関係でエージェントの導入ができない場合がある。

そのような場合でも、スクリプトを使ってプロセス監視 (サービス監視) を行うことは可能となる。

今回、Windowsのサービス監視を行うスクリプトを作ってみたので、その内容を記載する。

なお、Linuxのプロセス監視のスクリプトについては、以下記事を参照いただきたい。

実現方法

本スクリプトの設計概要を図示する。

このスクリプトは、確認対象のサービスを設定ファイル(check-service.conf)に記載しておき、Get-ServiceコマンドレットにてサービスがRunningステータスであるかどうかを確認する。

サービスダウンを検知した際は、Write-EventLogコマンドレットでApplicationイベントログにエラーメッセージを出力する。エラーメッセージ出力タイミングは、サービスダウンの初回発生時のみとし、それ以外は情報メッセージとして出力する。

以下に、本スクリプトで発生するメッセージを記載する。

サービス状態 メッセージ
正常時 [INFO] Service XXX up
正常状態継続時 [INFO] Service XXX still up
ダウン時 [ERROR] Service XXX down
ダウン状態継続時 [INFO] Service XXX still down

この処理をタスクスケジューラーで1分間隔で実行するよう登録し、定期的なサービス監視を実現する。

スクリプト実行手順

1. スクリプト実行前にイベントソースを登録

Windowsイベントログにイベントを出力する際に、事前にイベントソースの登録が必要となる。事前に管理者権限でPowerShellのプロンプトを開き、以下コマンドを実行しておくこと。

PS C:\> New-EventLog -LogName Application -Source "Service Check Script"

なお、イベントソースの登録削除は、以下のコマンドとなる。

PS C:\> Remove-EventLog -Source "Service Check Script"

2. スクリプト配置

以下にスクリプトのコードを記載する。GitHubにも配置してある。

スクリプトファイル:check-service.ps1

################
# Scripts name : check-service.ps1
# Usage        : ./check-service.ps1
#                同一ディレクトリにcheck-service.confを配置し、タスクスケジューラーで定期実行する。
#                事前にAdmin権限で以下コマンドをを実行すること。
#                New-EventLog -LogName Application -Source "Service Check Script"
# Description  : Windowsサービスチェックスクリプト
# Create       : 2022/05/02 tech-mmmm (https://tech-mmmm.blogspot.com/)
# Modify       : 
################

$currentdir = Split-Path -Parent $MyInvocation.MyCommand.Path
$conffile = $currentdir + "\check-service.conf"    # 設定ファイル
$tmpfile = $currentdir + "\check-service.tmp"      # サービス情報保存用一時ファイル
$event_source = "Service Check Script"             # スクリプトソース名

# すでにDownしているサービス情報を取得
if ( Test-Path -Path $tmpfile ){
    $down_service = Get-Content $tmpfile
}
Write-Output $null | Out-File $tmpfile

# 設定ファイル読み込み
foreach ($line in (Get-Content $conffile)) {   
    # コメント行と空行を処理しない
    if ( $line -notmatch "^ *#|^$" ){
        # 現在のサービス数を取得
        $count = (Get-Service -Name $line | Where-Object { $_.Status -eq "Running" }).count
        
        # サービス数チェック
        if ( $count -lt 1 ){
            # Down時の処理
            # Downしているサービスか確認
            if ( $down_service -eq $line ){
                # すでにDown
                $message = "Service """ + $line + """ still down"
                $event_type = "Information"
            }else{
                # 初回Down
                $message = "Service """ + $line + """ down"
                $event_type = "Error"
            }
            
            # イベントログに出力
            Write-Output $message
            Write-EventLog -LogName Application -EntryType $event_type -Source $event_source -EventId 100 -Message $message

            # Donwしているサービス情報を出力
            Write-Output $line | Out-File -Append $tmpfile
        }else{
            # Up時の処理
            # Downしていたサービスか確認
            if ( $down_service -eq $line ){
                # Downだった
                $message = "Service """ + $line + """ up"
                $event_type = "Information"                
            }else{
                # すでにUp
                $message = "Service """ + $line + """ still up"
                $event_type = "Information"
            }

            # イベントログに出力
            Write-Output $message
            Write-EventLog -LogName Application -EntryType $event_type -Source $event_source -EventId 100 -Message $message
        }
    }
}

exit 0

設定ファイル例:check-service.conf

# Service mame
Netlogon
W32Time
VMTools

3. タスクスケジューラーへの登録

タスクスケジューラーにて本スクリプトを1分間隔で実行するように設定する。こちらの方法については、以下別記事を参照いただきたい。

4. 監視テスト

実際にサービスを停止させて動作確認をしてみよう。W32Timeを停止させてサービス停止を検知することを確認してみる。

PS C:\> Stop-Service -Name W32Time
PS C:\> Get-EventLog -LogName Application -Source "Service Check Script"

   Index Time          EntryType   Source                 InstanceID Message
   ----- ----          ---------   ------                 ---------- -------
   12652 5 03 06:27    Information Service Check Script          100 Service "VMTools" still up
   12651 5 03 06:27    Error       Service Check Script          100 Service "W32Time" down  ★停止を検知
   12650 5 03 06:27    Information Service Check Script          100 Service "Netlogon" still up
~(以下略)~

次に、復旧時の動作を確認する。

PS C:\> Start-Service -Name W32Time
PS C:\> Get-EventLog -LogName Application -Source "Service Check Script"

   Index Time          EntryType   Source                 InstanceID Message
   ----- ----          ---------   ------                 ---------- -------
   12655 5 03 06:29    Information Service Check Script          100 Service "VMTools" still up
   12654 5 03 06:29    Information Service Check Script          100 Service "W32Time" up ★復旧
   12653 5 03 06:29    Information Service Check Script          100 Service "Netlogon" still up
~(以下略)~

以上。

更新履歴

  • 2017/12/18 新規作成
  • 2022/05/14 全体的にスクリプトの構成を見直し
2022年5月7日土曜日

プロセス監視スクリプト (Linux版)

サーバーのプロセス監視は、監視ソフトウェア(ZabbixやJP1など)を使えば当たり前のように実現できる。ただし、環境やライセンスの関係でエージェントの導入ができない場合がある。

そのような場合でも、スクリプトを使ってプロセス監視を行うことは可能となる。ログに出力さえできれば、Linuxの場合はrsyslogなどでログを別のサーバに転送でき、そのサーバで監視させるといったことも可能である。

今回は、Linuxのプロセス監視を行うスクリプトを作ってみたので、その内容を記載する。

実現方法

本スクリプトの設計概要を図示する。

このスクリプトは、設定ファイル(check-process.conf)に監視対象のプロセス及び起動プロセス数を記載しておき、psコマンドにて監視対象の起動プロセス数を確認する。

プロセスダウンを検知した際は、loggerコマンドで/var/log/messagesにエラーメッセージを出力する。エラーメッセージ出力タイミングは、プロセスダウンの初回発生時のみとし、それ以外は情報メッセージとして出力する。

以下に、本スクリプトで発生するメッセージを記載する。

プロセス状態 メッセージ
正常時 [INFO] Process XXX up
正常状態継続時 [INFO] Process XXX still up
ダウン時 [ERROR] Process XXX down
ダウン状態継続時 [INFO] Process XXX still down

この処理をcronで1分間隔で実行するよう登録し、定期的なプロセス監視を実現する。

スクリプト実行手順

1. スクリプト配置

以下にスクリプトのコードを記載する。GitHubにも配置してある。

スクリプト本体:check-process.sh

#!/bin/bash
################
# Scripts name : check-process.sh
# Usage        : ./check-process.sh
#                同一ディレクトリにcheck-process.confを配置し、cronで定期実行する。
# Description  : Linuxプロセスチェックスクリプト
# Create       : 2017/12/14 tech-mmmm (https://tech-mmmm.blogspot.com/)
# Modify       : 2022/05/01 tech-mmmm (https://tech-mmmm.blogspot.com/)
################

currentdir="$(dirname "$0")"
conffile="${currentdir}/check-process.conf"    # 設定ファイル
tmpfile="${currentdir}/check-process.tmp"      # プロセス情報保存用一時ファイル

# すでにDownしているプロセス情報を取得
if [ -f "${tmpfile}" ]; then
    down_process=$(paste -d "|" -s "${tmpfile}")
fi
echo -n > "${tmpfile}"

# 設定ファイル読み込み
while read line || [ -n "${line}" ]; do
    # 空白区切りで分割
    process_name=$(echo "${line}" | awk '{print $1}')
    process_num=$(echo "${line}" | awk '{print $2}')
    
    # コメント行と空行を処理しない
    if [ "$(echo "${process_name}" | grep -c -v -e '^ *#' -e '^$')" -gt 0 ]; then      
        # 現在のプロセス数を取得
        count=$(ps ahxo args | grep "${process_name}" | grep -c -v -e "^grep")
        
        # プロセス数チェック
        if [ "${count}" -lt "${process_num}" ]; then
            # Down時の処理
            # すでにDownしているプロセスか確認
            if [ -n "${down_process}" ] && [ "$(echo ${process_name} | grep -c -E ${down_process})" -gt 0 ]; then
                # すでにDown
                message="[INFO] Process \"${process_name}\" still down"
            else
                # 初回Down
                message="[ERROR] Process \"${process_name}\" down"
            fi
            # ログへ出力
            echo "${message}"
            logger "${message}"
            
            # Donwしているプロセス情報を出力
            echo "${process_name}" >> "${tmpfile}"
        else
            # Up時の処理
            # Downしていたプロセスか確認
            if [ -n "${down_process}" ] && [ "$(echo ${process_name} | grep -c -E ${down_process})" -gt 0 ]; then
                # Downだった
                message="[INFO] Process \"${process_name}\" up"
            else
                # すでにUp
                message="[INFO] Process \"${process_name}\" still up"
            fi
            # ログへ出力
            echo "${message}"
            logger "${message}"
        fi
    fi
done < "${conffile}"

exit 0

設定ファイル例:check-process.conf

# Process mame Number of process
/usr/sbin/chronyd 1
/usr/sbin/httpd 5

2. cronへの登録

スクリプトを/root/scriptディレクトリに配置した場合を例として、1分間隔で監視させるようcronを以下のように設定する。

# crontab -e
*/1 * * * * /root/script/check-process.sh

3. 監視テスト

実際にプロセスを停止させて動作確認をしてみよう。httpdを停止させてプロセス停止を検知することを確認してみる。

# systemctl stop httpd
# tail -10 /var/log/messages | grep -E "INFO|ERROR"
May  1 15:12:07 t1192rhel root[76941]: [INFO] Process "/usr/sbin/chronyd" still up
May  1 15:12:07 t1192rhel root[76955]: [ERROR] Process "/usr/sbin/httpd" down ★停止を検知

次に、復旧時の動作を確認する。

# systemctl start httpd
# tail -10 /var/log/messages | grep -E "INFO|ERROR"
May  1 15:12:07 t1192rhel root[76941]: [INFO] Process "/usr/sbin/chronyd" still up
May  1 15:12:07 t1192rhel root[76955]: [ERROR] Process "/usr/sbin/httpd" down
May  1 15:13:46 t1192rhel root[77291]: [INFO] Process "/usr/sbin/chronyd" still up
May  1 15:13:46 t1192rhel root[77308]: [INFO] Process "/usr/sbin/httpd" up ★復旧

以上。

更新履歴

  • 2017/12/16 新規作成
  • 2022/05/07 全体的にスクリプトの構成を見直し

人気の投稿