ChatGPTにシェルスクリプトをLambdaで動くPythonに書き換えてもらってAmazon LinuxのEOLにサクッと対応した話

これは TOWN Advent Calendar 2023 のエントリーです。

https://adventar.org/calendars/9382

TOWNでクロジカスケジュール管理のプロダクトマネージャーをしている岩崎と申します。

Amazon Linux のEOL

Amazon Linux がいよいよEOLを迎えます。

https://aws.amazon.com/jp/blogs/news/update-on-amazon-linux-ami-end-of-life/

メンテナンスサポート 2020 年 12 月 31 日を過ぎると Amazon Linux AMI には新たにメンテナンスサポート期間が設定されます (2023 年 12 月 31 日まで継続)。

Amazon Linux AMI のサポート期間終了に関する更新情報

SaaSサービスの運用において、サービス本体の構成はコードで管理されているものの、監視や集計などの運用バッチ処理はとりあえず常時稼働しているインスタンス上でシェルスクリプトを実行する、なんてケースもあるかと思います。初期に構築されたこれらのインスタンスは、内部でどのプログラムが動いているのか分からないため、Amazon Linux 2への移行が難しかったりもします。

しかしながら、2023年12月31日にAmazon Linux AMIのメンテナンスサポート期限が終了するため、Amazon Linux 2への移行をしないといけなくなりました。

構成管理されていないサーバーを移行する場合、考えなければならないこととして以下のようなことが発生します。

  • topコマンドやpsコマンドで稼働中のプロセスを確認する
  • デーモン化されているサービスを確認する
  • cronで定期実行されているプログラムを確認する

常時稼働中のプロセスやデーモン化しているサービスはそのまま移行する一方で、cronで実行されているプログラムは移行のタイミングで別の手段に切り替えることで、構成管理がしやすくなります。

cronの移行

cronで闇のシェルスクリプトが動いている、みたいな場合、複数台構成にした冗長化を考えると、複数のスクリプトが同時に動くのは避けたいところです。特に、これらのスクリプトが同じリソースやデータに同時アクセスすると、競合や予測できない事態が起きることがあります。

そもそもスクリプトを動かすのにEC2インスタンスが最適なのか、を考えてみると別にそこにこだわりはないし、言語も別にこだわりないし、たまたま実行環境がそこにあったのでEC2上でシェルスクリプトをcronで定期実行していただけ、だったりもします。

また、処理にそれなりのスペックが必要な場合、

  1. 常時稼働しているEC2インスタンス上でcronを利用して別のスペックの高いEC2インスタンスを起動し
  2. そのインスタンスで起動から一定時間後にcronが走るようにする

といった手法を用いることがあります。

これらのことを考えると、cronでの処理として欲しいのはスクリプトの実行環境だけであって、EC2の保守をしたいわけではない、ということに気がつきました。

Lambdaへの移行

現在、Lambdaがサポートする言語も増加しており、サーバーレスで実行可能な環境が整っています。

https://aws.amazon.com/jp/lambda/faqs/

AWS Lambda は、ネイティブでは、Java、Go、PowerShell、Node.js、C#、Python、Ruby のコードをサポートしています。

Q: AWS Lambda がサポートする言語は何ですか?

残念ながらLambdaではシェルスクリプトは動きませんので、いずれかの言語への変換が発生します。

どの言語を選ぶか、というところですが、個人的にはこういうスクリプトにはJavaなど、コンパイルが必要な言語は重厚すぎると感じます。また、Node.jsはネストが深くなりがちで、好みではありません。軽量な言語を選ぶならPythonやRubyが選択肢として考えられます。

しかし、普段はJavaとNode.jsをよく書きますが、PythonとRubyはほとんど書いたことがありません。書かれたコードを読み解くことはできますが、新たな言語を学習しながらシェルスクリプトを書き換えるのは大変です。移行先としては良さそうですが、新しい言語に慣れ親しむ必要があります。

ChatGPTの活用

そんな時にはChatGPTが大いに役立ちます。

ざっくりXXXなプログラムをPythonで書いて、みたいな指示でもそこそこの精度のプログラムを書いてくれますが、具体的な要件や追加仕様があれば、それに関する詳細な指示を与える必要があります。

でも、すでにあるシェルスクリプトであれば、このプログラムをPythonで書き換えて、でいけてしまいます。

sedやawkを利用している程度の複雑さであれば、かなり精度高く変換をしてくれます。

こんな感じのやり取りでスクリプトを書き換えてくれます。

User

次のシェルスクリプトをLambda上で動くPythonのコードに書き換えてください。

ChatGPT

もちろんです。シェルスクリプトをLambda上で実行されるPythonコードに変換するために、
具体的なシェルスクリプトを提供していただければ、それを元にPythonコードに変換します。
お手持ちのシェルスクリプトを共有していただけますか?

User

#!/bin/bash


if [ $# -ne 1 ]; then
exit 1
fi

TO=$1
FROM=aaa@example.com

DAY=`date +%Y%m%d`
# 以下略

ChatGPT

以下は、提供されたシェルスクリプトをPythonに変換したLambda関数の例です。
AWS Lambda上で実行することを前提としています。
import boto3
from datetime import datetime

def lambda_handler(event, context):
    to_email = "your_email@example.com"  # 送信先メールアドレスを指定
    from_email = "aaa@example.com"

    day = datetime.now().strftime("%Y%m%d")
    # 以下略
このコードは、AWS Lambda上で実行するために必要な変更が含まれています。
AWS Lambda関数にはLambdaの環境に応じた適切な設定が必要ですので、
ご自身のLambda関数の設定に合わせて変更してください。

1行も自力でPythonのプログラムを書くことなく、Lambdaに移行することができました。この移行により、Amazon Linuxを使用しなくても済むようになり、より柔軟で効率的な環境を構築することが可能になりました。

Lambdaに変更したことで、これまでgitで管理されていなかった闇スクリプトもgitで管理できるようになりました。

ちなみにRubyとPythonどちらを選ぶかですが、

https://repost.aws/ja/knowledge-center/start-stop-lambda-eventbridge

でPythonで動いている関数がすでにあり、実行環境のパターンを増やしたくないため今回はPythonを選択しました。

なおたまにLambda上で実行してみると

"errorMessage": "name 'time' is not defined", 

みたいなエラーが出ることがあり、ChatGPTに確認してみると、

すみません、time モジュールをインポートし忘れていたようです。
time モジュールを使用してタイムスタンプを生成しています。
以下の修正版コードでは、time モジュールを追加しています。

のようにうっかりを発動することがあります。 完全に信頼はせずに確認しながら動かすことが必要になります。

Lambdaをcronっぽく動かす

定期実行はAmazon EventBridge スケジューラで実行間隔をcron形式で指定できます。

https://docs.aws.amazon.com/ja_jp/scheduler/latest/UserGuide/schedule-types.html#cron-based

また、今まではEC2のインスタンスタイプを変えることでスペックを変更していましたが、Lambdaの場合は割当メモリを変えるなどより柔軟にコントロールができます。

まとめ

このようにしてAmazon Linuxで動いていたcronをLambdaに移行することでAmazon LinuxのEOLにサクッと対応することができました。