Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
17
Help us understand the problem. What is going on with this article?
@sayama0402

LambdaでEC2内のシェルスクリプトを実行

More than 1 year has passed since last update.

はじめに

本記事の対象となる読者

特定のトリガーでLambdaを起動して、EC2内のシェルスクリプトを実行したい

システム概要

上記のやりたかったことを実現するために使用したサービスは以下です。

  • AWS Lambda(以後Lambda)
  • AWS System Manager(以後SSM)
  • AWS Elastic Computer Cloud(以後EC2)

書かないこと

  • EC2インスタンスの構築方法

EC2

Amazon Linux2を使用して、無料利用枠でインスタンスを用意します。

EC2インスタンスを作成

EC2インスタンスを作成する前に以下のポリシーをアタッチしたIAMロールを作成しておきます。仮に名前はAWSServiceSSMRoleとしておきます。

  • AmazonEC2RoleforSSM
  • AmazonSSMFullAccess

上記で作成したロールをインスタンスに割り当てインスタンスを作成します。

ssm-agentのインストールは必要ありません。

インスタンス内にbashスクリプトを作成

ssh接続をして以下を実行していきます。

# 自身で設定した情報を使ってSSH接続
$ ssh ec2-user@host -i ~~.pem

# 現在地の確認
$ pwd
# 結果:/home/ec2-user

# test.txtを作成
$ touch test.txt

# 実行するshファイルを作成
$ vi test.sh

vimでtest.shを開いたら以下を入力します。

#!/bin/bash

echo hoge >> test.txt

入力したら、保存します。

$ sh test.sh

と実行するとtest.txthogeという文字列が書き込まれているかと思います。

Lambda

今回はAPI Gatewayを使用して、そのエンドポイントにPOSTがあったらLambdaを実行するように作成します。

serverless frameworkを使用して、lambdaを作成します。

$ sls create -t aws-nodejs -p myfunc

$ cd myfunc

上記を実行すると、 handler.jsserverless.yml が作成されます。

serverless.yml

API Gatewayを使用するので、eventsを設定します。

service: myfunc
provider:
  name: aws
  runtime: nodejs12.x

functions:
  hello:
    handler: handler.hello
    events:
    - http:
        path: hoge
        method: post
        integration: lambda

handler.js

AWS-SDK SSMクラスで用意されているsendCommandメソッドを使用します。
詳しくはこちらを参照してください。

sendCommandはSSMにあらかじめ登録されているドキュメントのコマンドを実行します
今回はデフォルトで用意されているAWS-RunShellScriptドキュメントを使用します。
AWS-RunShellScriptはただEC2のシェルスクリプトを実行するだけですが、もちろんSSMに自分でドキュメントを作成してそれを実行することも可能です。

lambdaではaws-sdkは標準でインストールされていますので、npm installなどでインストールする必要はありません。

'use strict'

const AWS = require('aws-sdk')
const SSM = new AWS.SSM({region: 'ap-northeast-1'})
const REMOTE_WORKING_DIR = '/home/ec2-user'

module.exports.main = async event => {
  try {
    // 実行したいコマンド
    let command = 'sh exec.sh'

    let params = {
      DocumentName: 'AWS-RunShellScript',
      InstanceIds: ['作成したEC2のインスタンスID'],
      Parameters: {
        commands: [command], // 配列で指定するので複数実行も出来る
        workingDirectory: [REMOTE_WORKING_DIR] // どの階層で実行するかを指定
      },
      // SSMの実行結果をCloudWatchにロギング
      CloudWatchOutputConfig: {
        CloudWatchLogGroupName: 'SSMLogs',
        CloudWatchOutputEnabled: true
      },
      // タイムアウト設定
      TimeoutSeconds: 3600 // 1 hour
    }

    SSM.sendCommand(params, function(err, data){
      if(err){
        console.log(err, err.stack)
      } else {
        console.log(data)
      }
    })
  } catch(e){
    console.log(e);
  }
}

上記を保存後エンドポイントにPOSTして実行します。

$ curl -X POST "serverlessで作成されたエンドポイント" -d "{}"

以上となります。

17
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
sayama0402
Javascript(Riot.js / Vue / React / Nodejs) / PHP(Wordpress, cakePHP, Laravel) / Ruby(Ruby on Rails) / Python(Django) / SQL / Linux / Swift / Docker / AWS / Serverless

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
17
Help us understand the problem. What is going on with this article?