1
Help us understand the problem. What are the problem?

posted at

updated at

S3に格納されたファイルを検知し、EC2上のシェルを自動実行する

S3に格納されたファイルを検知して、EC2上のシェルを自動実行する(&SNSにて、結果をメールに送信する)

(やった手順)
1.(EC2上)シェルの作成
2.(EC2上)シェルの動作確認
3.(AWS)S3バケットの作成
4.(AWS)Lambdaの作成 & IAMの設定
5.SNSの設定(トピックの作成 & サブスクリプションの作成)
6.動作確認

(省略していること)
・EC2へのsshの接続手順(teratermなどで、接続済みの状態で記載してます)
・EC2のインスタンス名などは、知っている状態で記載しています

1.(EC2上)シェルの作成【test.sh】

(※今回は環境の都合上、「hulft」ユーザで作成しています。)
(※合わせる必要がある箇所は、※表記していきます)
image.png

(【test.sh】の中身)

#!/bin/bash
# 動作確認

# Lambdaから引数を取得
VALUE=${1}
echo "Lambdaから取得した値は【"${VALUE}"】" # Lambdaから値を取得する前提で記載

echo "実行ユーザ確認"
whoami

# ディレクトリ移動
cd /***/***/***/***/work/

echo "現在パス確認"
DIR_VALUE=$(pwd)
echo "${DIR_VALUE}"

echo "実行前確認"
ls -l
echo ""

# ファイル作成
touch ${DIR_VALUE}/${VALUE}".txt"

echo "実行後確認"
ls -l

2.(EC2上)シェルの動作確認【test.sh】

引数を渡して、「〇〇.txt」ファイルが作成されるのを確認しました
image.png

3.(AWS)S3バケットの作成

普通に作成しました。
一応リージョンは「ap-northeast-1」で統一
S3バケットの下に「lambda-fin」のサブフォルダを作成
(ここの配下に、完了ファイルを格納予定です)
image.png

4.(AWS)Lambdaの作成 & IAMの設定

こちらも普通に作成
image.png

※S3のトリガーを設定します(格納されたタイミングなので、「ObjectCreateByPut」)
image.png

※タイムアウト時間は、処理によって設定します(今回は3分)
image.png

※アクセスする実行ロールに、ポリシー
「AmazonSSMFullAccess」(SSMを用いて、Lambdaからシェル実行を行う)
「AmazonSNSFullAccess」(SNSを用いて、シェル実行後、完了メールを送信する)
を追加します
image.png
(IAM設定画面)
image.png
(※SNSの設定は、後述)

(Lambdaの中身)

import boto3
import logging
import time
import json

# ログ設定
logger = logging.getLogger()
logger.setLevel(logging.INFO)
 
ssm = boto3.client('ssm')
sns = boto3.client('sns')

# 対象インスタンスを定義
instance = ["i-***************"]

# 実行するコマンドを定義(作成したシェルのパス&引数)
# (※シェルの実行ユーザと合わせる必要があります)
cmd_to_test = "su hulft -c \"bash /**/**/**/**/work/test.sh 9999\""

# 結果通知用TOPICを定義
# ここのarnは、後述するSNSのarnを転記
ERROR_TOPIC = 'arn:aws:sns:ap-northeast-1:*********:*********'
 INFO_TOPIC = 'arn:aws:sns:ap-northeast-1:*********:*********'

def lambda_handler(event, context):
    
    # S3に格納されたファイルを確認
    input_bucket = event['Records'][0]['s3']['bucket']['name']
    input_key = event['Records'][0]['s3']['object']['key']
    print("バケット名:" +  input_bucket , " ファイル名:" + input_key)
    
    try:
        # デプロイコマンドを実行
        res = ssm.send_command(
            InstanceIds = instance,
            DocumentName = "AWS-RunShellScript",
            Comment = 'Executing test command...', 
            TimeoutSeconds = 100, 
            Parameters = {
                "commands": [
                    cmd_to_test
                ]
            }
        )
        command_id = res['Command']['CommandId'] # CommandIdを取得

        # 処理完了まで5秒待つ
        time.sleep(5)

        # ステータスを取得
        list_invocations = ssm.list_command_invocations(
            CommandId = command_id,
            Details = True
            )
        deploy_res = list_invocations['CommandInvocations'][0]['Status']

        # 実行結果が失敗していれば通知の上、処理を中断
        if (deploy_res!='Success'):
            # メール通知
            res = sns.publish(
                TopicArn = ERROR_TOPIC,
                Message = 'テスト結果:'+ deploy_res + 'のため、テスト失敗',
                Subject = '【エラー】テスト失敗'
            )
            return False
        # メール通知
        res = sns.publish(
            TopicArn = INFO_TOPIC,
            Message = 'テスト成功',
            Subject = 'テスト成功'
        )
        return True

    except Exception as e:
        logger.error(e)
        raise e

5.SNSの設定(トピックの作成 & サブスクリプションの作成)

トピックの作成
(※ここのARNを、Lambdaに記載する)
image.png
トピックに紐づくサブスクリプションの作成
image.png

6.動作確認

これでいよいよ、
「S3にファイルを格納」したタイミングでLambdaが実行

Lambda処理内にて、SSMを利用して「send_command」実行
(send_commandの中身は、「bash 〇〇.sh (引数) キック」)

Ec2上のシェルがキックされ、結果によって、SNS経由してメール受領
となります。

(0) EC2上に「〇〇.txtがないこと」を確認
image.png

(1) S3に(任意の)ファイルをアップロード
image.png

(2)CloudWatchで動いているのを確認
image.png

(3)EC2上に「〇〇.txtができたこと」を確認
image.png

(4)メール受信していることを確認
image.png

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
1
Help us understand the problem. What are the problem?