Install Professor¶
The semi-easy way ...¶
ssh geant4gpvm01.fnal.gov
source /geant4/app/altups/setup
export PRODUCTS=${PRODUCTS}:/geant4/app/externals:/grid/fermiapp/products/common/db:/grid/fermiapp/products/larsoft
# setup the dependent products
setup geant4 v4_10_3 -q debug:e10
setup art v2_06_03 -q debug:e10:nu
cd /geant4/app/altups/professor
../altscripts/make_professor_ups_skeleton 2.2.2beta2 debug:e10
setup professor 2.2.2beta2 -q debug:e10
../altscripts/make_professor_install
The messy details¶
make_professor_ups_skeleton¶
#! /usr/bin/env bash
b0=`basename $0`
echo -e "${OUTCYAN}${SETUP_GEANT4}${OUTNOCOL}"
echo -e "${OUTCYAN}${SETUP_ART}${OUTNOCOL}"
echo -e "${OUTCYAN}start from UPS scratch${OUTNOCOL}"
export HERE=`pwd`
export PRODUCT="professor"
export VERSION_EXAMPLE="2.2.2beta2"
export QUALIFIER_EXAMPLE="debug:e10"
export FLAVOR=""
export VERBOSE=0
export ALLOWQUALMISMATCH=0
export DEPEND1PRD="geant4"
export DEPEND1VER_DEFAULT="<not-specified>"
export DEPEND1QUAL_DEFAULT="<not-specified>"
export DEPEND2PRD="art"
export DEPEND2VER_DEFAULT="<not-specified>"
export DEPEND2QUAL_DEFAULT="<not-specified>"
export showusage=0
export showpurpose=0
export showconfig=0
export doexit=-1
purpose() {
echo " " >&2
echo "Purpose: Create a skeleton UPS area for a version of $PRODUCT" >&2
echo " * Assumes $b0 is run from UPS area <path>/$PRODUCT" >&2
echo " where <path> is in \$PRODUCTS" >&2
echo " * Assumes that ${DEPENDPRD1} and ${DEPENDPRD2} have been setup " >&2
}
usage() {
echo " " >&2
echo "Usage: $b0 [options] <ups-version> <ups-qualifier> [svn-tag]" >&2
echo " -h | --help this message and quit" >&2
echo " -t | --test don't perform actual actions" >&2
echo " -v | --verbose increase verbosity" >&2
echo " --show-config show the configuration" >&2
echo " --qual-mismatch allow GENIE/ROOT qualifier to be different" >&2
echo " --checkout[=<val>] do SVN checkout [$CHECKOUT]" >&2
echo " [true]/false - do/don't attempt SVN checkout" >&2
echo " ssh - checkout w/ write privs" >&2
}
current_config() {
echo " " >&2
echo "Current Settings: PRODUCT=$PRODUCT" >&2
echo "<version>='${VERSION}'" >&2
echo "<qualifier>='${QUALIFIER}'" >&2
echo "<flavor>='${FLAVOR}'" >&2
echo "ISTEST=${ISTEST} VERBOSE=${VERBOSE}" >&2
echo "PRODUCTS=${PRODUCTS}" >&2
echo "will setup $DEPENDPRD1 $DEPENDVER1 -q $DEPENDQUAL1" >&2
echo "will setup $DEPENDPRD2 $DEPENDVER2 -q $DEPENDQUAL2" >&2
if [ "$GCCSETUP" != "native" ]; then
echo "will setup gcc $GCCSETUP"
fi
which gcc >&2
gcc --version | head -1 >&2
}
ESC="\e"
if [ "Darwin" == `uname` ]; then ESC="\x1B"; fi
OUTRED="${ESC}[0;31m"
OUTGREEN="${ESC}[0;32m"
OUTCYAN="${ESC}[0;36m"
OUTNOC="${ESC}[0m"
err_red() {
echo -n $'\e[0;31m' >&2 # works on Mac OS X as well
# echo -n -e "${OUTRED}" >&2
}
err_green() {
echo -n $'\e[0;32m' >&2
}
err_cyan() {
echo -n $'\e[0;36m' >&2
}
err_nocolor() {
echo -n $'\e[0m' >&2
# echo -n -e "${OUTNOC}" >&2
}
sortqual()
{
# alphabetize the qual components, remove trailing ":"
echo $1 | tr ":" "\n" | sort | tr "\n" ":" | sed -e "s/:$//"
}
check_cwd() {
# ensure that the product matches the current directory
PRDDIR=`basename $HERE`
if [ "$PRDDIR" != "$PRODUCT" ]; then
echo " " >&2
err_red
echo "$b0: HEY? working in '$PRDDIR' but skeleton for product '$PRODUCT'?" >&2
err_nocolor
showusage=1
doexit=2
fi
}
find_ups_top() {
# assume we're somewhere in the UPS area we want to add to
THISUPSTOP=`pwd`
while [ ! -d .upsfiles ]; do
cd ..
export THISUPSTOP=`pwd`
done
}
check_upsloc() {
LOCALDB=`dirname $HERE`
isthere=`echo $PRODUCTS | grep -c $LOCALDB`
if [ $isthere -lt 1 ]; then
echo " " >&2
err_red
echo "$b0: HEY? working in " >&2
echo " $HERE " >&2
echo "but base path not listed in \$PRODUCTS" >&2
echo " \$PRODUCTS=${PRODUCTS}" >&2
echo " "
err_green
echo "you probably want to do:"
err_cyan
echo "source ${THISUPSTOP}/setup"
echo "export PRODUCTS=\${PRODUCTS}:/geant4/app/externals:/grid/fermiapp/products/common/db:/grid/fermiapp/products/larsoft"
err_red
echo " "
echo "since it is unlikely to end happily ... I'll stop here"
err_nocolor
showpurpose=1
showusage=1
doexit=3
fi
}
check_depend() {
DEPEND1_SETUPVAR=`echo SETUP_${DEPEND1PRD} | tr [a-z] [A-Z]`
DEPEND1_SETUP="${!DEPEND1_SETUPVAR}"
if [ -z "${DEPEND1_SETUP}" ]; then
echo setup ${DEPEND1PRD} ${DEPEND1VER_DEFAULT} -q ${DEPEND1QUAL_DEFAULT}
echo setup ${DEPEND1PRD} ${DEPEND1VER_DEFAULT} -q ${DEPEND1QUAL_DEFAULT}
fi
DEPEND1VER=`echo ${DEPEND1_SETUP} | tr -s ' ' | cut -d' ' -f2`
DEPEND1QUAL=`echo ${DEPEND1_SETUP} | tr -s ' ' | cut -d' ' -f8`
DEPEND2_SETUPVAR=`echo SETUP_${DEPEND2PRD} | tr [a-z] [A-Z]`
DEPEND2_SETUP="${!DEPEND2_SETUPVAR}"
if [ -z "${DEPEND2_SETUP}" ]; then
echo setup ${DEPEND2PRD} ${DEPEND2VER_DEFAULT} -q ${DEPEND2QUAL_DEFAULT}
echo setup ${DEPEND2PRD} ${DEPEND2VER_DEFAULT} -q ${DEPEND2QUAL_DEFAULT}
fi
DEPEND2VER=`echo ${DEPEND2_SETUP} | tr -s ' ' | cut -d' ' -f2`
DEPEND2QUAL=`echo ${DEPEND2_SETUP} | tr -s ' ' | cut -d' ' -f8`
if [ "${DEPEND2PRD}" == "art" ]; then
cnu=`echo ${DEPEND2QUAL} | grep -c nu`
if [ $cnu -gt 0 ]; then
DEPEND2QUAL=`echo ${DEPEND2QUAL} | sed -e 's/:nu//' -e 's/nu://' `
fi
fi
GCCSETUP=`echo ${SETUP_GCC} | tr -s ' ' | cut -d' ' -f2`
GCCTABLELINE="setupRequired( gcc ${GCCSETUP} )"
good_depend=1
if [ $ALLOWQUALMISMATCH -eq 0 ]; then
prdqual=`sortqual $QUALIFIER`
depqual1=`sortqual $DEPEND1QUAL`
depqual2=`sortqual $DEPEND2QUAL`
if [ "$prdqual" != "$depqual1" -o "$prdqual" != "$depqual2" ]; then
echo " " >&2
err_red
echo "$b0: HEY? mismatch qualifiers" >&2
echo " $PRODUCT $QUALIFIER ($prdqual)" >&2
echo " $DEPENDPRD1 $DEPENDQUAL1 ($depqual1)" >&2
echo " $DEPENDPRD2 $DEPENDQUAL2 ($depqual2)" >&2
err_nocolor
good_depend=0
fi
fi
if [ ${good_depend} -eq 0 ]; then
echo " " >&2
err_red
echo "$b0: HEY? dependency should require '${DEPENDPRD}'" >&2
echo " but that has not been properly setup at this point" >&2
err_nocolor
showpurpose=1
showusage=1
doexit=4
fi
if [ "${DEPEND2PRD}" == "art" ]; then
cnu=`echo ${DEPEND2QUAL} | grep -c nu`
if [ $cnu -eq 0 ]; then
DEPEND2QUAL="${DEPEND2QUAL}:nu"
fi
fi
}
process_args() {
opterr=/tmp/getopt.err.$$
TEMP=`getopt -n $b0 -s bash -a \
--longoptions="help test verbose qual-mismatch-ok \
flavor: show-config product: " \
-o htvf -- "$@" 2> $opterr `
getoptstat=$?
eval set --"${TEMP}"
dohelp=0
if [ $getoptstat -ne 0 ]; then
showusage=1
doexit=1
err_red
echo " " >&2
cat $opterr >&2
err_nocolor
fi
rm $opterr
while [ $
case "$1" in
"--" ) shift; break ;;
-h | --help ) dohelp=1 ;;
-t | --test ) ISTEST=1 ;;
-v | --verbose ) let VERBOSE=${VERBOSE}+1 ;;
-f | --flavor ) FLAVOR="$2"; shift ;;
--show-config ) showconfig=1 ;;
--qual-mismatch-ok ) ALLOWQUALMISMATCH=1 ;;
--product ) PRODUCT=$2; shift ;;
esac
shift
done
if [ $dohelp -ne 0 ]; then
doexit=0
showpurpose=1
showusage=1
else
VERSION=$1
QUALIFIER=`sortqual $2`
if [ $
err_red
echo " " >&2
if [ $
echo "$b0: missing <version> and <qualifier> parameters" >&2
echo " consider ${VERSION_EXAMPLE} ${QUALIFIER_EXAMPLE}"
else
echo "$b0: missing <qualifier> parameter" >&2
echo " consider ${QUALIFIER_EXAMPLE}"
fi
echo " " >&2
err_nocolor
doexit=1
showusage=1
showconfig=1
fi
fi
}
find_ups_top
if [ -n "$THISUPSTOP" ]; then
if [ -d ${THISUPSTOP}/${PRODUCT} ]; then
cd $THISUPSTOP/${PRODUCT}
export HERE=`pwd`
fi
fi
process_args "$@"
if [ $VERBOSE -gt 0 ]; then
echo -e "${OUTGREEN}...done process_args ... start checks ${OUTNOC}"
fi
check_cwd
check_upsloc
check_depend
PYVERSION=`python --version 2>&1 | cut -d' ' -f2 | cut -d. -f1,2`
PRODUCTUC=`echo $PRODUCT | tr [a-z] [A-Z]`
echo -e "${OUTCYAN}PYVERSION=${PYVERSION} PRODUCTUC=${PRODUCTUC}${OUTNOCOL}"
if [ -z "$FLAVOR" ]; then
FLAVOR=`ups flavor `
fi
if [ $VERBOSE -gt 0 ]; then
echo -e "${OUTGREEN}...cross-checks complete${OUTNOC}"
fi
if [ $showpurpose -gt 0 ]; then purpose ; fi
if [ $showusage -gt 0 ]; then usage ; fi
if [ $showconfig -gt 0 ]; then current_config ; fi
echo " " >&2
if [ $doexit -ge 0 ]; then
exit $doexit
fi
if [ $VERBOSE -gt 0 ]; then
echo -e "${OUTGREEN}...start processing${OUTNOC}"
fi
FLAVORVF=${FLAVOR}
if [ "$FLAVOR" == "NULL" ]; then FLAVORVF="NULL_"; fi
if [ -z "$FLAVOR" ]; then
echo "FLAVOR was null -- can not proceed"
exit
fi
echo QUALIFIER=${QUALIFIER}
QPATH=`echo $QUALIFIER | tr ":" "\n" | sort | tr "\n" "-" | sed -e 's/-$//' | tr -d "\n" `
echo QPATH=${QPATH}
echo "prepare to generate ups framework for"
echo " setup ${PRODUCT} ${VERSION} -f ${FLAVOR} -q ${QUALIFIER}"
for p in ${VERSION}/${FLAVOR}-${QPATH}/ups \
${VERSION}/${FLAVOR}-${QPATH}/build \
${VERSION}/source \
${VERSION}.version
do
if [ ! -d $p ]; then mkdir -p $p; fi
done
tableFile=${VERSION}/${FLAVOR}-${QPATH}/ups/${PRODUCT}.table
versionFile=${VERSION}.version/${FLAVORVF}-${QPATH}
cat > ${tableFile} <<EOF
File=Table
Product=${PRODUCT}
Group:
Flavor=${FLAVOR}
Qualifiers="${QUALIFIER}"
Common:
Action=setup
proddir()
setupenv()
setupRequired( ${DEPEND1PRD} ${DEPEND1VER} -q ${DEPEND1QUAL} )
setupRequired( ${DEPEND2PRD} ${DEPEND2VER} -q ${DEPEND2QUAL} )
${GCCTABLELINE}
envSet(${PRODUCTUC}_DIR, \${UPS_PROD_DIR})
envSet(${PRODUCTUC}_FQ, ${FLAVOR}-${QPATH})
envSet(${PRODUCTUC}_FQ_DIR, \${UPS_PROD_DIR}/\${${PRODUCTUC}_FQ})
envSet(${PRODUCTUC}_VERSION, ${VERSION})
envSet(${PRODUCTUC}_SOURCE, \${UPS_PROD_DIR}/source)
pathAppend(LD_LIBRARY_PATH, \${UPS_PROD_DIR}/\${${PRODUCTUC}_FQ}/lib)
pathAppend(PATH, \${UPS_PROD_DIR}/\${${PRODUCTUC}_FQ}/bin)
pathAppend(PYTHONPATH, \${UPS_PROD_DIR}/\${${PRODUCTUC}_FQ}/lib/python${PYVERSION}/site-packages)
End:
EOF
if [ ! -f ${versionFile} ]; then
cat > ${versionFile} <<EOF
FILE = version
PRODUCT = ${PRODUCT}
VERSION = ${VERSION}
EOF
fi
iam=`whoami`
if [ "$iam" == "nusoft" ]; then
altiam=`klist | grep "Default principal" | cut -d':' -f2 | cut -d'@' -f1 | tr -d ' ' `
if [ -n "$altiam" ]; then
iam=${altiam}
echo "i am \"${iam}\""
fi
fi
nowGMT=`date -u "+%Y-%m-%d %H:%M:%S"`
nf=`grep QUALIFIERS ${versionFile} | grep -c \"${QUALIFIER}\"`
if [ $nf -ne 0 ]; then
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "${versionFile} already has an entry for \"${QUALIFIER}\""
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
else
cat >> ${versionFile} <<EOF
FLAVOR = ${FLAVOR}
QUALIFIERS = "${QUALIFIER}"
DECLARER = ${iam}
DECLARED = ${nowGMT} GMT
MODIFIER = ${iam}
MODIFIED = ${nowGMT} GMT
PROD_DIR = ${PRODUCT}/${VERSION}
UPS_DIR = ${FLAVOR}-${QPATH}/ups
TABLE_FILE = ${PRODUCT}.table
EOF
fi
if [ "$CHECKOUT" == "true" -o "$CHECKOUT" == "ssh" ]; then
source `${UPS_DIR}/bin/ups setup dk2nu $VERSION -f $FLAVOR -q $QUALIFIER`
cd $DK2NU_DIR
echo "starting checkout, currently in:"
echo " `pwd`"
echo svn checkout $FULLSVNPATH > svn.checkout.log 2>&1
svn checkout $FULLSVNPATH > svn.checkout.log 2>&1
fi
make_professor_install¶
#! /usr/bin/env bash
YODA_VER=1.6.6
EIGEN_VER=3.3.3
PROF_VER=2.2.2beta2
PROF_QUAL="debug:e10"
SKIP_WXPYTHON=1
export PROFINSTALL=${PROFESSOR_FQ_DIR}
export PYTHON_VERSION=`python --version 2>&1 | cut -d' ' -f2 | cut -d. -f1,2`
export PYTHON_SITEPKG=${PROFINSTALL}/lib/python${PYTHON_VERSION}/site-packages
if [[ -z "${PROFESSOR_FQ_DIR}" || ! -d ${PROFESSOR_FQ_DIR} ]]; then
echo -e "${OUTRED}no \${PROFESSOR_FQ_DIR} defined"
echo -e "or directory ${PROFESSOR_FQ_DIR} doesn't exist ${OUTNOCOL}"
exit 1
fi
if [ -z "${PROFESSOR_SOURCE}" ]; then
export PROFESSOR_SOURCE=${PROFESSOR_DIR}/source
fi
if [ ! -d "${PROFESSOR_SOURCE}" ]; then
mkdir -p ${PROFESSOR_SOURCE}
fi
rm -rf /tmp/pip-*
echo -e "${OUTGREEN}checking cython...${OUTNOCOL}"
cd ${PROFESSOR_SOURCE}
if [[ ! -d ${PYTHON_SITEPKG}/Cython || ! -f ${PROFESSOR_FQ_DIR}/bin/cython ]]; then
echo -e "${OUTGREEN}...building cython...${OUTNOCOL}"
pip install --install-option="--prefix=${PROFINSTALL}" cython \
> cython.pip.log 2>&1
if [ $? -ne 0 ]; then
echo -e "${OUTRED}cython installed failed${OUTNOCOL}"
exit 2
fi
fi
CVERSION=`cython --version 2>&1`
cython --version > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo -e "${OUTRED}cython --version failed${OUTNOCOL}"
exit 2
fi
echo -e "${OUTGREEN}cython version (${CVERSION}) complete ${OUTNOCOL}"
echo -e "${OUTGREEN}checking yoda...${OUTNOCOL}"
cd ${PROFESSOR_SOURCE}
if [ ! -f YODA-${YODA_VER}.tar.gz ]; then
echo -e "${OUTGREEN}...download yoda...${OUTNOCOL}"
curl -O https://www.hepforge.org/archive/yoda/YODA-${YODA_VER}.tar.gz
tar xzf YODA-${YODA_VER}.tar.gz
fi
if [ ! -f ${PROFINSTALL}/lib/libYODA.so ]; then
echo -e "${OUTGREEN}...configure yoda...${OUTNOCOL}"
cd YODA-${YODA_VER}
./configure --prefix=${PROFINSTALL} > yoda.config.log 2>&1
if [ $? -ne 0 ]; then
echo -e "${OUTRED}yoda config failed${OUTNOCOL}"
exit 2
fi
echo -e "${OUTGREEN}...build yoda...${OUTNOCOL}"
make -j2 > yoda.build.log 2>&1
if [ $? -ne 0 ]; then
echo -e "${OUTRED}yoda build failed${OUTNOCOL}"
exit 2
fi
echo -e "${OUTGREEN}...install yoda...${OUTNOCOL}"
make -j2 install > yoda.install.log 2>&1
if [ $? -ne 0 ]; then
echo -e "${OUTRED}yoda installed failed${OUTNOCOL}"
exit 2
fi
fi
echo -e "${OUTGREEN}yoda complete${OUTNOCOL}"
echo -e "${OUTGREEN}checking eigen...${OUTNOCOL}"
cd ${PROFESSOR_SOURCE}
if [ ! -f eigen_${EIGEN_VER}.tar.gz ]; then
echo -e "${OUTGREEN}..download eigen...${OUTNOCOL}"
curl -O https://bitbucket.org/eigen/eigen/get/${EIGEN_VER}.tar.gz
EIGENHEAD=`tar -tzf 3.3.3.tar.gz | cut -d/ -f1 | sort -u`
mv ${EIGEN_VER}.tar.gz eigen_${EIGEN_VER}.tar.gz
tar xzf eigen_${EIGEN_VER}.tar.gz
mv ${EIGENHEAD} eigen_${EIGEN_VER}
fi
if [ ! -d ${PROFINSTALL}/include/Eigen ]; then
echo -e "${OUTGREEN}...install eigen...${OUTNOCOL}"
cp -a eigen_${EIGEN_VER}/Eigen ${PROFINSTALL}/include > eigen.cp.log 2>&1
if [ $? -ne 0 ]; then
echo -e "${OUTRED}eigen installed failed${OUTNOCOL}"
exit 2
fi
fi
echo -e "${OUTGREEN}eigen complete${OUTNOCOL}"
echo -e "${OUTGREEN}checking iminuit...${OUTNOCOL}"
cd ${PROFESSOR_SOURCE}
if [ ! -d ${PYTHON_SITEPKG}/iminuit ]; then
echo -e "${OUTGREEN}...build iminuit...${OUTNOCOL}"
pip install --install-option="--prefix=${PROFINSTALL}" iminuit \
> iminuit.pip.log 2>&1
if [ $? -ne 0 ]; then
echo -e "${OUTRED}iminuit installed failed${OUTNOCOL}"
exit 2
fi
fi
echo -e "${OUTGREEN}iminuit complete${OUTNOCOL}"
echo -e "${OUTGREEN}checking matplotlib...${OUTNOCOL}"
cd ${PROFESSOR_SOURCE}
if [ ! -d ${PYTHON_SITEPKG}/matplotlib ]; then
echo -e "${OUTGREEN}...building matplotlib...${OUTNOCOL}"
pip install --install-option="--prefix=${PROFINSTALL}" matplotlib \
> matplotlib.pip.log 2>&1
if [ $? -ne 0 ]; then
echo -e "${OUTRED}matplotlib installed failed${OUTNOCOL}"
exit 2
fi
fi
echo -e "${OUTGREEN}matplotlib complete${OUTNOCOL}"
echo -e "${OUTGREEN}checking sympy...${OUTNOCOL}"
cd ${PROFESSOR_SOURCE}
if [ ! -d ${PYTHON_SITEPKG}/sympy ]; then
echo -e "${OUTGREEN}...building sympy...${OUTNOCOL}"
pip install --install-option="--prefix=${PROFINSTALL}" sympy \
> sympy.pip.log 2>&1
if [ $? -ne 0 ]; then
echo -e "${OUTRED}sympy installed failed${OUTNOCOL}"
exit 2
fi
fi
echo -e "${OUTGREEN}sympy complete${OUTNOCOL}"
echo -e "${OUTGREEN}checking wxpython / wxWindows...${OUTNOCOL}"
cd ${PROFESSOR_SOURCE}
if [ ${SKIP_WXPYTHON} -eq 1 ]; then
echo -e "${OUTCYAN}skip wxpython ....${OUTNOCOL}"
else
if [ ! -d ${PYTHON_SITEPKG}/wxpython ]; then
echo -e "${OUTGREEN}...building wxpython...${OUTNOCOL}"
pip install --install-option="--prefix=${PROFINSTALL}" wxpython \
> wxpython.pip.log
if [ $? -ne 0 ]; then
echo -e "${OUTRED}wxpython installed failed${OUTNOCOL}"
echo -e "${OUTCYAN}wxpython installed failed ... continue anyway${OUTNOCOL}"
fi
fi
fi
echo -e "${OUTGREEN}wxpython complete${OUTNOCOL}"
echo -e "${OUTGREEN}checking professor...${OUTNOCOL}"
cd ${PROFESSOR_SOURCE}
if [ ! -f Professor-${PROF_VER}.tar.gz ]; then
echo -e "${OUTGREEN}...download professor...${OUTNOCOL}"
curl -O https://www.hepforge.org/archive/professor/Professor-${PROF_VER}.tar.gz
tar xzf Professor-${PROF_VER}.tar.gz
fi
cd Professor-${PROF_VER}
echo -e "${OUTGREEN}...build professor...${OUTNOCOL}"
CXXFLAGS="-I${PROFINSTALL}/include -O4" make all > professor.build.log 2>&1
if [ $? -ne 0 ]; then
echo -e "${OUTRED}professor build failed${OUTNOCOL}"
exit 2
fi
echo -e "${OUTGREEN}...install professor...${OUTNOCOL}"
make install PREFIX=$PROFINSTALL > professor.install.log 2>&1
if [ $? -ne 0 ]; then
echo -e "${OUTRED}professor install failed${OUTNOCOL}"
exit 2
fi