用途:为 Rocky Linux 8.10 x86_64 上的 Synopsys / Cadence / Siemens EDA 工具准备 OS 级基础依赖(编译器、64 位运行时、X11/OpenGL、CAD 基础设施),并生成安装日志与依赖报告。
内容说明:
root / OS / 架构检查提前到日志目录创建之前,普通用户执行会直接看到权限提示。
DNF 元数据刷新加了容错,失败记录后继续,不再因
set -e中断。必需动态库(
libc、libstdc++、libgcc_s、libnsl.so.1、libssl.so.1.1、libcrypto.so.1.1)缺失会真正导致最终失败,不再出现“报告 SUCCESS 但库缺失”。必需软件包拆成多个小事务,单包不可用只影响所在小组。
可选包保留 DNF 错误输出到主日志,最终以逐包
rpm -q为准。Motif 只列
motif(已Obsoletes: openmotif);移除compat-openssl11(Rocky 8 原生即 1.1.1k),保留compat-openssl10供旧工具.so.10需求。DB 4.7 兼容链接仍默认关闭,启用时用
readelf -h验证目标为 x86-64 ELF。
使用方法:
chmod +x rocky810-eda-base.sh sudo ./rocky810-eda-base.sh # 需要 DB 4.7 兼容链接时(有 ABI 风险,非厂商支持) sudo EDA_DB47_COMPAT=1 ./rocky810-eda-base.sh # 必装组失败即停(默认是记录后继续) sudo EDA_CONTINUE_ON_REQUIRED_FAIL=0 ./rocky810-eda-base.sh
注意事项:
i686 库默认可选,是否安装应由
readelf -d <工具二进制> | grep NEEDED和ldd决定,不要盲目全装。DB 4.7 → 5.3 软链接只是链接器层面的变通,不保证 ABI 兼容。
脚本已在真实 Rocky 8.10 主机上执行过,包名是否全部存在于你启用的仓库、依赖是否冲突,但仍需单独确认。
脚本内容:
#!/usr/bin/env bash
#
# el8 (Rocky / RHEL / AlmaLinux 8.x) x86_64 - EDA base runtime preparation
# For Synopsys / Cadence / Siemens EDA environments.
#
# Create by Fasteda.cn
#
# Revision notes:
# - root check before any log-directory creation.
# - DNF metadata refresh wrapped with explicit error handling.
# - Missing REQUIRED runtime libraries fail the final status.
# - Required package groups split into smaller transactions.
# - Optional installs are per-package (el8 dnf has no
# `dnf install --skip-unavailable`; that flag is for history replay).
# - Motif / OpenSSL compat aligned with Rocky 8 reality:
# * motif obsoletes openmotif; only motif is listed.
# * compat-openssl11 removed (native OpenSSL is already 1.1.1k).
# * motif + compat-openssl10 are REQUIRED for typical EDA GUI/legacy.
# - Bare package name `libelf` removed; use elfutils-libelf only.
# - Common GUI/media deps added (gtk2, libpng12, libxslt, alsa, cups, LSB).
# - OS gate accepts rocky/rhel/almalinux on el8 (default still prefers 8.10).
# - Berkeley DB target validated with readelf -h, not just `file`.
# - DB47 compat remains opt-in and OFF by default.
#
set -Eeuo pipefail
# ------------------------------------------------------------
# 0. Root check FIRST — before touching /var/log
# ------------------------------------------------------------
if [[ "${EUID}" -ne 0 ]]; then
echo "[ERROR] Run as root: sudo $0"
exit 1
fi
if [[ ! -r /etc/os-release ]]; then
echo "[ERROR] /etc/os-release not found."
exit 1
fi
# shellcheck disable=SC1091
source /etc/os-release
case "${ID:-}" in
rocky|rhel|almalinux) ;;
*)
echo "[ERROR] Unsupported distribution ID='${ID:-}'."
echo "[ERROR] Supported: rocky, rhel, almalinux (el8)."
cat /etc/os-release
exit 1
;;
esac
# Prefer exact 8.10; allow other 8.x with a warning (binary-compatible family).
if [[ "${VERSION_ID:-}" != "8.10" ]]; then
if [[ "${VERSION_ID:-}" == 8.* ]] || [[ "${PLATFORM_ID:-}" == "platform:el8" ]]; then
echo "[WARN] Target is ${PRETTY_NAME:-unknown} (VERSION_ID=${VERSION_ID:-})."
echo "[WARN] Script is validated primarily on 8.10; continuing."
else
echo "[ERROR] This script targets el8 (preferably 8.10)."
cat /etc/os-release
exit 1
fi
fi
if [[ "$(uname -m)" != "x86_64" ]]; then
echo "[ERROR] Only x86_64 is supported."
exit 1
fi
# ------------------------------------------------------------
# 1. Configuration (safe to set after root check)
# ------------------------------------------------------------
LOG_DIR="/var/log/eda-install"
TIMESTAMP="$(date +%Y%m%d_%H%M%S)"
LOG_FILE="${LOG_DIR}/eda_install_${TIMESTAMP}.log"
REPORT_FILE="${LOG_DIR}/eda_report_${TIMESTAMP}.txt"
EDA_DB47_COMPAT="${EDA_DB47_COMPAT:-0}"
EDA_CONTINUE_ON_REQUIRED_FAIL="${EDA_CONTINUE_ON_REQUIRED_FAIL:-1}"
FAILED_REQUIRED=()
FAILED_OPTIONAL=()
INSTALLED_OPTIONAL=()
CHECK_RESULTS=()
MISSING_REQUIRED_LIBS=()
mkdir -p "$LOG_DIR"
exec > >(tee -a "$LOG_FILE") 2>&1
on_error() {
local rc=$?
echo
echo "[ERROR] Unexpected failure (exit=${rc}, line=${BASH_LINENO[0]:-unknown})."
echo "[ERROR] See log: $LOG_FILE"
exit "$rc"
}
trap on_error ERR
echo "============================================================"
echo " el8 EDA Base Environment Installation"
echo "============================================================"
echo "OS : ${PRETTY_NAME:-el8}"
echo "Architecture : $(uname -m)"
echo "Hostname : $(hostname)"
echo "Start : $(date)"
echo "Log : $LOG_FILE"
echo "DB47 compat : ${EDA_DB47_COMPAT} (0=off, 1=opt-in)"
echo "Required fail: continue=${EDA_CONTINUE_ON_REQUIRED_FAIL} (0=fail-fast)"
# ------------------------------------------------------------
# Helper functions
# ------------------------------------------------------------
# True if rpm name or name.arch is installed.
rpm_is_installed() {
local pkg="$1"
rpm -q "$pkg" >/dev/null 2>&1
}
install_required() {
local group="$1"
shift
echo
echo ">>> REQUIRED: ${group}"
if dnf install -y "$@"; then
echo "[OK] ${group}"
else
echo "[ERROR] Failed group: ${group}"
FAILED_REQUIRED+=("$group")
if [[ "$EDA_CONTINUE_ON_REQUIRED_FAIL" == "0" ]]; then
echo "[FATAL] Aborting on required group failure."
exit 1
fi
fi
}
# el8 DNF 4.x: do NOT use `dnf install --skip-unavailable`
# (that flag belongs to history replay, not install).
# Install each package individually so one missing NVR cannot abort the rest.
install_optional_group() {
local group="$1"
shift
echo
echo ">>> OPTIONAL group: ${group}"
local pkg rc
for pkg in "$@"; do
if rpm_is_installed "$pkg"; then
INSTALLED_OPTIONAL+=("$pkg")
echo " [PRESENT] $pkg (already installed)"
continue
fi
echo " [TRY ] $pkg"
# With set -E, a failing command can still fire ERR even under set +e.
# Temporarily clear the ERR trap around expected dnf failures.
trap - ERR
rc=0
dnf install -y "$pkg" || rc=$?
trap on_error ERR
if [[ $rc -eq 0 ]] && rpm_is_installed "$pkg"; then
INSTALLED_OPTIONAL+=("$pkg")
echo " [PRESENT] $pkg"
else
FAILED_OPTIONAL+=("$pkg")
echo " [ABSENT ] $pkg"
fi
done
}
# Prefer /lib64 file presence; fall back to ldconfig -p x86-64 entries.
# Plain `grep -F` on ldconfig alone has produced false negatives right after
# large multilib transactions on some el8 hosts.
library_found_x86_64() {
local lib="$1"
if [[ -e "/lib64/${lib}" || -e "/usr/lib64/${lib}" ]]; then
return 0
fi
ldconfig -p 2>/dev/null | grep -F "${lib}" | grep -q 'x86-64'
}
check_required_library() {
local lib="$1"
if library_found_x86_64 "$lib"; then
echo "[OK] ${lib}"
CHECK_RESULTS+=("[OK] ${lib}")
else
echo "[MISSING] ${lib} (REQUIRED)"
CHECK_RESULTS+=("[MISSING-REQUIRED] ${lib}")
MISSING_REQUIRED_LIBS+=("$lib")
fi
}
check_optional_library() {
local lib="$1"
if library_found_x86_64 "$lib"; then
echo "[OK] ${lib}"
CHECK_RESULTS+=("[OK] ${lib}")
else
echo "[OPTIONAL MISSING] ${lib}"
CHECK_RESULTS+=("[OPTIONAL MISSING] ${lib}")
fi
}
# ------------------------------------------------------------
# 2. DNF metadata — explicit error handling, do NOT abort
# ------------------------------------------------------------
echo
echo ">>> [1/10] Refreshing DNF metadata"
# PackageKit holding /var/lib/rpm causes: cannot open Packages database (-30969)
if command -v systemctl >/dev/null 2>&1; then
if systemctl is-active --quiet packagekit 2>/dev/null; then
echo "[INFO] Stopping PackageKit to avoid RPM DB lock contention."
systemctl stop packagekit 2>/dev/null || true
fi
fi
pkill -x packagekitd >/dev/null 2>&1 || true
rm -f /var/lib/rpm/__db.* 2>/dev/null || true
if ! dnf clean metadata; then
echo "[WARN] Failed to clean DNF metadata; continuing with cached metadata."
FAILED_REQUIRED+=("DNF metadata clean")
fi
if ! dnf makecache --refresh; then
echo "[ERROR] Failed to refresh DNF metadata."
FAILED_REQUIRED+=("DNF metadata refresh")
if [[ "$EDA_CONTINUE_ON_REQUIRED_FAIL" == "0" ]]; then
exit 1
fi
fi
# ------------------------------------------------------------
# 3. Development environment — split
# ------------------------------------------------------------
echo
echo ">>> [2/10] Development environment"
if dnf group install -y "Development Tools"; then
echo "[OK] Development Tools group"
else
echo "[WARN] Development Tools group could not be fully installed."
FAILED_OPTIONAL+=("Development Tools group")
fi
install_required "C/C++/Fortran compiler toolchain" \
gcc gcc-c++ gcc-gfortran make cmake binutils
# csh is typically provided by tcsh on el8; listing both is fine.
install_required "Scripting and build utilities" \
perl python3 ksh tcsh csh tcl tk environment-modules \
which file tar gzip bzip2 xz patch diffutils hostname
install_required "Core development headers" \
glibc-headers glibc-devel libstdc++ libstdc++-devel
# ------------------------------------------------------------
# 4. 64-bit runtime — split into logical groups
# ------------------------------------------------------------
echo
echo ">>> [3/10] 64-bit runtime libraries"
install_required "Base system runtime" \
glibc libgcc libstdc++ zlib ncurses-libs
install_required "Network and security runtime" \
libnsl libnsl2 libtirpc openssl-libs libcurl
# Use elfutils-libelf only — bare name `libelf` is not a reliable NVR on el8.
install_required "Compression, XML, and utility runtime" \
elfutils-libelf libpng libjpeg-turbo \
libuuid libxml2 expat libaio numactl-libs pcre libxslt libffi
install_required "Font and GUI runtime" \
fontconfig freetype libdb gtk2 gtk3
install_required "Legacy image / media helpers" \
libpng12 alsa-lib cups-libs
# redhat-lsb-core pulls many BaseOS tools; keep it optional so AppStream-only
# mirrors do not fail the whole required chain.
install_optional_group "LSB core compatibility" \
redhat-lsb-core
install_optional_group "Additional 64-bit development headers" \
zlib-devel ncurses-devel libnsl2-devel libtirpc-devel \
libpng-devel libjpeg-turbo-devel openssl-devel libuuid-devel \
libxml2-devel libcurl-devel libaio-devel pcre-devel libxslt-devel
# ------------------------------------------------------------
# 5. 32-bit compatibility — OPTIONAL by design
# ------------------------------------------------------------
echo
echo ">>> [4/10] 32-bit compatibility libraries (OPTIONAL)"
echo "[INFO] Verify actual ELF needs with: readelf -d <binary> | grep NEEDED"
echo "[INFO] and ldd <binary>; do not install i686 blindly."
install_optional_group "i686 core runtime" \
glibc.i686 libgcc.i686 libstdc++.i686 zlib.i686 \
ncurses-libs.i686 libnsl.i686 libnsl2.i686 libtirpc.i686 \
libdb.i686
install_optional_group "i686 X11/OpenGL libraries" \
libX11.i686 libXau.i686 libxcb.i686 libXext.i686 \
libXt.i686 libXtst.i686 libXrender.i686 libXft.i686 \
libXi.i686 libICE.i686 libSM.i686 libXpm.i686 \
libXmu.i686 libXrandr.i686 libXcursor.i686 libXdamage.i686 \
libXp.i686 libXv.i686 mesa-libGL.i686 mesa-libGLU.i686
# ------------------------------------------------------------
# 6. X11 / GUI / OpenGL
# ------------------------------------------------------------
echo
echo ">>> [5/10] X11, GUI and OpenGL"
install_required "Core X11 runtime" \
libX11 libXau libxcb libXext libXt libXtst libXrender \
libXft libXpm libXmu libXrandr libXcursor libXdamage libXi \
libXcomposite libXfixes libXinerama libXxf86vm libICE libSM
install_required "OpenGL, font, and display utilities" \
mesa-libGL mesa-libGLU mesa-dri-drivers fontconfig freetype \
xorg-x11-xauth xorg-x11-server-Xvfb xterm
install_optional_group "Additional X11 compatibility libraries" \
libXp libXv libXScrnSaver libXres libXxf86dga
# ------------------------------------------------------------
# 7. Legacy compatibility — Motif + OpenSSL 1.0 are REQUIRED
# ------------------------------------------------------------
echo
echo ">>> [6/10] Legacy EDA compatibility packages"
# motif obsoletes openmotif and provides openmotif; listing both is redundant.
install_required "Motif runtime (obsoletes openmotif)" \
motif
install_required "OpenSSL 1.0 legacy compatibility (.so.10)" \
compat-openssl10
install_optional_group "Motif / GUI development packages" \
motif-devel libX11-devel libXext-devel libXt-devel libXpm-devel \
libXmu-devel libXp-devel freetype-devel mesa-libGL-devel \
elfutils-libelf-devel libstdc++-devel.i686
# ------------------------------------------------------------
# 8. Berkeley DB compatibility — opt-in, with readelf validation
# ------------------------------------------------------------
echo
echo ">>> [7/10] Berkeley DB compatibility"
ldconfig
if [[ "$EDA_DB47_COMPAT" == "1" ]]; then
echo
echo "############################################################"
echo "# WARNING: EDA_DB47_COMPAT=1"
echo "# libdb-4.7.so -> libdb-5.3.so is a linker-level workaround."
echo "# It does NOT guarantee Berkeley DB 4.7 API/ABI compatibility."
echo "# Use only when a specific tool fails with libdb-4.7.so missing."
echo "############################################################"
DB53_LIB=""
for p in /usr/lib64/libdb-5.3.so /lib64/libdb-5.3.so; do
if [[ -e "$p" ]]; then
DB53_LIB="$p"
break
fi
done
if [[ -z "$DB53_LIB" ]]; then
DB53_LIB="$(ldconfig -p 2>/dev/null |
awk '$1 == "libdb-5.3.so" && /x86-64/ {print $NF; exit}')"
fi
if [[ -n "$DB53_LIB" && -e "$DB53_LIB" ]]; then
DB53_REAL="$(readlink -f "$DB53_LIB")"
DB47_LINK="/usr/lib64/libdb-4.7.so"
DB47_IS_OURS=0
# Stronger than `file`: verify ELF machine is x86-64.
if ! readelf -h "$DB53_REAL" 2>/dev/null | grep -q "Advanced Micro Devices X86-64"; then
echo "[ERROR] $DB53_REAL is not an x86-64 ELF object; refusing to link."
exit 1
fi
echo "DB 5.3 target: $DB53_REAL"
if [[ -L "$DB47_LINK" ]]; then
EXISTING_TARGET="$(readlink -f "$DB47_LINK" || true)"
if [[ "$EXISTING_TARGET" == "$DB53_REAL" ]]; then
echo "[OK] Existing DB 4.7 link already points to DB 5.3."
DB47_IS_OURS=1
else
echo "[WARN] Existing symlink points elsewhere; not overwritten:"
ls -l "$DB47_LINK"
fi
elif [[ -e "$DB47_LINK" ]]; then
echo "[WARN] Existing non-symlink DB 4.7 file; not overwritten:"
ls -l "$DB47_LINK"
else
ln -s "$DB53_REAL" "$DB47_LINK"
echo "[OK] Created $DB47_LINK -> $DB53_REAL"
DB47_IS_OURS=1
fi
if [[ "$DB47_IS_OURS" == "1" && -r "$DB47_LINK" ]]; then
if python3 -c 'import ctypes,sys; ctypes.CDLL(sys.argv[1])' "$DB47_LINK" 2>/dev/null; then
echo "[OK] DB 4.7 -> 5.3 compat link loads (linker-level only)."
CHECK_RESULTS+=("[OK] DB 4.7 compat link loads (ABI unverified)")
else
echo "[WARN] ctypes load test failed for the compat link."
CHECK_RESULTS+=("[WARN] DB compat link load test failed")
fi
elif [[ -r "$DB47_LINK" ]]; then
echo "[INFO] Existing libdb-4.7.so is not our link; load test skipped."
fi
else
echo "[WARN] libdb-5.3.so not found; DB 4.7 link not created."
FAILED_OPTIONAL+=("Berkeley DB 4.7 compat (target missing)")
fi
else
echo "[INFO] EDA_DB47_COMPAT=0 (default). libdb-4.7.so is NOT created."
echo "[INFO] If a Cadence tool fails with libdb-4.7.so missing:"
echo "[INFO] a) rerun with EDA_DB47_COMPAT=1 (ABI risk), or"
echo "[INFO] b) place a genuine CentOS 7 libdb-4.7.so in LD_LIBRARY_PATH."
fi
# ------------------------------------------------------------
# 9. CAD infrastructure
# ------------------------------------------------------------
echo
echo ">>> [8/10] CAD infrastructure and network utilities"
install_required "Remote access and network clients" \
openssh-clients openssh-server bind-utils net-tools iproute iputils
install_required "Filesystem and time services" \
nfs-utils autofs chrony rsync
install_required "Debugging and inspection tools" \
lsof strace gdb tcpdump procps-ng util-linux
# ------------------------------------------------------------
# 10. Runtime verification — REQUIRED libs affect final status
# ------------------------------------------------------------
echo
echo ">>> [9/10] Refresh linker cache and verify runtime"
ldconfig
# --- REQUIRED runtime libraries ---
check_required_library "libc.so.6"
check_required_library "libstdc++.so.6"
check_required_library "libgcc_s.so.1"
check_required_library "libnsl.so.1"
check_required_library "libssl.so.1.1"
check_required_library "libcrypto.so.1.1"
check_required_library "libssl.so.10"
check_required_library "libcrypto.so.10"
check_required_library "libXm.so.4"
check_required_library "libX11.so.6"
check_required_library "libGL.so.1"
# --- Optional / compatibility libraries ---
check_optional_library "libnsl.so.2"
check_optional_library "libdb-5.3.so"
check_optional_library "libtinfo.so.6"
check_optional_library "libXt.so.6"
check_optional_library "libpng12.so.0"
check_optional_library "libgtk-x11-2.0.so.0"
# ------------------------------------------------------------
# 11. Report
# ------------------------------------------------------------
echo
echo ">>> [10/10] Generate report"
{
echo "============================================================"
echo "el8 EDA Base Environment Report"
echo "============================================================"
echo "Date : $(date)"
echo "Hostname : $(hostname)"
echo "OS : ${PRETTY_NAME:-el8}"
echo "Architecture : $(uname -m)"
echo "DB47 compat : ${EDA_DB47_COMPAT} (0=off, 1=opt-in)"
echo
echo "Runtime checks:"
printf '%s\n' "${CHECK_RESULTS[@]}"
echo
echo "Required failures:"
if ((${#FAILED_REQUIRED[@]} == 0)); then
echo "None"
else
printf '%s\n' "${FAILED_REQUIRED[@]}"
fi
echo
echo "Missing REQUIRED libraries:"
if ((${#MISSING_REQUIRED_LIBS[@]} == 0)); then
echo "None"
else
printf '%s\n' "${MISSING_REQUIRED_LIBS[@]}"
fi
echo
echo "Optional packages ABSENT (rpm -q verified):"
if ((${#FAILED_OPTIONAL[@]} == 0)); then
echo "None"
else
printf '%s\n' "${FAILED_OPTIONAL[@]}" | sort -u
fi
echo
echo "Optional packages PRESENT (rpm -q verified):"
if ((${#INSTALLED_OPTIONAL[@]} == 0)); then
echo "None"
else
printf '%s\n' "${INSTALLED_OPTIONAL[@]}" | sort -u
fi
echo
echo "Berkeley DB files:"
ls -l /usr/lib64/libdb* 2>/dev/null || true
echo
echo "OpenSSL entries:"
ldconfig -p 2>/dev/null | grep -E 'libssl|libcrypto' || true
echo
echo "Key RPMs:"
rpm -q gcc gcc-c++ make cmake ksh tcsh tcl tk glibc \
libstdc++ libnsl libnsl2 libdb openssl-libs compat-openssl10 \
motif mesa-libGL xorg-x11-server-Xvfb gtk2 libpng12 \
redhat-lsb-core 2>/dev/null || true
echo
echo "Log : $LOG_FILE"
echo "Report : $REPORT_FILE"
echo "============================================================"
} | tee "$REPORT_FILE"
# ------------------------------------------------------------
# 12. Final status
# ------------------------------------------------------------
echo
echo "============================================================"
FINAL_FAIL=0
if ((${#FAILED_REQUIRED[@]} > 0)); then
echo "[FAILED] Required package groups failed."
FINAL_FAIL=1
fi
if ((${#MISSING_REQUIRED_LIBS[@]} > 0)); then
echo "[FAILED] Missing REQUIRED runtime libraries:"
printf ' - %s\n' "${MISSING_REQUIRED_LIBS[@]}"
FINAL_FAIL=1
fi
if ((FINAL_FAIL == 0)); then
echo "[SUCCESS] EDA base environment prepared."
else
echo "[FAILED] One or more required checks did not pass."
fi
echo
echo "HINT: For Siemens Calibre on Rocky/RHEL 8, if it reports VCO mismatch, try:"
echo " export USE_CALIBRE_VCO=aoi"
echo
echo "HINT: This script prepares OS runtime deps only. Install EDA tools,"
echo " FlexLM/SCL, and vendor modulefiles separately."
echo
echo "Log : $LOG_FILE"
echo "Report : $REPORT_FILE"
echo "============================================================"
exit "$FINAL_FAIL"


网友留言: