Skip to content

Shellcheck linter in Stork

Andrei Pavel requested to merge 876-shellcheck-linter-in-stork into master

Closes #876 (closed).

  • 51407073 add rake lint:shell task

  • 91736a87 add lint:shell to Gitlab CI

  • f54864c4 make shell changes suggested by shellcheck





Click here to get the full list of initial warnings.
In docker/init/init_db.sh line 10:
    source ${__dir}/init_${DB_TYPE}_db.sh
           ^----------------------------^ SC1090 (warning): ShellCheck can't follow non-constant source. Use a directive to specify location.
           ^------^ SC2086 (info): Double quote to prevent globbing and word splitting.
                         ^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: source "${_dir}"/init"${DB_TYPE}"_db.sh

In docker/init/init_mysql_db.sh line 1: echo "Database type: ${DB_TYPE}" ^-- SC2148 (error): Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

In docker/init/init_mysql_db.sh line 13: --user=${DB_ROOT_USER}
^-------------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: --user="${DB_ROOT_USER}" \

In docker/init/init_mysql_db.sh line 14: --password=${DB_ROOT_PASSWORD}
^-----------------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: --password="${DB_ROOT_PASSWORD}" \

In docker/init/init_mysql_db.sh line 15: --host=${DB_HOST}
^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: --host="${DB_HOST}" \

In docker/init/init_mysql_db.sh line 21: --user=${DB_ROOT_USER}
^-------------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: --user="${DB_ROOT_USER}" \

In docker/init/init_mysql_db.sh line 22: --password=${DB_ROOT_PASSWORD}
^-----------------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: --password="${DB_ROOT_PASSWORD}" \

In docker/init/init_mysql_db.sh line 23: --host=${DB_HOST}
^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: --host="${DB_HOST}" \

In docker/init/init_mysql_db.sh line 24: -e "$exist_query"
^----------^ SC2154 (warning): exist_query is referenced but not assigned.

In docker/init/init_mysql_db.sh line 25: ${DB_NAME} ^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: "${DB_NAME}"

In docker/init/init_mysql_db.sh line 35: --user=${DB_ROOT_USER}
^-------------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: --user="${DB_ROOT_USER}" \

In docker/init/init_mysql_db.sh line 36: --password=${DB_ROOT_PASSWORD}
^-----------------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: --password="${DB_ROOT_PASSWORD}" \

In docker/init/init_mysql_db.sh line 37: --host=${DB_HOST}
^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: --host="${DB_HOST}" \

In docker/init/init_mysql_db.sh line 43: --user=${DB_ROOT_USER}
^-------------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: --user="${DB_ROOT_USER}" \

In docker/init/init_mysql_db.sh line 44: --password=${DB_ROOT_PASSWORD}
^-----------------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: --password="${DB_ROOT_PASSWORD}" \

In docker/init/init_mysql_db.sh line 45: --host=${DB_HOST}
^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: --host="${DB_HOST}" \

In docker/init/init_mysql_db.sh line 54: kea-admin db-init ${DB_TYPE}
^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: kea-admin db-init "${DB_TYPE}" \

In docker/init/init_mysql_db.sh line 55: -u ${DB_USER}
^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: -u "${DB_USER}" \

In docker/init/init_mysql_db.sh line 56: -p ${DB_PASSWORD}
^------------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: -p "${DB_PASSWORD}" \

In docker/init/init_mysql_db.sh line 57: -n ${DB_NAME}
^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: -n "${DB_NAME}" \

In docker/init/init_mysql_db.sh line 58: -h ${DB_HOST} ^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: -h "${DB_HOST}"

In docker/init/init_mysql_db.sh line 64: --user=${DB_ROOT_USER}
^-------------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: --user="${DB_ROOT_USER}" \

In docker/init/init_mysql_db.sh line 65: --password=${DB_ROOT_PASSWORD}
^-----------------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: --password="${DB_ROOT_PASSWORD}" \

In docker/init/init_mysql_db.sh line 66: --host=${DB_HOST}
^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: --host="${DB_HOST}" \

In docker/init/init_mysql_db.sh line 67: ${DB_NAME} < $seed_file ^--------^ SC2086 (info): Double quote to prevent globbing and word splitting. ^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: "${DB_NAME}" < "$seed_file"

In docker/init/init_pgsql_db.sh line 1: echo "Database type: ${DB_TYPE}" ^-- SC2148 (error): Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

In docker/init/init_pgsql_db.sh line 3: until PGPASSWORD=${DB_ROOT_PASSWORD} psql -h ${DB_HOST} -U ${DB_ROOT_USER} -c "SELECT 1" > /dev/null 2>&1; ^--------^ SC2086 (info): Double quote to prevent globbing and word splitting. ^-------------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: until PGPASSWORD=${DB_ROOT_PASSWORD} psql -h "${DB_HOST}" -U "${DB_ROOT_USER}" -c "SELECT 1" > /dev/null 2>&1;

In docker/init/init_pgsql_db.sh line 14: -U ${DB_ROOT_USER}
^-------------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: -U "${DB_ROOT_USER}" \

In docker/init/init_pgsql_db.sh line 15: -h ${DB_HOST}
^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: -h "${DB_HOST}" \

In docker/init/init_pgsql_db.sh line 22: -U ${DB_ROOT_USER}
^-------------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: -U "${DB_ROOT_USER}" \

In docker/init/init_pgsql_db.sh line 23: -h ${DB_HOST}
^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: -h "${DB_HOST}" \

In docker/init/init_pgsql_db.sh line 24: -d ${DB_NAME}
^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: -d "${DB_NAME}" \

In docker/init/init_pgsql_db.sh line 25: -c "$exist_query" ^----------^ SC2154 (warning): exist_query is referenced but not assigned.

In docker/init/init_pgsql_db.sh line 36: -U ${DB_ROOT_USER}
^-------------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: -U "${DB_ROOT_USER}" \

In docker/init/init_pgsql_db.sh line 37: -h ${DB_HOST}
^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: -h "${DB_HOST}" \

In docker/init/init_pgsql_db.sh line 44: -U ${DB_ROOT_USER}
^-------------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: -U "${DB_ROOT_USER}" \

In docker/init/init_pgsql_db.sh line 45: -h ${DB_HOST}
^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: -h "${DB_HOST}" \

In docker/init/init_pgsql_db.sh line 54: kea-admin db-init ${DB_TYPE}
^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: kea-admin db-init "${DB_TYPE}" \

In docker/init/init_pgsql_db.sh line 55: -u ${DB_USER}
^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: -u "${DB_USER}" \

In docker/init/init_pgsql_db.sh line 56: -p ${DB_PASSWORD}
^------------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: -p "${DB_PASSWORD}" \

In docker/init/init_pgsql_db.sh line 57: -n ${DB_NAME}
^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: -n "${DB_NAME}" \

In docker/init/init_pgsql_db.sh line 58: -h ${DB_HOST} ^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: -h "${DB_HOST}"

In docker/init/init_pgsql_db.sh line 65: -U ${DB_ROOT_USER}
^-------------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: -U "${DB_ROOT_USER}" \

In docker/init/init_pgsql_db.sh line 66: -h ${DB_HOST}
^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: -h "${DB_HOST}" \

In docker/init/init_pgsql_db.sh line 67: -d ${DB_NAME} < $seed_file ^--------^ SC2086 (info): Double quote to prevent globbing and word splitting. ^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: -d "${DB_NAME}" < "$seed_file"

In etc/hooks/apk/isc-stork-agent.postinst line 8: mkdir -p -m 700 $home_dir/certs ^-- SC2174 (warning): When used with -p, -m only applies to the deepest directory.

In etc/hooks/apk/isc-stork-agent.postinst line 9: mkdir -p -m 700 $home_dir/tokens ^-- SC2174 (warning): When used with -p, -m only applies to the deepest directory.

In etc/hooks/apk/isc-stork-agent.postinst line 15: if [ $(getent group bind) ]; then ^------------------^ SC2046 (warning): Quote this to prevent word splitting.

In etc/hooks/apk/isc-stork-agent.postinst line 20: if [ $(getent group _kea) ]; then ^------------------^ SC2046 (warning): Quote this to prevent word splitting.

In etc/hooks/apk/isc-stork-server.postinst line 6: adduser -h $home_dir -D -S -H -g "Stork Server User" -G stork-server stork-server >/dev/null ^-------^ SC2154 (warning): home_dir is referenced but not assigned. ^-------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: adduser -h "$home_dir" -D -S -H -g "Stork Server User" -G stork-server stork-server >/dev/null

In etc/hooks/deb/isc-stork-agent.postinst line 8: mkdir -p -m 700 $home_dir/certs ^-- SC2174 (warning): When used with -p, -m only applies to the deepest directory.

In etc/hooks/deb/isc-stork-agent.postinst line 9: mkdir -p -m 700 $home_dir/tokens ^-- SC2174 (warning): When used with -p, -m only applies to the deepest directory.

In etc/hooks/deb/isc-stork-agent.postinst line 17: if [ $(getent group bind) ]; then ^------------------^ SC2046 (warning): Quote this to prevent word splitting.

In etc/hooks/deb/isc-stork-agent.postinst line 22: if [ $(getent group _kea) ]; then ^------------------^ SC2046 (warning): Quote this to prevent word splitting.

In etc/hooks/deb/isc-stork-agent.prerm line 6: if [ $status = "running" ] || [ $status = "degraded" ] || [ $status = "maintenance" ]; then ^-----^ SC2086 (info): Double quote to prevent globbing and word splitting. ^-----^ SC2086 (info): Double quote to prevent globbing and word splitting. ^-----^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: if [ "$status" = "running" ] || [ "$status" = "degraded" ] || [ "$status" = "maintenance" ]; then

In etc/hooks/deb/isc-stork-server.prerm line 6: if [ $status = "running" ] || [ $status = "degraded" ] || [ $status = "maintenance" ]; then ^-----^ SC2086 (info): Double quote to prevent globbing and word splitting. ^-----^ SC2086 (info): Double quote to prevent globbing and word splitting. ^-----^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: if [ "$status" = "running" ] || [ "$status" = "degraded" ] || [ "$status" = "maintenance" ]; then

In etc/hooks/freebsd/isc-stork-agent.postinst line 8: mkdir -p -m 700 $home_dir/certs ^-- SC2174 (warning): When used with -p, -m only applies to the deepest directory.

In etc/hooks/freebsd/isc-stork-agent.postinst line 9: mkdir -p -m 700 $home_dir/tokens ^-- SC2174 (warning): When used with -p, -m only applies to the deepest directory.

In etc/hooks/rpm/isc-stork-agent.postinst line 8: mkdir -p -m 700 $home_dir/certs ^-- SC2174 (warning): When used with -p, -m only applies to the deepest directory.

In etc/hooks/rpm/isc-stork-agent.postinst line 9: mkdir -p -m 700 $home_dir/tokens ^-- SC2174 (warning): When used with -p, -m only applies to the deepest directory.

In etc/hooks/rpm/isc-stork-agent.postinst line 12: if [ ! $(getent passwd stork-agent) ]; then ^--------------------------^ SC2046 (warning): Quote this to prevent word splitting.

In etc/hooks/rpm/isc-stork-agent.postinst line 17: if [ $(getent group named) ]; then ^-------------------^ SC2046 (warning): Quote this to prevent word splitting.

In etc/hooks/rpm/isc-stork-agent.postinst line 22: if [ $(getent group _kea) ]; then ^------------------^ SC2046 (warning): Quote this to prevent word splitting.

In etc/hooks/rpm/isc-stork-agent.prerm line 8: if [ $status = "running" ] || [ $status = "degraded" ] || [ $status = "maintenance" ]; then ^-----^ SC2086 (info): Double quote to prevent globbing and word splitting. ^-----^ SC2086 (info): Double quote to prevent globbing and word splitting. ^-----^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: if [ "$status" = "running" ] || [ "$status" = "degraded" ] || [ "$status" = "maintenance" ]; then

In etc/hooks/rpm/isc-stork-server.postinst line 6: if [ ! $(getent passwd stork-server) ]; then ^---------------------------^ SC2046 (warning): Quote this to prevent word splitting.

In etc/hooks/rpm/isc-stork-server.prerm line 6: if [ $status = "running" ] || [ $status = "degraded" ] || [ $status = "maintenance" ]; then ^-----^ SC2086 (info): Double quote to prevent globbing and word splitting. ^-----^ SC2086 (info): Double quote to prevent globbing and word splitting. ^-----^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: if [ "$status" = "running" ] || [ "$status" = "degraded" ] || [ "$status" = "maintenance" ]; then

In stork-demo.sh line 8: if ! [ -x $(command -v docker-compose) ] ^--------------------------^ SC2046 (warning): Quote this to prevent word splitting.

In stork-demo.sh line 100: read ACCESS_TOKEN ^--^ SC2162 (info): read without -r will mangle backslashes.

In stork-demo.sh line 106: if ! [ -z "${ACCESS_TOKEN}" ] ^-- SC2237 (style): Use [ -n .. ] instead of ! [ -z .. ].

In tests/pkgs-install/test-pkgs-install.sh line 24: if [ $pkg_type = 'deb' ]; then ^-------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: if [ "$pkg_type" = 'deb' ]; then

In tests/pkgs-install/test-pkgs-install.sh line 40: pkgs=ls $PKGS_DIR/isc-stork*$pkg_type ^-- SC2006 (style): Use $(...) notation instead of legacy backticks .... ^-------^ SC2086 (info): Double quote to prevent globbing and word splitting. ^-------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: pkgs=$(ls "$PKGS_DIR"/isc-stork*"$pkg_type")

In tests/pkgs-install/test-pkgs-install.sh line 42: lxc file push $file $cntr/root/$(basename $file) ^---^ SC2086 (info): Double quote to prevent globbing and word splitting. ^---------------^ SC2046 (warning): Quote this to prevent word splitting. ^---^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: lxc file push "$file" $cntr/root/$(basename "$file")

In tests/pkgs-install/test-pkgs-install.sh line 49: lxc exec $cntr -- $install /root/$(basename $file) ^------^ SC2086 (info): Double quote to prevent globbing and word splitting. ^---------------^ SC2046 (warning): Quote this to prevent word splitting. ^---^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: lxc exec $cntr -- "$install" /root/$(basename "$file")

In tests/pkgs-install/test-pkgs-install.sh line 50: pkg_name=echo $file | sed -n 's/.*\(isc-stork-[a-z]*\).*/\1/p' ^-- SC2006 (style): Use $(...) notation instead of legacy backticks .... ^---^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: pkg_name=$(echo "$file" | sed -n 's/.(isc-stork-[a-z]).*/\1/p')

In tests/pkgs-install/test-pkgs-install.sh line 51: if [ $pkg_name = "isc-stork-agent" ]; then ^-------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: if [ "$pkg_name" = "isc-stork-agent" ]; then

In tests/pkgs-install/test-pkgs-install.sh line 52: lxc exec $cntr -- systemctl enable $pkg_name ^-------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: lxc exec $cntr -- systemctl enable "$pkg_name"

In tests/pkgs-install/test-pkgs-install.sh line 53: lxc exec $cntr -- systemctl start $pkg_name ^-------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: lxc exec $cntr -- systemctl start "$pkg_name"

In tests/pkgs-install/test-pkgs-install.sh line 54: lxc exec $cntr -- systemctl status $pkg_name ^-------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: lxc exec $cntr -- systemctl status "$pkg_name"

In tests/pkgs-install/test-pkgs-install.sh line 58: lines_cnt=lxc exec $cntr -- $get_pkg_files $pkg_name | wc -l ^-- SC2006 (style): Use $(...) notation instead of legacy backticks .... ^------------^ SC2086 (info): Double quote to prevent globbing and word splitting. ^-------^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: lines_cnt=$(lxc exec $cntr -- "$get_pkg_files" "$pkg_name" | wc -l)

In tests/pkgs-install/test-pkgs-install.sh line 60: if [ $lines_cnt != ${PKG_FILES["$pkg_name-$pkg_type"]} ]; then ^--------^ SC2086 (info): Double quote to prevent globbing and word splitting. ^-- SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: if [ "$lines_cnt" != "${PKG_FILES["$pkg_name-$pkg_type"]}" ]; then

In utils/git-hooks/prepare-commit-msg line 4: BRANCH=git branch | grep '^\*' | cut -b3- ^-- SC2006 (style): Use $(...) notation instead of legacy backticks ....

Did you mean: BRANCH=$(git branch | grep '^*' | cut -b3-)

In utils/git-hooks/prepare-commit-msg line 8: ISSUE=git branch | grep -o '^\* [0-9]*' | cut -b3- ^-- SC2006 (style): Use $(...) notation instead of legacy backticks ....

Did you mean: ISSUE=$(git branch | grep -o '^* [0-9]*' | cut -b3-)

In utils/git-hooks/prepare-commit-msg line 12: ISSUEINMSG=head -n 1 $1 | grep -o '^\[#[0-9]*' | cut -b3- ^-- SC2006 (style): Use $(...) notation instead of legacy backticks .... ^-- SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: ISSUEINMSG=$(head -n 1 "$1" | grep -o '^[#[0-9]*' | cut -b3-)

In utils/git-hooks/prepare-commit-msg line 32: /bin/echo -n "[#$ISSUE] " > "$1.msg" ^-- SC3037 (warning): In POSIX sh, echo flags are undefined.

In utils/git-hooks/prepare-commit-msg line 34: /bin/echo -n "[$BRANCH] " > "$1.msg" ^-- SC3037 (warning): In POSIX sh, echo flags are undefined.

In utils/git-hooks-install line 17: exit -1 ^-- SC2242 (error): Can only exit with status 0-255. Other data should be written to stdout/stderr.

For more information: https://www.shellcheck.net/wiki/SC2148 -- Tips depend on target shell and y... https://www.shellcheck.net/wiki/SC2242 -- Can only exit with status 0-255. ... https://www.shellcheck.net/wiki/SC1090 -- ShellCheck can't follow non-const...





I did a small set of changes that either did not address a shellcheck warning or unintentionally addressed one. They are subject to discussion. Here they are:

  • I added a shebang to every script, even sourced ones. While not strictly necessary for production use, shellcheck uses the shebang to determine what shell is supposed to run the commands inside the script. To make the distinction between scripts that are run and scripts that are sourced, the latter can have its execution permission removed.
  • Wherever possible, I moved from bash to sh which is preferable for portability. There are a few places that use features from bash that don't have an easy alternative in POSIX sh: arrays, BASH_SOURCE, and pipefail. Not easy doesn't mean impossible, so if we want full sh conversion, let me know, and it'll be done.
  • Added set -eu in all shell scripts. -e was already added to some, but missing in others. -u, in my opinion, is a perfectly valid and useful check flag. It reports on unset variables. It can be easily circumvented. If you want a variable that returns empty string when not set, it can be achieved with the dash in the expression ${var-}, or you can even have default values e.g. ${var-default}. It is perfectly POSIX compliant.
  • ${var} is sometimes required instead of $var, for example, when you want to concatenate a constant and a variable: const${var}more_const. For this reason, I usually like to write all variables like ${var} for consistency. I have not overdone it here, however, to not introduce unnecessary changes and only did this in lines that were already changed to appease shellcheck warnings.
  • Replaced the ${BASH_SOURCE%/*} bashism which is hard to remember and always has to be looked up, with a dirname invocation.
  • To check the exit code of a command inline, it's enough to have if command; then ...; fi instead of if [ $(command) ]; then ...; fi. The second expression was used for getent invocations. In my experiments, the if-statement written like that always evaluates to false which would mean that it's not correct. Here's it running on a true command which should always return 0: if [ $(true) ]; then echo a; fi.
  • Smilarly, to check if a command is available, if command -v systemctl; then ...; fi is sufficient instead of if [ -x "$(command -v systemctl)" ]; then ...; fi. The first one also checks that the command is executable, because it would have not been considered a command if it weren't. I've also added a > /dev/null to keep the previous behavior of not displaying the output.
Edited by Andrei Pavel

Merge request reports