报错的版本:
#!/bin/bash
set -euo pipefail # 启用严格模式,但后续会临时关闭 -u 以兼容外部脚本
# 获取脚本所在目录(绝对路径)
SHELL_FOLDER=$(dirname "$(readlink -f "$0")")
cd "$SHELL_FOLDER" || { echo "错误:无法进入目录 $SHELL_FOLDER"; exit 1; }
# 设置环境变量(注意:如果后续 source 会覆盖 LD_LIBRARY_PATH,可考虑放在 source 之后)
export AMSR_DISABLE_INTEGRITY_CHECK=1
export AMSR_PROCESS_SHORT_NAME_PATH=""
# 临时关闭未定义变量检查,以兼容某些外部脚本
set +u
# 加载依赖环境(先检查文件是否存在)
if [ -f "/opt/senseauto/senseauto-rscl/active/resource/scripts/setup.bash" ]; then
source "/opt/senseauto/senseauto-rscl/active/resource/scripts/setup.bash"
else
echo "警告:未找到 senseauto-rscl 的 setup.bash,可能影响运行"
fi
if [ -f "/opt/senseauto/senseauto-framework-sdk/active/resource/scripts/setup.bash" ]; then
source "/opt/senseauto/senseauto-framework-sdk/active/resource/scripts/setup.bash"
else
echo "警告:未找到 senseauto-framework-sdk 的 setup.bash,可能影响运行"
fi
# 恢复未定义变量检查
set -u
# 现在设置 LD_LIBRARY_PATH(放在 source 之后,避免被覆盖)
export LD_LIBRARY_PATH="/svp/lib:${SHELL_FOLDER}/AdaptiveApplications/Transmsg/lib:${LD_LIBRARY_PATH:-}"
# 定义目录和文件夹名称
SOURCE_DIR="./AdaptiveApplications/Transmsg/gen"
TARGET_DIR="./AdaptiveApplications/output/opt/Transmsg"
FOLDER_NAME="etc"
# 确保目标目录存在
mkdir -p "${TARGET_DIR}"
# 检查目标目录中是否存在指定文件夹
if [ ! -d "${TARGET_DIR}/${FOLDER_NAME}" ]; then
echo "文件夹 ${FOLDER_NAME} 不存在,正在从 ${SOURCE_DIR} 拷贝..."
# 检查源文件夹是否存在
if [ -d "${SOURCE_DIR}/${FOLDER_NAME}" ]; then
# 使用 cp 命令拷贝文件夹(-r 递归,-p 保留属性)
cp -r "${SOURCE_DIR}/${FOLDER_NAME}" "${TARGET_DIR}/"
echo "拷贝成功!"
else
echo "错误:源文件夹 ${SOURCE_DIR}/${FOLDER_NAME} 不存在!"
exit 1
fi
else
echo "文件夹 ${FOLDER_NAME} 已存在,跳过拷贝。"
fi
# 进入程序目录并启动
cd "./AdaptiveApplications/output/opt/Transmsg" || { echo "错误:无法进入程序目录"; exit 1; }
# 检查可执行文件是否存在并有执行权限
if [ ! -x "./bin/Transmsg" ]; then
echo "错误:可执行文件 ./bin/Transmsg 不存在或没有执行权限"
exit 1
fi
./bin/Transmsg
报错版本2:
SHELL_FOLDER=$(dirname $(readlink -f "$0"))
cd $SHELL_FOLDER
export AMSR_DISABLE_INTEGRITY_CHECK=1
export AMSR_PROCESS_SHORT_NAME_PATH=""
export LD_LIBRARY_PATH=/svp/lib:${SHELL_FOLDER}/AdaptiveApplications/Transmsg/lib:$LD_LIBRARY_PATH
source /opt/senseauto/senseauto-rscl/active/resource/scripts/setup.bash
source /opt/senseauto/senseauto-framework-sdk/active/resource/scripts/setup.bash
# 定义目录和文件夹名称
SOURCE_DIR="./AdaptiveApplications/Transmsg/gen"
TARGET_DIR="./AdaptiveApplications/output/opt/Transmsg"
FOLDER_NAME="etc"
# 检查目标目录中是否存在指定文件夹
if [ ! -d "${TARGET_DIR}/${FOLDER_NAME}" ]; then
echo "文件夹 ${FOLDER_NAME} 不存在,正在从 ${SOURCE_DIR} 拷贝..."
# 检查源文件夹是否存在
if [ -d "${SOURCE_DIR}/${FOLDER_NAME}" ]; then
# 使用cp命令拷贝文件夹
cp -r "${SOURCE_DIR}/${FOLDER_NAME}" "${TARGET_DIR}/"
# 可选:检查拷贝是否成功
if [ $? -eq 0 ]; then
echo "拷贝成功!"
else
echo "拷贝失败!"
exit 1
fi
else
echo "错误:源文件夹 ${SOURCE_DIR}/${FOLDER_NAME} 不存在!"
exit 1
fi
else
echo "文件夹 ${FOLDER_NAME} 已存在,跳过拷贝。"
fi
cd ./AdaptiveApplications/output/opt/Transmsg
./bin/Transmsg
最后修改后能跑的版本:
#!/bin/bash
set -euo pipefail # 启用严格模式,但后续会临时关闭 -u 以兼容外部脚本
# 获取脚本所在目录(绝对路径)
SHELL_FOLDER=$(dirname "$(readlink -f "$0")")
cd "$SHELL_FOLDER" || { echo "错误:无法进入目录 $SHELL_FOLDER"; exit 1; }
# 设置环境变量(注意:如果后续 source 会覆盖 LD_LIBRARY_PATH,可考虑放在 source 之后)
export AMSR_DISABLE_INTEGRITY_CHECK=1
export AMSR_PROCESS_SHORT_NAME_PATH=""
# 临时关闭未定义变量检查,以兼容某些外部脚本
set +u
# 加载依赖环境(先检查文件是否存在)
if [ -f "/opt/senseauto/senseauto-rscl/active/resource/scripts/setup.bash" ]; then
source "/opt/senseauto/senseauto-rscl/active/resource/scripts/setup.bash"
else
echo "警告:未找到 senseauto-rscl 的 setup.bash,可能影响运行"
fi
if [ -f "/opt/senseauto/senseauto-framework-sdk/active/resource/scripts/setup.bash" ]; then
source "/opt/senseauto/senseauto-framework-sdk/active/resource/scripts/setup.bash"
else
echo "警告:未找到 senseauto-framework-sdk 的 setup.bash,可能影响运行"
fi
# 恢复未定义变量检查
set -u
# 现在设置 LD_LIBRARY_PATH(放在 source 之后,避免被覆盖)
export LD_LIBRARY_PATH="/svp/lib:${SHELL_FOLDER}/AdaptiveApplications/Transmsg/lib:${LD_LIBRARY_PATH:-}"
# 定义目录和文件夹名称
SOURCE_DIR="./AdaptiveApplications/Transmsg/gen"
TARGET_DIR="./AdaptiveApplications/output/opt/Transmsg"
FOLDER_NAME="etc"
# 确保目标目录存在
mkdir -p "${TARGET_DIR}"
# 检查目标目录中是否存在指定文件夹
if [ ! -d "${TARGET_DIR}/${FOLDER_NAME}" ]; then
echo "文件夹 ${FOLDER_NAME} 不存在,正在从 ${SOURCE_DIR} 拷贝..."
# 检查源文件夹是否存在
if [ -d "${SOURCE_DIR}/${FOLDER_NAME}" ]; then
# 使用 cp 命令拷贝文件夹(-r 递归,-p 保留属性)
cp -r "${SOURCE_DIR}/${FOLDER_NAME}" "${TARGET_DIR}/"
echo "拷贝成功!"
else
echo "错误:源文件夹 ${SOURCE_DIR}/${FOLDER_NAME} 不存在!"
exit 1
fi
else
echo "文件夹 ${FOLDER_NAME} 已存在,跳过拷贝。"
fi
# 进入程序目录并启动
cd "./AdaptiveApplications/output/opt/Transmsg" || { echo "错误:无法进入程序目录"; exit 1; }
# 检查可执行文件是否存在并有执行权限
if [ ! -x "./bin/Transmsg" ]; then
echo "错误:可执行文件 ./bin/Transmsg 不存在或没有执行权限"
exit 1
fi
./bin/Transmsg
报错现象1:
nvidia@tegra-ubuntu:/ota/ws_usharing/transmsg_l29_m18 _mcu$ ./start_transmsg_l29.sh
./start_transmsg_l29.sh: line 3: cd: too many arguments
文件夹 etc 已存在,跳过拷贝。
./bin/Transmsg: error while loading shared libraries: libTransmsgCM.so.1: cannot open shared object file: No such file or directory
报错现象2:
nvidia@tegra-ubuntu:/ota/ws_usharing/transmsg_l29_m18_mcu_version$ ./start_transmsg_l29.sh
文件夹 etc 已存在,跳过拷贝。
Log sink failed to initialize:
Error Message: kInitializationFailedUnableToOpenSinkFile: There was an error opening the specified file for the file sink
User Message: Invalid argument
ara::core::Initialize() failed! Error in amsr::log::internal::InitializeComponent(). Result contains: kInitializationFailedUnableToOpenSinkFile: There was an error opening the specified file for the file sink, Invalid argument
Initialization for Adaptive Application failed.
Result contains: kInitializationFailedUnableToOpenSinkFile: There was an error opening the specified file for the file sink, Invalid argument
Could not initialize Adaptive Application!
./start_transmsg_l29.sh: line 43: 17096 Aborted ./bin/Transmsg



==============修改解决的最关键的部分===============================
1. 解决 cd: too many arguments 错误
报错版本2(简单版)
bash
SHELL_FOLDER=$(dirname $(readlink -f "$0"))
cd $SHELL_FOLDER
- 变量未加引号,如果路径包含空格,
cd会收到多个参数,直接报错退出。
正常版本
bash
SHELL_FOLDER=$(dirname "$(readlink -f "$0")")
cd "$SHELL_FOLDER" || { echo "错误:无法进入目录 $SHELL_FOLDER"; exit 1; }
- 所有变量都加了双引号,并增加错误处理,确保工作目录正确切换。
2. 解决 libTransmsgCM.so.1: cannot open shared object file 和 "Log sink failed" 错误
2.1 LD_LIBRARY_PATH 设置时机错误
报错版本2(简单版)
bash
export LD_LIBRARY_PATH=/svp/lib:${SHELL_FOLDER}/AdaptiveApplications/Transmsg/lib:$LD_LIBRARY_PATH
source /opt/senseauto/senseauto-rscl/active/resource/scripts/setup.bash
source /opt/senseauto/senseauto-framework-sdk/active/resource/scripts/setup.bash
LD_LIBRARY_PATH在source之前设置,外部脚本很可能覆盖它,导致程序运行时找不到动态库。
正常版本
bash
# 临时关闭未定义变量检查,以兼容某些外部脚本
set +u
# 加载依赖环境(先检查文件是否存在)
if [ -f "/opt/senseauto/senseauto-rscl/active/resource/scripts/setup.bash" ]; then
source "/opt/senseauto/senseauto-rscl/active/resource/scripts/setup.bash"
else
echo "警告:未找到 senseauto-rscl 的 setup.bash,可能影响运行"
fi
# ... 第二个 source ...
# 恢复未定义变量检查
set -u
# 现在设置 LD_LIBRARY_PATH(放在 source 之后,避免被覆盖)
export LD_LIBRARY_PATH="/svp/lib:${SHELL_FOLDER}/AdaptiveApplications/Transmsg/lib:${LD_LIBRARY_PATH:-}"
- 将
LD_LIBRARY_PATH移到source之后,保证外部脚本的修改不会冲掉我们需要的库路径。
2.2 未定义变量导致脚本退出
报错版本1(严格模式)
bash
export LD_LIBRARY_PATH="/svp/lib:${SHELL_FOLDER}/AdaptiveApplications/Transmsg/lib:${LD_LIBRARY_PATH}"
- 在
set -u模式下,如果LD_LIBRARY_PATH之前未定义,${LD_LIBRARY_PATH}会触发"unbound variable"错误,脚本直接退出,根本不会启动程序。
正常版本
bash
export LD_LIBRARY_PATH="/svp/lib:${SHELL_FOLDER}/AdaptiveApplications/Transmsg/lib:${LD_LIBRARY_PATH:-}"
- 使用
${LD_LIBRARY_PATH:-}语法,当变量未定义时自动展开为空字符串,避免了脚本因未定义变量而退出。
=================================================================
为什么其他修改不是"一下就能跑"的决定性因素?
-
set +u/set -u包裹 source:这个在报错版本1中已经存在,但它只是防止外部脚本的未定义变量导致脚本中断;如果库路径问题没解决,程序依然无法运行。 -
mkdir -p和 可执行文件检查:这些是健壮性增强,但原程序如果已经存在目录和文件,它们不会成为启动的障碍。 -
文件存在性检查 :同样属于健壮性改进,即使没有这些检查,只要文件存在,
source仍会执行。
总结
让脚本"一下就能跑"的两个最直接的修改:
| 错误现象 | 错误代码(报错版本) | 修复代码(正常版本) |
|---|---|---|
cd: too many arguments |
cd $SHELL_FOLDER |
cd "$SHELL_FOLDER" |
libTransmsgCM.so.1: cannot open shared object file + "Log sink failed" |
export LD_LIBRARY_PATH=... 放在 source 之前 ,且使用 ${LD_LIBRARY_PATH} 未加 :- |
将 export 移到 source 之后 ,并改为 ${LD_LIBRARY_PATH:-} |
这两个修改分别解决了路径切换失败和动态库加载失败的问题,程序得以正常启动。其他健壮性改进则让脚本在各种异常情况下都能给出明确提示,属于锦上添花。