Skip to content

Instantly share code, notes, and snippets.

@tosin2013
Created April 28, 2026 18:59
Show Gist options
  • Select an option

  • Save tosin2013/3d53e4ab3f9d090174fb2f8e2dc9ca2f to your computer and use it in GitHub Desktop.

Select an option

Save tosin2013/3d53e4ab3f9d090174fb2f8e2dc9ca2f to your computer and use it in GitHub Desktop.
configure-aws-cli.sh
#!/bin/bash
#set -xe
function checkForProgramAndInstall() {
command -v $1 > /dev/null 2>&1
if [[ $? -eq 0 ]]; then
printf '%-72s %-7s\n' $1 "PASSED!";
else
sudo yum install -y $1
fi
}
# Print usage
usage() {
echo -n "${0} [OPTION]
Options:
-i, --install Install awscli latest binaries
-d, --delete Remove awscli
-h, --help Display this help and exit
USAGE: $0 -i aws_access_key_id aws_secret_access_key aws_region
"
}
if [ "$EUID" -ne 0 ]
then
RUN_SUDO="sudo"
fi
# Resolve the aws binary regardless of PATH state, install location, or
# whether the wrapper symlink at /usr/local/bin/aws was (re)created.
# Sets AWS_BIN to an absolute path on success.
resolve_aws_bin() {
if command -v aws >/dev/null 2>&1; then
AWS_BIN="$(command -v aws)"
elif [ -x /usr/local/bin/aws ]; then
AWS_BIN="/usr/local/bin/aws"
elif [ -x /usr/local/aws-cli/v2/current/bin/aws ]; then
AWS_BIN="/usr/local/aws-cli/v2/current/bin/aws"
else
# Last resort: any installed version under /usr/local/aws-cli/v2/<ver>/bin/aws.
# This catches the case where the installer skipped and the 'current' symlink
# was never created (or was stale). -xtype f (instead of -type f) is required
# because bin/aws is a symlink to ../dist/aws in the v2 layout.
local cand
cand="$(${RUN_SUDO} find /usr/local/aws-cli/v2/ -mindepth 3 -maxdepth 3 \
-path '*/bin/aws' -xtype f -executable 2>/dev/null \
| sort -V | tail -n 1)"
if [ -n "$cand" ] && [ -x "$cand" ]; then
AWS_BIN="$cand"
else
echo "Error: aws CLI binary not found after install" >&2
return 1
fi
fi
export AWS_BIN
return 0
}
function install_aws_cli(){
checkForProgramAndInstall curl
checkForProgramAndInstall unzip
# Idempotent download + extract. Skip the curl if we already have the zip,
# and use -o so unzip overwrites in place instead of prompting interactively
# when aws/ exists from a previous run. -q keeps the noise down.
if [ ! -f awscliv2.zip ]; then
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
fi
unzip -oq awscliv2.zip
# Heads-up if a system install exists but isn't traversable by the current
# user. We can't fix it without root, but flagging it tells the operator
# there's stale state to clean up.
if [ -d /usr/local/aws-cli/v2 ] && [ ! -r /usr/local/aws-cli/v2 ]; then
echo "NOTE: System AWS CLI exists at /usr/local/aws-cli/v2 but is not"
echo " readable by $(id -un). Continuing with per-user install."
echo " To remove the orphaned install, root can run:"
echo " sudo rm -rf /usr/local/aws-cli /usr/local/bin/aws /usr/local/bin/aws_completer"
echo " To fix perms in place instead:"
echo " sudo chmod -R a+rX /usr/local/aws-cli"
fi
# On boxes where vpcuser can't traverse /usr/local/aws-cli/v2 (perms locked
# to root), do a per-user install under $HOME/.local instead. No sudo, no
# symlink games, and $HOME/.local/bin is already first in PATH for vpcuser.
# --update makes the install command idempotent in either branch.
if [ "$(id -un)" = "vpcuser" ]; then
AWS_INSTALL_DIR="$HOME/.local/aws-cli"
AWS_BIN_DIR="$HOME/.local/bin"
mkdir -p "$AWS_BIN_DIR" "$AWS_INSTALL_DIR"
./aws/install --update -i "$AWS_INSTALL_DIR" -b "$AWS_BIN_DIR"
# Belt-and-suspenders: prepend to PATH for this shell, and persist for
# future logins if not already in .bashrc.
case ":$PATH:" in
*":$AWS_BIN_DIR:"*) ;;
*) export PATH="$AWS_BIN_DIR:$PATH" ;;
esac
grep -qxF "export PATH=\"$AWS_BIN_DIR:\$PATH\"" "$HOME/.bashrc" 2>/dev/null \
|| echo "export PATH=\"$AWS_BIN_DIR:\$PATH\"" >> "$HOME/.bashrc"
else
# Force a sane umask so the install tree comes out world-readable
# regardless of what the calling shell's umask is. This prevents the
# 0700-on-/usr/local/aws-cli/v2 bug we hit on the vpcuser box: a
# restrictive umask (e.g. 077) at install time makes the entire tree
# untraversable for non-root users. The subshell scopes the umask
# change so we don't perturb the rest of the script.
( umask 022 && ${RUN_SUDO} ./aws/install --update -i /usr/local/aws-cli -b /usr/local/bin )
# Post-install fix-up. When --update detects the same version is already
# installed, the installer prints "Skipping install" and does NOT create
# or refresh /usr/local/aws-cli/v2/current or /usr/local/bin/aws. If
# those were missing/stale going in (as on the broken box), they stay
# missing/stale on the way out. Repoint them at the latest version
# directory unconditionally — cheap and idempotent. Also force-open the
# tree perms so non-root users (vpcuser, etc.) can traverse and execute,
# which fixes the original "command not found" failure for non-root
# callers even if they're not the ones running this branch.
latest_dir="$(${RUN_SUDO} find /usr/local/aws-cli/v2/ -mindepth 1 -maxdepth 1 \
-type d ! -name current 2>/dev/null | sort -V | tail -n 1)"
if [ -n "$latest_dir" ] && [ -d "$latest_dir" ]; then
${RUN_SUDO} ln -sfn "$latest_dir" /usr/local/aws-cli/v2/current
${RUN_SUDO} ln -sf /usr/local/aws-cli/v2/current/bin/aws /usr/local/bin/aws
${RUN_SUDO} ln -sf /usr/local/aws-cli/v2/current/bin/aws_completer /usr/local/bin/aws_completer
${RUN_SUDO} chmod -R a+rX /usr/local/aws-cli
fi
fi
resolve_aws_bin || exit 1
"$AWS_BIN" --version || exit 1
if [ "$EUID" -ne 0 ]
then
rm -rf ${HOME}/awscli-bundle ${HOME}/awscli-bundle.zip
else
rm -rf /root/awscli-bundle /root/awscli-bundle.zip
fi
export AWSKEYID=${1}
export AWSSECRETKEY=${2}
export REGION=${3}
mkdir -p $HOME/.aws
cat >$HOME/.aws/credentials<<EOF
[default]
aws_access_key_id = ${AWSKEYID}
aws_secret_access_key = ${AWSSECRETKEY}
region = ${REGION}
EOF
cat $HOME/.aws/credentials
if [ -z "$SKIP_CHECK_CALLER_IDENTITY" ]
then
"$AWS_BIN" sts get-caller-identity || exit $?
fi
}
function delete_aws_cli(){
echo "*******************************"
echo " Removing aws cli "
echo "*******************************"
${RUN_SUDO} rm -rf /usr/local/bin/aws
${RUN_SUDO} rm -rf /usr/local/aws-cli/v2/
if [ "$EUID" -ne 0 ]
then
rm -rf $(find $HOME -name awscliv2.zip)
if [ -d $(pwd)/aws ];
then
rm -rf $(pwd)/aws
fi
else
rm -rf /root/awscli-bundle /root/awscli-bundle.zip
rm -rf /root/awscliv2.zip
rm -rf /root/aws
fi
exit 0
}
optstring=v
unset options
while (($#)); do
case $1 in
# If option is of type -ab
-[!-]?*)
# Loop over each character starting with the second
for ((i=1; i < ${#1}; i++)); do
c=${1:i:1}
# Add current char to options
options+=("-$c")
# If option takes a required argument, and it's not the last char make
# the rest of the string its argument
if [[ $optstring = *"$c:"* && ${1:i+1} ]]; then
options+=("${1:i+1}")
break
fi
done
;;
# If option is of type --foo=bar
--?*=*) options+=("${1%%=*}" "${1#*=}") ;;
# add --endopts for --
--) options+=(--endopts) ;;
# Otherwise, nothing special
*) options+=("$1") ;;
esac
shift
done
set -- "${options[@]}"
unset options
# Read the options and set stuff
while [[ $1 = -?* ]]; do
case $1 in
-h|--help) usage >&2; break ;;
-i|--install) shift; install_aws_cli $1 $2 $3;;
-d|--delete) shift; delete_aws_cli;;
--endopts) shift; break ;;
*) die "invalid option: '$1'." ;;
esac
shift
done
# Store the remaining part as arguments.
args+=("$@")
if [ -z $1 ];
then
usage
exit 1
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment