DEST=“${SRC}”/output
REVISION=“2.2.2”
DOWNLOAD_MIRROR == “china”
NTP_SERVER=“cn.pool.ntp.org” 通过网络校准您计算机上的时钟
BUILD_ALL
COLUMNS,
LINES
TTY_X, TTY_Y
LANGUAGE=“en_US:en”
CONSOLE_CHAR=“UTF-8”
FORCE_CHECKOUT=yes
PROGRESS_DISPLAY == none ?
OUTPUT_VERYSILENT=yes
OUTPUT_DIALOG=yes
PROGRESS_LOG_TO_FILE,
SHOW_WARNING=yes
USE_CCACHE
CCACHE=ccache
export PATH=“/usr/lib/ccache:$PATH”
PRIVATE_CCACHE
export CCACHE_DIR=$DEST/cache/ccache
OFFLINE_WORK
BUILD_OPT
BOARD
BOARD_TYPE=“conf”
LINUXFAMILY=“${BOARDFAMILY}”
KERNEL_TARGET
BRANCH
EXPERT
KERNEL_CONFIGURE
RELEASE_TARGET
RELEASE
BUILD_MINIMAL == yes
BUILD_DESKTOP
IMAGETYPE
EXTERNAL_NEW
CONTAINER_COMPAT=“no”
COMPRESS_OUTPUTIMAGE
CPUS
USEALLCORES
CTHREADS
GPG_PASS
IMAGE_TYPE
BOOTSOURCEDIR,
BOOTDIR,
BOOTBRANCH
LINUXSOURCEDIR,
KERNELDIR,
KERNELBRANCH
ATFSOURCE,
ATFSOURCEDIR,
ATFDIR,
ATFBRANCH
DEB_BRANCH
CHOSEN_UBOOT
CHOSEN_KERNEL
CHOSEN_ROOTFS
CHOSEN_DESKTOP
CHOSEN_KSRC
CLEAN_LEVEL
IGNORE_UPDATES
DEB_STORAGE
REPOSITORY_INSTALL
CHOSEN_UBOOT,
REVISION,
ARCH
EXTERNAL_NEW
BSP_BUILD
KERNEL_CONFIGURE
if [[ $(basename "$0") == main.sh ]]; then
basename
从文件名中剥离目录和后缀$0
执行文件名umask 002
文件权限是三类用户, 文件所有者user(u),文件所有者所在主群组group(g)、其它用户others(o),上述命令, 可清除其他用户的写权限.
[[ -n $COLUMNS ]] && stty cols $COLUMNS
TTY_X=$(($(stty size | awk '{print $2}')-6)) # determine terminal width
stty
检查和修改当前注册的终端的通信参数,
cols N,
tell the kernel that the terminal has N columnssize
显示终端的大小,即行数和列数source "${SRC}"/scripts/debootstrap.sh # system specific install
source "${SRC}"/scripts/image-helpers.sh # helpers for OS image building
source "${SRC}"/scripts/distributions.sh # system specific install
source "${SRC}"/scripts/desktop.sh # desktop specific install
source "${SRC}"/scripts/compilation.sh # patching and compilation of kernel, uboot, ATF
source "${SRC}"/scripts/makeboarddeb.sh # create board support package
source "${SRC}"/scripts/general.sh # general functions
source "${SRC}"/scripts/chroot-buildpackages.sh # building packages in chroot
source "${SRC}"/scripts/pack-uboot.sh
prepare_host_basic
if [[ -z $BUILD_OPT ]]; then
-z str
如果给定字符串的长度为0,测试结果为真。BUILD_OPT=$(whiptail --title "${titlestr}" --backtitle "${backtitle}" --notags \
--menu "${menustr}" "${TTY_Y}" "${TTY_X}" $((TTY_Y - 8)) \
--cancel-button Exit --ok-button Select "${options[@]}" \
3>&1 1>&2 2>&3)
whiptail 是替代 dialog 的实现,它基于 newt 库.而 newt 则是为了简化 ncurses 开发而产生的新的 tty 下的UI库
3>&1 1>&2 2>&3
The 3>&1 in your command line will create a new file descriptor and redirect it to 1 which is STDOUT. Now 1>&2 will redirect the file descriptor 1 to STDERR and 2>&3 will redirect file descriptor 2 to 3 which is STDOUT.
SRC=“$(dirname “$(realpath “${BASH_SOURCE[0]}”)”)”
CHANGED_FILES=$(git diff --name-only)
SHELL_ONLY=yes
export DEBIAN_FRONTEND=noninteractive
EXTER=“${SRC}/external”
CONFIG=“userpatches/config-$1.conf”
CONFIG_FILE=“$(realpath “$CONFIG”)”
CONFIG_PATH=$(dirname “$CONFIG_FILE”)
USERPATCHES_PATH=“$CONFIG_PATH”
BUILD_ALL == demo
SRC="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"`
BASH_SOURCE[0]
: 取得bash的当前路径, 以及完整命令realpath
: 获取bash绝对路径dirname
: 获取路径信息, 剔除文件名grep -q "[[:space:]]" <<<"${SRC}" && { echo "\"${SRC}\" contains whitespace. Not supported. Aborting." >&2 ; exit 1 ; }
<<<
: ${SRC}将作为grep命令, 需处理的信息grep -q "[[:space:]]"
: -q
, 不显示任何信息, [[:space:]]
, 匹配空白字符>&2
: 将echo包含的信息, 输出到控制台exit 1
: 退出执行cd "${SRC}" || exit
||
: 当测试条件有一个为真时返回0(真), 全假为假if [[ -f "${SRC}"/scripts/general.sh ]]; then
# shellcheck source=scripts/general.sh
source "${SRC}"/scripts/general.sh
else
echo "Error: missing build directory structure"
echo "Please clone the full repository by https://github.com/orangepi-xunlong/orangepi-build"
exit 255
fi
如果general.sh存在, 则(source)_执行_该脚本, 否则输出错误信息,
source的作用, 把一个文件的内容变成shell环境, 即general.sh包含的脚本函数, 将被缓冲, 等待后续调用.
if [[ $EUID == 0 ]] || [[ "$1" == vagrant ]]; then
:
elif [[ "$1" == docker || "$1" == dockerpurge || "$1" == docker-shell ]] && grep -q `whoami` <(getent group docker); then
:
else
display_alert "This script requires root privileges, trying to use sudo" "" "wrn"
sudo "$SRC/build.sh" "$@"
exit $?
fi
$EUID
: ??? 有效用户IDvagrant
: 一款用来构建虚拟开发环境的工具,非常适合 php/python/ruby/java 这类语言开发 web 应用,“代码在我机子上运行没有问题”这种说辞将成为历史。可以通过 Vagrant 封装一个 Linux 的开发环境,分发给团队成员。成员可以在自己喜欢的桌面系统(Mac /Windows /Linux)上开发程序,代码却能统一在封装好的环境里运行,非常霸气。docker
: 一个开源引擎,可以轻松为任何应用创建一个轻量级、可移植、自给自足的容器。开发者在笔记本上编译测试通过的容器, 可以批量在生产环境中部署,包括VMs(虚拟机)、bare metal、OpenStack 集群和其他的基础应用平台。dockerpurge
: ??? docker-purge, docker用户组docker-shell
: docker用户组grep -q `whoami` <(getent group docker);
在docker组中, 匹配用户名whoamiif [[ -z "$(which whiptail)" ]]; then
sudo apt-get update
sudo apt-get install -y whiptail
fi
-y
: -y/–yes/–assume-yes – assume “yes” as an answer to promptsapt-get install -y command is usually used to download your desired application which has many configuration options from an online software repository pointed to by your sources.list configuration file and install that application on your Linux machine in a non-interactive manner asking the apt-get package management tool to assume “yes” to any questions that pop-up during the installation process.
whiptail
: bash交互界面命令whiptail(消息框,提示框,输入框)if [[ -z "$(which getfacl)" ]]; then
sudo apt-get update
sudo apt-get install -y acl
fi
getfacl
: ”get file access control list“的缩写,其功能是用于显示文件或目录的ACL策略。对指定的文件或目录进行精准的权限控制,FACL一定是不二之选acl
: Access Control List 的缩写,主要的目的是在提供传统的 owner,group,others 的 read,write,execute 权限之外的细部权限配置。ACL 可以针对单一使用者,单一文件或目录来进行 r,w,x 的权限规范,对于需要特殊权限的使用状况非常有帮助检查是否支持ACL
ACL需要Linux内核和文件系统的配合才能工作,大多数Linux发行版本默认都是支持的。但最好能检查一下:
sudo tune2fs -l /dev/sda1 |grep “Default mount options:”
Default mount options: user_xattr acl
if [[ "$1" == vagrant && -z "$(which vagrant)" ]]; then
display_alert "Vagrant not installed." "Installing"
sudo apt-get update
sudo apt-get install -y vagrant virtualbox
fi
vagrant
: 一款用来构建虚拟开发环境的工具,非常适合 php/python/ruby/java 这类语言开发 web 应用,“代码在我机子上运行没有问题”这种说辞将成为历史。可以通过 Vagrant 封装一个 Linux 的开发环境,分发给团队成员。成员可以在自己喜欢的桌面系统(Mac /Windows /Linux)上开发程序,代码却能统一在封装好的环境里运行,非常霸气。if [[ "$1" == dockerpurge && -f /etc/debian_version ]]; then
display_alert "Purging Orange Pi Docker containers" "" "wrn"
docker container ls -a | grep orangepi | awk '{print $1}' | xargs docker container rm &> /dev/null
docker image ls | grep orangepi | awk '{print $3}' | xargs docker image rm &> /dev/null
shift
set -- "docker" "$@"
fi
-f
如果给定的文件存在,且是一个普通文件,测试结果为真。docker container ls -a
可以列出所有的容器,包括正在运行的和没有运行的容器awk '{print $1}'
将某行(一条记录)中, 以空格为分割符, 打印第一个字段xargs
The xargs command builds and executes commands provided through the standard input. It takes the input and converts it into a command argument for another command. This feature is particularly useful in file management, where xargs is used in combination with rm, cp, mkdir, and other similar commands.
&> /dev/null
将命令输出, 重定向至空设备文件, 即, 不显示任何信息docker image ls
列出所有的镜像 (包含中间镜像层)awk '{print $3}'
将某行(一条记录)中, 以空格为分割符, 打印第三个字段if [[ "$1" == docker-shell ]]; then
shift
SHELL_ONLY=yes
set -- "docker" "$@"
fi
shift
命令参数的顺位获取,可从第一个参数开始, 依次遍历每个参数, 然后进行相应处理set -- "docker" "$@"
直接运行set,会显示所有的环境变量和 Shell 函数
===========================================
$@表示从1开始的所有位置参数,每个参数是一个单独的字。单独引用时,$@相当于$1、$2、$3 …,表示多个单独的参数。前后加双引号引用时,“$@“相当于”$1”、“$2”、“$3”…,每个参数都是一个单独的前后加双引号的字符串。
=============================================
--
: If no arguments follow this option, then the positional parameters are unset. Otherwise, the positional parameters are set to the arguments, even if some of them begin with a ‘-’.
if [[ "$1" == docker && -f /etc/debian_version && -z "$(which docker)" ]]; then
# add exception for Ubuntu Focal until Docker provides dedicated binary
codename=$(lsb_release -sc)
codeid=$(lsb_release -is | awk '{print tolower($0)}')
[[ $codeid == linuxmint && $codename == debbie ]] && codename="buster" && codeid="debian"
[[ $codename == focal ]] && codename="bionic"
display_alert "Docker not installed." "Installing" "Info"
echo "deb [arch=amd64] https://download.docker.com/linux/${codeid} ${codename} edge" > /etc/apt/sources.list.d/docker.list
# minimal set of utilities that are needed for prep
packages=("curl" "gnupg" "apt-transport-https")
for i in "${packages[@]}"
do
[[ ! $(which $i) ]] && install_packages+=$i" "
done
[[ -z $install_packages ]] && apt-get update;apt-get install -y -qq --no-install-recommends $install_packages
curl -fsSL "https://download.docker.com/linux/${codeid}/gpg" | apt-key add -qq - > /dev/null 2>&1
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y -qq --no-install-recommends docker-ce
display_alert "Add yourself to docker group to avoid root privileges" "" "wrn"
"$SRC/build.sh" "$@"
exit $?
fi
-z "$(which docker)"
which 在环境变量$PATH目录里, 匹配文件名
-z str 如果给定字符串的长度为0,测试结果为真
codename=$(lsb_release -sc)
lsb_release 查看Linux发行版本, -s, --short 输出简短的描述信息, -c 发行版代号
codeid=$(lsb_release -is | awk '{print tolower($0)}')
lsb_release -is, -i 显示发行版的id,
awk ‘{print tolower($0)}’ 字符串中每个大写字符将更改为小写, $0从管道中, 传入的整个字符串
for i in "${packages[@]}"
[@]
迭代提取packages包含的所有_字串_(空格分隔)
[[ ! $(which $i) ]] && install_packages+=$i" "
which $i1, 测试字串对应的命令, 是否存在
+=
如果命令存在, 可追加到install_packages末尾
[[ -z $install_packages ]] && apt-get update;apt-get install -y -qq --no-install-recommends $install_packages
-z 如果给定字符串的长度为0,测试结果为真
-y assume “yes” as an answer to prompts
-qq 不输出信息,错误除外
–no-install-recommends 避免安装非必须的文件,从而减小镜像的体积
curl -fsSL "https://download.docker.com/linux/${codeid}/gpg" | apt-key add -qq - > /dev/null 2>&1
curl -fsSL
-f/–fail 不输出错误
-s/–silent 静默模式,不输出任何东西
-S/–show-error 只输出错误信息,通常与-s一起使用
-L/–location 让 HTTP 请求跟随服务器的重定向。curl 默认不跟随重定向
apt-key
管理Debian Linux系统中的软件包密钥2>&1
将标准错误重定向到标准输出display_alert "Add yourself to docker group to avoid root privileges" "" "wrn"
"$SRC/build.sh" "$@"
display_alert()
{
#[[ -n $DEST ]] && echo “Displaying message: $@” >> $DEST/debug/output.log
local tmp=“”
[[ -n $2 ]] && tmp=“[\e[0;33m $2 \x1B[0m]”
case $3 in
err) echo -e “[\e[0;31m error \x1B[0m] $1 $tmp”;;
wrn) echo -e “[\e[0;35m warn \x1B[0m] $1 $tmp”;;
ext) echo -e “[\e[0;32m o.k. \x1B[0m] \e[1;32m$1\x1B[0m $tmp”;;
info) echo -e “[\e[0;32m o.k. \x1B[0m] $1 $tmp”;;
*) echo -e “[\e[0;32m … \x1B[0m] $1 $tmp”;;
esac
}
display_alert “List of local repos” “local” “err”
display_alert “List of local repos” “local” “wrn”
display_alert “List of local repos” “local” “ext”
display_alert “List of local repos” “local” “info”
display_alert “List of local repos” “local” “other”
err) echo -e "[\e[0;31m error \x1B[0m] $1 $tmp";;
[\e[0;31m error \x1B[0m]
设置文本error的颜色值
# Create example configs if none found in userpatches
if [[ -z "$CONFIG" && -n "$1" && -f "${SRC}/userpatches/config-$1.conf" ]]; then
CONFIG="userpatches/config-$1.conf"
shift
fi
-z str 如果给定字符串的长度为0,测试结果为真。
-n str 如果给定字符串的长度大于0,测试结果为真
pushd $CONFIG_PATH > /dev/null
# shellcheck source=/dev/null
source "$CONFIG_FILE"
popd > /dev/null
pushd
将目录添加到目录堆栈顶部,切换当前工作目录到该目录source "$CONFIG_FILE"
将文件中的变量, 设定为环境变量popd
将目录栈中的栈顶目录, 出栈while [[ $1 == *=* ]]; do
parameter=${1%%=*}
value=${1##*=}
shift
display_alert "Command line: setting $parameter to" "${value:-(empty)}" "info"
eval "$parameter=\"$value\""
done
parameter=${1%%=*}
1: 即$1, =* : 匹配模式
====%
: 匹配等号后, 最短的字串,%%
: 匹配等号后, 最长的字串(贪婪匹配?)
value=${1##*=}
1: 即$1, *= : 匹配模式
====#
: 匹配等号前, 最短的数字,##
: 匹配等号前, 最长的数字(贪婪匹配?)
eval [args]
读取随后的参数,组合成一个简单的命令,然后提交Shell执行。
echo -e "[\e[0;32m o.k. \x1B[0m] This script will try to update"
git pull
CHANGED_FILES=$(git diff --name-only)
-e
输出文本中存在颜色值,[\e[0;32m o.k. \x1B[0m]
设置文本o.k.的颜色值
git pull
当前的本地分支, 将与(远程)唯一的追踪分支, 进行合并.
git diff --name-only
列出合并中, 被更改的文件
if [[ -n $CHANGED_FILES ]]; then
-n
如果给定字符串的长度大于0,测试结果为真
read -r
原样读取(Raw mode),不把反斜杠字符解释为转义字符
git checkout
用于切换分支或恢复工作树文件, 还会更新HEAD,将指定的分支设置为当前分支