UV-苹果系统M系列芯片安装(可用于Python多环境管理的工具)
UV-苹果系统M系列芯片安装(可用于Python多环境管理的工具)独立安装器:这里着重介绍一下因墙太高或者网络问题导致使用 curl -LsSf https://astral.sh/uv/install.sh | sh命令安装失败的方式:手动下载版本,然后将install.sh与下载的东西放在同一目录下,执行sudo sh install.sh即可,效果和使用 curl -LsSf https:/
UV-苹果系统M系列芯片安装(可用于Python多环境管理的工具)
独立安装器:
- macOS/Linux:curl -LsSf https://astral.sh/uv/install.sh | sh
- Windows:powershell -ExecutionPolicy ByPass -c “irm https://astral.sh/uv/install.ps1 | iex”
- 通过 PyPI:
- pip install uv 或 pipx install uv
- 自我更新:通过独立安装器安装后,可使用 uv self update 更新到最新版本。
这里着重介绍一下因墙太高或者网络问题导致使用 curl -LsSf https://astral.sh/uv/install.sh | sh命令安装失败的方式:
手动下载版本,然后将install.sh与下载的东西放在同一目录下,执行sudo sh install.sh即可,效果和使用 curl -LsSf https://astral.sh/uv/install.sh | sh命令一样,也可以自动更新,这也是最切合官方的方式。
当前最新版本是v0.8.22,其他版本只改一下脚本中的名称即可。
执行过程中会有apple不信任提示,

解决方法是点完成后到系统设置中-隐私与安全性
点仍要打开。
shell脚本会继续执行。
附:install.sh脚本不让传,直接放代码吧
uv的下载链接传到资源中了。
后面有时间补一个阿里云盘的下载链接
#!/bin/sh
# shellcheck shell=dash
# shellcheck disable=SC2039 # local is non-POSIX
#
# Licensed under the MIT license
# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
# This runs on Unix shells like bash/dash/ksh/zsh. It uses the common `local`
# extension. Note: Most shells limit `local` to 1 var per line, contra bash.
# Some versions of ksh have no `local` keyword. Alias it to `typeset`, but
# beware this makes variables global with f()-style function syntax in ksh93.
# mksh has this alias by default.
has_local() {
# shellcheck disable=SC2034 # deliberately unused
local _has_local
}
has_local 2>/dev/null || alias local=typeset
set -u
APP_NAME="uv"
APP_VERSION="0.8.22"
# Look for GitHub Enterprise-style base URL first (保留原逻辑,未修改)
if [ -n "${UV_INSTALLER_GHE_BASE_URL:-}" ]; then
INSTALLER_BASE_URL="$UV_INSTALLER_GHE_BASE_URL"
else
INSTALLER_BASE_URL="${UV_INSTALLER_GITHUB_BASE_URL:-https://github.com}"
fi
if [ -n "${UV_DOWNLOAD_URL:-}" ]; then
ARTIFACT_DOWNLOAD_URL="$UV_DOWNLOAD_URL"
elif [ -n "${INSTALLER_DOWNLOAD_URL:-}" ]; then
ARTIFACT_DOWNLOAD_URL="$INSTALLER_DOWNLOAD_URL"
else
ARTIFACT_DOWNLOAD_URL="${INSTALLER_BASE_URL}/astral-sh/uv/releases/download/0.8.22"
fi
if [ -n "${UV_PRINT_VERBOSE:-}" ]; then
PRINT_VERBOSE="$UV_PRINT_VERBOSE"
else
PRINT_VERBOSE=${INSTALLER_PRINT_VERBOSE:-0}
fi
if [ -n "${UV_PRINT_QUIET:-}" ]; then
PRINT_QUIET="$UV_PRINT_QUIET"
else
PRINT_QUIET=${INSTALLER_PRINT_QUIET:-0}
fi
if [ -n "${UV_NO_MODIFY_PATH:-}" ]; then
NO_MODIFY_PATH="$UV_NO_MODIFY_PATH"
else
NO_MODIFY_PATH=${INSTALLER_NO_MODIFY_PATH:-0}
fi
if [ "${UV_DISABLE_UPDATE:-0}" = "1" ]; then
INSTALL_UPDATER=0
else
INSTALL_UPDATER=1
fi
UNMANAGED_INSTALL="${UV_UNMANAGED_INSTALL:-}"
if [ -n "${UNMANAGED_INSTALL}" ]; then
NO_MODIFY_PATH=1
INSTALL_UPDATER=0
fi
AUTH_TOKEN="${UV_GITHUB_TOKEN:-}"
read -r RECEIPT <<EORECEIPT
{"binaries":["CARGO_DIST_BINS"],"binary_aliases":{},"cdylibs":["CARGO_DIST_DYLIBS"],"cstaticlibs":["CARGO_DIST_STATICLIBS"],"install_layout":"unspecified","install_prefix":"AXO_INSTALL_PREFIX","modify_path":true,"provider":{"source":"cargo-dist","version":"0.30.0"},"source":{"app_name":"uv","name":"uv","owner":"astral-sh","release_type":"github"},"version":"0.8.22"}
EORECEIPT
# Some Linux distributions don't set HOME (保留原逻辑,未修改)
# https://github.com/astral-sh/uv/issues/6965#issuecomment-2915796022
get_home() {
if [ -n "${HOME:-}" ]; then
echo "$HOME"
elif [ -n "${USER:-}" ]; then
getent passwd "$USER" | cut -d: -f6
else
getent passwd "$(id -un)" | cut -d: -f6
fi
}
# The HOME reference to show in user output. If `$HOME` isn't set, we show the absolute path instead.
get_home_expression() {
if [ -n "${HOME:-}" ]; then
# shellcheck disable=SC2016
echo '$HOME'
elif [ -n "${USER:-}" ]; then
getent passwd "$USER" | cut -d: -f6
else
getent passwd "$(id -un)" | cut -d: -f6
fi
}
INFERRED_HOME=$(get_home)
# shellcheck disable=SC2034
INFERRED_HOME_EXPRESSION=$(get_home_expression)
RECEIPT_HOME="${XDG_CONFIG_HOME:-$INFERRED_HOME/.config}/uv"
usage() {
# print help (保留原逻辑,未修改)
cat <<EOF
uv-installer.sh (本地安装版)
The installer for uv 0.8.22 (适配 M 系列芯片 macOS)
本脚本已修改为使用本地压缩包:uv-aarch64-apple-darwin.tar.gz
请确保以下文件在同一目录:
- install.sh (本脚本)
- uv-aarch64-apple-darwin.tar.gz (本地下载的压缩包)
安装路径优先级:
\$XDG_BIN_HOME → \$XDG_DATA_HOME/../bin → \$HOME/.local/bin
USAGE:
./install.sh [OPTIONS]
OPTIONS:
-v, --verbose
显示详细安装日志
-q, --quiet
关闭进度输出
--no-modify-path
不自动配置 PATH 环境变量(已废弃,建议用 UV_NO_MODIFY_PATH=1)
-h, --help
显示帮助信息
EOF
}
download_binary_and_run_installer() {
downloader --check
need_cmd uname
need_cmd mktemp
need_cmd chmod
need_cmd mkdir
need_cmd rm
need_cmd tar
need_cmd grep
need_cmd cat
# 处理命令行参数(保留原逻辑,未修改)
for arg in "$@"; do
case "$arg" in
--help)
usage
exit 0
;;
--quiet)
PRINT_QUIET=1
;;
--verbose)
PRINT_VERBOSE=1
;;
--no-modify-path)
say "--no-modify-path has been deprecated; please set UV_NO_MODIFY_PATH=1 in the environment"
NO_MODIFY_PATH=1
;;
*)
OPTIND=1
if [ "${arg%%--*}" = "" ]; then
err "unknown option $arg"
fi
while getopts :hvq sub_arg "$arg"; do
case "$sub_arg" in
h)
usage
exit 0
;;
v)
PRINT_VERBOSE=1
;;
q)
PRINT_QUIET=1
;;
*)
err "unknown option -$OPTARG"
;;
esac
done
;;
esac
done
###########################################################################
# 关键修改1:强制指定架构(M系列芯片macOS → aarch64-apple-darwin)
###########################################################################
local _true_arch="aarch64-apple-darwin" # 固定架构,避免自动检测错误
assert_nz "$_true_arch" "arch"
local _cur_arch="$_true_arch"
# 固定压缩包名称(与本地下载的文件名完全一致)
local _artifact_name="uv-aarch64-apple-darwin.tar.gz"
###########################################################################
# 关键修改2:解析压缩包信息(与本地文件匹配,无需修改)
###########################################################################
local _bins
local _zip_ext
local _arch
local _checksum_style
local _checksum_value
case "$_artifact_name" in
"uv-aarch64-apple-darwin.tar.gz")
_arch="aarch64-apple-darwin"
_zip_ext=".tar.gz"
_bins="uv uvx"
_bins_js_array='"uv","uvx"'
_libs=""
_libs_js_array=""
_staticlibs=""
_staticlibs_js_array=""
_updater_name=""
_updater_bin=""
;;
*)
err "内部错误:指定的压缩包名称不匹配!请确认本地文件是 uv-aarch64-apple-darwin.tar.gz"
;;
esac
# 替换收据中的占位符(保留原逻辑,未修改)
RECEIPT="$(echo "$RECEIPT" | sed s/'"CARGO_DIST_BINS"'/"$_bins_js_array"/)"
RECEIPT="$(echo "$RECEIPT" | sed s/'"CARGO_DIST_DYLIBS"'/"$_libs_js_array"/)"
RECEIPT="$(echo "$RECEIPT" | sed s/'"CARGO_DIST_STATICLIBS"'/"$_staticlibs_js_array"/)"
###########################################################################
# 关键修改3:使用本地压缩包,跳过远程下载(核心修改部分)
###########################################################################
# 1. 定义本地压缩包路径(与install.sh同目录,自动获取脚本所在目录)
local _local_archive="$(dirname "$0")/uv-aarch64-apple-darwin.tar.gz"
# 检查本地文件是否存在
if [ ! -f "$_local_archive" ]; then
err "本地压缩包不存在!请执行以下操作:
1. 确认下载的文件名为:uv-aarch64-apple-darwin.tar.gz
2. 将该文件与 install.sh 放在同一目录
3. 重新运行本脚本"
fi
# 2. 创建临时解压目录(与原逻辑一致)
local _dir
_dir="$(ensure mktemp -d)" || return 1
local _file="$_dir/input$_zip_ext" # 临时文件路径,保持原解压逻辑
say "使用本地压缩包安装 $APP_NAME $APP_VERSION (架构: $_arch)" 1>&2
say_verbose " 本地文件路径: $_local_archive" 1>&2
say_verbose " 临时解压路径: $_file" 1>&2
ensure mkdir -p "$_dir"
# 3. 复制本地压缩包到临时目录(替代原远程下载)
if ! cp "$_local_archive" "$_file"; then
err "复制本地压缩包失败!可能原因:
- 文件权限不足(尝试用 sudo ./install.sh 执行)
- 本地文件损坏(重新下载 uv-aarch64-apple-darwin.tar.gz)"
exit 1
fi
# 跳过校验和验证(本地文件已手动下载,无需校验)
say "跳过校验和验证(本地文件模式)"
###########################################################################
# 以下为原脚本逻辑(未修改):解压、安装、配置环境变量
###########################################################################
# ...and then the updater, if it exists (无更新器,跳过)
if [ -n "$_updater_name" ] && [ "$INSTALL_UPDATER" = "1" ]; then
local _updater_url="$ARTIFACT_DOWNLOAD_URL/$_updater_name"
local _updater_file="$_dir/$APP_NAME-update"
if ! downloader "$_updater_url" "$_updater_file"; then
say "failed to download $_updater_url"
say "this may be a standard network error, but it may also indicate"
say "that $APP_NAME's release process is not working. When in doubt"
say "please feel free to open an issue!"
exit 1
fi
_bins="$_bins $APP_NAME-update"
fi
# 解压压缩包
case "$_zip_ext" in
".zip")
ensure unzip -q "$_file" -d "$_dir"
;;
".tar."*)
ensure tar xf "$_file" --strip-components 1 -C "$_dir"
;;
*)
err "unknown archive format: $_zip_ext"
;;
esac
# 执行安装
install "$_dir" "$_bins" "$_libs" "$_staticlibs" "$_arch" "$@"
local _retval=$?
if [ "$_retval" != 0 ]; then
return "$_retval"
fi
# 清理临时目录
ignore rm -rf "$_dir"
# 生成安装收据
if [ "$INSTALL_UPDATER" = "1" ]; then
if ! mkdir -p "$RECEIPT_HOME"; then
err "unable to create receipt directory at $RECEIPT_HOME"
else
echo "$RECEIPT" > "$RECEIPT_HOME/$APP_NAME-receipt.json"
local _retval=$?
fi
else
local _retval=0
fi
return "$_retval"
}
# Replaces $HOME with the variable name for display to the user (保留原逻辑)
replace_home() {
local _str="$1"
if [ -n "${HOME:-}" ]; then
echo "$_str" | sed "s,$HOME,\$HOME,"
else
echo "$_str"
fi
}
json_binary_aliases() {
local _arch="$1"
case "$_arch" in
"aarch64-apple-darwin")
echo '{}'
;;
"aarch64-pc-windows-gnu")
echo '{}'
;;
"aarch64-unknown-linux-gnu")
echo '{}'
;;
"aarch64-unknown-linux-musl-dynamic")
echo '{}'
;;
"aarch64-unknown-linux-musl-static")
echo '{}'
;;
"arm-unknown-linux-gnueabihf")
echo '{}'
;;
"arm-unknown-linux-musl-dynamiceabihf")
echo '{}'
;;
"arm-unknown-linux-musl-staticeabihf")
echo '{}'
;;
"armv7-unknown-linux-gnueabihf")
echo '{}'
;;
"armv7-unknown-linux-musl-dynamiceabihf")
echo '{}'
;;
"armv7-unknown-linux-musl-staticeabihf")
echo '{}'
;;
"i686-pc-windows-gnu")
echo '{}'
;;
"i686-unknown-linux-gnu")
echo '{}'
;;
"i686-unknown-linux-musl-dynamic")
echo '{}'
;;
"i686-unknown-linux-musl-static")
echo '{}'
;;
"powerpc64-unknown-linux-gnu")
echo '{}'
;;
"powerpc64le-unknown-linux-gnu")
echo '{}'
;;
"riscv64gc-unknown-linux-gnu")
echo '{}'
;;
"s390x-unknown-linux-gnu")
echo '{}'
;;
"x86_64-apple-darwin")
echo '{}'
;;
"x86_64-pc-windows-gnu")
echo '{}'
;;
"x86_64-unknown-linux-gnu")
echo '{}'
;;
"x86_64-unknown-linux-musl-dynamic")
echo '{}'
;;
"x86_64-unknown-linux-musl-static")
echo '{}'
;;
*)
echo '{}'
;;
esac
}
aliases_for_binary() {
local _bin="$1"
local _arch="$2"
case "$_arch" in
"aarch64-apple-darwin")
case "$_bin" in
*)
echo ""
;;
esac
;;
"aarch64-pc-windows-gnu")
case "$_bin" in
*)
echo ""
;;
esac
;;
"aarch64-unknown-linux-gnu")
case "$_bin" in
*)
echo ""
;;
esac
;;
"aarch64-unknown-linux-musl-dynamic")
case "$_bin" in
*)
echo ""
;;
esac
;;
"aarch64-unknown-linux-musl-static")
case "$_bin" in
*)
echo ""
;;
esac
;;
"arm-unknown-linux-gnueabihf")
case "$_bin" in
*)
echo ""
;;
esac
;;
"arm-unknown-linux-musl-dynamiceabihf")
case "$_bin" in
*)
echo ""
;;
esac
;;
"arm-unknown-linux-musl-staticeabihf")
case "$_bin" in
*)
echo ""
;;
esac
;;
"armv7-unknown-linux-gnueabihf")
case "$_bin" in
*)
echo ""
;;
esac
;;
"armv7-unknown-linux-musl-dynamiceabihf")
case "$_bin" in
*)
echo ""
;;
esac
;;
"armv7-unknown-linux-musl-staticeabihf")
case "$_bin" in
*)
echo ""
;;
esac
;;
"i686-pc-windows-gnu")
case "$_bin" in
*)
echo ""
;;
esac
;;
"i686-unknown-linux-gnu")
case "$_bin" in
*)
echo ""
;;
esac
;;
"i686-unknown-linux-musl-dynamic")
case "$_bin" in
*)
echo ""
;;
esac
;;
"i686-unknown-linux-musl-static")
case "$_bin" in
*)
echo ""
;;
esac
;;
"powerpc64-unknown-linux-gnu")
case "$_bin" in
*)
echo ""
;;
esac
;;
"powerpc64le-unknown-linux-gnu")
case "$_bin" in
*)
echo ""
;;
esac
;;
"riscv64gc-unknown-linux-gnu")
case "$_bin" in
*)
echo ""
;;
esac
;;
"s390x-unknown-linux-gnu")
case "$_bin" in
*)
echo ""
;;
esac
;;
"x86_64-apple-darwin")
case "$_bin" in
*)
echo ""
;;
esac
;;
"x86_64-pc-windows-gnu")
case "$_bin" in
*)
echo ""
;;
esac
;;
"x86_64-unknown-linux-gnu")
case "$_bin" in
*)
echo ""
;;
esac
;;
"x86_64-unknown-linux-musl-dynamic")
case "$_bin" in
*)
echo ""
;;
esac
;;
"x86_64-unknown-linux-musl-static")
case "$_bin" in
*)
echo ""
;;
esac
;;
*)
echo ""
;;
esac
}
select_archive_for_arch() {
local _true_arch="$1"
local _archive
case "$_true_arch" in
"aarch64-apple-darwin")
_archive="uv-aarch64-apple-darwin.tar.gz"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
_archive="uv-x86_64-apple-darwin.tar.gz"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
*)
err "there isn't a download for your platform $_true_arch"
;;
esac
err "no compatible downloads were found for your platform $_true_arch"
}
check_glibc() {
local _min_glibc_major="$1"
local _min_glibc_series="$2"
_local_glibc="$(ldd --version | awk -F' ' '{ if (FNR<=1) print $NF }')"
if [ "$(echo "${_local_glibc}" | awk -F. '{ print $1 }')" = "$_min_glibc_major" ] && [ "$(echo "${_local_glibc}" | awk -F. '{ print $2 }')" -ge "$_min_glibc_series" ]; then
return 0
else
say "System glibc version (\`${_local_glibc}') is too old; checking alternatives" >&2
return 1
fi
}
# 安装核心逻辑(保留原脚本,未修改)
install() {
local _install_dir
local _lib_install_dir
local _receipt_install_dir
local _env_script_path
local _install_dir_expr
local _env_script_path_expr
local _force_install_dir
local _install_layout="unspecified"
local _shadowed_bins=""
if [ -n "${UV_INSTALL_DIR:-}" ]; then
_force_install_dir="$UV_INSTALL_DIR"
_install_layout="flat"
elif [ -n "${CARGO_DIST_FORCE_INSTALL_DIR:-}" ]; then
_force_install_dir="$CARGO_DIST_FORCE_INSTALL_DIR"
_install_layout="flat"
elif [ -n "$UNMANAGED_INSTALL" ]; then
_force_install_dir="$UNMANAGED_INSTALL"
_install_layout="flat"
fi
if [ -n "${_force_install_dir:-}" ]; then
if [ "$_install_layout" = "flat" ]; then
if [ "$_force_install_dir" = "${CARGO_HOME:-${INFERRED_HOME:-}/.cargo}" ]; then
_install_layout="cargo-home"
fi
fi
fi
if [ -n "${_force_install_dir:-}" ]; then
case "$_install_layout" in
"hierarchical")
_install_dir="$_force_install_dir/bin"
_lib_install_dir="$_force_install_dir/lib"
_receipt_install_dir="$_force_install_dir"
_env_script_path="$_force_install_dir/env"
_install_dir_expr="$(replace_home "$_force_install_dir/bin")"
_env_script_path_expr="$(replace_home "$_force_install_dir/env")"
;;
"cargo-home")
_install_dir="$_force_install_dir/bin"
_lib_install_dir="$_force_install_dir/bin"
_receipt_install_dir="$_force_install_dir"
_env_script_path="$_force_install_dir/env"
_install_dir_expr="$(replace_home "$_force_install_dir/bin")"
_env_script_path_expr="$(replace_home "$_force_install_dir/env")"
;;
"flat")
_install_dir="$_force_install_dir"
_lib_install_dir="$_force_install_dir"
_receipt_install_dir="$_install_dir"
_env_script_path="$_force_install_dir/env"
_install_dir_expr="$(replace_home "$_force_install_dir")"
_env_script_path_expr="$(replace_home "$_force_install_dir/env")"
;;
*)
err "Unrecognized install layout: $_install_layout"
;;
esac
fi
if [ -z "${_install_dir:-}" ]; then
_install_layout="flat"
if [ -n "${XDG_BIN_HOME:-}" ]; then
_install_dir="$XDG_BIN_HOME"
_lib_install_dir="$_install_dir"
_receipt_install_dir="$_install_dir"
_env_script_path="$XDG_BIN_HOME/env"
_install_dir_expr="$(replace_home "$_install_dir")"
_env_script_path_expr="$(replace_home "$_env_script_path")"
fi
fi
if [ -z "${_install_dir:-}" ]; then
_install_layout="flat"
if [ -n "${XDG_DATA_HOME:-}" ]; then
_install_dir="$XDG_DATA_HOME/../bin"
_lib_install_dir="$_install_dir"
_receipt_install_dir="$_install_dir"
_env_script_path="$XDG_DATA_HOME/../bin/env"
_install_dir_expr="$(replace_home "$_install_dir")"
_env_script_path_expr="$(replace_home "$_env_script_path")"
fi
fi
if [ -z "${_install_dir:-}" ]; then
_install_layout="flat"
if [ -n "${INFERRED_HOME:-}" ]; then
_install_dir="$INFERRED_HOME/.local/bin"
_lib_install_dir="$INFERRED_HOME/.local/bin"
_receipt_install_dir="$_install_dir"
_env_script_path="$INFERRED_HOME/.local/bin/env"
_install_dir_expr="$INFERRED_HOME_EXPRESSION/.local/bin"
_env_script_path_expr="$INFERRED_HOME_EXPRESSION/.local/bin/env"
fi
fi
if [ -z "$_install_dir_expr" ]; then
err "could not find a valid path to install to!"
fi
_fish_env_script_path="${_env_script_path}.fish"
_fish_env_script_path_expr="${_env_script_path_expr}.fish"
RECEIPT=$(echo "$RECEIPT" | sed "s,AXO_INSTALL_PREFIX,$_receipt_install_dir,")
RECEIPT=$(echo "$RECEIPT" | sed "s'\"binary_aliases\":{}'\"binary_aliases\":$(json_binary_aliases "$_arch")'")
RECEIPT=$(echo "$RECEIPT" | sed "s'\"install_layout\":\"unspecified\"'\"install_layout\":\"$_install_layout\"'")
if [ "$NO_MODIFY_PATH" = "1" ]; then
RECEIPT=$(echo "$RECEIPT" | sed "s'\"modify_path\":true'\"modify_path\":false'")
fi
say "installing to $_install_dir"
ensure mkdir -p "$_install_dir"
ensure mkdir -p "$_lib_install_dir"
local _src_dir="$1"
local _bins="$2"
local _libs="$3"
local _staticlibs="$4"
local _arch="$5"
for _bin_name in $_bins; do
local _bin="$_src_dir/$_bin_name"
ensure mv "$_bin" "$_install_dir"
ensure chmod +x "$_install_dir/$_bin_name"
for _dest in $(aliases_for_binary "$_bin_name" "$_arch"); do
ln -sf "$_install_dir/$_bin_name" "$_install_dir/$_dest"
done
say " $_bin_name"
done
for _lib_name in $_libs; do
local _lib="$_src_dir/$_lib_name"
ensure mv "$_lib" "$_lib_install_dir"
ensure chmod +x "$_lib_install_dir/$_lib_name"
say " $_lib_name"
done
for _lib_name in $_staticlibs; do
local _lib="$_src_dir/$_lib_name"
ensure mv "$_lib" "$_lib_install_dir"
ensure chmod +x "$_lib_install_dir/$_lib_name"
say " $_lib_name"
done
say "everything's installed!"
case :$PATH:
in *:$_install_dir:*) NO_MODIFY_PATH=1 ;;
*) ;;
esac
if [ "0" = "$NO_MODIFY_PATH" ]; then
add_install_dir_to_ci_path "$_install_dir"
add_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" ".profile" "sh"
exit1=$?
shotgun_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" ".profile .bashrc .bash_profile .bash_login" "sh"
exit2=$?
add_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" ".zshrc .zshenv" "sh"
exit3=$?
ensure mkdir -p "$INFERRED_HOME/.config/fish/conf.d"
exit4=$?
add_install_dir_to_path "$_install_dir_expr" "$_fish_env_script_path" "$_fish_env_script_path_expr" ".config/fish/conf.d/$APP_NAME.env.fish" "fish"
exit5=$?
if [ "${exit1:-0}" = 1 ] || [ "${exit2:-0}" = 1 ] || [ "${exit3:-0}" = 1 ] || [ "${exit4:-0}" = 1 ] || [ "${exit5:-0}" = 1 ]; then
say ""
say "To add $_install_dir_expr to your PATH, either restart your shell or run:"
say ""
say " source $_env_script_path_expr (sh, bash, zsh)"
say " source $_fish_env_script_path_expr (fish)"
fi
fi
_shadowed_bins="$(check_for_shadowed_bins "$_install_dir" "$_bins")"
if [ -n "$_shadowed_bins" ]; then
warn "The following commands are shadowed by other commands in your PATH:$_shadowed_bins"
fi
}
check_for_shadowed_bins() {
local _install_dir="$1"
local _bins="$2"
local _shadow
for _bin_name in $_bins; do
_shadow="$(command -v "$_bin_name")"
if [ -n "$_shadow" ] && [ "$_shadow" != "$_install_dir/$_bin_name" ]; then
_shadowed_bins="$_shadowed_bins $_bin_name"
fi
done
echo "$_shadowed_bins"
}
print_home_for_script() {
local script="$1"
local _home
case "$script" in
.zsh*)
if [ -n "${ZDOTDIR:-}" ]; then
_home="$ZDOTDIR"
else
_home="$INFERRED_HOME"
fi
;;
*)
_home="$INFERRED_HOME"
;;
esac
echo "$_home"
}
add_install_dir_to_ci_path() {
local _install_dir="$1"
if [ -n "${GITHUB_PATH:-}" ]; then
ensure echo "$_install_dir" >> "$GITHUB_PATH"
fi
}
add_install_dir_to_path() {
local _install_dir_expr="$1"
local _env_script_path="$2"
local _env_script_path_expr="$3"
local _rcfiles="$4"
local _shell="$5"
if [ -n "${INFERRED_HOME:-}" ]; then
local _target
local _home
for _rcfile_relative in $_rcfiles; do
_home="$(print_home_for_script "$_rcfile_relative")"
local _rcfile="$_home/$_rcfile_relative"
if [ -f "$_rcfile" ]; then
_target="$_rcfile"
break
fi
done
if [ -z "${_target:-}" ]; then
local _rcfile_relative
_rcfile_relative="$(echo "$_rcfiles" | awk '{ print $1 }')"
_home="$(print_home_for_script "$_rcfile_relative")"
_target="$_home/$_rcfile_relative"
fi
local _robust_line=". \"$_env_script_path_expr\""
local _pretty_line="source \"$_env_script_path_expr\""
if [ ! -f "$_env_script_path" ]; then
say_verbose "creating $_env_script_path"
if [ "$_shell" = "sh" ]; then
write_env_script_sh "$_install_dir_expr" "$_env_script_path"
else
write_env_script_fish "$_install_dir_expr" "$_env_script_path"
fi
else
say_verbose "$_env_script_path already exists"
fi
if ! grep -F "$_robust_line" "$_target" > /dev/null 2>/dev/null && \
! grep -F "$_pretty_line" "$_target" > /dev/null 2>/dev/null
then
if [ -f "$_env_script_path" ]; then
local _line
if [ "$_shell" = "fish" ]; then
_line="$_pretty_line"
else
_line="$_robust_line"
fi
say_verbose "adding $_line to $_target"
ensure echo "" >> "$_target"
ensure echo "$_line" >> "$_target"
return 1
fi
else
say_verbose "$_install_dir already on PATH"
fi
fi
}
shotgun_install_dir_to_path() {
local _install_dir_expr="$1"
local _env_script_path="$2"
local _env_script_path_expr="$3"
local _rcfiles="$4"
local _shell="$5"
if [ -n "${INFERRED_HOME:-}" ]; then
local _found=false
local _home
for _rcfile_relative in $_rcfiles; do
_home="$(print_home_for_script "$_rcfile_relative")"
local _rcfile_abs="$_home/$_rcfile_relative"
if [ -f "$_rcfile_abs" ]; then
_found=true
add_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" "$_rcfile_relative" "$_shell"
fi
done
if [ "$_found" = false ]; then
add_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" "$_rcfiles" "$_shell"
fi
fi
}
write_env_script_sh() {
local _install_dir_expr="$1"
local _env_script_path="$2"
ensure cat <<EOF > "$_env_script_path"
#!/bin/sh
# add binaries to PATH if they aren't added yet
# affix colons on either side of \$PATH to simplify matching
case ":\${PATH}:" in
*:"$_install_dir_expr":*)
;;
*)
# Prepending path in case a system-installed binary needs to be overridden
export PATH="$_install_dir_expr:\$PATH"
;;
esac
EOF
}
write_env_script_fish() {
local _install_dir_expr="$1"
local _env_script_path="$2"
ensure cat <<EOF > "$_env_script_path"
if not contains "$_install_dir_expr" \$PATH
# Prepending path in case a system-installed binary needs to be overridden
set -x PATH "$_install_dir_expr" \$PATH
end
EOF
}
get_current_exe() {
local _current_exe
if test -L /proc/self/exe ; then
_current_exe=/proc/self/exe
else
warn "Unable to find /proc/self/exe. System architecture detection might be inaccurate."
if test -n "$SHELL" ; then
_current_exe=$SHELL
else
need_cmd /bin/sh
_current_exe=/bin/sh
fi
warn "Falling back to $_current_exe."
fi
echo "$_current_exe"
}
get_bitness() {
need_cmd head
local _current_exe=$1
local _current_exe_head
_current_exe_head=$(head -c 5 "$_current_exe")
if [ "$_current_exe_head" = "$(printf '\177ELF\001')" ]; then
echo 32
elif [ "$_current_exe_head" = "$(printf '\177ELF\002')" ]; then
echo 64
else
err "unknown platform bitness"
fi
}
is_host_amd64_elf() {
local _current_exe=$1
need_cmd head
need_cmd tail
local _current_exe_machine
_current_exe_machine=$(head -c 19 "$_current_exe" | tail -c 1)
[ "$_current_exe_machine" = "$(printf '\076')" ]
}
get_endianness() {
local _current_exe=$1
local cputype=$2
local suffix_eb=$3
local suffix_el=$4
need_cmd head
need_cmd tail
local _current_exe_endianness
_current_exe_endianness="$(head -c 6 "$_current_exe" | tail -c 1)"
if [ "$_current_exe_endianness" = "$(printf '\001')" ]; then
echo "${cputype}${suffix_el}"
elif [ "$_current_exe_endianness" = "$(printf '\002')" ]; then
echo "${cputype}${suffix_eb}"
else
err "unknown platform endianness"
fi
}
check_loongarch_uapi() {
need_cmd base64
local _tmp
if ! _tmp="$(ensure mktemp)"; then
return 1
fi
ignore base64 -d > "$_tmp" <<EOF
f0VMRgIBAQAAAAAAAAAAAAIAAgEBAAAAeAAgAAAAAABAAAAAAAAAAAAAAAAAAAAAQQAAAEAAOAAB
AAAAAAAAAAEAAAAFAAAAAAAAAAAAAAAAACAAAAAAAAAAIAAAAAAAJAAAAAAAAAAkAAAAAAAAAAAA
AQAAAAAABCiAAwUAFQAGABUAByCAAwsYggMAACsAC3iBAwAAKwAxen0n
EOF
ignore chmod u+x "$_tmp"
if [ ! -x "$_tmp" ]; then
ignore rm "$_tmp"
return 1
fi
"$_tmp"
local _retval=$?
ignore rm "$_tmp"
return "$_retval"
}
ensure_loongarch_uapi() {
check_loongarch_uapi
case $? in
0)
return 0
;;
234)
err 'Your Linux kernel does not provide the ABI required by this distribution.'
;;
*)
warn "Cannot determine current system's ABI flavor, continuing anyway."
warn 'Note that the official distribution only works with the upstream kernel ABI.'
warn 'Installation will fail if your running kernel happens to be incompatible.'
;;
esac
}
get_architecture() {
local _ostype
local _cputype
_ostype="$(uname -s)"
_cputype="$(uname -m)"
local _clibtype="gnu"
local _local_glibc
if [ "$_ostype" = Linux ]; then
if [ "$(uname -o)" = Android ]; then
_ostype=Android
fi
if ldd --version 2>&1 | grep -q 'musl'; then
_clibtype="musl-dynamic"
else
_clibtype="gnu"
fi
fi
if [ "$_ostype" = Darwin ]; then
if [ "$_cputype" = i386 ]; then
if sysctl hw.optional.x86_64 2> /dev/null || true | grep -q ': 1'; then
_cputype=x86_64
fi
elif [ "$_cputype" = x86_64 ]; then
if sysctl hw.optional.arm64 2> /dev/null || true | grep -q ': 1'; then
_cputype=arm64
fi
fi
fi
if [ "$_ostype" = SunOS ]; then
if [ "$(/usr/bin/uname -o)" = illumos ]; then
_ostype=illumos
fi
if [ "$_cputype" = i86pc ]; then
_cputype="$(isainfo -n)"
fi
fi
local _current_exe
case "$_ostype" in
Android)
_ostype=linux-android
;;
Linux)
_current_exe=$(get_current_exe)
_ostype=unknown-linux-$_clibtype
_bitness=$(get_bitness "$_current_exe")
;;
FreeBSD)
_ostype=unknown-freebsd
;;
NetBSD)
_ostype=unknown-netbsd
;;
DragonFly)
_ostype=unknown-dragonfly
;;
Darwin)
_ostype=apple-darwin
;;
illumos)
_ostype=unknown-illumos
;;
MINGW* | MSYS* | CYGWIN* | Windows_NT)
_ostype=pc-windows-gnu
;;
*)
err "unrecognized OS type: $_ostype"
;;
esac
case "$_cputype" in
i386 | i486 | i686 | i786 | x86)
_cputype=i686
;;
xscale | arm)
_cputype=arm
if [ "$_ostype" = "linux-android" ]; then
_ostype=linux-androideabi
fi
;;
armv6l)
_cputype=arm
if [ "$_ostype" = "linux-android" ]; then
_ostype=linux-androideabi
else
_ostype="${_ostype}eabihf"
fi
;;
armv7l | armv8l)
_cputype=armv7
if [ "$_ostype" = "linux-android" ]; then
_ostype=linux-androideabi
else
_ostype="${_ostype}eabihf"
fi
;;
aarch64 | arm64)
_cputype=aarch64
;;
x86_64 | x86-64 | x64 | amd64)
_cputype=x86_64
;;
mips)
_cputype=$(get_endianness "$_current_exe" mips '' el)
;;
mips64)
if [ "$_bitness" -eq 64 ]; then
_ostype="${_ostype}abi64"
_cputype=$(get_endianness "$_current_exe" mips64 '' el)
fi
;;
ppc)
_cputype=powerpc
;;
ppc64)
_cputype=powerpc64
;;
ppc64le)
_cputype=powerpc64le
;;
s390x)
_cputype=s390x
;;
riscv64)
_cputype=riscv64gc
;;
loongarch64)
_cputype=loongarch64
ensure_loongarch_uapi
;;
*)
err "unknown CPU type: $_cputype"
esac
if [ "${_ostype}" = unknown-linux-gnu ] && [ "${_bitness}" -eq 32 ]; then
case $_cputype in
x86_64)
if is_host_amd64_elf "$_current_exe"; then {
err "x32 linux unsupported"
}; else
_cputype=i686
fi
;;
mips64)
_cputype=$(get_endianness "$_current_exe" mips '' el)
;;
powerpc64)
_cputype=powerpc
;;
aarch64)
_cputype=armv7
if [ "$_ostype" = "linux-android" ]; then
_ostype=linux-androideabi
else
_ostype="${_ostype}eabihf"
fi
;;
riscv64gc)
err "riscv64 with 32-bit userland unsupported"
;;
esac
fi
if [ "$_ostype" = "unknown-linux-gnueabihf" ] && [ "$_cputype" = armv7 ]; then
if ! (ensure grep '^Features' /proc/cpuinfo | grep -E -q 'neon|simd') ; then
_cputype=arm
fi
fi
_arch="${_cputype}-${_ostype}"
RETVAL="$_arch"
}
say() {
if [ "0" = "$PRINT_QUIET" ]; then
echo "$1"
fi
}
say_verbose() {
if [ "1" = "$PRINT_VERBOSE" ]; then
echo "$1"
fi
}
warn() {
if [ "0" = "$PRINT_QUIET" ]; then
local red
local reset
red=$(tput setaf 1 2>/dev/null || echo '')
reset=$(tput sgr0 2>/dev/null || echo '')
say "${red}WARN${reset}: $1" >&2
fi
}
err() {
if [ "0" = "$PRINT_QUIET" ]; then
local red
local reset
red=$(tput setaf 1 2>/dev/null || echo '')
reset=$(tput sgr0 2>/dev/null || echo '')
say "${red}ERROR${reset}: $1" >&2
fi
exit 1
}
need_cmd() {
if ! check_cmd "$1"
then err "need '$1' (command not found)"
fi
}
check_cmd() {
command -v "$1" > /dev/null 2>&1
return $?
}
assert_nz() {
if [ -z "$1" ]; then err "assert_nz $2"; fi
}
ensure() {
if ! "$@"; then err "command failed: $*"; fi
}
ignore() {
"$@"
}
downloader() {
_snap_curl=0
if command -v curl > /dev/null 2>&1; then
_curl_path=$(command -v curl)
if echo "$_curl_path" | grep "/snap/" > /dev/null 2>&1; then
_snap_curl=1
fi
fi
if check_cmd curl && [ "$_snap_curl" = "0" ]
then _dld=curl
elif check_cmd wget
then _dld=wget
elif [ "$_snap_curl" = "1" ]
then
say "curl installed with snap cannot be used to install $APP_NAME"
say "due to missing permissions. Please uninstall it and"
say "reinstall curl with a different package manager (e.g., apt)."
say "See https://github.com/boukendesho/curl-snap/issues/1"
exit 1
else _dld='curl or wget'
fi
if [ "$1" = --check ]
then need_cmd "$_dld"
elif [ "$_dld" = curl ]; then
if [ -n "${AUTH_TOKEN:-}" ]; then
curl -sSfL --header "Authorization: Bearer ${AUTH_TOKEN}" "$1" -o "$2"
else
curl -sSfL "$1" -o "$2"
fi
elif [ "$_dld" = wget ]; then
if [ -n "${AUTH_TOKEN:-}" ]; then
wget --header "Authorization: Bearer ${AUTH_TOKEN}" "$1" -O "$2"
else
wget "$1" -O "$2"
fi
else err "Unknown downloader"
fi
}
verify_checksum() {
local _file="$1"
local _checksum_style="$2"
local _checksum_value="$3"
local _calculated_checksum
if [ -z "$_checksum_value" ]; then
return 0
fi
case "$_checksum_style" in
sha256)
if ! check_cmd sha256sum; then
say "skipping sha256 checksum verification (it requires the 'sha256sum' command)"
return 0
fi
_calculated_checksum="$(sha256sum -b "$_file" | awk '{printf $1}')"
;;
sha512)
if ! check_cmd sha512sum; then
say "skipping sha512 checksum verification (it requires the 'sha512sum' command)"
return 0
fi
_calculated_checksum="$(sha512sum -b "$_file" | awk '{printf $1}')"
;;
sha3-256)
if ! check_cmd openssl; then
say "skipping sha3-256 checksum verification (it requires the 'openssl' command)"
return 0
fi
_calculated_checksum="$(openssl dgst -sha3-256 "$_file" | awk '{printf $NF}')"
;;
sha3-512)
if ! check_cmd openssl; then
say "skipping sha3-512 checksum verification (it requires the 'openssl' command)"
return 0
fi
_calculated_checksum="$(openssl dgst -sha3-512 "$_file" | awk '{printf $NF}')"
;;
blake2s)
if ! check_cmd b2sum; then
say "skipping blake2s checksum verification (it requires the 'b2sum' command)"
return 0
fi
local _well_known_blake2s_checksum="93314a61f470985a40f8da62df10ba0546dc5216e1d45847bf1dbaa42a0e97af"
local _test_blake2s
_test_blake2s="$(printf "can do blake2s" | b2sum -a blake2s | awk '{printf $1}')" || _test_blake2s=""
if [ "X$_test_blake2s" = "X$_well_known_blake2s_checksum" ]; then
_calculated_checksum="$(b2sum -a blake2s "$_file" | awk '{printf $1}')" || _calculated_checksum=""
else
say "skipping blake2s checksum verification (installed b2sum doesn't support blake2s)"
return 0
fi
;;
blake2b)
if ! check_cmd b2sum; then
say "skipping blake2b checksum verification (it requires the 'b2sum' command)"
return 0
fi
_calculated_checksum="$(b2sum "$_file" | awk '{printf $1}')"
;;
false)
;;
*)
say "skipping unknown checksum style: $_checksum_style"
return 0
;;
esac
if [ "$_calculated_checksum" != "$_checksum_value" ]; then
err "checksum mismatch
want: $_checksum_value
got: $_calculated_checksum"
fi
}
# 执行安装(保留原逻辑)
download_binary_and_run_installer "$@" || exit 1
文档与支持
- 官方文档:docs.astral.sh/uv
- 命令行帮助:uv help
- 由 Astral 开发支持,该公司也是 Python 工具 Ruff 的创作者。
技术架构
- 基于 Rust 开发,从代码结构看包含多个核心 crate(如 uv-git 处理 Git 仓库交互、uv-resolver 负责依赖解析、uv-distribution 处理分发逻辑等),整体设计注重性能和跨平台兼容性。
- 支持 Git 仓库作为依赖源,包含对 GitHub 等平台的适配逻辑,以及缓存、校验等机制。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)