Bash script to automate installing bunch of packages

For installing and updating many servers with uniform roles take a look at nanobsd. Works with filesystem "images" and enables image testing in advance, plus robust upgrades and rollbacks (version updates are close to atomic and require a single server reboot for the new version to be ran; in fact if kernel version remains the same, reboot -r works once, as it appears that kernel does not unlock the old filesystem prohibiting further updates until a real reboot). Not covering all the bases nor working in every case, but is very solid. Couple of years ago I got the impression Netflix uses nanobsd (or something similar) to manage their CDNs. Found it interesting, implemented nanobsd at work and never went back.
 
Don't use bash(1), as you'll have to install it 1st. Perhaps you can base it on this
Bash:
#!/bin/sh
env ASSUME_ALWAYS_YES=yes pkg-static bootstrap
while read pkgname; do
    env ASSUME_ALWAYS_YES=yes pkg install ${pkgname}
done < pkg_list.txt | tee pkg_autoinstaller_$(date +%Y%m%dT%H%M%S).log

Or maybe even
Bash:
env ASSUME_ALWAYS_YES=yes pkg-static bootstrap
env ASSUME_ALWAYS_YES=yes xargs pkg install < pkg_list.txt | tee pkg_autoinstaller_$(date +%Y%m%dT%H%M%S).log
Next small step to improve the automated script:
how to automatically choose the package list accordingly the name of server?

Example:
In work directory (on a usbmemstick or internal disk) exist
pkg_autoinstaller.sh
and a set of pkg list files
pkg_list_server1.local.net.txt
pkg_list_server2.local.net.txt
...


Script look at the server hostname in FreeBSD, than try to automatically finding appropriate pkg list file and installing all listed pkg.
If appropriate pkg list file not finded, script propose to choose pkg list manually OR entering server new hostname, apply changes to FreeBSD and then loading appropriate pkg list file.

Script onscreen menu in this case:
———
[ERROR] Package Autoinstaller not able to find pkg list that linked to this server.
You may choose pkg list manually or correct the server hostname to install appropriate packages.

1. server1.local.net
2. server2.local.net
...
C. Correct hostname (freebsd.local.net) of this server to install appropriate packages.

Enter You choose:
———

So User have to enter “1”, “2”, ... or “server2.local.net” and hit Enter. After that script doing the rest.
 
Bash:
#!/bin/sh
host=$(hostname -f)
pkgdir=~/test1 # where .txt files are
pkgfile=${pkgdir}/pkg_list_${host}.txt
if [ ! -s ${pkgfile} ] ; then
    echo "No packages list file (${pkgfile}) for host '${host}'"

    pkgfile=
    while [ -z "${pkgfile}" ] ; do
    echo "Which list file to use?"
    n=0
    for fn in ${pkgdir}/*.txt; do
        n=$((n+1))
        printf " %2d. %s\n" ${n} ${fn#${pkgdir}/}
    done

    sel=
    while :; do
        printf "Enter file number to use: "
        read sel
        [ "${sel}" -eq "${sel}" 2>/dev/null ] || continue
        [ ${sel} -gt 0 -a ${sel} -le ${n} ] || continue
        break
    done

    n=0
    for fn in ${pkgdir}/*.txt; do
        n=$((n+1))
        if [ ${n} -eq ${sel} ] ; then
        pkgfile=${fn}
        break
        fi
    done
    done
fi
echo "Using ${pkgfile}"
But have you considered using role-based packages lists? Also using interactive install scripts kind-of defeats the purpose :)
 
Bash:
#!/bin/sh
host=$(hostname -f)
pkgdir=~/test1 # where .txt files are
pkgfile=${pkgdir}/pkg_list_${host}.txt
if [ ! -s ${pkgfile} ] ; then
    echo "No packages list file (${pkgfile}) for host '${host}'"

    pkgfile=
    while [ -z "${pkgfile}" ] ; do
    echo "Which list file to use?"
    n=0
    for fn in ${pkgdir}/*.txt; do
        n=$((n+1))
        printf " %2d. %s\n" ${n} ${fn#${pkgdir}/}
    done

    sel=
    while :; do
        printf "Enter file number to use: "
        read sel
        [ "${sel}" -eq "${sel}" 2>/dev/null ] || continue
        [ ${sel} -gt 0 -a ${sel} -le ${n} ] || continue
        break
    done

    n=0
    for fn in ${pkgdir}/*.txt; do
        n=$((n+1))
        if [ ${n} -eq ${sel} ] ; then
        pkgfile=${fn}
        break
        fi
    done
    done
fi
echo "Using ${pkgfile}"
Thank You so much! ;)

What about last “C” option for changing hostname, apply settings and start script from scratch ?

C. Correct hostname (freebsd.local.net) of this server to install appropriate packages.
But have you considered using role-based packages lists? Also using interactive install scripts kind-of defeats the purpose :)
Normally whole script intended for running manually (or with help of Ansible), it just find appropriate pkg list file, run all installs, save log file (and Ansible pull it back together with sys log). Done.
Useful for admins who have no ZFS snapshots, whole drive backups, Ansible, and just have usb memstick with fresh FreeBSD install image and up to 100 FreeBSD boxes (colleges, campus, etc...)

This additional code needed in case
- server have default FreeBSD hostname (operator mistake during bare metal setup from memstick, for example);
- server have the name that not recognized as part of infrastructure;
Script waiting 20sec, after that if no entry, write “[ERROR] Appropriate pkg list not found for $(hostname -f)” to log file, write same to syslog, and exit with code “1”.

Of course, for bulk installing may be some pkg list file that named according default FreeBSD hostname. Like template...

So it would have fully automated behavior.

Could You be so please to correct code (adding “C” option + exit after 20s no entry) when having coffee break?

At the end of the week we all receive a nice script for making package list file and automatic installation. To not installing manually from scratch...
Each one of users here care about 3+ FreeBSD boxes (home, work, friends, etc), so script may be usable...

P.S. After You done, I would adding “S” option to selection and “-s” parameter to “making packages list and exit”.

S. Make list of packages that installed on this server.
 
You do need to have a working repo on the other end. If you build it yourself, there are tools available to take care of LOTS of details for you. One such tool is Poudriere. But from a personal and incomplete experience, I can say that Poudriere is a VERY unwieldy beast.
 
Yeah, OP's gotta be willing to do the work to adjust the available code to fit his own scenario. I do that all the time, I don't expect a runnable line of code, just some helpful ideas of what might work, and then I do the rest myself.
 
Let's not confuse charity with work :)
What you're asking will take a bit more time than a coffee break.
Sorry, I cannot even have a thought about using You!

Just from the point of view that something on which I spend 3-7h, for You may be 20 min. Sorry again. I go to seeking Stackoverflow and Google...
 
Yeah, OP's gotta be willing to do the work to adjust the available code to fit his own scenario. I do that all the time, I don't expect a runnable line of code, just some helpful ideas of what might work, and then I do the rest myself.
Agree with You.

Because I using FreeBSD a long time ago before now, I forgot all details. And now in time of war in Ukraine, I try to solve the problem because no sufficient time to learn.

Sorry again one time. And thank You and all here for help!
 
Back
Top