以下のような状況を想定して、自動化の練習
想定タスク
AWS上にあるWindowサーバで毎日Powershellでログを出力するジョブが動いていて、
以下を手動で確認・報告・記録している。
1.ログが出力されているか
2.ログにエラーが含まれていないか
3.チャットで報告
4.Excelにログの出力時間を記入
自分が考えたシナリオ
1.ログが出力されているか、またそのログにエラーが含まれていないか確認→その結果をS3に転送する
2.lambdaでS3にログが転送されていることを確認し、その結果をチャットで連携+Excelに出力する
構成
テストなんでめちゃシンプル
(構成図雑すぎたので消しました...)
サーバーの構築
・パブリックサブネットにwindowsサーバ1台
(プライベートサブネットに置くとopensshserver有効化したり、タイムゾーン設定したり、AWSCLI設定するのだるかったのでパブリックにしました。)
・opensshserverの有効化
・AWSCLIのインストールとIAMの設定
※ちょいハマり
sshした時AWSCLIのパスが通ってなくて実行できなかった。環境変数PATHに追加する
slackの設定
API公開しているチャットツールだったらなんでもいい。
powershell
・ログの存在確認
・ログにエラーが含まれていないか確認しファイルに出力
・ファイルをS3に転送
Check_log.ps1
# 監視対象のエラーパターンリスト
$errorPatterns = @("error", "failure", "failed")
# 監視対象のファイルリスト
$watchFiles = @("logfile1.log", "logfile2.log", "logfile3.log")
# 監視対象のディレクトリ
$watchDir = "C:\path\to\your\log\directory"
# 現在の日時を取得
$currentTime = Get-Date -Format "yyyyMMddHH"
# 出力ファイルのパス
$outputFilePath = "C:\path\to\output\directory\$env:COMPUTERNAME`_$currentTime.txt"
# S3のバケット名とパス
$s3Bucket = "your-bucket-name"
$s3Path = "your/path"
# 出力ファイル初期化とホスト名の追加
$hostnameLine = "hostname: $env:COMPUTERNAME"
$hostnameLine | Out-File -FilePath $outputFilePath
# 各ファイルをチェック
foreach ($file in $watchFiles) {
$fullPath = Join-Path -Path $watchDir -ChildPath $file
if (Test-Path $fullPath) {
$modificationTime = (Get-Item $fullPath).LastWriteTime
$errorLines = $errorPatterns | ForEach-Object { Select-String -Path $fullPath -Pattern $_ -AllMatches } | Where-Object { $_ }
$status = if ($errorLines) { "NG" } else { "OK" }
# 出力用の文字列を作成
$output = "$file`t$modificationTime`t$status`n"
# ログをファイルに追加
Add-Content -Path $outputFilePath -Value $output
} else {
Add-Content -Path $outputFilePath -Value "File not found: $fullPath`n"
}
}
# S3にファイルを転送 (AWS CLIを使用)
$finalS3Path = "$s3Path/$($env:COMPUTERNAME)_$currentTime.txt"
& aws s3 cp $outputFilePath s3://$s3Bucket/$finalS3Path
# S3への転送が成功した場合、ローカルのファイルを削除
if ($?) {
Remove-Item -Path $outputFilePath
}
Check_log.ps1をスケジューラーに登録
Linuxで言うところのcronだよね?
windowsよくわからないからAIに聞きました。
ステップ 1: タスクスケジューラーを開く
スタートメニューから「タスクスケジューラー」を検索し、開きます。
「アクション」メニューから「タスクの作成」を選択します。
ステップ 2: タスクの作成
「全般」タブで、タスクに名前と説明を付けます。
「最上位の特権で実行する」をチェックし、必要に応じて「ユーザがログオンしているかどうかにかかわらず実行する」を選択します。
「設定」タブで、OS のバージョンに合わせた設定を選びます。
ステップ 3: トリガーの設定
「トリガー」タブを開き、「新規」をクリックします。
トリガーの条件を設定します。例えば、毎日特定の時間に実行する、システム起動時に実行するなど、様々な設定が可能です。
設定が完了したら「OK」をクリックして保存します。
ステップ 4: アクションの設定
「アクション」タブを開き、「新規」をクリックします。
「プログラムの開始」を選択します。
「プログラム/スクリプト」欄に powershell.exe を入力します。
「引数の追加」欄に -File "スクリプトのパス" を入力します。
「開始時」欄にスクリプトが存在するディレクトリを入力します。
ステップ 5: 条件と設定の調整
「条件」タブと「設定」タブで、タスクの実行条件や追加設定を調整します。例えば、ネットワーク接続が必要な場合、特定のネットワークが利用可能な時にのみ実行するよう設定できます。
ステップ 6: タスクの保存と実行
全ての設定が完了したら、「OK」をクリックしてタスクを保存します。
タスクスケジューラーのライブラリに新しく作成したタスクが表示されることを確認し、必要に応じて「右クリック > 実行」で手動で実行してテストします。
S3の作成
省略
lambdaの作成
Lambda 関数の作成:
AWS マネジメントコンソールにログインし、Lambda を選択して「関数の作成」をクリックします。
「新しい関数を作成」を選び、関数名を入力し、ランタイムとしてPythonを選択します。
適切なIAMロールを設定します。このロールにはS3へのアクセス権限、Slackへのポスト権限などが必要です。
IAMロールの権限設定:
Lambda関数用のIAMロールに、S3からファイルを読み込むための権限とSlack APIを使用するためのHTTPS接続権限を追加します。
環境変数の設定:
SlackのWebhook URLやS3のバケット名など、スクリプト内で使用する変数をLambdaの環境変数として設定します。
Lambda 関数の実装
Excelの処理はpandasが必要で、ライブラリ作成しないといけないみたいなんで断念しました。
import os
import json
import boto3
import datetime
import urllib.request
from zoneinfo import ZoneInfo # Python 3.9 以上が必要
# ホスト名と和名の対応辞書
host_names = {
"xxxxxxxx_xxxx": "テストサーバ1"
}
def lambda_handler(event, context):
s3 = boto3.client('s3')
bucket_name = os.environ['S3_BUCKET_NAME'] # 環境変数からバケット名を取得
prefix = os.environ.get('S3_PREFIX', 'log/') # 環境変数からプレフィックスを取得、デフォルトは 'log/'
# 日本のタイムゾーンで現在の日付を取得
tokyo_zone = ZoneInfo("Asia/Tokyo")
today = datetime.datetime.now(tokyo_zone).strftime('%Y%m%d')
# S3バケットからファイルをすべて取得
response = s3.list_objects_v2(Bucket=bucket_name, Prefix=prefix)
files_to_process = []
for obj in response.get('Contents', []):
filename = obj['Key']
# ファイル名から日付部分を切り出す。フォーマットは "xxxxxxxx_xxxx_yyyymmddhh.txt"
file_date = filename.split('_')[-1][:8] # 日付部分のみ抽出
if file_date == today:
files_to_process.append(filename)
for file_key in files_to_process:
# S3からファイルをダウンロード
file_obj = s3.get_object(Bucket=bucket_name, Key=file_key)
file_content = file_obj['Body'].read().decode('utf-8')
# ファイル名からプレフィックスと余分なスラッシュを取り除いてホスト名部分を抽出
host_name_key = file_key.replace(prefix, "").split('_')[0].lstrip('/')
# Slackメッセージの構築
message = "##" + host_names.get(host_name_key, "Unknown Host") + "\n" + file_content
# Slackに投稿
slack_url = os.environ['SLACK_WEBHOOK_URL'] # 環境変数からSlack webhook URLを取得
headers = {'Content-type': 'application/json'}
payload = {'text': message}
data = json.dumps(payload).encode('utf-8')
request = urllib.request.Request(slack_url, data=data, headers=headers, method='POST')
with urllib.request.urlopen(request) as response:
response_body = response.read().decode('utf-8')
# 処理結果のログ
print(f'Processed {len(files_to_process)} files.')
return {
'statusCode': 200,
'body': json.dumps('Process completed successfully')
}
なんとか成功、、、、、w