#!/usr/bin/env bash
# NOTE 这个脚本可以用 bash 或 zsh 运行,在 Linux 下请用 root 权限运行,否则不会尝试设置开机自启动服务 # NOTE 可用环境变量 VERSION 指定要下载的版本号 # NOTE 可用环境变量 NOSTARTUP 禁用自动设置开机启动
# NOTE 操作系统中必须安装有 wget (我不用 curl,因为 curl 访问 github 好像有 bug,经常返回空页面) if ! command -v wget >&-; then echo “请安装 wget” exit 1 fi
# inetutils (apt) # net-tools (yum) get-local-ipv4-using-hostname() { hostname -I 2>&- | awk ‘{print $1}’ }
# iproute2 get-local-ipv4-using-iproute2() { # OR ip route get 1.2.3.4 | awk ‘{print $7}’ ip -4 route 2>&- | awk ‘{print $NF}’ | grep -Eo –color=never ‘[0-9]+(.[0-9]+){3}’ }
# net-tools get-local-ipv4-using-ifconfig() { ( ifconfig 2>&- || ip addr show 2>&- ) | grep -Eo ‘^s+inets+S+’ | grep -Eo ‘[0-9]+(.[0-9]+){3}’ | grep -Ev ‘127.0.0.1|0.0.0.0’ }
# 获取本机 IPv4 地址 get-local-ipv4() { set -o pipefail get-local-ipv4-using-hostname || get-local-ipv4-using-iproute2 || get-local-ipv4-using-ifconfig }
# 获取本机 IPv4 地址(只取第一个) get-local-ipv4-select() { local ips=$(get-local-ipv4) local retcode=$? if [ $retcode -ne 0 ]; then return $retcode fi grep -m 1 “^192.” <<<“$ips” || grep -m 1 “^172.” <<<“$ips” || grep -m 1 “^10.” <<<“$ips” || head -n 1 <<<“$ips” }
# 操作系统的名称 PLATFORM=$(uname -s) # 操作系统的 CPU 架构 ARCH=$(uname -m) # alist 项目的 github 主页链接 ALIST_GITHUB_URL=https://github.com/alist-org/alist # 默认的 alist 软件包,会根据系统信息自动确定,不能确定的留空 ALIST_DEFAULT_ASSET= # 已选择的 alist 软件包,此参数被 download-asset 函数设置 ALIST_SELECTED_ASSET= if [ “$PLATFORM” = ‘Darwin’ ]; then if [ “$ARCH” = ‘arm64’ ] || [ “$ARCH” = ‘aarch64’ ]; then ALIST_DEFAULT_ASSET=alist-darwin-arm64.tar.gz elif [ “$ARCH” = ‘x86_64’ ] || [ “$ARCH” = ‘amd64’ ]; then ALIST_DEFAULT_ASSET=alist-darwin-amd64.tar.gz fi elif [ “$PLATFORM” = ‘Linux’ ]; then if [ “$ARCH” = ‘arm64’ ] || [ “$ARCH” = ‘aarch64’ ]; then ALIST_DEFAULT_ASSET=alist-linux-musl-arm64.tar.gz elif [ “$arch” = ‘armv7l’ ]; then ALIST_DEFAULT_ASSET=alist-linux-musleabihf-armv7l.tar.gz elif [ “$ARCH” = ‘x86_64’ ] || [ “$ARCH” = ‘amd64’ ]; then ALIST_DEFAULT_ASSET=alist-linux-musl-amd64.tar.gz elif [ “$ARCH” = ‘mips’ ]; then ALIST_DEFAULT_ASSET=alist-linux-musl-mips.tar.gz elif [ “$ARCH” = ‘mipsle’ ]; then ALIST_DEFAULT_ASSET=alist-linux-musl-mipsle.tar.gz elif [ “$ARCH” = ‘mips64’ ]; then ALIST_DEFAULT_ASSET=alist-linux-musl-mips64.tar.gz elif [ “$ARCH” = ‘mips64le’ ]; then ALIST_DEFAULT_ASSET=alist-linux-musl-mipsle.tar.gz elif [ “$ARCH” = ‘ppc64le’ ]; then ALIST_DEFAULT_ASSET=alist-linux-musl-ppc64le.tar.gz elif [ “$ARCH” = ‘riscv64’ ]; then ALIST_DEFAULT_ASSET=alist-linux-riscv64.tar.gz elif [ “$ARCH” = ‘s390x’ ]; then ALIST_DEFAULT_ASSET=alist-linux-musl-s390x.tar.gz fi # NOTE 暂时不管 Windows # elif [ “$PLATFORM“ = ‘Windows’ ]; then fi
# 当前系统所用的进程启动器 SYSTEM_INIT= if [ -n “${NOSTARTUP+x}” ]; then SYSTEM_INIT=unset elif [ “$PLATFORM” = ‘Darwin’ ]; then SYSTEM_INIT=$(ps -p 1 -o comm=) elif [ “$PLATFORM” = ‘Linux’ ]; then # ps -p 1 -o comm= # NOTE 也可以用这个命令,但是但有些嵌入式系统,ps 没有 -p 选项 # SYSTEM_INIT=$(cat /proc/1/cmdline) SYSTEM_INIT=$(cat /proc/1/comm) # NOTE 暂时不管 Windows # elif [ “$PLATFORM“ = ‘Windows’ ]; then # # fi
# 获取某个 github 页面的响应。$1: github 链接。 request-github-url() { local url=$1 if [ -z “$url” ]; then echo ‘不能是空链接’ return 1 fi if [[ $url == /* ]]; then url=https://github.com$url elif [ “$url” = https://github.com ]; then true elif [[ $url != https://github.com/* ]]; then url=https://github.com/$url fi local page=$(wget -q -O – “$url”) local retcode=$? # NOTE 我发现,如果使用 curl,可能会因为访问失败,而返回空页面,虽然目前使用 wget,但为了以防万一 while [ -z “$page” ]; do echo $’x1b[38;5;1mx1b[1mRETRYINGx1b[0m:’ “$url” >&2 page=$(wget -q -O – “$url”) retcode=$? done if [ $retcode -ne 0 ]; then echo -n “$page” >&2 return $retcode fi echo -n “$page” }
# 获取某个项目最新的 release 链接。$1: 项目的 github 主页链接。 github-newest-release-link() { local url=$1 if [ -z “$url” ]; then echo ‘不能是空链接’ return 1 fi if [[ $url == /* ]]; then url=https://github.com$url elif [ “$url” = https://github.com ]; then true elif [[ $url != https://github.com/* ]]; then url=https://github.com/$url fi
local release_link=$(request-github-url “$1” | grep -o “${url#https://github.com}”‘/releases/tag/[^”]+’) if [ $? -ne 0 ] || [ -z “$release_link” ]; then echo ‘获取 release_link 失败’ return 1 fi release_link=https://github.com$release_link echo -n $release_link }
# 下载软件包,如果软件包已存在,则跳过。$1: 版本号。 download-asset() { local version=$1 local release_link= if [ -z “$version” ] || ! [[ “$version” =~ ^v?[0-9.]+$ ]] ; then echo ‘版本号未知,正尝试获取最新版本 …’ release_link=$(github-newest-release-link “$ALIST_GITHUB_URL”) local retcode=$? if [ $retcode -ne 0 ]; then return $retcode fi version=$(basename “$release_link”) else if ! [[ “$version” == v* ]]; then version=v$version fi release_link=$ALIST_GITHUB_URL/releases/tag/$version fi
local assets_link=”${release_link//tag///expanded_assets/}” local assets_page=$(request-github-url “$assets_link”)
local ifs=$IFS
local var IFS=$’n’ local links=() for var in $(echo “$assets_page” | grep -o ‘href=”[^”]+’); do links+=(“${var/href=”/https://github.com}”) done IFS=$ifs
local length=${#links[@]}
local flag=0 IFS=$’n’ local names=() for var in $(echo “$assets_page” | grep ‘^ <span’ | grep -o ‘>[^<]*<‘); do if [ $flag -eq 0 ]; then names+=(“${var:1:-1}”) flag=1 else names[-1]=”${names[-1]}””${var:1:-1}” flag=0 fi done IFS=$ifs
local default_index if [ -n “$ZSH_VERSION” ]; then for ((i=1; i<=$length; i++)); do if [ “${names[$i]}” = “$ALIST_DEFAULT_ASSET” ]; then default_index=$i fi printf ‘%2s | ‘ $i echo “${names[$i]} |” “${links[$i]}” done else for ((i=0; i<$length; i++)); do if [ “${names[$i]}” = “$ALIST_DEFAULT_ASSET” ]; then default_index=$i fi printf ‘%2s | ‘ $i echo “${names[$i]} |” “${links[$i]}” done fi
local link name chosen_index if [ -z “$default_index” ]; then while true; do echo -n “请选择一个数字:” read chosen_index chosen_index=$(tr -d ‘[:space:]’ <<<“$chosen_index”) if [ -z “$chosen_index” ]; then continue fi link=”${links[$chosen_index]}” if [ -z “$link” ]; then continue fi name=”${names[$chosen_index]}” break done else while true; do echo -n “请选择一个数字(默认值 $default_index):” read chosen_index chosen_index=$(tr -d ‘[:space:]’ <<<“$chosen_index”) if [ -z “$chosen_index” ]; then chosen_index=default_index fi link=”${links[$chosen_index]}” if [ -z “$link” ]; then continue fi name=”${names[$chosen_index]}” break done fi
ALIST_SELECTED_ASSET=${version}_$name if ! [ -f “$ALIST_SELECTED_ASSET” ]; then wget -O “$ALIST_SELECTED_ASSET” “$link” fi }
#
cd ~
download-asset “$VERSION” if [ $? -ne 0 ]; then echo ‘获取软件包失败’ >&2 exit 1 fi
mkdir -p ~/alist.d/data tar –overwrite -xzf “$ALIST_SELECTED_ASSET” -C alist.d
# NOTE 因为在我的 openwrt 上 pgrep 没有 -u 选项 😂 if pgrep -u a $USER &>/dev/null; then pgrep_arr=(pgrep -u $USER) else pgrep_arr=(pgrep) fi
echo if [ $EUID -eq 0 ]; then prep=() else prep=(sudo) fi case $(basename “$SYSTEM_INIT”) in ‘launchd’) if [ $EUID -eq 0 ]; then service=alist else service=alist-$USER fi service_file=”$HOME/Library/LaunchAgents/$service.plist” mkdir -p “$HOME/Library/LaunchAgents” echo $’x1b[38;5;2mx1b[1mService filex1b[0m:’ “$service_file” echo $’x1b[38;5;2mx1b[1m>>>x1b[0m’ tee “$service_file” << EOF <?xml version=”1.0″ encoding=”UTF-8″?> <!DOCTYPE plist PUBLIC “-//Apple//DTD PLIST 1.0//EN” “http://www.apple.com/DTDs/PropertyList-1.0.dtd”> <plist version=”1.0″> <dict> <key>Description</key> <string>ALIST – 🗂️ A file list program that supports multiple storage, powered by Gin and Solidjs.</string> <key>Documentation</key> <string>https://alist.nn.ci/guide/</string> <key>Label</key> <string>com.alist</string> <key>UserName</key> <string>$USER</string> <key>KeepAlive</key> <true /> <key>ProgramArguments</key> <array> <string>/bin/sh</string> <string>-c</string> <string>’$HOME/alist.d/alist’ server –data ‘$HOME/alist.d/data'</string> </array> <key>RunAtLoad</key> <true /> <key>OnDemand</key> <false /> <key>LaunchOnlyOnce</key> <true /> <key>StandardErrorPath</key> <string>/tmp/$service.err</string> <key>StandardOutPath</key> <string>/tmp/$service.out</string> </dict> </plist> EOF if [ $? -eq 0 ]; then echo $’x1b[38;5;2mx1b[1m<<<x1b[0m’ echo $’x1b[38;5;2mx1b[1mSTART servicex1b[0m:’ “launchctl load -w ‘$service_file'” echo $’x1b[38;5;2mx1b[1mSTOP servicex1b[0m:’ “launchctl unload ‘$service_file'” launchctl unload “$service_file” 2>&- launchctl load -w “$service_file” fi ;; ‘systemd’) if [ $EUID -eq 0 ]; then service=alist else service=alist-$USER fi service_file=/etc/systemd/system/$service.service echo $’x1b[38;5;2mx1b[1mService filex1b[0m:’ “$service_file” echo $’x1b[38;5;2mx1b[1m>>>x1b[0m’ “${prep[@]}” tee “$service_file” << EOF [Unit] Description=’ALIST – 🗂️ A file list program that supports multiple storage, powered by Gin and Solidjs.’ Documentation=’https://alist.nn.ci/guide/’ After=network.target
[Service] Type=simple User=$USER Restart=on-failure ExecStart=’$HOME/alist.d/alist’ server –data ‘$HOME/alist.d/data’
[Install] WantedBy=default.target EOF if [ $? -eq 0 ]; then echo $’x1b[38;5;2mx1b[1m<<<x1b[0m’ echo $’x1b[38;5;2mx1b[1mSTART servicex1b[0m:’ “service $service start” echo $’x1b[38;5;2mx1b[1mSTOP servicex1b[0m:’ “systemctl start $service” echo $’x1b[38;5;2mx1b[1mSTART servicex1b[0m:’ “service $service stop” echo $’x1b[38;5;2mx1b[1mSTOP servicex1b[0m:’ “systemctl stop $service” “${prep[@]}” systemctl enable “$service” “${prep[@]}” systemctl stop “$service” “${prep[@]}” systemctl start “$service” fi ;; ‘init’) if [ $EUID -eq 0 ]; then service=alist else service=alist-$USER fi service_file=/etc/init/$service.conf echo $’x1b[38;5;2mx1b[1mService filex1b[0m:’ “$service_file” echo $’x1b[38;5;2mx1b[1m>>>x1b[0m’ “${prep[@]}” tee “$service_file” << EOF description “ALIST – 🗂️ A file list program that supports multiple storage, powered by Gin and Solidjs.” documentation “https://alist.nn.ci/guide/”
start on filesystem or runlevel [2345] stop on runlevel [!2345]
respawn
exec ‘$HOME/alist.d/alist’ server –data ‘$HOME/alist.d/data’ EOF if [ $? -eq 0 ]; then echo $’x1b[38;5;2mx1b[1m<<<x1b[0m’ echo $’x1b[38;5;2mx1b[1mSTART servicex1b[0m:’ “service $service start” echo $’x1b[38;5;2mx1b[1mSTOP servicex1b[0m:’ “service $service stop” “${prep[@]}” service “$service” enable “${prep[@]}” service “$service” stop “${prep[@]}” service “$service” start fi ;; ‘procd’) if [ $EUID -eq 0 ]; then service=alist else service=alist-$USER fi service_file=/etc/init.d/$service echo $’x1b[38;5;2mx1b[1mService filex1b[0m:’ “$service_file” echo $’x1b[38;5;2mx1b[1m>>>x1b[0m’ “${prep[@]}” tee “$service_file” << EOF #!/bin/sh /etc/rc.common
USE_PROCD=1
START=99 STOP=99
Description=’ALIST – 🗂️ A file list program that supports multiple storage, powered by Gin and Solidjs.’ Documentation=’https://alist.nn.ci/guide/’
start_service() { procd_open_instance procd_set_param command ‘$HOME/alist.d/alist’ server –data ‘$HOME/alist.d/data’ procd_set_param respawn procd_set_param user $USER procd_set_param stdout 1 procd_set_param stderr 1 procd_set_param pidfile /var/run/alist-$USER.pid procd_close_instance } EOF if [ $? -eq 0 ]; then echo $’x1b[38;5;2mx1b[1m<<<x1b[0m’ “${prep[@]}” chmod +x “$service_file” echo $’x1b[38;5;2mx1b[1mSTART servicex1b[0m:’ “service $service start” echo $’x1b[38;5;2mx1b[1mSTOP servicex1b[0m:’ “service $service stop” “${prep[@]}” service “$service” enable “${prep[@]}” service “$service” stop “${prep[@]}” service “$service” start fi ;; *) # 默认情况 echo $’x1b[38;5;2mx1b[1mSTART servicex1b[0m:’ “‘$HOME/alist.d/alist’ start –data ‘$HOME/alist.d/data'” echo $’x1b[38;5;2mx1b[1mSTOP servicex1b[0m:’ “‘$HOME/alist.d/alist’ stop” # NOTE 如果有已经运行的实例,终结之 “${pgrep_arr[@]}” alist | xargs kill -9 “$HOME/alist.d/alist” start –data “$HOME/alist.d/data” ;; esac
~/alist.d/alist admin –data ~/alist.d/data
echo echo -e ‘x1b[38;5;3mDocumentationx1b[0m: https://alist.nn.ci/guide/’ echo -e “x1b[38;5;3mServer onx1b[0m: http://$(get-local-ipv4-select):5244”
|
暂无评论内容