0ba17462c2e7b3f97e2bcac98b278057886281d5 maximilianh Fri Apr 25 16:26:06 2025 +0200 adding GBIC mode for OSX, no ticket yet, waiting for GBIC for arm on linux update ticket diff --git src/product/installer/browserSetup.sh src/product/installer/browserSetup.sh index 65fbe7d363c..22ea3664220 100644 --- src/product/installer/browserSetup.sh +++ src/product/installer/browserSetup.sh @@ -377,31 +377,31 @@ loaded on-the-fly from UCSC. update - update the genome browser software and data, updates all tables of an assembly, like "mirror" cgiUpdate - update only the genome browser software, not the data. Not recommended, see documentation. clean - remove temporary files of the genome browser older than one day, but do not delete any uploaded custom tracks addTools - copy the UCSC User Tools, e.g. blat, featureBits, overlapSelect, bedToBigBed, pslCDnaFilter, twoBitToFa, gff3ToGenePred, bedSort, ... to /usr/local/bin This has to be run after the browser has been installed, other- wise these packages may be missing: libpng zlib libmysqlclient dev - install git/gcc/c++/freetype/etc, clone the kent repo into ~/kent and build the CGIs into /usr/local/apache so you can try them right away. Useful if you want to develop your own track - types. + type. (OSX OK) mysql - Patch my.cnf and recreate Mysql users. This can fix a broken Mysql server after an update to Mysql 8. parameters for 'minimal', 'mirror' and 'update': <assemblyList> - download Mysql + /gbdb files for a space-separated list of genomes examples: bash $0 install - install Genome Browser, do not download any genome assembly, switch to on-the-fly mode (see the -f option) bash $0 minimal hg19 - download only the minimal tables for the hg19 assembly bash $0 mirror hg19 mm9 - download hg19 and mm9, switch to offline mode (see the -o option) bash $0 -t noEncode mirror hg19 - install Genome Browser, download hg19 @@ -532,52 +532,55 @@ # by default and somehow the section doesn't seem to take effect since a specific [mariadb] section also exists in the mariadb-server.cnf. # As a result, we only modify the mariadb-server config file MYCNF=/etc/my.cnf.d/mariadb-server.cnf elif [ -f /etc/mysql/mariadb.conf.d/*-server.cnf ] ; then # Ubuntu with mariadb. Must come before etc/my.cnf MYCNF=/etc/mysql/mariadb.conf.d/*-server.cnf elif [ -f /etc/mysql/mysql.conf.d/mysqld.cnf ] ; then # Ubuntu 16, 18, 20 with mysqld MYCNF=/etc/mysql/mysql.conf.d/mysqld.cnf elif [ -f /etc/my.cnf ] ; then # generic Centos 6-8 MYCNF=/etc/my.cnf elif [ -f /etc/mysql/my.cnf ] ; then # generic Ubuntu 14 MYCNF=/etc/mysql/my.cnf + elif [ -f /opt/homebrew/etc/my.cnf ]; then + # homebrew on ARMs + MYCNF=/opt/homebrew/etc/my.cnf else echo Could not find my.cnf. Adapt 'setMYCNF()' in browserSetup.sh and/or contact us. exit 1 fi echo Found Mariadb config file: $MYCNF } function mysqlStrictModeOff () { # make sure that missing values in mysql insert statements do not trigger errors, #18368 = deactivate strict mode # This must happen before Mariadb is started or alternative Mariadb must be restarted after this has been done setMYCNF echo Deactivating MySQL strict mode sed -Ei '/^.(mysqld|server).$/a sql_mode=' $MYCNF } function mysqlAllowOldPasswords # mysql >= 8 does not allow the old passwords anymore. But our client is still compiled # with the old, non-SHA256 encryption. So we must deactivate this new feature. -# What will MariaDB do? +# We do not support MySQL anymore, so this function could be removed { -echo2 'Checking for Mysql version >= 8' +echo2 'Checking for Mysql version >= 8 (not officially supported by our software)' MYSQLMAJ=`mysql -e 'SHOW VARIABLES LIKE "version";' -NB | cut -f2 | cut -d. -f1` setMYCNF if [ "$MYSQLMAJ" -ge 8 ] ; then echo2 'Mysql >= 8 found, checking if default-authentication allows native passwords' if grep -q default-authentication $MYCNF; then echo2 "default-authentication already set in $MYCNF" else echo2 Changing $MYCNF to allow native passwords and restarting Mysql echo '[mysqld]' >> $MYCNF echo 'default-authentication-plugin=mysql_native_password' >> $MYCNF stopMysql startMysql fi fi @@ -622,30 +625,31 @@ { echo2 if [[ "$DIST" == "OSX" ]]; then echo2 You can browse the genome at http://127.0.0.1:8080 #/usr/bin/open http://127.0.0.1:8080 else echo2 You can now access this server under one of these IP addresses: echo2 From same host: http://127.0.0.1 echo2 From same network: http://`ip route get 8.8.8.8 | awk 'NR==1 {print $NF}'` echo2 From the internet: http://`downloadFileQuiet http://icanhazip.com` fi echo2 } # On OSX, we have to compile everything locally +# DEPRECATED. This can be used to build a native OSX app. But not supported right now. function setupCgiOsx () { if [[ "$BUILDKENT" == "0" ]]; then echo2 echo2 Downloading Precompiled OSX CGI-BIN binaries echo2 cd $APACHEDIR downloadFile $CGIBINURL | tar xz chown -R $APACHEUSER:$APACHEUSER cgi-bin/ return fi echo2 echo2 Now downloading the UCSC source tree into $APACHEDIR/kent echo2 The compiled binaries will be installed into $APACHEDIR/cgi-bin @@ -878,48 +882,47 @@ if [ `numCompare $VERNUM 9` == "<" ] ; then installPy2MysqlRedhat else echo2 Not installing Python2, this Linux does not have it and it should not be needed anymore fi fi # open port 80 in firewall if which firewall-cmd ; then echo2 Opening port HTTP/80 in firewall using the command firewall-cmd sudo firewall-cmd --zone=public --permanent --add-service=http sudo firewall-cmd --reload fi } -# OSX specific setup of the installation -function installOsx () +function installOsxDevTools () +# make sure that the xcode command line tools are installed { # check for xcode if [ -f /usr/bin/xcode-select 2> /dev/null > /dev/null ]; then echo2 Found XCode else echo2 - echo2 'This installer has to compile the UCSC tools locally on OSX.' - echo2 'Please install XCode from https://developer.apple.com/xcode/downloads/' - echo2 'Start XCode once and accept the Apple license.' - echo2 'Then run this script again.' - exit 100 + echo2 'This installer has to compile the UCSC tools locally on OSX. We need clang. Starting installation.' + xcode-select --install 2> /dev/null >/dev/null fi +} - # make sure that the xcode command line tools are installed - echo2 Checking/Installing Xcode Command line tools - xcode-select --install 2> /dev/null >/dev/null || true +# OSX specific setup of the installation +function installOsx () +{ + installOsxDevTools # in case that it is running, try to stop Apple's personal web server, we need access to port 80 # ignore any error messages #if [ -f /usr/sbin/apachectl ]; then #echo2 Stopping the Apple Personal Web Server #/usr/sbin/apachectl stop 2> /dev/null || true #launchctl unload -w /System/Library/LaunchDaemons/org.apache.httpd.plist 2> /dev/null || true #fi if [ -f ~/.my.cnf ]; then echo2 echo2 ~/.my.cnf already exists. This will interfere with the installation. echo2 The file will be renamed to ~/.my.cnf.old now. mv ~/.my.cnf ~/.my.cnf.old waitKey @@ -1410,51 +1413,111 @@ # the custom track database needs it own user and permissions $MYSQL -e "CREATE USER ctdbuser@localhost IDENTIFIED BY 'ctdbpassword';" $MYSQL -e "GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,ALTER,INDEX "\ "on customTrash.* TO ctdbuser@localhost;" # removed these now for the new hgGateway page, Apr 2016 # by default hgGateway needs an empty hg19 database, will crash otherwise # $MYSQL -e 'CREATE DATABASE IF NOT EXISTS hg19' # mm9 needs an empty hg18 database $MYSQL -e 'CREATE DATABASE IF NOT EXISTS hg18' $MYSQL -e "FLUSH PRIVILEGES;" } -# set this machine for browser development: install required tools, clone the tree, build it -function buildTree () + +# install clang, brew and configure Apple's Apache, so we can build the tree on OSX +function setupBuildOsx () +{ + # install clang + installOsxDevTools + + which -s brew > /dev/null + if [[ $? != 0 ]] ; then + echo2 Homebrew not found. Installing now. + ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" + else + brew update + fi + echo2 Installing homebrew packages libpng, openssl, mariadb, git + brew install libpng openssl mariadb git + + #if ! libpng-config --version > /dev/null 2>&1; then + #if ! mariadb --version > /dev/null 2>&1; then + #if ! git --version > /dev/null 2>&1; then + #if ! openssl --version > /dev/null 2>&1; then + + echo2 Allowing write for all on Apple's Apache htdocs/cgi-bin directories + echo2 This requires sudo, so please enter the admin password now + sudo chmod a+rw /Library/WebServer/CGI-Executables + sudo chmod a+rw /Library/WebServer/Documents + + # create symlinks to Apple's paths so all our normal makefiles work + if [ ! -e /usr/local/apache ]; then + echo2 Creating /usr/local/apache to fill with symlinks later + sudo mkdir -p /usr/local/apache + sudo chmod a+rw /usr/local/apache + fi + + if [ ! -e /usr/local/apache/cgi-bin ]; then + echo2 Creating symlink /usr/local/apache/cgi-bin to /Library/WebServer/CGI-Executables + sudo ln -s /Library/WebServer/CGI-Executables /usr/local/apache/cgi-bin + fi + if [ ! -e /usr/local/apache/htdocs ]; then + echo2 Creating symlink /usr/local/apache/htdocs to /Library/WebServer/Documents + sudo ln -s /Library/WebServer/Documents/ /usr/local/apache/htdocs + fi + + # switch on CGIs in Apple's Apache and restart it + sudo sed -i '' -E 's/^\s*#(LoadModule cgid_module)/\1/; s/^\s*#(LoadModule cgi_module)/\1/' /etc/apache2/httpd.conf + sudo /usr/sbin/apachectl restart +} + +# install gcc, make etc so we can build the tree on linux +function setupBuildLinux () { echo2 Installing required linux packages from repositories: Git, GCC, G++, Mysql-client-libs, uuid, etc waitKey if [[ "$DIST" == "debian" ]]; then apt-get install make git gcc g++ libpng-dev libmysqlclient-dev uuid-dev libfreetype-dev elif [[ "$DIST" == "redhat" ]]; then yum install -y git vim gcc gcc-c++ make libpng-devel libuuid-devel freetype-devel else echo Error: Cannot identify linux distribution exit 100 fi +} + +# set this machine for browser development: install required tools, clone the tree, build it +function buildTree () +{ + if [[ "$DIST" == "OSX" ]]; then + setupBuildOsx + else + setupBuildLinux + fi + if [ ! -e ~/kent ]; then echo2 Cloning kent repo into ~/kent using git with --depth=1 waitKey cd ~ git clone https://github.com/ucscGenomeBrowser/kent.git --depth=1 + fi echo2 Now building CGIs from ~/kent to /usr/local/apache/cgi-bin - echo2 Copying JS/HTML/CSS to /usr/local/apache/htdocs + echo2 Installing JS/HTML/CSS to /usr/local/apache/htdocs waitKey cd ~/kent/src make -j8 cgi-alpha } # main function, installs the browser on Redhat/Debian and potentially even on OSX function installBrowser () { if [ -f $COMPLETEFLAG ]; then echo2 error: the file $COMPLETEFLAG exists. It seems that you have installed the browser already. echo2 If you want to reset the Apache directory, you can run '"rm -rf /usr/local/apache"' and echo2 then run this script again. exit 100 fi @@ -1466,31 +1529,33 @@ echo This script will go through three steps: echo "1 - setup apache and mysql, open port 80, deactivate SELinux" echo "2 - copy CGI binaries into $CGIBINDIR, html files into $HTDOCDIR" echo "3 - optional: download genome assembly databases into mysql and /gbdb" echo echo This script will now install and configure Mysql and Apache if they are not yet installed. echo "Your distribution's package manager will be used for this." echo If Mysql is not installed yet, it will be installed, secured and a root password defined. echo echo This script will also deactivate SELinux if active and open port 80/http. waitKey # ----- OS - SPECIFIC part ----- if [ ! -f $COMPLETEFLAG ]; then if [[ "$DIST" == "OSX" ]]; then - installOsx + #installOsx + # on OSX, install clang, brew, kent and build the CGIs from scratch + buildTree elif [[ "$DIST" == "debian" ]]; then installDebian elif [[ "$DIST" == "redhat" ]]; then installRedhat fi fi # OS-specific mysql/apache installers can SET_MYSQL_ROOT to 1 to request that the root # mysql user password be changed # ---- END OS-SPECIFIC part ----- mysqlAllowOldPasswords if [[ "${SET_MYSQL_ROOT}" == "1" ]]; then mysqlChangeRootPwd @@ -1533,93 +1598,102 @@ mkdir -p $APACHEDIR/userdata/cramCache/{error,pending} chmod -R 777 $APACHEDIR/userdata/cramCache # ------------------- # CGI installation # ------------------- echo2 echo2 Creating $CGIBINDIR and $HTDOCDIR and downloading contents from UCSC waitKey # create apache directories: HTML files, CGIs, temporary and custom track files mkdir -p $HTDOCDIR $CGIBINDIR $TRASHDIR $TRASHDIR/customTrash # the CGIs create links to images in /trash which need to be accessible from htdocs cd $HTDOCDIR + if [ ! -e $TRASHDIR ]; then ln -fs $TRASHDIR + fi # write the sample hg.conf ti the cgi-bin directory echo2 Creating Genome Browser config file $CGIBINDIR/hg.conf echo "$HG_CONF_STR" > $CGIBINDIR/hg.conf # hg.conf tweaks # redhat distros have the same default socket location set in mysql as # in our binaries. To allow mysql to connect, we have to remove the socket path. # Also change the psxy path to the correct path for redhat, /usr/bin/ if [ "$DIST" == "redhat" ]; then echo2 Adapting mysql socket locations in $APACHEDIR/cgi-bin/hg.conf sed -i "/socket=/s/^/#/" $CGIBINDIR/hg.conf sed -i "/^hgc\./s/.usr.lib.gmt.bin/\/usr\/bin/" $CGIBINDIR/hg.conf elif [ "$DIST" == "OSX" ]; then # in OSX adapt the sockets # note that the sed -i syntax is different from linux echo2 Adapting mysql socket locations in $CGIBINDIR/hg.conf - sockFile=$APACHEDIR/ext/mysql.socket + #sockFile=$APACHEDIR/ext/mysql.socket + sockFile=`mysql -NBe 'show variables like "socket"' | cut -f2` $SEDINPLACE "s|^#?socket=.*|socket=$sockFile|" $CGIBINDIR/hg.conf $SEDINPLACE "s|^#?customTracks.socket.*|customTracks.socket=$sockFile|" $CGIBINDIR/hg.conf $SEDINPLACE "s|^#?db.socket.*|db.socket=$sockFile|" $CGIBINDIR/hg.conf $SEDINPLACE "s|^#?central.socket.*|central.socket=$sockFile|" $CGIBINDIR/hg.conf fi # check if UCSC or genome-euro MySQL server is closer echo comparing latency: genome.ucsc.edu Vs. genome-euro.ucsc.edu eurospeed=$( (time -p (for i in `seq 10`; do curl -sSI genome-euro.ucsc.edu > /dev/null; done )) 2>&1 | grep real | cut -d' ' -f2 ) ucscspeed=$( (time -p (for i in `seq 10`; do curl -sSI genome.ucsc.edu > /dev/null; done )) 2>&1 | grep real | cut -d' ' -f2 ) if [[ $(awk '{if ($1 <= $2) print 1;}' <<< "$eurospeed $ucscspeed") -eq 1 ]]; then echo genome-euro seems to be closer echo modifying hg.conf to pull data from genome-euro instead of genome sed -i s/slow-db.host=genome-mysql.soe.ucsc.edu/slow-db.host=genome-euro-mysql.soe.ucsc.edu/ $CGIBINDIR/hg.conf sed -i "s#gbdbLoc2=http://hgdownload.soe.ucsc.edu/gbdb/#gbdbLoc2=http://hgdownload-euro.soe.ucsc.edu/gbdb/#" $CGIBINDIR/hg.conf HGDOWNLOAD=hgdownload-euro.soe.ucsc.edu else echo genome.ucsc.edu seems to be closer echo not modifying $CGIBINDIR/hg.conf fi - # download the CGIs if [[ "$OS" == "OSX" ]]; then - setupCgiOsx + #setupCgiOsx + echo2 Running on OSX, assuming that CGIs are already built into /usr/local/apache/cgi-bin else # don't download RNAplot, it's a 32bit binary that won't work anywhere anymore but at UCSC # this means that hgGene cannot show RNA structures but that's not a big issue $RSYNC -avzP --exclude=RNAplot $HGDOWNLOAD::cgi-bin/ $CGIBINDIR/ # now add the binaries for dot and RNAplot $RSYNC -avzP $HGDOWNLOAD::genome/admin/exe/external.x86_64/RNAplot $CGIBINDIR/ $RSYNC -avzP $HGDOWNLOAD::genome/admin/exe/external.x86_64/loader/dot_static $CGIBINDIR/loader/ fi # download the html docs, exclude some big files on OSX - rm -rf $APACHEDIR/htdocs/goldenpath # try to minimize storage for OSX, mostly laptops if [ "$OS" == "OSX" ]; then - $RSYNC --delete -azP --exclude=training --exclude=ENCODE --exclude=encode --exclude=rosenbloom.pdf --exclude=pubs*.pdf --exclude=*.{bb,bam,bai,bw,gz,2bit} --exclude=goldenpath $HGDOWNLOAD::htdocs/ $HTDOCDIR/ + #$RSYNC --delete -azP --exclude=training --exclude=ENCODE --exclude=encode --exclude=rosenbloom.pdf --exclude=pubs*.pdf --exclude=*.{bb,bam,bai,bw,gz,2bit} --exclude=goldenpath $HGDOWNLOAD::htdocs/ $HTDOCDIR/ + echo2 Not syncing htdocs folder, assuming that these were built from source. + echo2 PDF and other large files only present at UCSC will be missing from htdocs. + waitKey else + rm -rf $APACHEDIR/htdocs/goldenpath $RSYNC -avzP --exclude ENCODE/**.pdf $HGDOWNLOAD::htdocs/ $HTDOCDIR/ fi # assign all files just downloaded to a valid user. # This also allows apache to write into the trash dir + if [ "$OS" == "OSX" ]; then + echo2 OSX: Not chowning /usr/local/apache subdirectories + else chown -R $APACHEUSER:$APACHEUSER $CGIBINDIR $HTDOCDIR $TRASHDIR touch $COMPLETEFLAG echo2 Install complete. You should now be able to point your web browser to this machine echo2 and test your UCSC Genome Browser mirror. It will be too slow for practical use. echo2 echo2 Notice that this mirror is still configured to use Mysql and data files loaded echo2 through the internet from UCSC. From most locations on the world, this is very slow. echo2 It also requires an open outgoing TCP port 3306 for Mysql to genome-mysql.soe.ucsc.edu/genome-euro-mysql.soe.ucsc.edu, echo2 and open TCP port 80 to hgdownload.soe.ucsc.edu/hgdownload-euro.soe.ucsc.edu. echo2 echo2 To finish the installation, you need to download genome data to the local echo2 disk. To download a genome assembly and all its files now, call this script again with echo2 the parameters 'download "<assemblyName1> <assemblyName2> ..."', e.g. '"'bash $0 mirror mm10 hg19'"' @@ -1883,31 +1957,38 @@ echo2 echo2 The mirror should be functional now. It contains some basic assembly tables echo2 and will download missing data from the UCSC servers. This requires echo2 two open ports, outgoing, TCP, from this machine: echo2 - to genome-mysql.soe.ucsc.edu, port 3306, to load MySQL tables echo2 - to hgdownload.soe.ucsc.edu, port 80, to download non-MySQL data files echo2 - or the above two servers European counterparts: echo2 genome-euro-mysql.soe.ucsc.edu and hgdownload-euro.soe.ucsc.edu echo2 showMyAddress goOnline } function checkDownloadUdr () +# download the faster downloader udr that is compatible with rsync and change the global variable RSYNC { + if [[ "$OS" == "OSX" ]]; then + return + fi + + RSYNC="/usr/local/bin/udr rsync" + # Download my own statically compiled udr binary if [[ ! -f /usr/local/bin/udr ]]; then echo2 'Downloading download-tool udr (UDP-based rsync with multiple streams) to /usr/local/bin/udr' waitKey downloadFile $UDRURL > /usr/local/bin/udr chmod a+x /usr/local/bin/udr fi } function cleanTrash () { echo2 Removing files older than one day in $TRASHDIR, not running on $TRASHDIR/ct # -L = follow symlinks # -atime +1 = files older than one day find -L $TRASHDIR -not -path $TRASHDIR/ct/\* -and -type f -atime +1 -exec rm -f {} \; @@ -2022,31 +2103,30 @@ ONLYGENOMES=0 elif [[ "$val" == "noEncode" ]]; then RSYNCOPTS="-m --include=wgEncodeGencode* --include=*/ --exclude=wgEncode*" ONLYGENOMES=0 elif [[ "$val" == "main" ]]; then # gbCdnaInfo # SNP table selection explained in #17335 RSYNCOPTS="-m --include=grp.* --include=*gold* --include=augustusGene.* --include=chromInfo.* --include=cpgIslandExt.* --include=cpgIslandExtUnmasked.* --include=cytoBandIdeo.* --include=genscan.* --include=microsat.* --include=simpleRepeat.* --include=tableDescriptions.* --include=ucscToINSDC.* --include=windowmaskerSdust.* --include=gold.* --include=chromInfo.* --include=trackDb* --include=hgFindSpec.* --include=gap.* --include=*.2bit --include=html/description.html --include=refGene* --include=refLink.* --include=wgEncodeGencode* --include=snp146Common* --include=snp130* --include=snp142Common* --include=snp128* --include=gencode* --include=rmsk* --include=*/ --exclude=*" ONLYGENOMES=1 # do not download hgFixed,go,proteome etc else echo "Unrecognized -t value. Please read the help message, by running bash $0 -h" exit 100 fi ;; u) - RSYNC="/usr/local/bin/udr rsync" checkDownloadUdr ;; o) if [ ! -f $APACHEDIR/cgi-bin/hg.conf ]; then echo Please install a browser first, then switch the data loading mode. fi goOffline echo $APACHEDIR/cgi-bin/hg.conf was modified. echo Offline mode: data is loaded only from the local Mysql database and file system. echo Use the parameter -f to switch to on-the-fly mode. exit 0 ;; f) if [ ! -f $APACHEDIR/cgi-bin/hg.conf ]; then @@ -2130,41 +2210,49 @@ if [ "$DIST" == "none" ]; then echo Sorry, unable to detect your linux distribution. echo Currently only Debian and Redhat-style distributions are supported. exit 100 fi lastArg=${*: -1:1} if [[ "$#" -gt "1" && ( "${2:0:1}" == "-" ) || ( "${lastArg:0:1}" == "-" ) ]]; then echo "Error: The options have to be specified before the command, not after it." echo echo "$HELP_STR" exit 100 fi -if uname -m | grep -vq _64; then - echo "Your machine does not seem to be a 64bit system" - echo "Sorry, the Genome Browser requires a 64bit linux." +UNAMEM=`uname -m` +if [[ ! "$UNAMEM" == *_64 && ! "$OS" == "OSX" ]]; then + echo "Sorry, the Genome Browser requires a 64bit linux or OSX." exit 100 fi -if [[ "$EUID" != "0" ]]; then - echo "This script must be run as root or with sudo like this:" +if [[ "$EUID" == "0" ]]; then + if [[ "$OS" == "OSX" ]]; then + echo "On OSX, this script must not be run with sudo, so we can install brew." echo "sudo -H $0" exit 100 fi +else + if [[ "$OS" != "OSX" ]]; then + echo "On Linux, this script must be run as root or with sudo like below, so we can run apt/yum:" + echo "sudo -H $0" + exit 100 + fi +fi if [ "${1:-}" == "install" ]; then installBrowser elif [ "${1:-}" == "minimal" ]; then downloadMinimal ${@:2} # all arguments after the second one elif [ "${1:-}" == "mirror" ]; then downloadGenomes ${@:2} # all arguments after the second one elif [ "${1:-}" == "cgiUpdate" ]; then cgiUpdate elif [ "${1:-}" == "update" ]; then updateBrowser ${@:2} # all arguments after the second one