Files
enginex-ascend-910-vllm/csrc/scripts/package/common/sh/common_func_v2.inc
Sun Ruoxi 7f8a1b1f7a init v0.23.0
Signed-off-by: Sun Ruoxi <sunruoxi@4paradigm.com>
2026-08-27 15:11:51 +08:00

1730 lines
42 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/sh
# -----------------------------------------------------------------------------------------------------------
# Copyright (c) 2025 Huawei Technologies Co., Ltd.
# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
# CANN Open Software License Agreement Version 2.0 (the "License").
# Please refer to the License for details. You may not use this file except in compliance with the License.
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
# See LICENSE in the root of the software repository for the full text of the License.
# -----------------------------------------------------------------------------------------------------------
# 公共函数库
# 总setenv文件权限
SETENV_MOD="550"
# 总setenv文件可写状态权限
SETENV_WRITEABLE_MOD="600"
# 默认特性配置
DEFAULT_FEATURE_PARAM="all n all"
#export PS4='+ ${FUNCNAME[0]:+${FUNCNAME[0]}():} ${BASH_SOURCE}:${LINENO}: '
#set -x
RESET_MOD="750"
# db.info文件格式如下
# ---
# CommonLib|atc,fwkacllib
# Compiler|atc,fwkacllib
# ---
# 使用"|"分隔模块名和包名列表,包名列表使用","分隔
# 文件中块名保持以升序排序
PKG_DB_INFO_RELPATH="var/ascend_package_db.info"
# 缓存mod文件名
STASH_MOD_PATH="stash_mod.txt"
# stash_mod文件权限
STASH_FILE_MOD="600"
# 写日志
log() {
local cur_date_="$(date +"%Y-%m-%d %H:%M:%S")"
local log_type_="${1}"
local msg_="${2}"
local log_format_="[Common] [${cur_date_}] [${log_type_}]: ${msg_}"
if [ "${log_type_}" = "INFO" ]; then
echo "${log_format_}"
elif [ "${log_type_}" = "WARNING" ]; then
echo "${log_format_}"
elif [ "${log_type_}" = "ERROR" ]; then
echo "${log_format_}"
elif [ "${log_type_}" = "DEBUG" ]; then
echo "${log_format_}" 1> /dev/null
fi
}
# 返回列表长度
__length_list() {
local list="$1"
local var="$2"
local list_item
local cnt=0
for list_item in ${list}; do
cnt=$((cnt+1))
done
eval "${var}=\"${cnt}\""
}
# 获取列表索引值
__index_list() {
local list="$1"
shift
local list_item
local cnt=0
if [ $# -eq 0 ]; then
return 0
fi
for list_item in ${list}; do
if [ ${1} -eq ${cnt} ]; then
eval "${2}=\"${list_item}\""
shift 2
if [ $# -eq 0 ]; then
return 0
fi
fi
cnt=$((cnt+1))
done
return 0
}
# 从列表中移除一项
__remove_item_in_list() {
local to_removed="$1"
shift
local list="$*"
local list_item
local new_list
for list_item in ${list}; do
if [ "${to_removed}" != "${list_item}" ]; then
if [ "${new_list}" = "" ]; then
new_list="${list_item}"
else
new_list="${new_list} ${list_item}"
fi
fi
done
echo "${new_list}"
}
# 元素是否在列表中
__item_in_list() {
local _outvar="$1"
local _item="$2"
shift 2
local _list_item
local _matched="false"
for _list_item in $*; do
if [ "${_item}" = "${_list_item}" ]; then
_matched="true"
break
fi
done
eval "${_outvar}=\"${_matched}\""
}
# 反转列表
__reverse_list() {
local _outvar="$1"
local _list="$2"
local _new_list=""
local _list_item
for _list_item in ${_list}; do
if [ "${_new_list}" = "" ]; then
_new_list="${_list_item}"
else
_new_list="${_list_item} ${_new_list}"
fi
done
eval "${_outvar}=\"${_new_list}\""
}
# 修改各文件及目录的属性
change_own() {
local recursive="$3"
local option=""
local username="${USERNAME}"
local usergroup="${USERGROUP}"
if [ "$2" != "NA" ]; then
if [ "${recursive}" = "true" ]; then
option="-R"
fi
eval chown ${option} -h \"$2\" \"$1\"
if [ $? -ne 0 ]; then
log "ERROR" "$1 chown failed!"
return 1
fi
fi
}
# 获取install_for_all文件权限
get_install_for_all_mod() {
local _outvar="$1"
local _mod="$2"
local _new_mod _other_mod
_new_mod="${_mod%?}"
_other_mod="${_new_mod#${_new_mod%?}}"
_other_mod="$(($_other_mod & 5))" # other权限位移除写权限仅支持普通用户运行
eval "${_outvar}=\"${_new_mod}${_other_mod}\""
}
# 修改各文件及目录的权限
change_mod() {
local mod="$2"
local install_for_all="$3"
local recursive="$4"
local option="" new_mod
# 对于软连接可能目标文件还没有拷贝进来导致无法修改mod这里过滤掉软连接
if [ -L "$1" ]; then
return 0
fi
if [ "$2" != "NA" ]; then
if [ "${recursive}" = "true" ]; then
option="-R"
fi
# 如果设置了install_for_all则安装时other权限跟group权限对齐
if [ "${install_for_all}" = "y" ]; then
get_install_for_all_mod new_mod "$mod"
chmod ${option} "${new_mod}" "$1"
else
chmod ${option} "$2" "$1"
fi
if [ $? -ne 0 ]; then
log "ERROR" "$1 chmod failed!"
return 1
fi
fi
return 0
}
# 获取文件权限
get_file_mod() {
local _outvar="$1"
local _options="" _ret
shift
while true; do
case "$1" in
-L|--dereference)
_options="${_options} $1"
shift
;;
*)
break
;;
esac
done
local _path="$1"
local _result
_result="$(stat ${_options} -c %a "${_path}")"
_ret="$?" && [ $_ret -ne 0 ] && return $_ret
eval "${_outvar}=\"${_result}\""
}
# 检查路径是否为绝对路径
__check_abs_path() {
local path="$1"
if [ "${path#/}" != "${path}" ]; then
is_abs_path="true"
else
is_abs_path="false"
fi
}
__set_abs_path() {
local install_path="$1"
local path="$2"
local varname="$3"
local is_abs_path
__check_abs_path "${path}"
if [ "${is_abs_path}" != "true" ]; then
eval "${varname}=\"${install_path}/${path}\""
else
eval "${varname}=\"${path}\""
fi
}
# 创建目录
make_dir() {
local path="$1"
mkdir -p "${path}"
if [ $? -ne 0 ]; then
log "ERROR" "${path} mkdir failed!"
exit 1
fi
return 0
}
# 检查install_path在docker_root之中
check_install_path_in_docker_root() {
local install_path="$1"
local docker_root="$2"
echo "${install_path}" | grep "^${docker_root}" > /dev/null 2>&1
if [ $? -ne 0 ]; then
log "ERROR" "check install path ${install_path} in docker root ${docker_root} failed!"
return 1
fi
return 0
}
# 移除路径右侧斜线(/)
rstrip_path() {
local _outvar="$1"
local _path="$2"
_path="$(echo "${_path}" | sed "s/\/\+\$//g")"
eval "${_outvar}=\"${_path}\""
}
# 包是否在tools目录下
is_package_under_tools() {
local _outvar="$1"
local _package="$2"
local _result_iput="false"
if [ "${_package}" = "aoe" ] || [ "${_package}" = "nca" ] || [ "${_package}" = "amct_acl" ] || [ "${_package}" = "ncs" ]; then
_result_iput="true"
fi
eval "${_outvar}=\"${_result_iput}\""
}
# 获取包目录名
get_package_dir() {
local _outvar="$1"
local _package="$2"
local _is_under_tools _result
if [ "${USE_SHARE_INFO}" == "y" ]; then
_result="share/info"
else
is_package_under_tools "_is_under_tools" "${_package}"
if [ "${_is_under_tools}" = "true" ]; then
_result="tools"
else
_result=""
fi
fi
eval "${_outvar}=\"${_result}\""
}
# 获取包目录路径
get_package_dirpath() {
local _outvar="$1"
local _package="$2"
local _is_under_tools _result
if [ "${USE_SHARE_INFO}" == "y" ]; then
_result="share/info/${_package}"
else
is_package_under_tools "_is_under_tools" "${_package}"
if [ "${_is_under_tools}" = "true" ]; then
_result="tools/${_package}"
else
_result="${_package}"
fi
fi
eval "${_outvar}=\"${_result}\""
}
# 获取包ascend_install.info路径
get_package_install_info() {
local _outvar="$1"
local _install_path="$2"
local _version_dir="$3"
local _package="$4"
local _package_dirpath=""
eval "${_outvar}=\"\""
get_package_dirpath "_package_dirpath" "${_package}"
eval "${_outvar}=\"${_install_path}/${_version_dir}/${_package_dirpath}/ascend_install.info\""
}
# 获取包version.info路径
get_package_version_info() {
local _outvar="$1"
local _install_path="$2"
local _version_dir="$3"
local _package="$4"
local _package_dirpath=""
eval "${_outvar}=\"\""
get_package_dirpath "_package_dirpath" "${_package}"
eval "${_outvar}=\"${_install_path}/${_version_dir}/${_package_dirpath}/version.info\""
}
# 获取包filelist.csv路径
get_package_filelist() {
local _outvar="$1"
local _install_path="$2"
local _version_dir="$3"
local _package="$4"
local _package_dirpath=""
eval "${_outvar}=\"\""
get_package_dirpath "_package_dirpath" "${_package}"
eval "${_outvar}=\"${_install_path}/${_version_dir}/${_package_dirpath}/script/filelist.csv\""
}
# 获取包install_common_parser.sh路径
get_package_install_common_parser() {
local _outvar="$1"
local _install_path="$2"
local _version_dir="$3"
local _package="$4"
local _package_dirpath=""
eval "${_outvar}=\"\""
get_package_dirpath "_package_dirpath" "${_package}"
eval "${_outvar}=\"${_install_path}/${_version_dir}/${_package_dirpath}/script/install_common_parser.sh\""
}
# 获取latest_manager的install_common_parser.sh路径
get_latest_manager_install_common_parser() {
local _outvar="$1"
local _install_path="$2"
local _latest_dir="$3"
eval "${_outvar}=\"${_install_path}/${_latest_dir}/var/manager/install_common_parser.sh\""
}
# 获取包script目录路径
get_package_script_dirpath() {
local _outvar="$1"
local _install_path="$2"
local _version_dir="$3"
local _package="$4"
local _package_dirpath=""
eval "${_outvar}=\"\""
get_package_dirpath "_package_dirpath" "${_package}"
eval "${_outvar}=\"${_install_path}/${_version_dir}/${_package_dirpath}/script\""
}
# 检查参数不为空
check_param_not_empty() {
local name="$1"
local error_msg="$2"
local value
eval "value=\"\${${name}}\""
if [ "${value}" = "" ]; then
comm_log "ERROR" "$2"
return 1
fi
return 0
}
# 检查文件存在
check_file_exists() {
local path="$1"
local error_msg="$2"
if [ ! -f "${path}" ]; then
comm_log "ERROR" "$2"
return 1
fi
return 0
}
# 检查返回值是否为0
check_ret_error() {
local ret="$1"
local msg="$2"
if [ ${ret} -ne 0 ]; then
comm_log "ERROR" "${msg}"
return ${ret}
fi
return 0
}
# 检查返回值是否为0
check_ret_warning() {
local ret="$1"
local msg="$2"
if [ ${ret} -ne 0 ]; then
comm_log "WARNING" "${msg}"
return ${ret}
fi
return 0
}
# 获取真实路径
get_realpath() {
local _outvar="$1"
local _path_gr="$2"
_path_gr="$(readlink -f "${_path_gr}")"
eval "${_outvar}=\"${_path_gr}\""
}
# 检查返回值是否为0
cleanup_if_error() {
local ret="$1"
local cleanup="$2"
if [ ${ret} -ne 0 ]; then
eval "${cleanup}"
return ${ret}
fi
return 0
}
# 获取临时目录
get_tmp_root() {
local _outvar="$1"
local _result_gtr
if [ -d "${HOME}" ]; then
_result_gtr="${HOME}"
elif [ $(id -u) -eq 0 ] && [ -d "/root" ]; then
_result_gtr="/root"
else
_result_gtr="${PWD}"
fi
eval "${_outvar}=\"${_result_gtr}\""
return 0
}
# 获取临时文件
get_tmp_file() {
local _outvar="$1"
local _filename="$2"
local _tmp_file_gtf _result
get_tmp_root "_tmp_file_gtf"
_result=$(mktemp "$_tmp_file_gtf/${_filename}_XXXXXX")
check_ret_warning "$?" "mktemp $_tmp_file_gtf/${_filename}_XXXXXX failed."
ret="$?" && [ $ret -ne 0 ] && return $ret
eval "${_outvar}=\"${_result}\""
return 0
}
# 获取包架构
get_scene_arch() {
local _outvar="$1"
local _scene_filepath="$2"
local _result
_result="$(grep "^arch=" "${_scene_filepath}" | cut -d= -f2-)"
eval "${_outvar}=\"${_result}\""
}
# 打包feature参数
pack_feature_param() {
local _outvar="$1"
local _feature_type="$2"
local _feature_exclude_all="$3"
local _chip="$4"
eval "${_outvar}=\"${_feature_type} ${_feature_exclude_all} ${_chip}\""
}
# 解包feature参数
# 注意,调用解包时参数不可加引号
unpack_feature_param() {
local _feature_type_var="$1"
local _feature_exclude_all_var="$2"
local _chip_var="$3"
shift 3
eval "${_feature_type_var}=\"${1}\""
eval "${_feature_exclude_all_var}=\"${2}\""
eval "${_chip_var}=\"${3}\""
}
# 展开version.info文件中参数
expand_version_file() {
if [ "${VERSION_FILE}" = "" ]; then
return 0
fi
get_version "VERSION" "${VERSION_FILE}"
get_version_dir "VERSION_DIR" "${VERSION_FILE}"
}
# 提取第一项
extract_1st() {
local _outvar="$1"
eval "${_outvar}=\"$2\""
}
# 提取第二项
extract_2nd() {
local _outvar="$1"
eval "${_outvar}=\"$3\""
}
# 路径转为sed正则表达式
path_to_regex() {
local _outvar="$1"
local _path="$2"
local _reslut_ptr="$(echo "${_path}" | sed "s#\/#\\\/#g")"
eval "${_outvar}=\"${_reslut_ptr}\""
}
# 设置默认值
set_default() {
local _outvar="$1"
local _input="$2"
local _default="$3"
if [ "${_input}" = "" ]; then
eval "${_outvar}=\"${_default}\""
else
eval "${_outvar}=\"${_input}\""
fi
}
# 标准化feature参数
# 输入的feature参数中如果有all字段表示安装所有feature
# 则将feature参数重置为all在后续流程中安装所有feature
# 卸载流程中feature与chip强制为all保证卸载掉block中的所有文件
normalize_feature() {
local _outvar="$1"
local _feature_nf="$2"
local _operation="$3"
if [ "$_operation" = "uninstall" ]; then
eval "${_outvar}=\"all\""
return 0
fi
if [ "$_feature_nf" = "" ]; then
eval "${_outvar}=\"all\""
return 0
fi
case "${_feature_nf}" in
all,*)
_feature_nf="all"
;;
*,all)
_feature_nf="all"
;;
*,all,*)
_feature_nf="all"
;;
esac
eval "${_outvar}=\"${_feature_nf}\""
}
# 删除软连接
remove_softlink_icp() {
local softlink="$1"
if [ "${softlink}" = "" ]; then
return 0
fi
if [ "${softlink}" != "NA" ] && [ -L "${softlink}" ]; then
rm -f "${softlink}"
if [ $? -ne 0 ]; then
log "ERROR" "remove ${softlink} failed!"
return 1
fi
fi
return 0
}
#移除文件
remove_file() {
local target="$1"
local softlink="$2"
local ret
if [ -e "${target}" ] || [ -L "${target}" ]; then
rm -f "${target}"
if [ $? -ne 0 ]; then
log "ERROR" "remove ${target} failed!"
return 1
fi
fi
remove_softlink_icp "${softlink}"
ret="$?" && [ ${ret} -ne 0 ] && return ${ret}
return 0
}
# 创建文件夹
create_folder() {
local install_path="$1"
local target="$2"
local softlinks_str="$3"
local ret target_abs
__set_abs_path "${install_path}" "${target}" "target_abs"
if [ ! -d "${target_abs}" ]; then
make_dir "${target_abs}"
ret="$?" && [ ${ret} -ne 0 ] && return ${ret}
fi
change_mod "${target_abs}" "${RESET_MOD}" ""
ret="$?" && [ ${ret} -ne 0 ] && return ${ret}
if [ "${softlinks_str}" != "NA" ]; then
create_softlink_by_install_path "${install_path}" "${target}" "${softlinks_str}"
ret="$?" && [ ${ret} -ne 0 ] && return ${ret}
fi
return 0
}
# 创建目录
create_dirs() {
local install_path="$1"
local line="$2"
local target
local target_abs
local softlinks_str
local ret
__index_list "${line}" 1 "target" 4 "softlinks_str"
__set_abs_path "${install_path}" "${target}" "target_abs"
if [ -L "${target_abs}" ] ; then
rm -f "${target_abs}"
log "WARNING" "${target_abs} is an existing soft-link, deleted."
fi
create_folder "${install_path}" "${target}" "${softlinks_str}"
ret="$?" && [ ${ret} -ne 0 ] && return ${ret}
return 0
}
# 修改目录的权限和属组
reset_mod_dirs() {
local install_path="$1"
local line="$2"
local mod
local target
local target_abs
local is_abs_path ret
__index_list "${line}" 1 "target"
__set_abs_path "${install_path}" "${target}" "target_abs"
# 目录不存在时跳过
if [ ! -d "${target_abs}" ]; then
return 0
fi
# 只处理目录,没有处理目录的软链接
change_mod "${target_abs}" "${RESET_MOD}" "" "false"
ret="$?" && [ ${ret} -ne 0 ] && return ${ret}
return 0
}
# 递归修改目录的权限和属组
reset_mod_dirs_recursive() {
local install_path="$1"
local line="$2"
local mod
local target
local target_abs
local is_abs_path ret
__index_list "${line}" 1 "target"
__set_abs_path "${install_path}" "${target}" "target_abs"
# 目录不存在时跳过
if [ ! -d "${target_abs}" ]; then
return 0
fi
# 只处理目录,没有处理目录的软链接
change_mod "${target_abs}" "${RESET_MOD}" "" "true"
ret="$?" && [ ${ret} -ne 0 ] && return ${ret}
return 0
}
__unpack_softlinks() {
local softlinks_str="$1"
local varname="$2"
local item
local temp
OLD_IFS="${IFS}"
IFS=";"
temp=""
for item in ${softlinks_str}; do
if [ "${temp}" = "" ]; then
temp="${item}"
else
temp="${temp} ${item}"
fi
done
IFS="${OLD_IFS}"
eval "${varname}=\"${temp}\""
}
#移除文件夹
remove_dir_icp() {
if [ -e "$1" ] || [ -L "$1" ]; then
rm -fr "$1"
if [ $? -ne 0 ]; then
log "ERROR" "$1 remove failed!"
return 1
fi
fi
return 0
}
# 创建软链时,移除存在的目录
remove_exists_dir_in_create_softlink() {
local dirpath="$1"
if [ -d "${dirpath}" ] && [ ! -L "${dirpath}" ]; then
log "WARNING" "${dirpath} is an existing directory in create softlink, deleted."
change_mod "${dirpath}" "700" "n" "true"
remove_dir_icp "${dirpath}"
fi
}
# 创建绝对软链接
create_softlink_icp_absolute() {
local src_path="$1"
local dst_path="$2"
remove_exists_dir_in_create_softlink "${dst_path}"
ln -sfn "${src_path}" "${dst_path}"
if [ $? -ne 0 ]; then
log "ERROR" "create softlink absolute from ${src_path} to ${dst_path} failed!"
return 1
fi
return 0
}
# 该函数与common_func.inc脚本中的相同
# install_common_parser.sh不一定能source到common_func.inc原因见source common_func.inc的注释
# 所以这里需要重复定义
create_softlink_icp_relative() {
local src_path="$1"
local dst_path="$2"
local source="top${src_path}"
local target="top${dst_path}"
# 若变量内容从尾向前的数据符合,则将符合的最短数据删除
local common="${target%/*}"
# 若变量内容从头开始的数据符合,则将符合的最短数据删除
local forward="${source#"$common"/}"
local result=""
while [ "${forward}" = "${source}" ]; do
common="$(dirname "$common")"
forward="${source#"$common"/}"
result="../${result}"
done
result="${result}${forward}"
remove_exists_dir_in_create_softlink "${dst_path}"
ln -sfn "${result}" "${dst_path}"
if [ $? -ne 0 ]; then
log "ERROR" "create softlink relative from ${src_path} to ${dst_path} failed!"
return 1
fi
return 0
}
# 创建软连接
create_softlink_by_install_path() {
local install_path="$1"
local target="$2"
local softlinks_str="$3"
local softlinks softlink
local target_abs
local softlink_abs
local is_abs_path
local ret
if [ "${softlinks_str}" = "NA" ]; then
return 0
fi
__unpack_softlinks "${softlinks_str}" "softlinks"
for softlink in ${softlinks}; do
__check_abs_path "${target}"
if [ "${is_abs_path}" = "true" ]; then
__set_abs_path "${install_path}" "${softlink}" "softlink_abs"
create_softlink_icp_absolute "${target}" "${softlink_abs}"
ret="$?" && [ ${ret} -ne 0 ] && return ${ret}
continue
fi
__check_abs_path "${softlink}"
if [ "${is_abs_path}" = "true" ]; then
__set_abs_path "${install_path}" "${target}" "target_abs"
create_softlink_icp_absolute "${target_abs}" "${softlink}"
ret="$?" && [ ${ret} -ne 0 ] && return ${ret}
continue
fi
create_softlink_icp_relative "${install_path}/${target}" "${install_path}/${softlink}"
ret="$?" && [ ${ret} -ne 0 ] && return ${ret}
done
return 0
}
# 创建软链接。icp后缀为避免重名
create_softlink_icp() {
local options=""
local is_relative="false"
while true; do
case "$1" in
-r|--relative)
is_relative="true"
shift
;;
-*)
log "ERROR" "unsupported option $1 in create softlink icp!"
return 1
;;
*)
break
;;
esac
done
local src_path="$1"
local dst_path="$2"
if [ "${is_relative}" = "true" ]; then
create_softlink_icp_relative "${src_path}" "${dst_path}"
else
create_softlink_icp_absolute "${src_path}" "${dst_path}"
fi
}
# 修改权限和属组
change_mod_and_own(){
local target="$1"
local mod="$2"
local own="$3"
local install_for_all="$4"
local recursive="$5"
local ret
change_mod "${target}" "${mod}" "${install_for_all}" "${recursive}"
ret="$?" && [ $ret -ne 0 ] && return $ret
change_own "${target}" "${own}" "${recursive}"
ret="$?" && [ $ret -ne 0 ] && return $ret
return 0
}
# 修改目录的权限和属组
change_mod_and_own_dirs() {
local install_path="$1"
local line="$2"
local target
local mod
local own
local is_abs_path
__index_list "${line}" 1 "target" 2 "mod" 3 "own"
__check_abs_path "${target}"
if [ "${is_abs_path}" != "true" ]; then
target="${install_path}/${target}"
fi
if [ ! -d "${target}" ]; then
return 0
fi
# 只处理目录,没有处理目录的软链接
change_mod_and_own "${target}" "${mod}" "${own}" "${INSTALL_FOR_ALL}" "false"
}
# 创建stash_mod.txt文件
create_stash_mod() {
local install_path="$1"
rm -f "${install_path}/${STASH_MOD_PATH}"
touch "${install_path}/${STASH_MOD_PATH}"
chmod ${STASH_FILE_MOD} "${install_path}/${STASH_MOD_PATH}"
}
# 删除stash_mod.txt文件
remove_stash_mod() {
local install_path="$1"
rm -f "${install_path}/${STASH_MOD_PATH}"
}
# 修改目录的权限和属组
restore_stash_mod() {
local install_path="$1"
local line="$2"
local target
local target_abs
local mod
local is_abs_path ret
__index_list "${line}" 0 "target" 1 "mod"
__set_abs_path "${install_path}" "${target}" "target_abs"
# 目录不存在时跳过
if [ ! -d "${target_abs}" ]; then
return 0
fi
# 只处理目录,没有处理目录的软链接
change_mod "${target_abs}" "${mod}" "${INSTALL_FOR_ALL}"
ret="$?" && [ ${ret} -ne 0 ] && return ${ret}
return 0
}
# 修改目录的权限,暂存原文件权限
reset_mod_dirs_with_stash_mod() {
local install_path="$1"
local line="$2"
local mod
local target
local target_abs
local is_abs_path ret
__index_list "${line}" 1 "target"
__set_abs_path "${install_path}" "${target}" "target_abs"
# 目录不存在时跳过
if [ ! -d "${target_abs}" ]; then
return 0
fi
get_file_mod "mod" "${target_abs}"
echo "${target}:${mod}" >> "${install_path}/${STASH_MOD_PATH}"
# 只处理目录,没有处理目录的软链接
change_mod "${target_abs}" "${RESET_MOD}" ""
ret="$?" && [ ${ret} -ne 0 ] && return ${ret}
return 0
}
# 删除软连接列表
remove_softlinks() {
local install_path="$1"
local softlinks_str="$2"
local softlinks softlink softlink_abs ret
__unpack_softlinks "${softlinks_str}" "softlinks"
for softlink in ${softlinks}; do
__set_abs_path "${install_path}" "${softlink}" "softlink_abs"
remove_softlink_icp "${softlink_abs}"
ret="$?" && [ ${ret} -ne 0 ] && return ${ret}
done
return 0
}
# 删除安装文件夹
remove_install_dirs() {
local install_path="$1"
local line="$2"
local target softlinks_str is_abs_path
__index_list "${line}" 1 "target" 4 "softlinks_str"
if [ "${target}" != "NA" ]; then
__check_abs_path "${target}"
if [ "${is_abs_path}" != "true" ]; then
target="${install_path}/${target}"
fi
if [ -d "${target}" ]; then
# 不同的blocks中可能配置相同的dir_info。目录不为空时不删除。
if [ "$(ls -A "${target}")" != "" ]; then
return 0
fi
remove_dir_icp "${target}"
ret="$?" && [ $ret -ne 0 ] && return $ret
fi
if [ "${softlinks_str}" != "NA" ]; then
remove_softlinks "${install_path}" "${softlinks_str}"
ret="$?" && [ ${ret} -ne 0 ] && return ${ret}
fi
fi
return 0
}
# 获取所有的blocks
get_blocks_info() {
local _outvar="$1"
local _install_path="$2"
local _result _db_filepath="${_install_path}/${PKG_DB_INFO_RELPATH}"
if [ ! -f "${_db_filepath}" ]; then
return 0
fi
_result="$(cut -d'|' -f1 "${_db_filepath}" | xargs)"
eval "${_outvar}=\"${_result}\""
}
# 列表转为正则表达式
trans_list_to_regex() {
local _outvar="$1"
local _value="$2"
# 移除右侧空白符mawk无法编译右侧存在空白符时的正则表达式^(EngineeringCommon|)$
local _result="$(echo "$_value" | sed 's/\s\+$//g' | sed 's/ /|/g' | xargs printf "^(%s)$")"
eval "${_outvar}=\"${_result}\""
}
parse_filelist_core() {
awk -F, '{ print $3,$4,$6,$7,$9,$12,$13,$14,$15 }'
}
# 过滤公共路径条目
filter_common_dirs() {
awk -F, '
$11 == "Y" {
print $0
}
$11 == "YY" {
print $1 "," $2 "," $3 "," $4 "," $5 "," $6 "," $7 "," $8 ",NA," $10 "," $11 "," $12 "," $13 "," $14 "," $15 "," $16
}
'
}
# 过滤包内软链
filter_pkg_inner_softlink() {
awk -F, '$15 != "NA" { print $0 }'
}
# 过滤块
filter_blocks() {
local blocks="$1"
local blocks_reg
trans_list_to_regex "blocks_reg" "$blocks"
awk -F, "\$14 ~ \"$blocks_reg\" {print \$0}"
}
# 过滤不匹配块
filterfalse_blocks() {
local blocks="$1"
local blocks_reg
trans_list_to_regex "blocks_reg" "$blocks"
awk -F, "\$14 !~ \"$blocks_reg\" {print \$0}"
}
# 过滤操作类型条目
filter_operate_type() {
local operator_type="$1"
local operator_type_reg
trans_list_to_regex "operator_type_reg" "$operator_type"
# ~为部分匹配,正则表达式需要匹配头尾
awk -F, "\$2 ~ \"$operator_type_reg\" {print \$0}"
}
# 过滤安装类型条目
filter_install_type() {
local install_type="$1"
local install_type_reg
# 注意:特征串不能嵌套,否则会错误匹配
if [ "$install_type" != "full" ] && [ "$install_type" != "debug" ]; then
install_type_reg="(all)|($install_type)"
else
install_type_reg="(all)|(docker)|(devel)|(run)"
fi
awk -F, "\$8 ~ \"$install_type_reg\" {print \$0}"
}
# 过滤特性参数
filter_feature_param() {
local feature_param="$1"
local feature_type
local feature_exclude_all # feature是否为排除公共all文件
local chip chip_list # 芯片类型
local feature_list feature_type_list
unpack_feature_param "feature_type" "feature_exclude_all" "chip" ${feature_param}
if [ "$feature_type" != "all" ]; then
feature_list="$(echo $feature_type | tr ',' ' ')"
if [ "${feature_exclude_all}" = "y" ]; then
feature_type_list="${feature_list}"
else
feature_type_list="comm ${feature_list}"
fi
else
feature_type_list="all"
fi
if [ "$chip" != "all" ]; then
chip_list="all $(echo $chip | tr ',' ' ')"
else
chip_list="all"
fi
# filelist中的feature为all表示所有场景下都安装这个文件
# 输入参数中的feature为all表示安装所有的feature
awk -v feature_type_list="${feature_type_list}" \
-v chip_list="${chip_list}" '
BEGIN {
FS= ","
split(feature_type_list, input_feature_type_arr, " ")
split(chip_list, input_chip_arr, " ")
}
function match_feature_type(features_str) {
if (feature_type_list == "all") {
return 1
}
matched_feature_type_tmp=0
split(features_str, features, ";")
for(i in features)
{
for(j in input_feature_type_arr) {
if(input_feature_type_arr[j] == features[i]) {
matched_feature_type_tmp = 1
break;
}
}
}
return matched_feature_type_tmp
}
function match_chip(chip_str) {
if (chip_list == "all") {
return 1
}
matched_chip_tmp=0
split(chip_str, chips, ";")
for(i in chips)
{
for(j in input_chip_arr) {
if(input_chip_arr[j] == chips[i]) {
matched_chip_tmp = 1
break;
}
}
}
return matched_chip_tmp
}
{
matched_feature_type = match_feature_type($10);
if (matched_feature_type == 0) next;
matched_chip = match_chip($16)
if (matched_chip == 0) next
print $0
}'
}
# 读取fileist的第2行到最后行
tail_filelist() {
local filelist_path="$1"
tail -n +2 "$filelist_path"
}
# 解析filelist.csv脚本
parse_filelist() {
local install_type="$1"
local operate_type="$2"
local filelist_path="$3"
local feature_param="$4"
local filter_type="$5"
local blocks="$6"
if [ ! -f "$filelist_path" ]; then
log "ERROR" "filelist $filelist_path does not exist!"
exit 1
fi
# 注意这里的filelist需要是全局变量。其它函数如add_filelist_blocks_info会引用这个变量。
filelist=$(
parse_filelist_v2 "$install_type" "$operate_type" "$filelist_path" "$feature_param" \
"$filter_type" "$blocks"
)
}
# 解析filelist.csv脚本
parse_filelist_v2() {
local install_type="$1"
local operate_type="$2"
local filelist_path="$3"
local feature_param="$4"
local filter_type="$5"
local blocks="$6"
local filter_cmds=""
if [ "$operate_type" != "all" ]; then
filter_cmds="$filter_cmds | filter_operate_type \"$operate_type\""
fi
if printf "%s" "$filter_type" | grep -Eq "\<filter_common_dirs\>"; then
filter_cmds="$filter_cmds | filter_common_dirs"
fi
if printf "%s" "$filter_type" | grep -Eq "\<filter_by_pkg_inner_softlink\>"; then
filter_cmds="$filter_cmds | filter_pkg_inner_softlink"
fi
if printf "%s" "$filter_type" | grep -Eq "\<filter_by_blocks\>|\<filterfalse_blocks\>" && [ "$blocks" != "" ]; then
filter_cmds="$filter_cmds | filterfalse_blocks \"$blocks\""
fi
if printf "%s" "$filter_type" | grep -Eq "\<filter_blocks\>" && [ "$blocks" != "" ]; then
filter_cmds="$filter_cmds | filter_blocks \"$blocks\""
fi
tail_filelist "$filelist_path" \
| filter_install_type "$install_type" \
| filter_feature_param "$feature_param" \
| eval cat $filter_cmds \
| parse_filelist_core
}
pack_exec_params() {
local _outvar="$1"
local _exec_mode="$2"
eval "${_outvar}=\"${_exec_mode}\""
}
# 迭代filelist中的条目执行操作
foreach_filelist_exec() {
local filelist="$1"
local sort_filelist="$2"
local exec_mode="$3"
local exec_func="$4"
local install_path="$5"
local ret=0 tmp_ret exec_params
shift 5
pack_exec_params "exec_params" "${exec_mode}"
if [ "${sort_filelist}" = "reverse" ]; then
# 对第二列文件路径做倒序排列,保证先删除子文件夹,再删除父文件夹
# 不可以使用echo "${filelist}"
# 在dash中会消耗\\$username:\\$usergroup中的一个反斜线bash与busybox的sh无此问题
# 需要使用here document防止shell的解析过程
filelist=$(sort -k2,2 -b -r <<EOF
${filelist}
EOF
)
elif [ "${sort_filelist}" = "no" ]; then
# 不排序
:
else
log "ERROR" "sort_filelist param wrong! sort_filelist is ${sort_filelist}, exec_func is ${exec_func}, parse_func is ${parse_func}"
exit 1
fi
if [ "${exec_mode}" = "concurrency" ] || [ "${exec_mode}" = "normal" ]; then
# 并发模式或正常模式
:
else
log "ERROR" "exec_mode param wrong! exec_mode is ${exec_mode}, exec_func is ${exec_func}, parse_func is ${parse_func}"
exit 1
fi
while read line; do
array=${line}
__length_list "${array}" "len_array"
if [ ${len_array} -eq 0 ]; then
continue
fi
"${exec_func}" "${install_path}" "${line}" "${exec_params}" "$@"
tmp_ret="$?" && [ ${tmp_ret} -ne 0 ] && ret="${tmp_ret}"
done << EOF
${filelist}
EOF
if [ "${exec_mode}" = "concurrency" ]; then
wait
fi
return $ret
}
# 迭代遍历filelist中的条目执行一些操作
foreach_filelist() {
local filter_type="$1"
local exec_func="$2"
local install_type="$3"
local install_path="$4"
local operate_type="$5"
local filelist_path="$6"
local feature_param="$7"
local sort_filelist="$8" # 排序filelist可选参数为[no,reverse]
local exec_mode="$9" # 执行模式,可选参数为[normal,concurrency]
shift 9
local ret blocks
if [ "$filter_type" = "filter_by_blocks" ]; then
get_blocks_info "blocks" "$install_path"
fi
foreach_filelist_v2 "$exec_func" "$install_type" "$install_path" "$operate_type" "$filelist_path" \
"$feature_param" "$filter_type" "$blocks" "$sort_filelist" "$exec_mode" "$@"
ret="$?" && [ $ret -ne 0 ] && return $ret
return 0
}
# 迭代遍历filelist中的条目执行一些操作
foreach_filelist_v2() {
local exec_func="$1"
local install_type="$2"
local install_path="$3"
local operate_type="$4"
local filelist_path="$5"
local feature_param="$6"
local filter_type="$7"
local blocks="$8"
local sort_filelist="$9" # 排序filelist可选参数为[no,reverse]
local exec_mode="${10}" # 执行模式,可选参数为[normal,concurrency]
shift 10
local filter_cmds=""
local ret
parse_filelist "${install_type}" "${operate_type}" "${filelist_path}" "${feature_param}" \
"${filter_type}" "${blocks}"
foreach_filelist_exec "${filelist}" "${sort_filelist}" "${exec_mode}" "${exec_func}" "${install_path}" "$@"
ret="$?" && [ $ret -ne 0 ] && return $ret
return 0
}
# 解析stash_mod.txt
parse_stashmod() {
local stashmod_path="$1"
if [ ! -f "${stashmod_path}" ]; then
log "ERROR" "stash mod ${stashmod_path} does not exist!"
exit 1
fi
stashmod_list=$(awk '
BEGIN{
FS=":"
}
{
print $1,$2
}' "${stashmod_path}")
}
# 迭代遍历stash_mod中的条目执行操作
foreach_stashmod() {
local exec_func="$1"
local install_path="$2"
local sort_type="$3" # 排序方式,可选参数为[no,reverse]
local array
local len_array
local line
local ret=0 tmp_ret
parse_stashmod "${install_path}/${STASH_MOD_PATH}"
if [ "${sort_type}" = "reverse" ]; then
# 对第二列文件路径做倒序排列,保证先处理子文件夹,再处理父文件夹
stashmod_list=$(echo "${stashmod_list}" | sort -k1,1 -r)
elif [ "${sort_type}" = "no" ]; then
# 不排序
echo > /dev/null
else
log "ERROR" "sort_type param wrong! sort_type is ${sort_type}, exec_func is ${exec_func}"
exit 1
fi
while read line; do
array=${line}
__length_list "${array}" "len_array"
if [ ${len_array} -eq 0 ]; then
continue
fi
"${exec_func}" "${install_path}" "${line}"
tmp_ret="$?" && [ ${tmp_ret} -ne 0 ] && ret="${tmp_ret}"
done << EOF
${stashmod_list}
EOF
return $ret
}
# 创建目录并且设置权限
make_dir_with_permission() {
local path="$1"
local mod="$2"
local username="$3"
local usergroup="$4"
local install_for_all="$5"
local ret
make_dir "${path}"
ret="$?" && [ ${ret} -ne 0 ] && return ${ret}
change_mod "${path}" "${mod}" "${install_for_all}"
ret="$?" && [ ${ret} -ne 0 ] && return ${ret}
change_own "${path}" "${username}:${usergroup}"
ret="$?" && [ ${ret} -ne 0 ] && return ${ret}
return 0
}
# blocks转换为db.info配置
blocks_to_db_item() {
local package="$1"
local version_dir="$2"
xargs printf "%s|[$package:$version_dir]\n"
}
# 折叠第2个参数
# 需要保证输入数据第1个参数已排序
fold_2() {
local fs="$1"
local concat="$2"
local options=""
if [ "$fs" != "" ]; then
options="-F$fs"
fi
awk $options -v CONCAT="$concat" '
NR == 1 {
field1 = $1
field2 = $2
}
NR != 1 {
if (field1 == $1) {
field2 = field2 CONCAT $2
} else {
print field1 FS field2
field1 = $1
field2 = $2
}
}
END {
if (field1) {
print field1 FS field2
}
}'
}
# 折叠第3个参数保持第2个参数
# 需要保证输入数据第1个参数已排序
fold_3_keep_2() {
local fs="$1"
local concat="$2"
local options=""
if [ "$fs" != "" ]; then
options="-F$fs"
fi
awk $options -v CONCAT="$concat" '
NR == 1 {
field1 = $1
field2 = $2
field3 = $3
}
NR != 1 {
if (field1 == $1) {
field3 = field3 CONCAT $3
} else {
print field1 FS field2 FS field3
field1 = $1
field2 = $2
field3 = $3
}
}
END {
if (field1) {
print field1 FS field2 FS field3
}
}'
}
# 根据第1列排序
sort_1() {
local sep="$1"
local options=""
if [ "$sep" != "" ]; then
options="-t$sep"
fi
sort $options -k1,1 -s
}
# 显示3,4列有差异的条目
show_diff_3_4() {
awk '$3 != $4 { print $0 }'
}
# 显示具有最少列数的条目
show_min_nf() {
local min_nf="$1"
awk -v MIN_NF="$min_nf" 'NF >= MIN_NF { print $0 }'
}
# 选取第3,2,1列
select_fields_3_2_1() {
awk '{print $3, $2, $1}'
}
# 选取第1列
select_fields_1() {
awk '{print $1}'
}
# 删除db.info配置
del_db_items() {
local package="$1"
local version_dir="$2"
sed "s/\\[$package:$version_dir\\]//g; /|\$/d"
}
# 保留块最后一个配置
# 输出第1列第2列包名第3列版本目录
remain_db_last_item() {
awk -F '[|:\\[\\]]+' '{ print $1, $(NF-2), $(NF-1) }'
}
# 移除空白行
remove_blank_line() {
sed '/^$/d'
}
# 保证文件权限
ensure_permission() {
local path="$1"
local mod="$2"
local username="$3"
local usergroup="$4"
local install_for_all="$5"
change_mod "$path" "$mod" "$install_for_all"
ret=$? && [ $ret -ne 0 ] && return $ret
change_own "$path" "$username:$usergroup"
ret=$? && [ $ret -ne 0 ] && return $ret
return 0
}
# 创建文件
touch_file() {
local path="$1"
local mod="$2"
local username="$3"
local usergroup="$4"
local install_for_all="$5"
local ret
touch "$path"
ret=$? && [ $ret -ne 0 ] && return $ret
ensure_permission "$path" "$mod" "$username" "$usergroup" "$install_for_all"
ret=$? && [ $ret -ne 0 ] && return $ret
return 0
}
# 保证文件存在
ensure_file() {
local path="$1"
local mod="$2"
local username="$3"
local usergroup="$4"
local install_for_all="$5"
local ret
if [ ! -f "$path" ]; then
touch_file "$path" "$mod" "$username" "$usergroup" "$install_for_all"
ret=$? && [ $ret -ne 0 ] && return $ret
fi
return 0
}
# 写文本文件
write_text() {
local content="$1"
local filepath="$2"
printf "%s\n" "$content" > "$filepath"
}
# 修改文件权限并操作
with_chmod() {
local path="$1"
local mod="$2"
local origin_mod ret
shift 2
origin_mod="$(stat -L -c "%a" "$path")"
chmod "$mod" "$path"
"$@"
ret="$?"
chmod "$origin_mod" "$path"
return $ret
}
# filelist中所有公共目录的块
all_common_dirs_blocks_in_filelist() {
local install_type="$1"
local filelist_path="$2"
local feature_param="$3"
parse_filelist_v2 "$install_type" "all" "$filelist_path" "$feature_param" "filter_common_dirs" "" \
| cut -d' ' -f8 | sort | uniq
}
# 是否为版本目录
is_version_dirpath() {
local version_dirpath="$1"
if [ -d "$version_dirpath/share/info" ]; then
return 0
fi
if [ -f "$version_dirpath/var/ascend_package_db.info" ]; then
return 0
fi
return 1
}