お久しぶりです。
今回は、半年ほど前に業務で担当した PowerShell でのスクリプト作成に苦戦したので、記事として残したいと思います。
スクリプト作成の経緯
本来はスクリプト作成担当はチーム内のメンバーでしたが、体調不良で案件から外れてしまい急遽、本番環境で使用予定の 「CloudWatch LogsのログをS3にエクスポートするスクリプト」 の作成担当になりました。スクリプトの作成経験がなかったので、当時は自分でもどうなっていくのか分からない状況でした。
スクリプト条件
作成したスクリプトの条件です。
※この他にも細かい条件がいくつかありました。
- Windows Server 2019 で動かす
- AWS CLI "create-export-task" コマンドを使用
- 毎月特定の日時に、前月1ヵ月分のログが保存されているロググループ約30個分のログを特定のS3へエクスポート
- スクリプト開始、終了をイベントログに出力
- スクリプト実行時に、"create-export-task" コマンドで作成する、エクスポートタスクのステタースをイベントログに出力
- エクスポートタスクのステータスが "RUNNING"の場合は1分待機し、再度タスクのステータスを取得
スクリプト詳細
以下が、作成したスクリプトになります。
# 第1引数 ロググループ名
# 第2引数 S3バケット名
function CheckArguments {
param(
[Parameter(Mandatory=$true)][string[]]$Arguments
)
if ($Arguments.Count -eq 2) {
return $true
}
else {
return $false
}
}
# スクリプト実行時に引数を変数に格納する例
$log_group = $args[0]
$s3 = $args[1]
# 引数が無い場合終了
if([string]::IsNullorEmpty($args[0])) {
Write-EventLog -LogName Application -Source "CloudLogExptScriptPS" -EntryType Warning -EventId 300 -Message "<ps1.ファイル名>:<$log_group>: <$s3>:IWARN: Argument is incorrect."
Exit
}
# スクリプト開始メッセージ イベントログ出力
Write-EventLog -LogName Application -Source "CloudLogExptScriptPS" -EntryType Information -EventId 300 -Message "<ps1.ファイル名>:<$log_group>:<$s3>:INFO: Start."
# 引数の数をチェックする
$result = CheckArguments -Arguments $args
if ($result -eq $false) {
# 引数不正イベントログに出力
Write-EventLog -LogName Application -Source "CloudLogExptScriptPS" -EntryType Warning -EventId 300 -Message "<ps1.ファイル名>: <$log_group>: <$s3>:IWARN: Argument is incorrect."
Exit
}
# 関数 エクスポート対象開始日付取得【CurrentTimeToStartUnixTime()】
function CurrentTimeToStartUnixTime() {
# 現在日時の DateTime を取得
$now = Get-Date "0:00:00"
# 前月の1日を取得
$firstday = (Get-Date $now -Day 1).AddMonths(-1)
# UNIX時間に変換
(($firstday) - (Get-Date("1970/1/1 0:0:0 GMT"))).TotalSeconds
}
# CurrentTimeToStartUnixTime
$firstday_unix = CurrentTimeToStartUnixTime
# 変数に格納された関数名の関数を実行
$from = $firstday_unix
# 関数 エクスポート対象終了日付取得【CurrentTimeToEndtUnixTime()】
function CurrentTimeToEndtUnixTime() {
# 現在日時の DateTime を取得
$now = Get-Date "23:59:59"
# 前月の最終日
$lastday = (Get-Date $now -Day 1).AddDays(-1)
# UNIX時間に変換
(($lastday) - (Get-Date("1970/1/1 0:0:0 GMT"))).TotalSeconds
}
# CurrentTimeToEndtUnixTime
$lastday_unix = CurrentTimeToEndtUnixTime
# 変数に格納された関数名の関数を実行
$to = $lastday_unix
# 現在日時の DateTime を取得
$now = Get-Date
# 前月を取得
$prevMonth = $now.AddMonths(-1)
# yyyymm形式の文字列に変換して出力
$taskname = $prevMonth.ToString("yyyyMM")
# 末尾000追加
$000 = "000"
# エクスポートタスク作成
$taskIDinfoJson = aws logs create-export-task --profile exportlogs --task-name "$taskname" --log-group-name "$log_group" --from $from$000 --to $to$000 --destination "$s3" --destination-prefix "$log_group/$taskname"
# エクスポートタスク作成チェック
if($taskIDinfoJson -eq "True"){
else{
Write-EventLog -LogName Application -Source "CloudLogExptScriptPS" -EntryType Error -EventId 300 -Message "<ps1.ファイル名>:<$log_group>: <$s3>:IERROR: Task startup confirmation error"
break
}
}
$taskIDinfo = $taskIDinfoJson | ConvertFrom-json
$script:taskID = $taskIDInfo.taskId
# タスクID表示
# Write-Host $script:taskID
$exportStatusInfoJson = aws logs --profile exportlogs describe-export-tasks --task-id "$script:taskID"
$exportStatusInfo = $exportStatusInfoJson | ConvertFrom-Json
$script:exportStatus = $exportStatusInfo.exportTasks.status.code
# タスクのステータスが "COMPLETED" の場合は、"COMPLETED" とタスクのIDを出力し、スクリプトを終了
# タスクのステータスが "RUNNING"の場合は、1分待機し、再度タスクのステータスを取得
# タスクのステータスが "COMPLETED"または "RUNNING" 以外の場合は、エラーメッセージと第1引数、第2引数を出力してスクリプトを終了
for (;;) {
# タスクの状態を取得
$exportStatusInfoJson = aws logs --profile exportlogs describe-export-tasks --task-id $script:taskID
$exportStatusInfo = $exportStatusInfoJson | ConvertFrom-Json
$script:exportStatus = $exportStatusInfo.exportTasks.status.code
# Write-Host $script:exportStatus
if ($script:exportStatus -eq "COMPLETED") {
$Result = $true
# スクリプト正常終了
Write-EventLog -LogName Application -Source "CloudLogExptScriptPS" -EntryType Information -EventId 300 -Message "<ps1.ファイル名>:<$log_group>:<$s3>:INFO: Normal end."
# タスクが完了している場合の処理
break
}
elseif($script:exportStatus -eq "RUNNING") {
$Result = $true
# タスクが実行中の場合の処理
Start-Sleep -Seconds 60
}
else {
$Result = $false
# タスクがキャンセル、失敗、保留中の場合の処理
Write-EventLog -LogName Application -Source "CloudLogExptScriptPS" -EntryType Warning -EventId 300 -Message "<ps1.ファイル名>:<$log_group>: <$s3>:IERROR: Task Status Check Error STATUS = $script:exportStatus"
break
}
$script:exportStatus = 0
continue
}
まとめ
スクリプトが正常に動作するには
・上記で紹介したスクリプト約30個を実行するための別のスクリプト作成
・毎月特定の日時に実行するためのタスクスケジューラの設定
・イベントログ出力のためのソース作成コマンド実施
など他の作業もありましたが、今回は省かせていただきました。
初めてスクリプト作成する身としては、条件も多く大変でしたが試行錯誤してなんとか作成できました。
自身のために書きましたが、誰かの参考になればいいなと思います。