Programmering og de kreative løsninger

I et forsøg på at gøre opdateringer af jails automatiske, løb jeg ind i et mindre problem med sproget SH.

Kodeuddrag fra teksteditor

Billedet viser oprettelsen af en liste i SH.

SH bruges typisk til systemadministration, og er det eneste sprog som min jail-server understøtter. Så for ikke at skulle installere mere software på serveren, ville jeg foretrække en løsning med SH. Selv en kreativ en.

OK, så jeg har 2 lister: Én over kørende jails og én over hvilket jails der skal opdateres. Et punkt fra den ene liste bliver holdt op imod alle punkterne fra den anden, og er der et match, bliver det pågældende jail opdateret. Simpelt.

Min umiddelbare tanke var at lave en løs sammenlig imellem listerne

if [[ $(jls name) =~ ${auto[@]} ]];

Men det virker selvfølgelig ikke, for en if er ikke lavet til at tjekke mere end én ting. Og det gælder ikke kun i SH, men alle sprog. Der er brug for at bringe listen ind i et loop, køre over hvert element på den ene liste, for så at sammenligne med hvert element på den anden liste.

Men loops understøtter ikke to lister.

Løsningen? To loops.

# Populate $j_au first from the running jails
for j_au in $(jls name); do
# Then populate $up_au from the acl in the header
for up_au in ${auto[@]}; do
# If they match, the jail is updated
if [[ "$j_au" = "$up_au" ]]; then
up_jls "$j_au"
fi
done

Det ydre loop stiller hvert element (navnet på et jail) til rådighed i en variabel, som det indre loop så kan sammenligne med. Opstår der et match, bliver navnet på jail’et givet til funktionen up_jls, som opdaterer jail’et.

// Nicky

Det fulde script:

#!/usr/bin/env bash
#
# acl for jails to autoupdate
declare -a auto=(
"dns"
"mx"
"prx"
"nt"
"rc"
"nc"
"pa"
"ma"
"for"
"fa"
"dls"
)
#
# Function to update jails
up_jls() {
echo
echo "Updates packagelist for $1"
# If the pkgs list does not need upgrading, don't do anything
pkg_out=$(pkg --jail $1 upgrade --dry-run)
if [[ $pkg_out =~ "Your packages are up to date." ]]; then
echo "Packages for $1 are up to date"
else
# Otherwise upgrade, remove unused deps and clear the pkg cache
pkg --jail $1 upgrade --no-repo-update --yes
pkg --jail $1 autoremove --yes
pkg --jail $1 clean --all --yes
if [[ "$1" == "prx" ]]; then
# Only reload apache, if the jail is running the TTP
service -j $1 apache24 reload
else
# All other jails services is restarted
service -j $1 -R
fi
echo "All done for $1"
fi
sleep 2
}
#
# Evaluate given parameters, if any
if [[ -n $1 ]]; then
while [ $# -ne 0 ]; do
p="$1"
shift
case "$p" in
# Update all jls, no matter the acl
-a|--all)
for j in `jls name`; do
up_jls "$j"
done
echo "All running jails has been updated"
exit 0
;;
-h|--help)
echo "With no parameters, all running jails on the acl in the header is updated"
echo
echo "-a or --all updates all running jails without regard to the acl"
echo
echo "-h or --help shows this text"
echo
echo "All other parameters are taken as jail names, and the jail is"
echo " updated if a running jail is matching that name"
echo
echo "Peace out"
exit 0
;;
# Test if parameter is a jail name and update it
*)
if [[ $(jls name) =~ "$p" ]]; then
up_jls "$p"
else
echo "$p does not match a running jail"
sleep 2
fi
;;
esac
done
# And if no parameter was given, an autoupdate from the acl is done
else
# Populate $j_au first from the running jails
for j_au in $(jls name); do
# Then populate $up_au from the acl in the header
for up_au in ${auto[@]}; do
# If they match, the jail is updated
if [[ "$j_au" = "$up_au" ]]; then
up_jls "$j_au"
fi
done
done
fi
#
exit 0

Skriv et svar