Amazon Linux 2が2026年6月30日にEOLになるので、あの鳥を逃がしてみた

Amazon Linux 2が2026年6月30日にEOLになるので、あの鳥を逃がしてみた

Amazon Linux 2は2026年6月30日にEOLを迎えます。継続利用は避け、Amazon Linux 2023などへの移行を検討しましょう。それはそうと、このブログではAmazon Linux 2 にいる鳥を逃がしています。鳥を逃がしたい場合は参考にしてください。
2026.06.30

コンバンハ、千葉(幸)です。

Amazon Linux 2のサポート終了日は2026年6月30日に設定されています。

振り返ってみると歴史は長いもので、下記のようなイベントをたどってきました。

  • 2017年11月:Amazon Linux 2の発表
  • 2018年6月:5年間のLTS(Long Term Support)を含む正式リリース
  • 2022年夏:サポート期限が2023年6月30日から2024年6月30日に延長
  • 2022年12月:サポート期限が2024年6月30日から2025年6月30日に延長
  • 2024年12月:サポート期限が2025年6月30日から2026年6月30日に延長

わたし自身は2020年前後によくお世話になりました。

Amazon Linux2と言えばSSHログインした際に下記のようなバナーが表示されるイメージを持つ人が多いのではないでしょうか。

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

AL2_banner

しかしある時から、以下のようにが出迎えてくれるようになっています。

Amazon_Linux2_bird

   ,     #_
   ~\_  ####_        Amazon Linux 2
  ~~  \_#####\
  ~~     \###|       AL2 End of Life is 2025-06-30.
  ~~       \#/ ___
   ~~       V~' '->
    ~~~         /    A newer version of Amazon Linux is available!
      ~~._.   _/
         _/ _/       Amazon Linux 2023, GA and supported until 2028-03-15.
       _/m/'           https://aws.amazon.com/linux/amazon-linux-2023/

これはAmazon Linux 2023のログインバナーでお馴染みの鳥ですね。わたしはこの形状の鳥を見ると染めたくなります。なぜなら、染め方を知っているからです。

ドリルを持っていれば穴を開けたくなるように、染め方を知っている故にこの鳥も染めてみたくなります。どのようなカラーに染め上げるのがいいかなと思案している中で、ふと 染めるのではなく逃がした方がいいのではないか? と考えるようになりました。

EOLを告げるため、終わりゆくこの場所にとどまり続けているこの鳥をあの空に還してやること。それこそが今の自分に与えられた役目なのではないかと思うようになったのです。それを思いついた時にわたしの脳天に稲妻が走り、世界の色が違って見えるようになりました。

今回はこの鳥を逃がしてみたいと思います。お前を囲む鳥籠など、もはや無い。 そう精一杯伝えてやりましょう。

先にまとめ

  • Amazon Linux 2は2026年6月30日にEOLを迎え、以降はセキュリティアップデートが提供されなくなります
  • Amazon Linux 2023などへの移行を検討しましょう

https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/using-features.migration-al.generic.from-al2.html

  • この後の文章は特に読まなくても困りません

プロローグ:私は鳥を逃がしたい

鳥が僕らの町にやってきた日

古来より人類は鳥のことを何らかシンボリックな存在として捉えて生きてきました。ある時は幸福を象徴するもの、ある時は不幸を撒き散らすもの、そしてある時は季節の変わり目を告げるもの──といった具合です。

空翔けるすべを持たず、両の翼で天を往く彼らをただ地べたから見上げ続けてきた我々にとっては、それもまた当然のことかもしれません。いつしか自分たちが鋼鉄の塊に乗って彼らより高く、そして速く空を駆けることができるようになった後も、我々は鳥を見上げ続けています。「ここではないどこか」。いつも探し求めるその場所へ、何の隔たりもなく自由に移動できるIconとして彼らを捉え続けているのです。

いつからAmazon Linux 2に鳥が来たか知っていますか?

Amazon Linux 2のログインバナーにいつからか鳥が来るようになりました。正確な日付は分かりませんが、まぁ大体、2023年9月20日くらいです。

「鳥来たじゃん!!」と浮き足立っていた私は、当時のAMIからインスタンスを立ち上げて、鳥がいるかいないかを手元のメモに記録していました。

当時のメモから引用
% aws ec2 describe-images \
  --owners amazon \
  --filters "Name=name,Values=amzn2-ami-kernel-5.10*x86_64-gp2" \
  --query 'reverse(sort_by(Images, &CreationDate))[].[Name,ImageId]' \
  --output text
amzn2-ami-kernel-5.10-hvm-2.0.20230926.0-x86_64-gp2     ami-0adac58024a7f03bb 鳥いる
amzn2-ami-kernel-5.10-hvm-2.0.20230912.0-x86_64-gp2     ami-03a1b4db103179555 鳥いない
amzn2-ami-kernel-5.10-hvm-2.0.20230906.0-x86_64-gp2     ami-0f89bdd365c3d966d
amzn2-ami-kernel-5.10-hvm-2.0.20230822.0-x86_64-gp2     ami-07d6bd9a28134d3b3
amzn2-ami-kernel-5.10-hvm-2.0.20230808.0-x86_64-gp2     ami-044dbe71ee2d3c59e
amzn2-ami-kernel-5.10-hvm-2.0.20230727.0-x86_64-gp2     ami-0e25eba2025eea319 鳥いない
amzn2-ami-kernel-5.10-hvm-2.0.20230719.0-x86_64-gp2     ami-09bad682e5ae72267
amzn2-ami-kernel-5.10-hvm-2.0.20230628.0-x86_64-gp2     ami-05ffd9ad4ddd0d6e2
amzn2-ami-kernel-5.10-hvm-2.0.20230612.0-x86_64-gp2     ami-0b51fe1c0254d8fc9
amzn2-ami-kernel-5.10-hvm-2.0.20230530.0-x86_64-gp2     ami-0d739893974bd27d0
amzn2-ami-kernel-5.10-hvm-2.0.20230515.0-x86_64-gp2     ami-07c2a88388bb80eb0
……

今はもう当時のAMIにはアクセスできないので自分のメモを信じるしかないですが、20230926のAMIには鳥いる、20230912のAMIには鳥いないと書かれています。

もちろん、AMIからのローンチ時にアップデートがかからないよう以下のユーザーデータを入れていたはずです。

#cloud-config
repo_upgrade: none

ということで、大体そのくらいにAmazon Linux 2に鳥が来たはずです。

僕が初めて鳥を染めた日

わたしは普段、クラスメソッド株式会社でソリューションアーキテクトとして働いています。2020年1月から今のキャリアをスタートし、AWSを中心としたお客様への技術支援、プリセールス活動、ブログ執筆や登壇などを行ってきました。

それと並行して、2023年8月からは鳥染士(とりぞめ-し)としての業も開始しました。鳥染士とは、Amazon Linux 2023にいる鳥に色をつける人のことです。たまに鳥を赤くしたり、「この鳥も染めたら面白そうだな」とニヤニヤする活動が主です。鳥染士ならではの苦労ポイントとしては、業務中にAmazon Linuxの鳥を見ると少し笑いそうになることです。

わたしがはじめて鳥染め(とりぞめ)に手を染めた時のエントリが以下です。

https://dev.classmethod.jp/articles/i-dyed-amazon-linux-2023-bird-blue/

  • echo コマンドでは色属性のエスケープシーケンスを記述することで文字色を変える
  • /etc/update-motd.d/配下にechoコマンドを含むbashスクリプトを配置し、ログイン時にmotdでバナー表示する

というアプローチを取りました。今から鳥染めに挑戦したい方は参考にしてください。

Amazon Linux2の鳥も染めてみたい、いや……

2023年9月22日のつぶやきです。

https://x.com/batchicchi/status/1705110141522305208

3年前の自分は、Amazon Linux 2の鳥に対しても鳥染士としての役割を果たそうとしていました。何なら実際に途中まで染めていました。ただ、途中で「あ、ちょっとAmazon Linux 2023とAmazon Linux 2で勝手が違うや」ということに気づいたり、「そもそもこれって面白いか……?」と思ったり、「鳥を染めるって何?」何のためにやってんの?などと正気に戻ったりして、道なかばで倒れていました。当時のブログの下書きの最終更新時刻は2年くらい止まっていました。

しかし、Amazon Linux 2がいよいよEOLを迎えるこのタイミングでふと気づきました。鳥は染めるもんじゃない、逃すもんだと。染めるのは二番煎じ感があるけど、逃すのならまた新鮮さがある。楽しそう。鳥も嬉しい。今なら生成AIもあって簡単に逃がせそう。

こうしてわたしは鳥逃士(とりのが-し)としての役割を果たすことに決めました。Amazon Linux2の鳥を、ただの鳥に。お前を囲む鳥籠など、もはや無い。

Amazon Linux2の鳥をどうやって逃すか

鳥が逃げていくアニメーションを動かすスクリプトを作ります。まぁそれはさっとできるでしょう。そのスクリプトを上手いところに配置して、SSHログイン時に表示させたいです。

Amazon Linux 2023 で鳥を染めたときのように、motd関連のあれこれを確認してみましょう。

まずは/etc/update-motd.d/から。

$ ls -la /etc/update-motd.d/
total 24
drwxr-xr-x  2 root root   86 Jun  8  2021 .
drwxr-xr-x 81 root root 8192 Oct  4 15:18 ..
-rwxr-xr-x  1 root root  553 Sep  4 21:56 30-banner
-rwxr-xr-x  1 root root   67 Sep 13  2021 50-amazon-linux-extras-news
-rwxr-xr-x  1 root root  454 Sep  4 21:56 70-available-updates

一番大事そうな/etc/update-motd.d/30-banner の中身。ここを置き換えるのが手っ取り早いでしょうか。

$ cat /etc/update-motd.d/30-banner 
#!/bin/sh
test -e /etc/os-release && os_release='/etc/os-release' || os_release='/usr/lib/os-release'
. "${os_release}"
cat << EOF
   ,     #_
   ~\_  ####_        ${PRETTY_NAME:-Amazon Linux 2}
  ~~  \_#####\\
  ~~     \###|       AL2 End of Life is ${SUPPORT_END:-2025-06-30}.
  ~~       \#/ ___
   ~~       V~' '->
    ~~~         /    A newer version of Amazon Linux is available!
      ~~._.   _/
         _/ _/       Amazon Linux 2023, GA and supported until 2028-03-15.
       _/m/'           https://aws.amazon.com/linux/amazon-linux-2023/

EOF

ついでに他においてあるファイルも確認します。

$ cat /etc/update-motd.d/50-amazon-linux-extras-news 
#!/bin/bash
timeout 5s amazon-linux-extras system_motd 2>/dev/null
$ cat /etc/update-motd.d/70-available-updates 
#!/bin/bash

# Possible summaries include:
# No packages needed for security; %d packages available
# %d package(s) needed[ (+%d related)] for security, out of %d available
# There are [[%d security update(s)[ out of ]%d total update(s)]] available
LANG=C timeout 30s /usr/bin/yum \
    --debuglevel 2 \
    --security check-update 2>/dev/null \
        | grep -P '(?<! 0 packages) available$' \
    && echo 'Run "sudo yum update" to apply all updates.'

その他のパスもざっと確認します。Amazon Linux 2023では存在しているがAmazon Linux 2では存在しない、というものがちょこちょこあります。

# ls -l /usr/lib/motd
ls: cannot access /usr/lib/motd: No such file or directory

# ls -l /etc/motd
lrwxrwxrwx 1 root root 25 Oct 13 22:21 /etc/motd -> /var/lib/update-motd/motd

# cat /var/lib/update-motd/motd 
   ,     #_
   ~\_  ####_        Amazon Linux 2
  ~~  \_#####\
  ~~     \###|       AL2 End of Life is 2025-06-30.
  ~~       \#/ ___
   ~~       V~' '->
    ~~~         /    A newer version of Amazon Linux is available!
      ~~._.   _/
         _/ _/       Amazon Linux 2023, GA and supported until 2028-03-15.
       _/m/'           https://aws.amazon.com/linux/amazon-linux-2023/

11 package(s) needed for security, out of 11 available
Run "sudo yum update" to apply all updates.

# ls -l /etc/motd.d/
ls: cannot access /etc/motd.d/: No such file or directory

# ls -l /run/motd
ls: cannot access /run/motd: No such file or directory

# ls -l /run/motd.d/
ls: cannot access /run/motd.d/: No such file or directory

update-motdの確認。

$ systemctl status update-motd
 update-motd.service - Dynamically Generate Message Of The Day
   Loaded: loaded (/usr/lib/systemd/system/update-motd.service; enabled; vendor preset: enabled)
   Active: active (exited) since Wed 2023-10-04 15:19:05 UTC; 1min 31s ago
  Process: 3126 ExecStart=/usr/sbin/update-motd (code=exited, status=0/SUCCESS)
 Main PID: 3126 (code=exited, status=0/SUCCESS)
   CGroup: /system.slice/update-motd.service

Oct 04 15:18:33 ip-172-31-38-67.ap-northeast-1.compute.internal systemd[1]: Starting Dynamically Generate Message Of The Day...
Oct 04 15:19:05 ip-172-31-38-67.ap-northeast-1.compute.internal systemd[1]: Started Dynamically Generate Message Of The Day.

大体わかりました。

スクリプトは/etc/update-motd.d/ではなく/etc/profile.d/に置く

先に結論から書くと、/etc/update-motd.d/配下にアニメーションスクリプトを格納しても想定通りの挙動を示しませんでした。

update-motd.serviceはブート時に1回だけ実行され、/etc/update-motd.d/配下のスクリプトを実行して結果を/var/lib/update-motd/motdに書き込み、以降のSSHログインではそのファイルを表示するだけ、という仕組みのようです。(あまりここで調査に時間をかけると「何やってるんだろう……」という気持ちが湧いてくるので、「ようです」程度の調査で早々に切り上げました。)

アニメーションを実現するには、TTYに直接出力できる場所でスクリプトを動かす必要があります。今回は/etc/profile.d/を選びました。

/etc/profile.d/のスクリプトはSSHログインシェル起動時に/etc/profileからsourceされます。TTYが使えるので、tputでカーソルを動かしたり色をつけたりといったインタラクティブな表示が可能です。

Amazon Linux 2の鳥を逃す構成

今回は下記の構成で逃がしてみます。

AL Bird diagram

パブリックサブネットにAmazon Linux 2のEC2インスタンスを起動し、AWSマネジメントコンソールからEC2 Instance ConnectでSSH接続します。

SSH接続した際に鳥が逃げれば、鳥逃士としての役割は完了です。

ちなみに鳥はどこから逃げるんでしょうね?やはりInternet Gatewayを経由してインターネットに抜けていくんでしょうか。

AL Bird diagram path2

いえ、今回はインターネット経由で接続して逃してみるものの、インターネットへのアウトバウンドができない構成で検証しても鳥は逃げられるはずです。そうなると、こうですね。

Bird Fly Path

「上」に鳥は逃げていきます。鳥はパケットじゃないので、ルートテーブルを読めません。Internet Gatewayは通らないでしょうね。何言ってるんでしょうね。

Amazon Linux 2の鳥を逃す構成を作成する

一式まとめて作成するCloudFormationテンプレートを作りました。

折りたたみ
free-al2-bird.yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: Free the AL2 Bird - AL2 instance with bird animation on login

Parameters:
  InstanceType:
    Type: String
    Default: t3.micro

Resources:
  # VPC
  Vpc:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: free-al2-bird-vpc

  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: free-al2-bird-igw

  VpcGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref Vpc
      InternetGatewayId: !Ref InternetGateway

  PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref Vpc
      CidrBlock: 10.0.0.0/24
      AvailabilityZone: !Select [0, !GetAZs ""]
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: free-al2-bird-subnet-public

  RouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref Vpc
      Tags:
        - Key: Name
          Value: free-al2-bird-rtb-public

  DefaultRoute:
    Type: AWS::EC2::Route
    DependsOn: VpcGatewayAttachment
    Properties:
      RouteTableId: !Ref RouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  SubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref RouteTable

  # Security Group
  SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: free-al2-bird-sg
      GroupDescription: Allow SSH from EC2 Instance Connect (ap-northeast-1)
      VpcId: !Ref Vpc
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 3.112.23.0/29
          Description: EC2 Instance Connect ap-northeast-1
      Tags:
        - Key: Name
          Value: free-al2-bird-sg

  # EC2
  Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-06087cfd700858bee
      InstanceType: !Ref InstanceType
      SubnetId: !Ref PublicSubnet
      SecurityGroupIds:
        - !Ref SecurityGroup
      Tags:
        - Key: Name
          Value: free-al2-bird-ec2
      UserData:
        Fn::Base64: |
          #!/bin/bash

          cat << 'BIRDSCRIPT' > /etc/profile.d/bird.sh
          #!/bin/bash

          # SSH ログイン時のみ実行
          [ -t 1 ]                 || return 0
          [ -n "$TERM" ]           || return 0
          [ -n "$SSH_CONNECTION" ] || return 0

          Q="'"
          BOLD=$'\e[1m'
          RESET=$'\e[0m'
          RAINBOW=($'\e[31m' $'\e[33m' $'\e[32m' $'\e[36m' $'\e[34m' $'\e[35m')
          BIRD_H=10
          TRAVEL=60

          BANNER=(
              "   ,     #_"
              "   ~\\_  ####_        Amazon Linux 2"
              "  ~~  \\_#####\\"
              "  ~~     \\###|       AL2 End of Life is 2026-06-30."
              "  ~~       \\#/ ___"
              "   ~~       V~${Q} ${Q}->"
              "    ~~~         /    A newer version of Amazon Linux is available!"
              "      ~~._.   _/"
              "         _/ _/       Amazon Linux 2023, GA and supported until 2028-03-15."
              "       _/m/${Q}           https://aws.amazon.com/linux/amazon-linux-2023/"
          )

          BIRD=(
              "   ,     #_"
              "   ~\\_  ####_"
              "  ~~  \\_#####\\"
              "  ~~     \\###|"
              "  ~~       \\#/ ___"
              "   ~~       V~${Q} ${Q}->"
              "    ~~~         /"
              "      ~~._.   _/"
              "         _/ _/"
              "       _/m/${Q}"
          )

          draw_bird() {
              local col=$1 row_off=$2 i row
              shift 2
              for ((i = 0; i < BIRD_H; i++)); do
                  row=$(( BASE_ROW + row_off + i ))
                  if (( row >= 0 && row < ROWS )); then
                      tput cup "$row" 0
                      printf '%*s' "$COLS" ''
                      if (( col < COLS )); then
                          tput cup "$row" "$col"
                          if (( flying )); then
                              printf '%s' "${BOLD}${RAINBOW[$(( (i + col / 4) % 6 ))]}$1${RESET}"
                          else
                              printf '%s' "$1"
                          fi
                      fi
                  fi
                  shift
              done
          }

          clear_rows() {
              local row_off=$1 i row
              for ((i = 0; i < BIRD_H; i++)); do
                  row=$(( BASE_ROW + row_off + i ))
                  if (( row >= 0 && row < ROWS )); then
                      tput cup "$row" 0
                      printf '%*s' "$COLS" ''
                  fi
              done
          }

          draw_trail() {
              local bird_col=$1 bird_row_off=$2
              local bird_top=$(( BASE_ROW + bird_row_off ))
              local bird_bot=$(( bird_top + BIRD_H - 1 ))
              local bird_right=$(( bird_col + 22 ))
              local chars=('.' ',' '~' '*' '-')
              local i tr tc n j dots
              for ((i = 0; i < ${#trail_cols[@]}; i++)); do
                  tr=$(( trail_rows[i] + RANDOM % 3 - 1 ))
                  tc=$(( trail_cols[i] + RANDOM % 3 - 1 ))
                  (( tr < 0 || tc < 0 )) && continue
                  (( tr >= bird_top && tr <= bird_bot && tc >= bird_col && tc <= bird_right )) && continue
                  dots=''
                  n=$(( RANDOM % 2 + 1 ))
                  for ((j = 0; j < n; j++)); do dots+="${chars[$(( RANDOM % 5 ))]}"; done
                  tput cup "$tr" "$tc"
                  printf '%s' "$dots"
              done
          }

          COLS=$(tput cols)
          ROWS=$(tput lines)
          BASE_ROW=0

          tput civis
          trap 'tput cnorm; tput cup $(( ROWS - 1 )) 0' EXIT INT TERM
          clear

          flying=0
          draw_bird 0 0 "${BANNER[@]}"
          sleep 0.8

          flying=1
          col=0
          prev_row_off=0
          trail_cols=()
          trail_rows=()

          while (( col <= TRAVEL )); do
              row_off=$(( - col * BIRD_H / TRAVEL ))
              clear_rows "$prev_row_off"

              trail_cols+=("$(( col + 14 ))")
              trail_rows+=("$(( BASE_ROW + row_off + 5 ))")
              while (( ${#trail_cols[@]} > 6 )); do
                  trail_cols=("${trail_cols[@]:1}")
                  trail_rows=("${trail_rows[@]:1}")
              done

              draw_bird "$col" "$row_off" "${BIRD[@]}"
              draw_trail "$col" "$row_off"
              prev_row_off=$row_off
              sleep 0.08
              (( col += 4 ))
          done

          for ((i = 0; i < BIRD_H; i++)); do
              tput cup "$i" 0
              printf '%*s' "$COLS" ''
          done
          tput cup 0 0
          printf '%s\n' "Amazon Linux 2は2026/06/30でEOLです"
          LAST=$(last -n 2 -i "$USER" 2>/dev/null | grep -v "still logged" | grep "$USER" | head -1 | awk '{print $4,$5,$6,$7,"from",$3}')
          [[ "$LAST" =~ ^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) ]] && printf 'Last login: %s\n' "$LAST"
          BIRDSCRIPT

          chmod +x /etc/profile.d/bird.sh

Outputs:
  InstanceId:
    Value: !Ref Instance
  PublicIp:
    Value: !GetAtt Instance.PublicIp

VPC一式とEC2インスタンスを作成し、ユーザーデータでスクリプトも配置しています。作成されるリソース一覧はこちら。

論理ID リソース種別 Name タグ
Vpc AWS::EC2::VPC free-al2-bird-vpc
InternetGateway AWS::EC2::InternetGateway free-al2-bird-igw
VpcGatewayAttachment AWS::EC2::VPCGatewayAttachment (タグなし)
PublicSubnet AWS::EC2::Subnet free-al2-bird-subnet-public
RouteTable AWS::EC2::RouteTable free-al2-bird-rtb-public
DefaultRoute AWS::EC2::Route (タグなし)
SubnetRouteTableAssociation AWS::EC2::SubnetRouteTableAssociation (タグなし)
SecurityGroup AWS::EC2::SecurityGroup free-al2-bird-sg
Instance AWS::EC2::Instance free-al2-bird-ec2

使用するAMI IDはハードコーディングしています。下記の結果から、一番新しいものを指定しています。

~ $ aws ec2 describe-images \
>   --owners amazon \
>   --filters "Name=name,Values=amzn2-ami-kernel-5.10*x86_64-gp2" \
>   --query 'reverse(sort_by(Images, &CreationDate))[].[Name,ImageId]' \
>   --output text
amzn2-ami-kernel-5.10-hvm-2.0.20260629.0-x86_64-gp2     ami-06087cfd700858bee
amzn2-ami-kernel-5.10-hvm-2.0.20260622.1-x86_64-gp2     ami-07c647553a2f27949
amzn2-ami-kernel-5.10-hvm-2.0.20260615.0-x86_64-gp2     ami-0187c7df27ec175e1
amzn2-ami-kernel-5.10-hvm-2.0.20260608.0-x86_64-gp2     ami-0464ea504c6b43640
amzn2-ami-kernel-5.10-hvm-2.0.20260526.0-x86_64-gp2     ami-0b268943ac284f0c8
amzn2-ami-kernel-5.10-hvm-2.0.20260515.0-x86_64-gp2     ami-0324af2ca26d828c5
amzn2-ami-kernel-5.10-hvm-2.0.20260511.1-x86_64-gp2     ami-0cc213517bf63b8ad
amzn2-ami-kernel-5.10-hvm-2.0.20260508.0-x86_64-gp2     ami-0e56fdd7002dd4962
amzn2-ami-kernel-5.10-hvm-2.0.20260504.0-x86_64-gp2     ami-04633509de692dab5
amzn2-ami-kernel-5.10-hvm-2.0.20260427.1-x86_64-gp2     ami-0f0cee67f8a8a3f07
amzn2-ami-kernel-5.10-hvm-2.0.20260413.0-x86_64-gp2     ami-0d8fbaea8b647edac
amzn2-ami-kernel-5.10-hvm-2.0.20260406.1-x86_64-gp2     ami-0b23654657ee2874f

作成したEC2インスタンスの/etc/profile.d/に配置されるスクリプトは以下です。

bird.sh
#!/bin/bash

# sourced か直接実行かを判定して早期終了
if (return 0 2>/dev/null); then
    _exit() { return "$1"; }
else
    _exit() { exit "$1"; }
fi

# SSH ログイン時のみ実行
[ -t 1 ]                 || _exit 0
[ -n "$TERM" ]           || _exit 0
[ -n "$SSH_CONNECTION" ] || _exit 0

Q="'"
BOLD=$'\e[1m'
RESET=$'\e[0m'
RAINBOW=($'\e[31m' $'\e[33m' $'\e[32m' $'\e[36m' $'\e[34m' $'\e[35m')
BIRD_H=10
TRAVEL=60

BANNER=(
    "   ,     #_"
    "   ~\\_  ####_        Amazon Linux 2"
    "  ~~  \\_#####\\"
    "  ~~     \\###|       AL2 End of Life is 2026-06-30."
    "  ~~       \\#/ ___"
    "   ~~       V~${Q} ${Q}->"
    "    ~~~         /    A newer version of Amazon Linux is available!"
    "      ~~._.   _/"
    "         _/ _/       Amazon Linux 2023, GA and supported until 2028-03-15."
    "       _/m/${Q}           https://aws.amazon.com/linux/amazon-linux-2023/"
)

BIRD=(
    "   ,     #_"
    "   ~\\_  ####_"
    "  ~~  \\_#####\\"
    "  ~~     \\###|"
    "  ~~       \\#/ ___"
    "   ~~       V~${Q} ${Q}->"
    "    ~~~         /"
    "      ~~._.   _/"
    "         _/ _/"
    "       _/m/${Q}"
)

draw_bird() {
    local col=$1 row_off=$2 i row
    shift 2
    for ((i = 0; i < BIRD_H; i++)); do
        row=$(( BASE_ROW + row_off + i ))
        if (( row >= 0 && row < ROWS )); then
            tput cup "$row" 0
            printf '%*s' "$COLS" ''
            if (( col < COLS )); then
                tput cup "$row" "$col"
                if (( flying )); then
                    printf '%s' "${BOLD}${RAINBOW[$(( (i + col / 4) % 6 ))]}$1${RESET}"
                else
                    printf '%s' "$1"
                fi
            fi
        fi
        shift
    done
}

clear_rows() {
    local row_off=$1 i row
    for ((i = 0; i < BIRD_H; i++)); do
        row=$(( BASE_ROW + row_off + i ))
        if (( row >= 0 && row < ROWS )); then
            tput cup "$row" 0
            printf '%*s' "$COLS" ''
        fi
    done
}

draw_trail() {
    local bird_col=$1 bird_row_off=$2
    local bird_top=$(( BASE_ROW + bird_row_off ))
    local bird_bot=$(( bird_top + BIRD_H - 1 ))
    local bird_right=$(( bird_col + 22 ))
    local chars=('.' ',' '~' '*' '-')
    local i tr tc n j dots
    for ((i = 0; i < ${#trail_cols[@]}; i++)); do
        tr=$(( trail_rows[i] + RANDOM % 3 - 1 ))
        tc=$(( trail_cols[i] + RANDOM % 3 - 1 ))
        (( tr < 0 || tc < 0 )) && continue
        (( tr >= bird_top && tr <= bird_bot && tc >= bird_col && tc <= bird_right )) && continue
        dots=''
        n=$(( RANDOM % 2 + 1 ))
        for ((j = 0; j < n; j++)); do dots+="${chars[$(( RANDOM % 5 ))]}"; done
        tput cup "$tr" "$tc"
        printf '%s' "$dots"
    done
}

COLS=$(tput cols)
ROWS=$(tput lines)
BASE_ROW=0

tput civis
trap 'tput cnorm' EXIT INT TERM
clear

flying=0
draw_bird 0 0 "${BANNER[@]}"
sleep 0.8

flying=1
col=0
prev_row_off=0
trail_cols=()
trail_rows=()

while (( col <= TRAVEL )); do
    row_off=$(( - col * BIRD_H / TRAVEL ))
    clear_rows "$prev_row_off"

    trail_cols+=("$(( col + 14 ))")
    trail_rows+=("$(( BASE_ROW + row_off + 5 ))")
    while (( ${#trail_cols[@]} > 6 )); do
        trail_cols=("${trail_cols[@]:1}")
        trail_rows=("${trail_rows[@]:1}")
    done

    draw_bird "$col" "$row_off" "${BIRD[@]}"
    draw_trail "$col" "$row_off"
    prev_row_off=$row_off
    sleep 0.08
    (( col += 4 ))
done

# 鳥が通った可能性のある行をすべてクリア
for ((i = 0; i < BIRD_H; i++)); do
    tput cup "$i" 0
    printf '%*s' "$COLS" ''
done
tput cup 0 0
printf '%s\n' "Amazon Linux 2は2026/06/30でEOLです"
LAST=$(last -n 2 -i "$USER" 2>/dev/null | grep -v "still logged" | grep "$USER" | head -1 | awk '{print $4,$5,$6,$7,"from",$3}')
[[ "$LAST" =~ ^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) ]] && printf 'Last login: %s\n' "$LAST"

このCloudFormationテンプレートをデプロイしました。いざ、実践です!

Amazon Linux 2の鳥を逃がしてみた

デプロイされたEC2インスタンスに、EC2 Instance Connectで接続してみます。

ALBird1

はい、鳥が逃げました!分かりました?

もう一回載せますね。

AL Bird2

はい、逃げてますね!!gifなのでわかりづらいかもしれないですが。

ローカルだともうちょっと動きがわかりやすいかもなので載せておくとこうです。

ALbird iterm

カラフルに色を変えながら右上に逃げていく鳥がそこにいますね。EOLを告げる役割を課せられた鳥を、空に還すことができました。これがわたしの鳥逃士としてのデビューです。お前を囲む鳥籠など……もはや無いんだよ。

接続するたびにそこに戻ってるんですけどね。細かいことは気にしたら負けですよ。

苦労したこと

生成AIに↓これは何?と聞くと鳥と判別してくれました。

   ,     #_
   ~\_  ####_     
  ~~  \_#####\
  ~~     \###|
  ~~       \#/ ___   
   ~~       V~' '->
    ~~~         /
      ~~._.   _/
         _/ _/
       _/m/'

ただ、羽ばたくアニメーションにしたいので3コマくらい別パターンを作って、と頼んでもうまくいきませんでした。「羽を下にしているパターン」と何度頼んでも、人間の脳には理解できない記号の塊が排出されるだけでした。しょうがないので、ポーズは固定のまま飛んでいくパターンにしました。

あとは定期的に湧き上がっている「自分はいま何をやってるんだろう」という思いとの付き合い方にも苦労しました。7割くらいは業務時間外に書いているから許して、と誰かに謝っていました。家族が寝静まった後に鳥を逃がしている時間が、わたしにとって何かの救いだったのかもしれません。

終わりに

Amazon Linux 2が2026年6月30日にEOLになるので、あの鳥を逃がしてみたという話でした。繰り返しになりますが、Amazon Linux 2は2026年6月30日にEOLです。セキュリティアップデートの提供がなくなります。早めの移行を検討しましょう。


IMG_3880


ちなみにあの鳥の名前は何て言うんでしょうね?調べてみてもピンとくるものは出てきませんでした。唯一、GitHubのissueで「AL bird」と呼称されている例を見かけました。それに則って読んでいくのもいいかもしれませんね。もし自由に名付けていいなら、「六之助」という名前を推奨したいです。


IMG_3881


このブログはAmazon Linux 2のEOLを啓蒙する目的で書きました。断じてふざけているわけではありません。ただ、あまり職場で読むには適していないかもしれません。人に薦める時は、休憩時間とかにこっそり読んでと伝えてあげてください。鳥も空の彼方から、それを望んでいると思います。

以上、チバユキ (@batchicchi)がお送りしました。


al2 last

参考


クラスメソッドのエンジニアと1on1で話してみませんか?

選考に関係のないカジュアルな面談です。
「技術スタックや開発環境について詳しく知りたい」「実際のプロジェクト事例を聞きたい」「リモートワークや評価制度について確認したい」など、気になることを直接エンジニアに質問できます。
カジュアル面談に申し込む

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事