Skip to content

标准的脚本结构

标准的 shell 脚本通常遵循一种基本的结构,这有助于组织代码并使其更易于理解和维护。以下是一个典型的 shell 脚本的基本结构:

bash
#!/bin/bash  # 指定解释器路径,这一行告诉系统该脚本应该使用哪个 shell 来执行  
  
# 脚本的元数据或描述  
# 这是一个注释,用于描述脚本的目的、作者、版本等信息  
# Author: Your Name  
# Version: 1.0  
# Description: This script does something useful  
  
# 定义函数(可选)  
function my_function() {  
    # 函数体  
    echo "This is my function."  
}  
  
# 脚本的主体部分  
# 这里放置脚本的主要逻辑  
  
# 可以先定义一些变量  
my_variable="Hello, World!"  
  
# 然后是命令和逻辑  
echo "Starting the script..."  
echo "The value of my_variable is: $my_variable"  
  
# 调用之前定义的函数  
my_function  
  
# 如果有条件判断,可以这样写  
if [ some_condition ]; then  
    echo "Condition is true."  
else  
    echo "Condition is false."  
fi  
  
# 循环结构示例  
for i in {1..5}  
do  
    echo "Iteration $i"  
done  
  
# 脚本结束时的消息或清理操作(可选)  
echo "Script execution finished."  
  
# 退出脚本,可以返回一个退出状态码  
exit 0  # 0 通常表示成功,非零值表示错误或异常

在上面的示例中,注意以下几点:

  1. #!/bin/bash 是 shebang 行,它指定了用于执行脚本的 shell 解释器。对于 Bash 脚本,这通常是 /bin/bash,但也可能是其他 shell 的路径,如 /bin/sh/usr/bin/env bash 等。
  2. 注释以 # 开头,它们不会被执行,但可以提供有关脚本或其部分的信息。
  3. 函数定义使用 function 关键字(尽管在 Bash 中这不是必需的)或简单地使用函数名后跟 ()
  4. 脚本的主体部分包含了脚本的主要逻辑,包括变量定义、命令执行、条件判断和循环等。
  5. 在脚本的末尾,可以使用 exit 命令来指定脚本的退出状态码。通常,exit 0 表示成功,而非零值表示出现了某种错误或异常情况。
  6. 脚本应该具有良好的可读性和可维护性,这意味着代码应该清晰、简洁,并遵循良好的编程实践。

参考一个实际的开源的项目例子,mirrord 安装脚本如下:

bash
#!/bin/bash
# mirrord installer
#             _                        _ 
#   _ __ ___ (_)_ __ _ __ ___  _ __ __| |
#  | '_ ` _ \| | '__| '__/ _ \| '__/ _` |
#  | | | | | | | |  | | | (_) | | | (_| |
#  |_| |_| |_|_|_|  |_|  \___/|_|  \__,_|
#
# Usage:
#   curl -fsSL https://github.com/metalbear-co/mirrord/raw/latest/scripts/install.sh | sh
set -e

file_issue_prompt() {
  echo "If you wish us to support your platform, please file an issue"
  echo "https://github.com/metalbear-co/mirrord/issues/new"
  exit 1
}

get_latest_version() {
  local res=$(curl --proxy socks5h://192.168.1.154:1080 -fsSL https://github.com/metalbear-co/mirrord/raw/latest/Cargo.toml | grep -m 1 version | cut -d' ' -f3 | tr -d '\"')
  echo $res
}

copy() {
  if [[ ":$PATH:" == *":$HOME/.local/bin:"* ]]; then
      if [ ! -d "$HOME/.local/bin" ]; then
        mkdir -p "$HOME/.local/bin"
      fi
      mv /tmp/mirrord "$HOME/.local/bin/mirrord"
  else
      # Try without sudo first, run with sudo only if mv failed without it.
      mv /tmp/mirrord /usr/local/bin/mirrord || (
        echo "Cannot write to installation target directory as current user, writing as root."
        sudo mv /tmp/mirrord /usr/local/bin/mirrord
      )
  fi
}

# This function decides what version will be installed based on the following priority:
# 1. Environment variable `VERSION` is set.
# 2. Command line argument is passed.
# 3. Latest available on GitHub
function get_version() {
  if [[ -z "$VERSION" ]]; then
      if [[ -n "$1" ]]; then
          VERSION="$1"
      else
          VERSION=$(get_latest_version)
      fi
  fi
  echo $VERSION
}

function install() {
  local version=$(get_version $1);
  echo "Installing version $version"
  if [[ "$OSTYPE" == "linux"* ]]; then
      ARCH=$(uname -m);
      OS="linux";
      if [[ "$ARCH" != "x86_64" && "$ARCH" != "aarch64" ]]; then
          echo "mirrord is only available for linux x86_64/aarch64 architecture"
          file_issue_prompt
          exit 1
      fi
  elif [[ "$OSTYPE" == "darwin"* ]]; then
      ARCH="universal";
      OS="mac";
  else
      echo "mirrord isn't supported for your platform - $OSTYPE"
      file_issue_prompt
      exit 1
  fi
  # curl --proxy socks5h://192.168.1.154:1080 -o /tmp/mirrord -fsSL https://github.com/metalbear-co/mirrord/releases/download/$version/mirrord_$OS\_$ARCH
  chmod +x /tmp/mirrord
  copy
  echo "mirrord installed! Have fun! For feedback and support, join our Discord server: https://discord.gg/metalbear, open an issue or discussion on our GitHub: https://github.com/metalbear-co/mirrord/ or send us an email at hi@metalbear.co"
}


install $1