mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-08-28 11:56:07 +00:00
* install.sh: install the Rust maintenance worker The release publishes weed-worker but the installer only knew weed and the Rust volume server, so the one binary that cannot be built without a Rust toolchain was the one you had to download by hand. --component all skips it on a platform it has no build for rather than failing an install that already put two binaries in place; asking for it by name there still says so. Claude-Session: https://claude.ai/code/session_01Rkp1Mw5E89Jp6dzJFYiMrm * install.sh: clean each component's temp directory as it finishes The EXIT trap is per-process, so installing more than one component left every extraction but the last behind. Cleaning at the end of the function keeps the trap for the paths that exit early. Claude-Session: https://claude.ai/code/session_01Rkp1Mw5E89Jp6dzJFYiMrm
358 lines
12 KiB
Bash
Executable File
358 lines
12 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# SeaweedFS Installer
|
|
# Downloads Go and/or Rust binaries from GitHub releases.
|
|
#
|
|
# Usage:
|
|
# curl -fsSL https://raw.githubusercontent.com/seaweedfs/seaweedfs/master/install.sh | bash
|
|
# curl -fsSL ... | bash -s -- --component volume-rust --large-disk
|
|
# curl -fsSL ... | bash -s -- --version 4.34 --dir /usr/local/bin
|
|
#
|
|
# Options:
|
|
# --component COMP Which binary to install: weed, volume-rust, worker-rust, all (default: weed)
|
|
# --version VER Release version tag (default: latest)
|
|
# --large-disk Use large disk variant (5-byte offset, 8TB max volume)
|
|
# --dir DIR Installation directory (default: /usr/local/bin)
|
|
# --help Show this help message
|
|
|
|
set -euo pipefail
|
|
|
|
REPO="seaweedfs/seaweedfs"
|
|
COMPONENT="weed"
|
|
VERSION=""
|
|
LARGE_DISK=false
|
|
INSTALL_DIR="/usr/local/bin"
|
|
WORKER_INSTALLED=false
|
|
|
|
# Colors (if terminal supports them)
|
|
if [ -t 1 ]; then
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[0;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
else
|
|
RED='' GREEN='' YELLOW='' BLUE='' NC=''
|
|
fi
|
|
|
|
info() { echo -e "${BLUE}[info]${NC} $*"; }
|
|
ok() { echo -e "${GREEN}[ok]${NC} $*"; }
|
|
warn() { echo -e "${YELLOW}[warn]${NC} $*"; }
|
|
error() { echo -e "${RED}[error]${NC} $*" >&2; exit 1; }
|
|
|
|
usage() {
|
|
sed -n '/^# Usage:/,/^$/p' "$0" | sed 's/^# \?//'
|
|
exit 0
|
|
}
|
|
|
|
# Parse arguments
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--component) COMPONENT="$2"; shift 2 ;;
|
|
--version) VERSION="$2"; shift 2 ;;
|
|
--large-disk) LARGE_DISK=true; shift ;;
|
|
--dir) INSTALL_DIR="$2"; shift 2 ;;
|
|
--help|-h) usage ;;
|
|
*) error "Unknown option: $1. Use --help for usage." ;;
|
|
esac
|
|
done
|
|
|
|
# Detect OS and architecture
|
|
detect_platform() {
|
|
local os arch
|
|
|
|
case "$(uname -s)" in
|
|
Linux*) os="linux" ;;
|
|
Darwin*) os="darwin" ;;
|
|
MINGW*|MSYS*|CYGWIN*) os="windows" ;;
|
|
FreeBSD*) os="freebsd" ;;
|
|
*) error "Unsupported OS: $(uname -s)" ;;
|
|
esac
|
|
|
|
case "$(uname -m)" in
|
|
x86_64|amd64) arch="amd64" ;;
|
|
aarch64|arm64) arch="arm64" ;;
|
|
armv7l|armv6l) arch="arm" ;;
|
|
*) error "Unsupported architecture: $(uname -m)" ;;
|
|
esac
|
|
|
|
echo "${os}" "${arch}"
|
|
}
|
|
|
|
# Get latest release tag from GitHub API
|
|
get_latest_version() {
|
|
local url="https://api.github.com/repos/${REPO}/releases/latest"
|
|
if command -v curl &>/dev/null; then
|
|
curl -fsSL "$url" | grep '"tag_name"' | head -1 | sed 's/.*"tag_name": *"\([^"]*\)".*/\1/'
|
|
elif command -v wget &>/dev/null; then
|
|
wget -qO- "$url" | grep '"tag_name"' | head -1 | sed 's/.*"tag_name": *"\([^"]*\)".*/\1/'
|
|
else
|
|
error "Neither curl nor wget found. Please install one."
|
|
fi
|
|
}
|
|
|
|
# Download a file
|
|
download() {
|
|
local url="$1" dest="$2"
|
|
info "Downloading ${url}"
|
|
if command -v curl &>/dev/null; then
|
|
curl -fsSL -o "$dest" "$url"
|
|
elif command -v wget &>/dev/null; then
|
|
wget -qO "$dest" "$url"
|
|
fi
|
|
}
|
|
|
|
# Build Go weed binary asset name
|
|
go_asset_name() {
|
|
local os="$1" arch="$2"
|
|
local suffix="${os}_${arch}"
|
|
if [ "$LARGE_DISK" = true ]; then
|
|
suffix="${suffix}_large_disk"
|
|
fi
|
|
echo "${suffix}.tar.gz"
|
|
}
|
|
|
|
# Build Rust volume server asset name
|
|
rust_asset_name() {
|
|
local os="$1" arch="$2"
|
|
local prefix="weed-volume"
|
|
if [ "$LARGE_DISK" = true ]; then
|
|
prefix="weed-volume_large_disk"
|
|
else
|
|
prefix="weed-volume"
|
|
fi
|
|
local suffix="${os}_${arch}"
|
|
if [ "$os" = "windows" ]; then
|
|
echo "${prefix}_${suffix}.zip"
|
|
else
|
|
echo "${prefix}_${suffix}.tar.gz"
|
|
fi
|
|
}
|
|
|
|
# Does a release carry this asset? Answers 0 for yes and 1 for a 404, and stops
|
|
# the installer on anything else: a rate limit or a network blip must not read
|
|
# as "this release predates the binary" and quietly skip it.
|
|
asset_exists() {
|
|
local url="$1" code=""
|
|
if command -v curl &>/dev/null; then
|
|
code="$(curl -sL -o /dev/null -I -w '%{http_code}' "$url" || true)"
|
|
elif command -v wget &>/dev/null; then
|
|
# --spider's exit status folds 404 in with every other server error, so
|
|
# read the status line itself; -S prints one per redirect hop.
|
|
code="$(wget -S --spider -q -O /dev/null "$url" 2>&1 | awk '/^ *HTTP\// {c=$2} END {print c}')"
|
|
fi
|
|
|
|
case "$code" in
|
|
200) return 0 ;;
|
|
404) return 1 ;;
|
|
*) error "Could not check ${url} (HTTP ${code:-none}). Retry, or install components one at a time." ;;
|
|
esac
|
|
}
|
|
|
|
# Build Rust maintenance worker asset name. No large-disk variant: the worker
|
|
# maintains tables through the namespace and never opens a volume file.
|
|
worker_asset_name() {
|
|
local os="$1" arch="$2"
|
|
echo "weed-worker_${os}_${arch}.tar.gz"
|
|
}
|
|
|
|
# Install a single component
|
|
install_component() {
|
|
local component="$1" os="$2" arch="$3"
|
|
local asset_name download_url tmpdir
|
|
|
|
tmpdir="$(mktemp -d)"
|
|
trap "rm -rf '$tmpdir'" EXIT
|
|
|
|
case "$component" in
|
|
weed)
|
|
asset_name="$(go_asset_name "$os" "$arch")"
|
|
download_url="https://github.com/${REPO}/releases/download/${VERSION}/${asset_name}"
|
|
download "$download_url" "${tmpdir}/${asset_name}"
|
|
|
|
info "Extracting ${asset_name}..."
|
|
tar xzf "${tmpdir}/${asset_name}" -C "$tmpdir"
|
|
|
|
# The Go release action puts the binary inside a directory
|
|
local weed_bin
|
|
weed_bin="$(find "$tmpdir" -name 'weed' -type f | head -1)"
|
|
if [ -z "$weed_bin" ]; then
|
|
weed_bin="$(find "$tmpdir" -name 'weed.exe' -type f | head -1)"
|
|
fi
|
|
if [ -z "$weed_bin" ]; then
|
|
error "Could not find weed binary in archive"
|
|
fi
|
|
|
|
chmod +x "$weed_bin"
|
|
install_binary "$weed_bin" "weed"
|
|
ok "Installed weed to ${INSTALL_DIR}/weed"
|
|
;;
|
|
|
|
volume-rust)
|
|
# Check platform support for Rust volume server
|
|
case "$os" in
|
|
linux|darwin|windows) ;;
|
|
*) error "Rust volume server is not available for ${os}. Supported: linux, darwin, windows" ;;
|
|
esac
|
|
case "$arch" in
|
|
amd64|arm64) ;;
|
|
*) error "Rust volume server is not available for ${arch}. Supported: amd64, arm64" ;;
|
|
esac
|
|
|
|
asset_name="$(rust_asset_name "$os" "$arch")"
|
|
download_url="https://github.com/${REPO}/releases/download/${VERSION}/${asset_name}"
|
|
download "$download_url" "${tmpdir}/${asset_name}"
|
|
|
|
info "Extracting ${asset_name}..."
|
|
if [ "$os" = "windows" ]; then
|
|
unzip -q "${tmpdir}/${asset_name}" -d "$tmpdir"
|
|
else
|
|
tar xzf "${tmpdir}/${asset_name}" -C "$tmpdir"
|
|
fi
|
|
|
|
local rust_bin
|
|
if [ "$LARGE_DISK" = true ]; then
|
|
rust_bin="$(find "$tmpdir" -name 'weed-volume-large-disk*' -type f | head -1)"
|
|
else
|
|
rust_bin="$(find "$tmpdir" -name 'weed-volume-normal*' -type f | head -1)"
|
|
fi
|
|
if [ -z "$rust_bin" ]; then
|
|
rust_bin="$(find "$tmpdir" -name 'weed-volume*' -type f | head -1)"
|
|
fi
|
|
if [ -z "$rust_bin" ]; then
|
|
error "Could not find weed-volume binary in archive"
|
|
fi
|
|
|
|
chmod +x "$rust_bin"
|
|
local dest_name="weed-volume"
|
|
if [ "$os" = "windows" ]; then
|
|
dest_name="weed-volume.exe"
|
|
fi
|
|
install_binary "$rust_bin" "$dest_name"
|
|
ok "Installed weed-volume to ${INSTALL_DIR}/${dest_name}"
|
|
;;
|
|
|
|
worker-rust)
|
|
# Published for linux only: the worker runs beside the cluster it
|
|
# maintains, and its dependency tree makes every extra target an
|
|
# expensive build.
|
|
case "$os" in
|
|
linux) ;;
|
|
*) error "Rust maintenance worker is not available for ${os}. Supported: linux" ;;
|
|
esac
|
|
case "$arch" in
|
|
amd64|arm64) ;;
|
|
*) error "Rust maintenance worker is not available for ${arch}. Supported: amd64, arm64" ;;
|
|
esac
|
|
|
|
asset_name="$(worker_asset_name "$os" "$arch")"
|
|
download_url="https://github.com/${REPO}/releases/download/${VERSION}/${asset_name}"
|
|
download "$download_url" "${tmpdir}/${asset_name}"
|
|
|
|
info "Extracting ${asset_name}..."
|
|
tar xzf "${tmpdir}/${asset_name}" -C "$tmpdir"
|
|
|
|
local worker_bin
|
|
worker_bin="$(find "$tmpdir" -name 'weed-worker' -type f | head -1)"
|
|
if [ -z "$worker_bin" ]; then
|
|
error "Could not find weed-worker binary in archive"
|
|
fi
|
|
|
|
chmod +x "$worker_bin"
|
|
install_binary "$worker_bin" "weed-worker"
|
|
WORKER_INSTALLED=true
|
|
ok "Installed weed-worker to ${INSTALL_DIR}/weed-worker"
|
|
;;
|
|
|
|
*)
|
|
error "Unknown component: ${component}. Use: weed, volume-rust, worker-rust, all"
|
|
;;
|
|
esac
|
|
|
|
# The trap is per-process, so a later component's would replace this one and
|
|
# leave the earlier extraction behind. Clean up here and hand the trap back;
|
|
# the error paths above exit, which still fires it.
|
|
rm -rf "$tmpdir"
|
|
trap - EXIT
|
|
}
|
|
|
|
# Copy binary to install dir, using sudo if needed
|
|
install_binary() {
|
|
local src="$1" name="$2"
|
|
local dest="${INSTALL_DIR}/${name}"
|
|
|
|
mkdir -p "$INSTALL_DIR" 2>/dev/null || true
|
|
|
|
if [ -w "$INSTALL_DIR" ]; then
|
|
cp "$src" "$dest"
|
|
else
|
|
info "Need elevated permissions to write to ${INSTALL_DIR}"
|
|
sudo cp "$src" "$dest"
|
|
fi
|
|
chmod +x "$dest" 2>/dev/null || sudo chmod +x "$dest"
|
|
}
|
|
|
|
main() {
|
|
info "SeaweedFS Installer"
|
|
|
|
read -r os arch <<< "$(detect_platform)"
|
|
info "Detected platform: ${os}/${arch}"
|
|
|
|
if [ -z "$VERSION" ]; then
|
|
info "Resolving latest release..."
|
|
VERSION="$(get_latest_version)"
|
|
if [ -z "$VERSION" ]; then
|
|
error "Could not determine latest version. Specify with --version"
|
|
fi
|
|
fi
|
|
info "Version: ${VERSION}"
|
|
|
|
if [ "$LARGE_DISK" = true ]; then
|
|
info "Variant: large disk (8TB max volume)"
|
|
else
|
|
info "Variant: normal (32GB max volume)"
|
|
fi
|
|
|
|
case "$COMPONENT" in
|
|
all)
|
|
install_component "weed" "$os" "$arch"
|
|
install_component "volume-rust" "$os" "$arch"
|
|
# The worker is published for linux amd64/arm64 only, and only by
|
|
# releases new enough to carry it; skip either case rather than fail
|
|
# an install that has already put two binaries in place.
|
|
if [ "$os" != "linux" ] || { [ "$arch" != "amd64" ] && [ "$arch" != "arm64" ]; }; then
|
|
warn "Skipping the Rust maintenance worker: no build for ${os}/${arch}"
|
|
elif ! asset_exists "https://github.com/${REPO}/releases/download/${VERSION}/$(worker_asset_name "$os" "$arch")"; then
|
|
warn "Skipping the Rust maintenance worker: ${VERSION} does not carry one"
|
|
else
|
|
install_component "worker-rust" "$os" "$arch"
|
|
fi
|
|
;;
|
|
*)
|
|
install_component "$COMPONENT" "$os" "$arch"
|
|
;;
|
|
esac
|
|
|
|
echo ""
|
|
ok "Installation complete!"
|
|
if [ "$COMPONENT" = "weed" ] || [ "$COMPONENT" = "all" ]; then
|
|
info " weed: ${INSTALL_DIR}/weed"
|
|
fi
|
|
if [ "$COMPONENT" = "volume-rust" ] || [ "$COMPONENT" = "all" ]; then
|
|
info " weed-volume: ${INSTALL_DIR}/weed-volume"
|
|
fi
|
|
if [ "$WORKER_INSTALLED" = true ]; then
|
|
info " weed-worker: ${INSTALL_DIR}/weed-worker"
|
|
fi
|
|
echo ""
|
|
info "Quick start:"
|
|
info " weed master # Start master server"
|
|
info " weed volume -mserver=localhost:9333 # Start Go volume server"
|
|
info " weed-volume -mserver localhost:9333 # Start Rust volume server"
|
|
if [ "$WORKER_INSTALLED" = true ]; then
|
|
info " weed-worker --admin localhost:23646 # Start the Rust maintenance worker"
|
|
fi
|
|
}
|
|
|
|
main
|