Update install-ruby-rvm.sh

This commit is contained in:
gru
2026-04-09 09:08:43 +02:00
parent e67eb26110
commit e4ed6669c4

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Recompile Openssl 1.1.1w on RHEL9+ and install Old Rubies # Recompile OpenSSL 1.1.1w on RHEL9+ and install old Rubies
# Mateusz Gruszczyński @linuxiarz.pl # Mateusz Gruszczyński @liuxiarz.pl
set -eo pipefail set -eo pipefail
@@ -8,25 +8,111 @@ OPENSSL_VERSION="1.1.1w"
OPENSSL_PREFIX="/opt/openssl111" OPENSSL_PREFIX="/opt/openssl111"
SRC_DIR="/usr/local/src" SRC_DIR="/usr/local/src"
if [ "${EUID}" -ne 0 ]; then FORCE_OPENSSL=0
echo "ERROR: run this script as root" WEB_PROXY=""
exit 1 TARGET_RUBY_VERSION=""
fi
if [ $# -ne 1 ]; then usage() {
echo "Usage: $0 2.7.X" cat <<EOF
exit 1 Usage:
fi $0 --version 2.7.X [--force-openssl] [--webproxy http://proxy:port]
RUBY_VERSION="$1" Options:
--version VER Ruby version to install, e.g. 2.7.8
--force-openssl Force rebuild of OpenSSL ${OPENSSL_VERSION}
--webproxy URL Proxy URL used for downloads and RVM, e.g. http://proxy.example:8080
-h, --help Show this help
if [[ ! "${RUBY_VERSION}" =~ ^2\.7\.[0-9]+$ ]]; then Examples:
echo "ERROR: only Ruby 2.7.X is allowed" $0 --version 2.7.8
echo "Example: $0 2.7.8" $0 --version 2.7.8 --force-openssl
$0 --version 2.7.8 --webproxy http://proxy.local:8080
Backward compatibility:
$0 2.7.8
EOF
}
die() {
echo "ERROR: $*" >&2
exit 1 exit 1
fi }
log() {
echo "$*"
}
command_exists() {
command -v "$1" >/dev/null 2>&1
}
package_installed() {
local pkg="$1"
rpm -q "${pkg}" >/dev/null 2>&1 && return 0
rpm -q --whatprovides "${pkg}" >/dev/null 2>&1 && return 0
return 1
}
parse_args() {
while [ $# -gt 0 ]; do
case "$1" in
--version)
shift
[ $# -gt 0 ] || die "--version requires a value"
[ -z "${TARGET_RUBY_VERSION}" ] || die "Ruby version already provided: ${TARGET_RUBY_VERSION}"
TARGET_RUBY_VERSION="$1"
;;
--force-openssl)
FORCE_OPENSSL=1
;;
--webproxy)
shift
[ $# -gt 0 ] || die "--webproxy requires a value"
WEB_PROXY="$1"
;;
-h|--help)
usage
exit 0
;;
-*)
die "unknown option: $1"
;;
*)
[ -z "${TARGET_RUBY_VERSION}" ] || die "Ruby version already provided: ${TARGET_RUBY_VERSION}"
TARGET_RUBY_VERSION="$1"
;;
esac
shift
done
[ -n "${TARGET_RUBY_VERSION}" ] || die "missing Ruby version, use --version 2.7.X"
if [[ ! "${TARGET_RUBY_VERSION}" =~ ^2\.7\.[0-9]+$ ]]; then
die "only Ruby 2.7.X is allowed, e.g. 2.7.9"
fi
}
apply_proxy_env() {
if [ -n "${WEB_PROXY}" ]; then
export http_proxy="${WEB_PROXY}"
export https_proxy="${WEB_PROXY}"
export ftp_proxy="${WEB_PROXY}"
export all_proxy="${WEB_PROXY}"
export HTTP_PROXY="${WEB_PROXY}"
export HTTPS_PROXY="${WEB_PROXY}"
export FTP_PROXY="${WEB_PROXY}"
export ALL_PROXY="${WEB_PROXY}"
log "Using web proxy: ${WEB_PROXY}"
fi
}
load_rvm() { load_rvm() {
export rvm_silence_path_mismatch_check_flag=1
if [ -s /etc/profile.d/rvm.sh ]; then if [ -s /etc/profile.d/rvm.sh ]; then
. /etc/profile.d/rvm.sh . /etc/profile.d/rvm.sh
elif [ -s /usr/local/rvm/scripts/rvm ]; then elif [ -s /usr/local/rvm/scripts/rvm ]; then
@@ -34,27 +120,97 @@ load_rvm() {
elif [ -s /root/.rvm/scripts/rvm ]; then elif [ -s /root/.rvm/scripts/rvm ]; then
. /root/.rvm/scripts/rvm . /root/.rvm/scripts/rvm
else else
echo "ERROR: RVM was not found" die "RVM was not found"
exit 1
fi fi
if ! command -v rvm >/dev/null 2>&1; then if ! command -v rvm >/dev/null 2>&1; then
echo "ERROR: RVM is not available in this shell" die "RVM is not available in this shell"
exit 1
fi fi
} }
ruby_already_installed() { download_file() {
if command -v ruby >/dev/null 2>&1; then local url="$1"
current_ruby_version="$(ruby -e 'print RUBY_VERSION' 2>/dev/null || true)" local output="$2"
if [ "${current_ruby_version}" = "${RUBY_VERSION}" ]; then
echo "Ruby ${RUBY_VERSION} is already available in PATH" if command_exists wget; then
return 0 if [ -n "${WEB_PROXY}" ]; then
wget \
-e use_proxy=yes \
-e "http_proxy=${WEB_PROXY}" \
-e "https_proxy=${WEB_PROXY}" \
-O "${output}" \
"${url}"
else
wget -O "${output}" "${url}"
fi fi
return
fi fi
if rvm list strings | grep -Fxq "ruby-${RUBY_VERSION}"; then if command_exists curl; then
echo "Ruby ${RUBY_VERSION} is already installed in RVM" if [ -n "${WEB_PROXY}" ]; then
curl --proxy "${WEB_PROXY}" -fL -o "${output}" "${url}"
else
curl -fL -o "${output}" "${url}"
fi
return
fi
die "neither wget nor curl is available"
}
openssl_installation_ok() {
local openssl_bin="${OPENSSL_PREFIX}/bin/openssl"
local version_output
[ -x "${openssl_bin}" ] || return 1
[ -d "${OPENSSL_PREFIX}/include/openssl" ] || return 1
[ -f "${OPENSSL_PREFIX}/lib/libssl.so" ] || [ -f "${OPENSSL_PREFIX}/lib64/libssl.so" ] || return 1
[ -f "${OPENSSL_PREFIX}/lib/libcrypto.so" ] || [ -f "${OPENSSL_PREFIX}/lib64/libcrypto.so" ] || return 1
version_output="$(
LD_LIBRARY_PATH="${OPENSSL_PREFIX}/lib:${OPENSSL_PREFIX}/lib64:${LD_LIBRARY_PATH:-}" \
"${openssl_bin}" version 2>/dev/null || true
)"
[[ "${version_output}" == OpenSSL\ ${OPENSSL_VERSION}* ]]
}
ruby_in_path_ok() {
local ruby_version openssl_version
command_exists ruby || return 1
ruby_version="$(ruby -e 'print RUBY_VERSION' 2>/dev/null || true)"
[ "${ruby_version}" = "${TARGET_RUBY_VERSION}" ] || return 1
openssl_version="$(ruby -ropenssl -e 'print OpenSSL::OPENSSL_VERSION' 2>/dev/null || true)"
[[ "${openssl_version}" == OpenSSL\ ${OPENSSL_VERSION}* ]]
}
ruby_in_rvm_present() {
rvm list strings | grep -Fxq "ruby-${TARGET_RUBY_VERSION}"
}
ruby_in_rvm_ok() {
local ruby_version openssl_version
ruby_in_rvm_present || return 1
ruby_version="$(rvm "ruby-${TARGET_RUBY_VERSION}" do ruby -e 'print RUBY_VERSION' 2>/dev/null || true)"
[ "${ruby_version}" = "${TARGET_RUBY_VERSION}" ] || return 1
openssl_version="$(rvm "ruby-${TARGET_RUBY_VERSION}" do ruby -ropenssl -e 'print OpenSSL::OPENSSL_VERSION' 2>/dev/null || true)"
[[ "${openssl_version}" == OpenSSL\ ${OPENSSL_VERSION}* ]]
}
ruby_already_installed() {
if ruby_in_rvm_ok; then
log "Ruby ${TARGET_RUBY_VERSION} is already installed in RVM and linked with OpenSSL ${OPENSSL_VERSION}"
return 0
fi
if ruby_in_path_ok; then
log "Ruby ${TARGET_RUBY_VERSION} is already available in PATH and linked with OpenSSL ${OPENSSL_VERSION}"
return 0 return 0
fi fi
@@ -62,29 +218,86 @@ ruby_already_installed() {
} }
install_build_dependencies() { install_build_dependencies() {
echo "[1/6] Installing build dependencies" log "[1/6] Checking build dependencies"
local missing_packages=()
local packages=(
curl
wget
tar
xz
bzip2
git
perl-core
pkgconfig
zlib-devel
readline-devel
libyaml-devel
libffi-devel
gdbm-devel
ncurses-devel
gmp-devel
autoconf
automake
libtool
bison
)
local pkg
for pkg in "${packages[@]}"; do
if ! package_installed "${pkg}"; then
missing_packages+=("${pkg}")
fi
done
local need_devtools=0
if ! command_exists gcc || ! command_exists g++ || ! command_exists make; then
need_devtools=1
fi
if [ "${need_devtools}" -eq 0 ] && [ "${#missing_packages[@]}" -eq 0 ]; then
log "All required build dependencies are already installed"
return 0
fi
if [ "${need_devtools}" -eq 1 ]; then
log "Installing missing group: Development Tools"
dnf groupinstall -y "Development Tools" dnf groupinstall -y "Development Tools"
dnf install -y \ fi
curl tar xz bzip2 git perl-core pkgconfig \
zlib-devel readline-devel libyaml-devel libffi-devel \ if [ "${#missing_packages[@]}" -gt 0 ]; then
gdbm-devel ncurses-devel gmp-devel autoconf automake libtool bison log "Installing missing packages: ${missing_packages[*]}"
dnf install -y "${missing_packages[@]}"
fi
} }
install_openssl() { install_openssl() {
echo "[2/6] Preparing OpenSSL ${OPENSSL_VERSION}" local tarball="openssl-${OPENSSL_VERSION}.tar.gz"
local srcdir="openssl-${OPENSSL_VERSION}"
local url="https://www.openssl.org/source/old/1.1.1/${tarball}"
if [ "${FORCE_OPENSSL}" -eq 0 ] && openssl_installation_ok; then
log "[2/6] OpenSSL ${OPENSSL_VERSION} already exists and works in ${OPENSSL_PREFIX}, skipping"
return 0
fi
log "[2/6] Preparing OpenSSL ${OPENSSL_VERSION}"
mkdir -p "${SRC_DIR}" mkdir -p "${SRC_DIR}"
mkdir -p "${OPENSSL_PREFIX}" mkdir -p "${OPENSSL_PREFIX}"
cd "${SRC_DIR}" cd "${SRC_DIR}"
if [ ! -f "openssl-${OPENSSL_VERSION}.tar.gz" ]; then if [ ! -f "${tarball}" ] || [ "${FORCE_OPENSSL}" -eq 1 ]; then
curl -fLO "https://www.openssl.org/source/old/1.1.1/openssl-${OPENSSL_VERSION}.tar.gz" rm -f "${tarball}"
download_file "${url}" "${tarball}"
else
log "Using existing source archive: ${SRC_DIR}/${tarball}"
fi fi
rm -rf "openssl-${OPENSSL_VERSION}" rm -rf "${srcdir}"
tar xf "openssl-${OPENSSL_VERSION}.tar.gz" tar xf "${tarball}"
cd "openssl-${OPENSSL_VERSION}" cd "${srcdir}"
echo "[3/6] Building OpenSSL into ${OPENSSL_PREFIX}" log "[3/6] Building OpenSSL into ${OPENSSL_PREFIX}"
./config \ ./config \
--prefix="${OPENSSL_PREFIX}" \ --prefix="${OPENSSL_PREFIX}" \
--openssldir="${OPENSSL_PREFIX}" \ --openssldir="${OPENSSL_PREFIX}" \
@@ -93,41 +306,80 @@ install_openssl() {
make -j"$(nproc)" make -j"$(nproc)"
rm -rf "${OPENSSL_PREFIX:?}/"* rm -rf "${OPENSSL_PREFIX:?}/"*
make install_sw make install_sw
openssl_installation_ok || die "OpenSSL ${OPENSSL_VERSION} verification failed after build"
} }
install_ruby_with_rvm() { install_ruby_with_rvm() {
echo "[4/6] Configuring RVM build environment" local -a rvm_args
local action="install"
log "[4/6] Configuring RVM build environment"
rvm autolibs disable rvm autolibs disable
export CPPFLAGS="-I${OPENSSL_PREFIX}/include" export CPPFLAGS="-I${OPENSSL_PREFIX}/include"
export CFLAGS="-I${OPENSSL_PREFIX}/include" export CFLAGS="-I${OPENSSL_PREFIX}/include"
export LDFLAGS="-L${OPENSSL_PREFIX}/lib -Wl,-rpath,${OPENSSL_PREFIX}/lib" export LDFLAGS="-L${OPENSSL_PREFIX}/lib -L${OPENSSL_PREFIX}/lib64 -Wl,-rpath,${OPENSSL_PREFIX}/lib -Wl,-rpath,${OPENSSL_PREFIX}/lib64"
export PKG_CONFIG_PATH="${OPENSSL_PREFIX}/lib/pkgconfig" export PKG_CONFIG_PATH="${OPENSSL_PREFIX}/lib/pkgconfig:${OPENSSL_PREFIX}/lib64/pkgconfig"
export RUBY_CONFIGURE_OPTS="--with-openssl-dir=${OPENSSL_PREFIX}" export RUBY_CONFIGURE_OPTS="--with-openssl-dir=${OPENSSL_PREFIX}"
echo "[5/6] Installing Ruby ${RUBY_VERSION} with RVM" if ruby_in_rvm_present; then
rvm install "${RUBY_VERSION}" --with-openssl-dir="${OPENSSL_PREFIX}" action="reinstall"
fi
rvm_args=("${action}" "${TARGET_RUBY_VERSION}" "--with-openssl-dir=${OPENSSL_PREFIX}")
if [ -n "${WEB_PROXY}" ]; then
rvm_args+=("--proxy" "${WEB_PROXY}")
fi
log "[5/6] ${action^}ing Ruby ${TARGET_RUBY_VERSION} with RVM"
rvm "${rvm_args[@]}"
} }
verify_installation() { verify_installation() {
echo "[6/6] Verifying installation" log "[6/6] Verifying installation"
rvm use "${RUBY_VERSION}" >/dev/null
local installed_ruby_version installed_openssl_version
if ruby_in_rvm_ok; then
installed_ruby_version="$(rvm "ruby-${TARGET_RUBY_VERSION}" do ruby -e 'print RUBY_VERSION')"
installed_openssl_version="$(rvm "ruby-${TARGET_RUBY_VERSION}" do ruby -ropenssl -e 'print OpenSSL::OPENSSL_VERSION')"
elif ruby_in_path_ok; then
installed_ruby_version="$(ruby -e 'print RUBY_VERSION')" installed_ruby_version="$(ruby -e 'print RUBY_VERSION')"
installed_openssl_version="$(ruby -ropenssl -e 'print OpenSSL::OPENSSL_VERSION')" installed_openssl_version="$(ruby -ropenssl -e 'print OpenSSL::OPENSSL_VERSION')"
else
die "Ruby ${TARGET_RUBY_VERSION} verification failed"
fi
echo "Installed Ruby version: ${installed_ruby_version}" log "Installed Ruby version: ${installed_ruby_version}"
echo "Linked OpenSSL version: ${installed_openssl_version}" log "Linked OpenSSL version: ${installed_openssl_version}"
} }
load_rvm main() {
[ "${EUID}" -eq 0 ] || die "run this script as root"
if ruby_already_installed; then parse_args "$@"
echo "Nothing to do" log "Requested Ruby version: ${TARGET_RUBY_VERSION}"
apply_proxy_env
load_rvm
if ruby_already_installed; then
log "Nothing to do"
exit 0 exit 0
fi fi
install_build_dependencies install_build_dependencies
install_openssl install_openssl
install_ruby_with_rvm
verify_installation if ruby_already_installed; then
log "Ruby is already installed after OpenSSL verification/build, skipping RVM build"
verify_installation
exit 0
fi
install_ruby_with_rvm
verify_installation
}
main "$@"