Shell Script Example
This shell script is from Jetson’s JetPack. It downloads and installs pytorch. I added highlighting and comments to help myself understand bash language.
#!/bin/bash
# #! is shebang interpreter directive, it sets which interpreter to use
# when called using ./
#
# Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
# Note the following
# 1. how a dialog is constructed
# 2. commands like eval, echo, $?
# eval - construct command by concatenating arguments
# $? - exit status of the most recently executed foreground pipeline.
APP_TITLE="Hello AI World (jetson-inference)"
LOG="[jetson-inference] "
WGET_QUIET="--quiet"
#
# exit message for user
#
function exit_message()
{
echo " "
if [ $1 = 0 ]; then
echo "$LOG installation complete, exiting with status code $1"
else
echo "$LOG errors encountered during installation, exiting with code $1"
fi
echo "$LOG to run this tool again, use the following commands:"
echo " "
echo " $ cd /build"
echo " $ ./install-pytorch.sh"
echo " "
exit $1
}
#
# prompt user for retry
#
function retry_prompt()
{
dialog --backtitle "$APP_TITLE" \
--title "Download Error" \
--colors \
--extra-button \
--extra-label "Next" \
--cancel-label "Quit" \
--ok-label "Retry" \
--yesno "\nFailed to download '$1' (error code=$2)\n\nWould you like to try downloading it again?\n\n\ZbNote:\Zn if this error keeps occuring, see here:\n https://eLinux.org/Jetson_Zoo" 12 60
local retry_status=$?
clear
WGET_QUIET="--verbose"
if [ $retry_status = 1 ]; then
echo "$LOG packages failed to download"
exit_message 1
elif [ $retry_status != 0 ]; then
return 1
fi
return 0
}
#
# try to download a file from URL
#
function attempt_download_file()
{
local filename=$1
local URL=$2
wget $WGET_QUIET --show-progress --progress=bar:force:noscroll --no-check-certificate $URL -O $filename
local wget_status=$?
if [ $wget_status != 0 ]; then
echo "$LOG wget failed to download '$filename' (error code=$wget_status)"
return $wget_status
fi
#mv $filename $OUTPUT_DIR
return 0
}
#
# download a file from URL
#
function download_file()
{
local filename=$1
local URL=$2
WGET_QUIET="--quiet"
while true; do
attempt_download_file $filename $URL
local download_status=$?
if [ $download_status = 0 ]; then
return 0
fi
retry_prompt $filename $download_status
local retry_status=$?
if [ $retry_status != 0 ]; then
return 1
fi
done
}
#
# download and install a pip wheel
#
function download_wheel()
{
local filename=$2
local URL=$3
download_file $filename $URL
local download_status=$?
if [ $download_status != 0 ]; then
echo "$LOG failed to download $filename"
return 1
fi
$1 install $filename
local install_status=$?
if [ $install_status != 0 ]; then
echo "$LOG failed to install $filename"
echo "$LOG -- command: $1 install $filename"
echo "$LOG -- error code: $install_status"
return 1
fi
return 0
}
#
# check if a particular deb package is installed with dpkg-query
# arg $1 -> package name
# arg $2 -> variable name to output status to (e.g. HAS_PACKAGE=1)
#
function find_deb_package()
{
local PKG_NAME=$1
local HAS_PKG=`dpkg-query -W --showformat='${Status}\n' $PKG_NAME|grep "install ok installed"`
if [ "$HAS_PKG" == "" ]; then
echo "$LOG Checking for '$PKG_NAME' deb package...not installed"
return 1
else
echo "$LOG Checking for '$PKG_NAME' deb package...installed"
eval "$2=INSTALLED" # construct command by concatenating arguments
return 0
fi
}
#
# install a debian package if it isn't already installed
# arg $1 -> package name
# arg $2 -> variable name to output status to (e.g. FOUND_PACKAGE=INSTALLED)
#
function install_deb_package()
{
local PKG_NAME=$1
# check to see if the package is already installed
find_deb_package $PKG_NAME $2
local pkg_status=$?
# if not, install the package
if [ $pkg_status != 0 ]; then
echo "$LOG Missing '$PKG_NAME' deb package...installing '$PKG_NAME' package."
sudo apt-get --force-yes --yes install $PKG_NAME
else
return 0
fi
# verify that the package was installed
find_deb_package $PKG_NAME $2
local install_status=$?
if [ $install_status != 0 ]; then
echo "$LOG Failed to install '$PKG_NAME' deb package."
exit_message 1
#return 1
else
echo "$LOG Successfully installed '$PKG_NAME' deb package."
return 0
fi
}
#
# install PyTorch
#
function install_pytorch_v110_python27()
{
echo "$LOG Downloading PyTorch v1.1.0 (Python 2.7)..."
# install apt packages
install_deb_package "python-pip" FOUND_PIP
install_deb_package "qtbase5-dev" FOUND_QT5
install_deb_package "libjpeg-dev" FOUND_JPEG
install_deb_package "zlib1g-dev" FOUND_ZLIB
# install pytorch wheel
download_wheel pip "torch-1.1.0-cp27-cp27mu-linux_aarch64.whl" "https://nvidia.box.com/shared/static/o8teczquxgul2vjukwd4p77c6869xmri.whl"
local wheel_status=$? # exit status of the most recently executed foreground pipeline.
if [ $wheel_status != 0 ]; then
echo "$LOG failed to install PyTorch v1.1.0 (Python 2.7)"
return 1
fi
# build torchvision
echo "$LOG cloning torchvision..."
rm -r -f torchvision-27
git clone -bv0.3.0 https://github.com/dusty-nv/vision torchvision-27
cd torchvision-27
echo "$LOG building torchvision for Python 2.7..."
sudo python setup.py install
cd ../
return 0
}
function install_pytorch_v110_python36()
{
echo "$LOG Downloading PyTorch v1.1.0 (Python 3.6)..."
# install apt packages
install_deb_package "python3-pip" FOUND_PIP3
install_deb_package "qtbase5-dev" FOUND_QT5
install_deb_package "libjpeg-dev" FOUND_JPEG
install_deb_package "zlib1g-dev" FOUND_ZLIB
# install pytorch wheel
download_wheel pip3 "torch-1.1.0-cp36-cp36m-linux_aarch64.whl" "https://nvidia.box.com/shared/static/j2dn48btaxosqp0zremqqm8pjelriyvs.whl"
local wheel_status=$?
if [ $wheel_status != 0 ]; then
echo "$LOG failed to install PyTorch v1.1.0 (Python 3.6)"
return 1
fi
# build torchvision
echo "$LOG cloning torchvision..."
rm -r -f torchvision-36
git clone -bv0.3.0 https://github.com/dusty-nv/vision torchvision-36
cd torchvision-36
echo "$LOG building torchvision for Python 3.6..."
sudo python3 setup.py install
cd ../
return 0
}
#
# check L4T version
#
function check_L4T_version()
{
JETSON_L4T_STRING=$(head -n 1 /etc/nv_tegra_release)
if [ -z $2 ]; then
echo "$LOG reading L4T version from \"dpkg-query --show nvidia-l4t-core\""
JETSON_L4T_STRING=$(dpkg-query --showformat='${Version}' --show nvidia-l4t-core)
local JETSON_L4T_ARRAY=(${JETSON_L4T_STRING//./ })
#echo ${JETSON_L4T_ARRAY[@]}
#echo ${#JETSON_L4T_ARRAY[@]}
JETSON_L4T_RELEASE=${JETSON_L4T_ARRAY[0]}
JETSON_L4T_REVISION=${JETSON_L4T_ARRAY[1]}
else
echo "$LOG reading L4T version from /etc/nv_tegra_release"
JETSON_L4T_RELEASE=$(echo $JETSON_L4T_STRING | cut -f 2 -d ' ' | grep -Po '(?<=R)[^;]+')
JETSON_L4T_REVISION=$(echo $JETSON_L4T_STRING | cut -f 2 -d ',' | grep -Po '(?<=REVISION: )[^;]+')
fi
JETSON_L4T_VERSION="$JETSON_L4T_RELEASE.$JETSON_L4T_REVISION"
echo "$LOG Jetson BSP Version: L4T R$JETSON_L4T_VERSION"
if [ $JETSON_L4T_RELEASE -lt 32 ]; then
dialog --backtitle "$APP_TITLE" \
--title "PyTorch Automated Install requires JetPack ≥4.2" \
--colors \
--msgbox "\nThis script to install PyTorch from pre-built binaries\nrequires \ZbJetPack 4.2 or newer\Zn (L4T R32.1 or newer).\n\nThe version of L4T on your system is: \ZbL4T R${JETSON_L4T_VERSION}\Zn\n\nIf you wish to install PyTorch for training on Jetson,\nplease upgrade to JetPack 4.2 or newer, or see these\ninstructions to build PyTorch from source:\n\n \Zbhttps://eLinux.org/Jetson_Zoo\Zn\n\nNote that PyTorch isn't required to build the repo,\njust for re-training networks onboard your Jetson.\nYou can proceed following Hello AI World without it,\nexcept for the parts on Transfer Learning with PyTorch." 20 60
clear
echo " "
echo "[jetson-inference] this script to install PyTorch from pre-built binaries"
echo " requires JetPack 4.2 or newer (L4T R32.1 or newer). "
echo " the version of L4T on your system is: L4T R${JETSON_L4T_VERSION}"
echo " "
echo " if you wish to install PyTorch for training on Jetson,"
echo " please upgrade to JetPack 4.2 or newer, or see these"
echo " instructions to build PyTorch from source:"
echo " "
echo " > https://eLinux.org/Jetson_Zoo"
echo " "
echo " note that PyTorch isn't required to build the repo,"
echo " just for re-training networks onboard your Jetson."
echo " "
echo " you can proceed following Hello AI World without it,"
echo " except for the parts on Transfer Learning with PyTorch."
exit_message 1
fi
}
# check for dialog package
install_deb_package "dialog" FOUND_DIALOG
echo "$LOG FOUND_DIALOG=$FOUND_DIALOG"
# use customized RC config
export DIALOGRC=./install-pytorch.rc
# check L4T version
check_L4T_version
#
# main menu
#
while true; do
packages_selected=$(dialog --backtitle "$APP_TITLE" \
--title "PyTorch Installer (L4T R$JETSON_L4T_VERSION)" \
--cancel-label "Quit" \
--colors \
--checklist "If you want to train DNN models on your Jetson, this tool will download and install PyTorch. Select the desired versions of pre-built packages below, or see \Zbhttp://eLinux.org/Jetson_Zoo\Zn for instructions to build from source. \n\nYou can skip this step and select Quit if you don't want to install PyTorch.\n\n\ZbKeys:\Zn\n ↑↓ Navigate Menu\n Space to Select \n Enter to Continue\n\n\ZbPackages to Install:\Zn" 20 80 2 \
--output-fd 1 \
1 "PyTorch v1.1.0 for Python 2.7" off \
2 "PyTorch v1.1.0 for Python 3.6" off \
)
package_selection_status=$?
clear
echo "$LOG Package selection status: $package_selection_status"
if [ $package_selection_status = 0 ]; then
if [ -z "$packages_selected" ]; then
echo "$LOG No packages were selected for download."
else
echo "$LOG Packages selected for download: $packages_selected"
for pkg in $packages_selected
do
if [ $pkg = 1 ]; then
install_pytorch_v110_python27
elif [ $pkg = 2 ]; then
install_pytorch_v110_python36
fi
done
fi
exit_message 0
else
echo "$LOG Package selection cancelled."
exit_message 0
fi
exit_message 0
done