
Amazon Linux 2 reaches EOL on June 30, 2026, so I tried letting that bird fly free
This page has been translated by machine translation. View original
Good Evening, this is Chiba (Ko).
The end-of-support date for Amazon Linux 2 has been set to June 30, 2026.
Looking back, it has a long history, having gone through the following events:
- November 2017: Announcement of Amazon Linux 2
- June 2018: Official release including 5-year LTS (Long Term Support)
- Summer 2022: Support deadline extended from June 30, 2023 to June 30, 2024
- December 2022: Support deadline extended from June 30, 2024 to June 30, 2025
- December 2024: Support deadline extended from June 30, 2025 to June 30, 2026
I personally made good use of it around 2020.
When it comes to Amazon Linux 2, many people probably have the image of the following banner being displayed when logging in via SSH.
__| __|_ )
_| ( / Amazon Linux 2 AMI
___|\___|___|

However, at some point, a bird started greeting you as follows.

, #_
~\_ ####_ 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/
This is the familiar bird from the Amazon Linux 2023 login banner. When I see this shape of bird, I want to dye it. Because I know how to dye it.
Just like how having a drill makes you want to drill holes, knowing how to dye makes me want to dye this bird too. While thinking about what color would be best to dye it, I suddenly started wondering whether it would be better to let it fly free rather than dye it.
To announce the EOL, letting this bird — which has remained in this place that is coming to an end — return to that sky. I came to think that this is the role given to me now. When I thought of that, lightning ran through the top of my head, and the colors of the world looked different to me.
This time, I'd like to let this bird go free. There is no longer any cage surrounding you. Let's tell it that with all our might.
Summary First
- Amazon Linux 2 will reach EOL on June 30, 2026, after which security updates will no longer be provided
- Let's consider migrating to Amazon Linux 2023 or similar
- You won't have any trouble even if you don't read the rest of this article
Prologue: I Want to Free the Bird
The Day the Bird Came to Our Town
Since ancient times, humanity has lived viewing birds as something symbolic. Sometimes as symbols of happiness, sometimes as spreaders of misfortune, and sometimes as announcers of seasonal changes — and so on.
For us, who have no means to soar through the sky and have only been able to gaze up at them flying through the heavens on both wings from the ground below, this may be quite natural. Even after we eventually became able to ride iron masses higher and faster through the sky than they can, we continue to look up at birds. "Somewhere other than here." We continue to see them as an icon that can freely move, without any barriers, to that place we are always searching for.
Do you know when the bird first came to Amazon Linux 2?
At some point, a bird started appearing in the Amazon Linux 2 login banner. I don't know the exact date, but well, roughly around September 20, 2023.
Excited with "The bird came!!", I was launching instances from AMIs of that era and recording in my notes whether a bird was present or not.
% 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 bird present
amzn2-ami-kernel-5.10-hvm-2.0.20230912.0-x86_64-gp2 ami-03a1b4db103179555 no bird
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 no bird
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
……
I can no longer access the AMIs from back then so I have no choice but to trust my own notes, but it says bird present for the 20230926 AMI and no bird for the 20230912 AMI.
Of course, I must have entered the following user data to prevent updates from being applied at launch from the AMI.
#cloud-config
repo_upgrade: none
So, the bird should have come to Amazon Linux 2 around about that time.
The Day I First Dyed a Bird
I normally work as a Solutions Architect at Classmethod, Inc. I started my current career in January 2020, and have been providing technical support to customers centered on AWS, conducting pre-sales activities, writing blog posts, and giving presentations.
In parallel with that, from August 2023 I also began work as a Bird Dyer (toridome-shi). A Bird Dyer is someone who adds color to the bird in Amazon Linux 2023. My main activities include occasionally making the bird red and grinning to myself thinking "it might be fun to dye this bird too." The unique hardship of being a Bird Dyer is that I tend to almost laugh when I see the Amazon Linux bird during work.
The entry from when I first got my hands dirty with bird dyeing (toridome) is below.
The approach I took was:
- Using escape sequences for color attributes in the echo command to change the text color
- Placing a bash script containing echo commands under
/etc/update-motd.d/to display the banner via motd at login time
Please use it as a reference if you want to try bird dyeing yourself.
I Want to Dye the Amazon Linux 2 Bird Too, But...
This is a tweet from September 22, 2023.
My past self from three years ago was trying to fulfill the role of Bird Dyer for the Amazon Linux 2 bird as well. I had actually even started dyeing it partway through. However, midway through I noticed "ah, Amazon Linux 2023 and Amazon Linux 2 work a bit differently," and thought "is this actually interesting...?", and came back to my senses wondering "what even is dyeing a bird?" and "why am I doing this?", and ended up collapsing halfway through. The last update time on my blog draft from back then had been frozen for about 2 years.
However, right at this timing when Amazon Linux 2 is finally reaching EOL, I suddenly realized something. A bird isn't something you dye — it's something you set free. Dyeing it feels like a second helping, but setting it free feels fresh again. Sounds fun. The bird would be happy too. Now with generative AI, it seems easy to set it free.
And so I decided to fulfill my role as a Bird Releaser (torinoga-shi). The Amazon Linux 2 bird, back to being just a bird. There is no longer any cage surrounding you.
How to Free the Amazon Linux 2 Bird
I'll create a script that runs an animation of the bird flying away. Well, that should be easy enough. I want to place that script somewhere suitable and have it display when logging in via SSH.
Let's check on the motd-related details, just like when I dyed the bird in Amazon Linux 2023.
First, /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
The contents of the most important-looking /etc/update-motd.d/30-banner. It might be quickest to replace this.
$ 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
While we're at it, let's also check the other files placed there.
$ 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.'
Let's also quickly check the other paths. There are some that exist in Amazon Linux 2023 but do not exist in 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
Checking 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.
I've got a general understanding now.
Place the Script in /etc/profile.d/ Rather Than /etc/update-motd.d/
To state the conclusion first, placing the animation script under /etc/update-motd.d/ did not produce the expected behavior.
It seems that update-motd.service is executed only once at boot time, runs the scripts under /etc/update-motd.d/, writes the results to /var/lib/update-motd/motd, and for subsequent SSH logins it just displays that file. (Since spending too much time investigating here would make me start to feel "what am I even doing...", I wrapped up the investigation quickly with just a "it seems that way" level of understanding.)
To achieve animation, the script needs to run in a place where it can output directly to the TTY. This time I chose /etc/profile.d/.
Scripts in /etc/profile.d/ are sourced from /etc/profile when the SSH login shell starts. Since the TTY is available, interactive display such as moving the cursor with tput or adding colors is possible.
Configuration for Freeing the Amazon Linux 2 Bird
This time I'll free it using the following configuration.

I'll launch an Amazon Linux 2 EC2 instance in a public subnet and connect via SSH using EC2 Instance Connect from the AWS Management Console.
If the bird flies away when I connect via SSH, my role as a Bird Releaser is complete.
By the way, where exactly does the bird fly away to? Does it go out to the internet via the Internet Gateway?

No, while this time I'm connecting via the internet to release it, the bird should be able to fly away even in a configuration without outbound internet access. In that case, it would be like this.

The bird flies away "upward." Since the bird isn't a packet, it can't read the route table. It probably won't go through the Internet Gateway. What am I even saying.
Creating the Configuration to Free the Amazon Linux 2 Bird
I created a CloudFormation template that creates everything at once.
Expand
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 will reach EOL on 2026/06/30"
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
It creates a VPC and all related resources along with an EC2 instance, and also places the script via user data. Here is the list of resources created.
| Logical ID | Resource Type | Name Tag |
|---|---|---|
Vpc |
AWS::EC2::VPC | free-al2-bird-vpc |
InternetGateway |
AWS::EC2::InternetGateway | free-al2-bird-igw |
VpcGatewayAttachment |
AWS::EC2::VPCGatewayAttachment | (no tag) |
PublicSubnet |
AWS::EC2::Subnet | free-al2-bird-subnet-public |
RouteTable |
AWS::EC2::RouteTable | free-al2-bird-rtb-public |
DefaultRoute |
AWS::EC2::Route | (no tag) |
SubnetRouteTableAssociation |
AWS::EC2::SubnetRouteTableAssociation | (no tag) |
SecurityGroup |
AWS::EC2::SecurityGroup | free-al2-bird-sg |
Instance |
AWS::EC2::Instance | free-al2-bird-ec2 |
The AMI ID used is hardcoded. From the results below, I'm specifying the most recent one.
~ $ 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
The script placed in /etc/profile.d/ of the created EC2 instance is as follows.
#!/bin/bash
# Determine if sourced or directly executed, and exit early
if (return 0 2>/dev/null); then
_exit() { return "$1"; }
else
_exit() { exit "$1"; }
fi
# Run only on SSH login
[ -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
# Clear all rows where the bird may have passed
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 will reach EOL on 2026/06/30"
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"
I deployed this CloudFormation template. Now, let's put it into practice!
I Released the Amazon Linux 2 Bird
Let me try connecting to the deployed EC2 instance via EC2 Instance Connect.

Yes, the bird flew away! Could you tell?
Let me show it one more time.

Yes, it's flying away!! It might be a bit hard to see since it's a gif.
It might be a bit easier to see the movement locally, so here it is.

There's a bird flying away toward the upper right, changing colors in a rainbow pattern. I was able to return to the sky the bird that had been given the role of announcing the EOL. This is my debut as a bird releaser. The cage that surrounded you... no longer exists.
It keeps coming back every time you connect, though. Don't sweat the small stuff.
Challenges
When I asked a generative AI "what is this?", it identified it as a bird.
, #_
~\_ ####_
~~ \_#####\
~~ \###|
~~ \#/ ___
~~ V~' '->
~~~ /
~~._. _/
_/ _/
_/m/'
However, when I asked it to create about 3 different frame patterns for a flapping animation, it didn't go well. No matter how many times I asked for "a pattern with wings down," it only produced a jumble of symbols that the human brain could not comprehend. So I settled on a fixed pose flying away instead.
I also struggled with dealing with the recurring thought of "what on earth am I doing right now." About 70% of this was written outside of work hours, and I found myself apologizing to someone for that. The time spent releasing a bird after my family had gone to sleep may have been some kind of salvation for me.
Closing
This was about releasing that bird because Amazon Linux 2 reaches EOL on June 30, 2026. To reiterate, Amazon Linux 2 reaches EOL on June 30, 2026. Security updates will no longer be provided. Consider migrating sooner rather than later.

By the way, what is that bird's name? Even after looking it up, nothing that resonated came up. The only example I found was it being referred to as "AL bird" in a GitHub issue. Following that convention might not be a bad idea. If I were free to name it, I would like to suggest the name "Rokunosuke."

This blog was written for the purpose of raising awareness about the EOL of Amazon Linux 2. I am absolutely not joking around. However, it may not be entirely suitable for reading at work. When recommending it to others, please tell them to sneak a read during a break. I believe the bird, from somewhere beyond the sky, would wish for that too.
That's all from Chiba Yuki (@batchicchi).

References
- Amazon Linux 2のサポート期限が2025年6月末まで延長されました | DevelopersIO
- セッション「Amazon Linux AL2023 and beyond」参加してこれからの Amazon Linux について聞いてきました #AWSreInvent #CMP206 | DevelopersIO
- Amazon Linux パートナー - Amazon Web Services (AWS)
- [Bug] - motd resets when new AL2023 update is available · Issue #358 · amazonlinux/amazon-linux-2023
