Sysadmin Mega Thread

2 Likes

this is a specialized instance with one use. /mnt isnā€™t perfect, but it was set up before we had sysadmins at the company. So basically, decision made before me.

Developers arenā€™t sysadmins, usually.

It wasnā€™t a ticket. It was a slack message with not a whole lot of information and like 30 replies. someone @ me in the thread to get my attention in the first place.

I got it sorted in about an hour of getting notified, but a good 25 minutes of that was figuring out why I couldnā€™t ssh into the instance in question. :angry:


I used this as an example of a situation that can be encountered in the real world, not as an example of people not following standards or an excuse for people to rage about it.

In the industry, you have to put up with things that arenā€™t just right and your only recourse is to change it during a change window if you really want to. Weā€™re so focused on other more pressing things that an instance thatā€™s not configured perfectly in a dev environment isnā€™t a big deal, as long as itā€™s not causing problems.

6 Likes

Thanks for the tip. Thatā€™s going to be my life soon.

1 Like

Hey, itā€™s not all bad. You come out looking like a fucking hero every time.

And if you do it publicly enough, you get gifts from devs when you go to meetups. :smiley:

2 Likes

work meetups shouldnt be the place to give away herpes

Oh, I was talking about whiskey, but now I know to stay away from your company.

7 Likes

The only times i have had to reboot pfsense have been for updates or power outages.

I havenā€™t seen it crash.

: ${KB:=$((   1000))} ${KiB:=$((1<<10))}; readonly KB KiB
: ${MB:=$((1000*KB))} ${MiB:=$((1<<20))}; readonly MB MiB
: ${GB:=$((1000*MB))} ${GiB:=$((1<<30))}; readonly GB GiB
: ${TB:=$((1000*GB))} ${TiB:=$((1<<40))}; readonly TB TiB
2 Likes

Take your witchcraft elsewhere sir

2 Likes

Burn Him

What does it look like to use it?

Mind you there are probably fancier things you can do with those in bash, but even in posix shell itā€™s fairly convenient:

example1()
{
        local file=$1
        local ARBITRARY_LIMIT=$(( 10 * GB ))
        local file_size=$(stat -f %z $file)
        if [ $file_size -gt $ARBITRARY_LIMIT ]; then
                echo "That's a big file!"
        else
                echo "I've seen bigger."
        fi
}

example2()
{
        local mem=$(awk '/real memory/ { print $4 }' /var/run/dmesg.boot)
        echo "$(( mem / GiB )) GiB installed memory"
}
1 Like

Cool, I will definitely use that. The syntax is really weird. Iā€™ve never seen that use of the colon, setting up the variables with the bashy := stuff and then declaring them. Does set -u break it?

The reason for that (and I screwed this up in example2 even, if you caught that edit) is that readonly will complain if you try to set the variable again, even if it is the same value.

${VAR:=VALUE} checks if VAR is null or undefined, and sets it to VALUE if so.
Probably ${VAR=VALUE} would be more correct (in case you need a constant for a null value or to allow a null override) because it only sets VAR if it is unset.

     ${parameter:=word}
             Assign Default Values.  If parameter is unset or null, the
             expansion of word is assigned to parameter.  In all cases, the
             final value of parameter is substituted.  Quoting inside word
             does not prevent field splitting or pathname expansion.  Only
             variables, not positional parameters or special parameters, can
             be assigned in this way.
     In the parameter expansions shown previously, use of the colon in the
     format results in a test for a parameter that is unset or null; omission
     of the colon results in a test for a parameter that is only unset.

This pattern allows for constants to be defined in a way that doesnā€™t break if the script gets sourced multiple times, and it allows the default values to be overridden by the environment. Not exactly useful in the case of units, but for other constants like limits or paths or names it is handy.

$ unset TB
$ TB=1
sh: TB: is read only
$ set -u TB
$ TB=1
sh: TB: is read only
$

The : convention is something I picked up from BSD rc scripts.
: is shorthand for true, which does nothing with its arguments. The parameter expansions are done by the shell, and : ignores the resulting substituted value.

From /etc/rc.d/sshd:

: ${sshd_rsa_enable:="yes"}
: ${sshd_dsa_enable:="no"}
: ${sshd_ecdsa_enable:="yes"}
: ${sshd_ed25519_enable:="yes"}

This sets default values for the variables if they have not been explicitly set to something else in rc.conf.

2 Likes

Ah, I didnā€™t know you could throw arguments after it.

I actually donā€™t know if Iā€™d ever use it. It looks pretty esoteric and all it really saves you is a few lines and some readonlys.

It doesnā€™t save you any readonlys, it just happens to make readonly work because it doesnā€™t set if itā€™s already set.

The main use of := is setting a default value. Compare:

: ${port:=1234}
# vs
port=${port:+1234}
# vs
[ -n "$port" ] || port=1234
run_server()
{
        local HOST PORT
        : ${HOST=localhost}
        : ${PORT=8080}
        echo "listening on $HOST:$PORT"
}
run_server
PORT=9999 run_server
listening on localhost:8080
listening on localhost:9999

I use this a lot in my scripts, for example the top of my script that creates a VM for hacking in:

: ${EXTRA_PACKAGES:="\
        emacs-nox    \
        git          \
        neovim       \
        ripgrep      \
        tmux         \
        vim-console  \
        zsh          \
"}
readonly EXTRA_PACKAGES

: ${BHYVE_DATASET:="storage/bhyve"}
: ${BRIDGE:="bridge0"}
: ${CPUS:="8"}
: ${NMDM_PROP:="com.freqlabs:libvirt_nmdm"}
: ${MEMORY:="16G"}
readonly BHYVE_DATASET BRIDGE CORES NMDM_PROP MEMORY

I can override things when I call the script if needed:

CPUS=4 MEMORY=4G create-work-vm

Another example from the system:

/usr/libexec/bsdinstall/zfsboot
45:: ${ZFSBOOT_POOL_NAME:=zroot}
50:: ${ZFSBOOT_POOL_CREATE_OPTIONS:=-O compress=lz4 -O atime=off}
55:: ${ZFSBOOT_BEROOT_NAME:=ROOT}
60:: ${ZFSBOOT_BOOTFS_NAME:=default}
65:: ${ZFSBOOT_VDEV_TYPE:=stripe}
70:: ${ZFSBOOT_FORCE_4K_SECTORS:=1}
81:: ${ZFSBOOT_GELI_KEY_FILE:=/boot/encryption.key}
92:: ${ZFSBOOT_BOOT_POOL_CREATE_OPTIONS:=}
97:: ${ZFSBOOT_BOOT_POOL_NAME:=bootpool}
102:: ${ZFSBOOT_BOOT_POOL_SIZE:=2g}
107:: ${ZFSBOOT_DISKS:=}
112:: ${ZFSBOOT_PARTITION_SCHEME:=}
117:: ${ZFSBOOT_BOOT_TYPE:=}
123:: ${ZFSBOOT_SWAP_SIZE:=2g}
176:: ${ZFSBOOT_CONFIRM_LAYOUT:=1}
1559:   : ${ZFSBOOT_BOOT_TYPE:=UEFI}
1560:   : ${ZFSBOOT_PARTITION_SCHEME:=GPT}
1567:           : ${ZFSBOOT_BOOT_TYPE:=BIOS+UEFI}
1568:           : ${ZFSBOOT_PARTITION_SCHEME:=GPT}
1570:           : ${ZFSBOOT_BOOT_TYPE:=BIOS}
1571:           : ${ZFSBOOT_PARTITION_SCHEME:=GPT}
2 Likes

I donā€™t mind those, but for static things like MB/MiB, setting default value implies it could be something else, which it never would.

Sorry Iā€™m being a little pedantic.This is neat stuff and Iā€™m glad you shared it. Iā€™m always interested to learn weird bashisms.

2 Likes

Right the idea with combining it with readonly is to allow the script to be sourced without things breaking:

lib.sh:

: ${KB:=$((   1000))} ${KiB:=$((1<<10))}; readonly KB KiB
: ${MB:=$((1000*KB))} ${MiB:=$((1<<20))}; readonly MB MiB
: ${GB:=$((1000*MB))} ${GiB:=$((1<<30))}; readonly GB GiB
: ${TB:=$((1000*GB))} ${TiB:=$((1<<40))}; readonly TB TiB
$ . lib.sh
# now maybe I decide to edit the script to add some more things
# I can source it again to update my env
$ . lib.sh

In contrast this would break:

readonly KB=$((   1000)) KiB=$((1<<10))
readonly MB=$((1000*KB)) MiB=$((1<<20))
readonly GB=$((1000*MB)) GiB=$((1<<30))
readonly TB=$((1000*GB)) TiB=$((1<<40))
$ . lib.sh
$ . lib.sh
readonly: KB: is read only

It makes it safe to set these in a .profile or to source in other scripts that might be sourced.

1 Like

Youā€™d be surprised at how many all day issues stem from something minor that was overlooked. Even sysadmins come across this in their own setups no matter how well it is documented. The only thing that comes after is how much self-loathing and alcohol is involved with such a simple fix, yet took soo long to figure out.

1 Like

22 posts were split to a new topic: FreeNAS Troubleshooting