关于使用 Navicat 后 Arch 启动 Kernel Panic 的后续内容

前情提要 最近更新了 arch 在开机 Loading inital ramdisk 后会 kernel panic - #4,来自 依云

最近花了不少时间重装系统和恢复开发环境,原本一切正常,直到我尝试使用 Navicat 提供的 Appimage 连接达梦数据库时开始旧疾复发。为了连接达梦数据库 Navicat 需要安装一个 odbc 驱动。

在达梦官网的驱动包里有一个脚本 install_obdc_linux.sh 我还没完全看懂这个的内容,使用 sudo 执行后会在 /opt/etc 下创建一些目录并写入内容。

https://www.navicat.com.cn/support/help/当我想在-navicat-中创建连接到达梦数据库的连接时,我收到一个报错信息是“需要达梦-odbc-驱动程序”,这是什么意思以及我该怎么做呢?

安装完驱动后最重启 navicat 可以正常使用并连接数据库,但是一段时间后 navicat 将无法打开,并且会提示 segment fault,然后在关机时有一个叫 User Manager 的服务会卡 1min 左右,接着就是 Kernel Panic 了。

目前我还没搞清楚怎么处理,我手动把 /opt/etc 下面的一些内容删除过后重启正常了,看看有没有哪位大佬知道怎么回事

# install_odbc_linux.sh
#!/bin/sh

# ============================================================================
# Dameng ODBC Driver Installer for Linux (System & Flatpak)
# ============================================================================
# Description: This script installs the Dameng ODBC driver for both standard
#              system use and for sandboxed Flatpak applications.
# ============================================================================

# --- Configuration Constants ---
LIB_NAME="libdodbc.so"

# System-wide installation config
SYSTEM_DEST_PATH_DEFAULT="/opt/dameng_odbc"
SYSTEM_CONF_FILE="/etc/ld.so.conf.d/dameng_odbc.conf"
SYSTEM_DRIVER_SECTION="DM8 ODBC DRIVER"
ENV_VAR_FILE="/etc/profile.d/dm_home.sh"

# Flatpak-specific installation config
FLATPAK_DEST_PATH="$HOME/.config/navicat/ODBC/dameng"
FLATPAK_CONF_FILE="/etc/ld.so.conf.d/dameng_odbc_flatpak.conf"
FLATPAK_DRIVER_SECTION="DM8 ODBC DRIVER FLATPAK"

ODBC_INST_FILE="/etc/odbcinst.ini"

# --- Color Definitions ---
ORANGE='\033[0;33m'
NC='\033[0m' # No Color

# --- Help Message ---
show_help() {
  echo "Usage: $0"
  echo "Installs the Dameng ODBC driver for both system and Flatpak use."
  echo
  echo "This script must be run from the directory containing the Dameng"
  echo "ODBC driver files (e.g., libdodbc.so)."
  echo
  echo "Options:"
  echo "  -h, --help         Show this help message"
  exit 0
}

# --- Argument Parser ---
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
  show_help
fi

# ============================================================================
# User Confirmation
# ============================================================================
printf "\nThis script installs the Dameng ODBC driver for both standard system use and for sandboxed Flatpak applications.\n"
printf "${ORANGE}It will use 'sudo' to modify system configuration files in '/etc'.${NC}\n"
printf "You will be prompted for your password to proceed.\n\n"
printf "Press [Enter] to continue or Ctrl+C to cancel... "
read -r _ # Wait for user input, store it in a throwaway variable
echo
echo

# ============================================================================
# Pre-run Checks
# ============================================================================
# Check for required tools
REQUIRED_TOOLS="grep awk sed sudo ldconfig cp mkdir dirname chmod tee"
MISSING_TOOLS=""

for tool in $REQUIRED_TOOLS; do
  if ! command -v "$tool" >/dev/null 2>&1; then
    MISSING_TOOLS="$MISSING_TOOLS $tool"
  fi
done

if [ -n "$MISSING_TOOLS" ]; then
  echo "ERROR: Missing required tools:"
  for t in $MISSING_TOOLS; do
    echo "  - $t"
  done
  exit 1
fi

# --- Main Execution ---

# Get the directory where the script and driver files are located
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
if [ ! -f "${SCRIPT_DIR}/${LIB_NAME}" ]; then
    echo "ERROR: The required driver file '${LIB_NAME}' was not found in the script's directory."
    echo "Please run this script from the same folder where the Dameng driver files are located."
    exit 1
fi

# ============================================================================
# Phase 1: File Installation
# ============================================================================
echo "--- Phase 1: File Installation ---"
echo
echo "First, for the main system-wide installation:"
printf "Enter path (or press Enter to use default: %s): " "$SYSTEM_DEST_PATH_DEFAULT"
read -r USER_PATH

# Set system destination path to default if user input is empty
if [ -z "$USER_PATH" ]; then
  SYSTEM_DEST_PATH="$SYSTEM_DEST_PATH_DEFAULT"
else
  SYSTEM_DEST_PATH="$USER_PATH"
fi

# --- System Installation ---
echo "Installing system driver to: ${SYSTEM_DEST_PATH} (requires sudo)..."
sudo mkdir -p "$SYSTEM_DEST_PATH"
if [ $? -ne 0 ]; then
    echo "ERROR: Failed to create system destination directory."
    exit 1
fi
sudo find "$SCRIPT_DIR" -mindepth 1 -maxdepth 1 -not -name "$(basename "$0")" -exec cp -r {} "$SYSTEM_DEST_PATH/" \;
if [ $? -ne 0 ]; then
    echo "ERROR: Failed to copy files to the system destination."
    exit 1
fi
echo "System driver files copied successfully."
echo

# --- Flatpak Installation ---
echo "Installing Flatpak driver to: ${FLATPAK_DEST_PATH}..."
mkdir -p "$FLATPAK_DEST_PATH"
if [ $? -ne 0 ]; then
    echo "ERROR: Failed to create Flatpak destination directory."
    exit 1
fi
find "$SCRIPT_DIR" -mindepth 1 -maxdepth 1 -not -name "$(basename "$0")" -exec cp -r {} "$FLATPAK_DEST_PATH/" \;
if [ $? -ne 0 ]; then
    echo "ERROR: Failed to copy files to the Flatpak destination."
    exit 1
fi
echo "Flatpak driver files copied successfully."
echo

# ============================================================================
# Phase 2: System Configuration
# ============================================================================
echo "--- Phase 2: System Configuration (requires sudo) ---"
echo

# --- Configure System Driver ---
echo "Configuring the system-wide driver..."
echo "$SYSTEM_DEST_PATH" | sudo tee "$SYSTEM_CONF_FILE" >/dev/null
if sudo grep -q "^\\[${SYSTEM_DRIVER_SECTION}\\]" "$ODBC_INST_FILE" 2>/dev/null; then
  echo "Replacing previous '${SYSTEM_DRIVER_SECTION}' entry..."
  TEMP_FILE=$(mktemp)
  # Corrected awk command to reliably delete the entire section
  sudo awk -v section="[${SYSTEM_DRIVER_SECTION}]" '
    $0 == section { in_section = 1; next }
    $0 ~ /^\[/ { in_section = 0 }
    !in_section { print }
  ' "$ODBC_INST_FILE" > "$TEMP_FILE" && sudo mv "$TEMP_FILE" "$ODBC_INST_FILE"
fi
{
  printf "\n[%s]\n" "$SYSTEM_DRIVER_SECTION"
  printf "Description = Dameng ODBC Driver\n"
  printf "Driver = %s/%s\n" "$SYSTEM_DEST_PATH" "$LIB_NAME"
} | sudo tee -a "$ODBC_INST_FILE" >/dev/null
echo "System driver configured."
echo

# --- Configure Flatpak Driver ---
echo "Configuring the Flatpak-specific driver..."
echo "$FLATPAK_DEST_PATH" | sudo tee "$FLATPAK_CONF_FILE" >/dev/null
if sudo grep -q "^\\[${FLATPAK_DRIVER_SECTION}\\]" "$ODBC_INST_FILE" 2>/dev/null; then
  echo "Replacing previous '${FLATPAK_DRIVER_SECTION}' entry..."
  TEMP_FILE=$(mktemp)
  # Corrected awk command to reliably delete the entire section
  sudo awk -v section="[${FLATPAK_DRIVER_SECTION}]" '
    $0 == section { in_section = 1; next }
    $0 ~ /^\[/ { in_section = 0 }
    !in_section { print }
  ' "$ODBC_INST_FILE" > "$TEMP_FILE" && sudo mv "$TEMP_FILE" "$ODBC_INST_FILE"
fi
{
  printf "\n[%s]\n" "$FLATPAK_DRIVER_SECTION"
  printf "Description = Dameng ODBC Driver (Flatpak)\n"
  printf "Driver = %s/%s\n" "$FLATPAK_DEST_PATH" "$LIB_NAME"
} | sudo tee -a "$ODBC_INST_FILE" >/dev/null
echo "Flatpak driver configured."
echo

# --- Finalize Linker ---
echo "Updating linker cache..."
sudo ldconfig
echo "Linker cache updated."
echo

# ============================================================================
# Phase 2a: Set System Environment Variable
# ============================================================================
echo "--- Phase 2a: Setting DM_HOME Environment Variable for System Install ---"
echo

# First, check if the variable is already set in the current environment
if [ -n "$DM_HOME" ]; then
    DM_HOME_ACTION="existed"
    EXISTING_VALUE="$DM_HOME"
    echo "Environment variable 'DM_HOME' is already set in the current session."
    echo "Value: $EXISTING_VALUE"
    echo "Skipping this step."
else
    # If not in current session, check persistent system-wide profile files
    EXISTING_SETTING=$(grep -r "^export DM_HOME=" /etc/profile.d/ /etc/environment 2>/dev/null | head -n 1)
    if [ -n "$EXISTING_SETTING" ]; then
        DM_HOME_ACTION="existed"
        EXISTING_VALUE=$(echo "$EXISTING_SETTING" | cut -d'=' -f2)
        echo "System environment variable 'DM_HOME' appears to be already set in configuration files."
        echo "Found setting: $EXISTING_VALUE"
        echo "Skipping this step to avoid conflicts."
    else
        # If it doesn't exist anywhere, set it for the system-wide path.
        echo "Setting system environment variable 'DM_HOME' to '${SYSTEM_DEST_PATH}'..."
        # Create a script in /etc/profile.d to set the variable for all users on login
        echo "export DM_HOME=\"${SYSTEM_DEST_PATH}\"" | sudo tee "${ENV_VAR_FILE}" >/dev/null
        sudo chmod +x "${ENV_VAR_FILE}"
        if [ $? -eq 0 ]; then
            DM_HOME_ACTION="set"
            echo "Successfully created ${ENV_VAR_FILE}."
            echo "The 'DM_HOME' variable will be available in new terminal sessions or after a reboot."
        else
            DM_HOME_ACTION="failed"
            echo "ERROR: Failed to create environment variable file."
        fi
    fi
fi
echo

# ============================================================================
# Phase 3: Installation Summary
# ============================================================================
echo "--- Phase 3: Installation Summary ---"
echo
echo "==================================================="
echo "  Dameng ODBC Driver Installation Complete"
echo "==================================================="
echo
echo "  --- System Installation ---"
printf "  %-22s %s\n" "Driver Name:" "$SYSTEM_DRIVER_SECTION"
printf "  %-22s %s\n" "Installed To:" "$SYSTEM_DEST_PATH"
if [ "$DM_HOME_ACTION" = "set" ]; then
    printf "  %-22s %s\n" "Environment Variable:" "DM_HOME set to ${SYSTEM_DEST_PATH}"
elif [ "$DM_HOME_ACTION" = "existed" ]; then
    printf "  %-22s %s\n" "Environment Variable:" "DM_HOME already exists (Value: ${EXISTING_VALUE})"
fi
echo
echo "  --- Flatpak Installation ---"
printf "  %-22s %s\n" "Driver Name:" "$FLATPAK_DRIVER_SECTION"
printf "  %-22s %s\n" "Installed To:" "$FLATPAK_DEST_PATH"
echo
echo "  The drivers are now configured for use."
echo "==================================================="
echo

简单来说就是这个脚本会插入一堆自己的 so,相比 Arch 自带的更旧。在 sudo ldconfig 后系统的动态链接库会被劫持,导致其他系统组件也加载这些老旧动态链接库导致崩溃……怎么会有这么抽象的代码

PS:你可以尝试询问 AI 来自行打包,不建议在 Arch 上直接安装 Appimage 之类的包/执行自己不懂的脚本

Aur库里的navicat,可以试试,我一直在用没问题