1
0
mirror of https://github.com/EV21/dynb.git synced 2025-12-26 16:39:32 +01:00

🎨 fix shell style

This commit is contained in:
2021-09-13 13:36:12 +02:00
parent d92cdb2652
commit 24aa20be3b

356
dynb.sh
View File

@@ -108,40 +108,44 @@ function logtime() {
# The main domain as an identifier for the dns zone is required for the updateRecord call # The main domain as an identifier for the dns zone is required for the updateRecord call
function getMainDomain() { function getMainDomain() {
request=$( echo "{}" | \ request=$(
jq '(.method="nameserver.list")' | \ echo "{}" |
jq "(.params.user=\"$DYNB_USERNAME\")" | \ jq '(.method="nameserver.list")' |
jq "(.params.user=\"$DYNB_USERNAME\")" |
jq "(.params.pass=\"$DYNB_PASSWORD\")" jq "(.params.pass=\"$DYNB_PASSWORD\")"
) )
_response=$(curl --silent \ _response=$(
curl --silent \
"$_interface_str" \ "$_interface_str" \
--user-agent "$_userAgent" \ --user-agent "$_userAgent" \
--header "Content-Type: application/json" \ --header "Content-Type: application/json" \
--request POST $_INWX_JSON_API_URL \ --request POST $_INWX_JSON_API_URL \
--data "$request" | jq ".resData.domains[] | select(inside(.domain=\"$DYNB_DYN_DOMAIN\"))" --data "$request" | jq ".resData.domains[] | select(inside(.domain=\"$DYNB_DYN_DOMAIN\"))"
) )
_main_domain=$( echo "$_response" | jq --raw-output '.domain' ) _main_domain=$(echo "$_response" | jq --raw-output '.domain')
} }
function fetchDNSRecords() { function fetchDNSRecords() {
request=$( echo "{}" | \ request=$(
jq '(.method="'nameserver.info'")' | \ echo "{}" |
jq "(.params.user=\"$DYNB_USERNAME\")" | \ jq '(.method="'nameserver.info'")' |
jq "(.params.pass=\"$DYNB_PASSWORD\")" | \ jq "(.params.user=\"$DYNB_USERNAME\")" |
jq "(.params.domain=\"$_main_domain\")" | \ jq "(.params.pass=\"$DYNB_PASSWORD\")" |
jq "(.params.domain=\"$_main_domain\")" |
jq "(.params.name=\"$DYNB_DYN_DOMAIN\")" jq "(.params.name=\"$DYNB_DYN_DOMAIN\")"
) )
_response=$( curl --silent \ _response=$(
curl --silent \
"$_interface_str" \ "$_interface_str" \
--user-agent "$_userAgent" \ --user-agent "$_userAgent" \
--header "Content-Type: application/json" \ --header "Content-Type: application/json" \
--request POST $_INWX_JSON_API_URL \ --request POST $_INWX_JSON_API_URL \
--data "$request" --data "$request"
) )
_dns_records=$( echo "$_response" | jq '.resData.record[]' ) _dns_records=$(echo "$_response" | jq '.resData.record[]')
} }
# requires parameter A or AAAA # requires parameter A or AAAA
@@ -161,18 +165,18 @@ function getDNSIP() {
# 2. param: IP check server address # 2. param: IP check server address
# result to stdout # result to stdout
function getRemoteIP() { function getRemoteIP() {
if [[ -n $_DNS_checkServer ]]; then if [[ -n $_DNS_checkServer ]]; then
curl --silent "$_interface_str" --user-agent "$_userAgent" \ curl --silent "$_interface_str" --user-agent "$_userAgent" \
--ipv"${1}" --dns-servers "$_DNS_checkServer" --location "${2}" --ipv"${1}" --dns-servers "$_DNS_checkServer" --location "${2}"
else else
curl --silent "$_interface_str" --user-agent "$_userAgent" \ curl --silent "$_interface_str" --user-agent "$_userAgent" \
--ipv"${1}" --location "${2}" --ipv"${1}" --location "${2}"
fi fi
# shellcheck disable=2181 # shellcheck disable=2181
if [[ $? -gt 0 ]]; then if [[ $? -gt 0 ]]; then
errorMessage "IPCheck (getRemoteIP ${1}) request failed" errorMessage "IPCheck (getRemoteIP ${1}) request failed"
exit 1 exit 1
fi fi
} }
# requires parameter # requires parameter
@@ -187,23 +191,25 @@ function updateRecord() {
IP=$_new_IPv6 IP=$_new_IPv6
fi fi
if [[ $IP != "" ]]; then if [[ $IP != "" ]]; then
request=$( echo "{}" | \ request=$(
jq '(.method="nameserver.updateRecord")' | \ echo "{}" |
jq "(.params.user=\"$DYNB_USERNAME\")" | \ jq '(.method="nameserver.updateRecord")' |
jq "(.params.pass=\"$DYNB_PASSWORD\")" | \ jq "(.params.user=\"$DYNB_USERNAME\")" |
jq "(.params.id=\"$ID\")" | \ jq "(.params.pass=\"$DYNB_PASSWORD\")" |
jq "(.params.content=\"$IP\")" | \ jq "(.params.id=\"$ID\")" |
jq "(.params.ttl=\"$TTL\")" jq "(.params.content=\"$IP\")" |
jq "(.params.ttl=\"$TTL\")"
) )
_response=$(curl --silent \ _response=$(
"$_interface_str" \ curl --silent \
--user-agent "$_userAgent" \ "$_interface_str" \
--header "Content-Type: application/json" \ --user-agent "$_userAgent" \
--request POST $_INWX_JSON_API_URL \ --header "Content-Type: application/json" \
--data "$request" --request POST $_INWX_JSON_API_URL \
) --data "$request"
echo -e "$(echo "$_response" | jq --raw-output '.msg')\n Domain: $DYNB_DYN_DOMAIN\n new IPv${1}: $IP" )
echo -e "$(echo "$_response" | jq --raw-output '.msg')\n Domain: $DYNB_DYN_DOMAIN\n new IPv${1}: $IP"
fi fi
} }
@@ -219,26 +225,26 @@ function dynupdate() {
DYNV6_DYNDNS_UPDATE_URL="https://dynv6.com/api/update?zone=$DYNB_DYN_DOMAIN&token=$DYNB_TOKEN&" DYNV6_DYNDNS_UPDATE_URL="https://dynv6.com/api/update?zone=$DYNB_DYN_DOMAIN&token=$DYNB_TOKEN&"
case $DYNB_SERVICE_PROVIDER in case $DYNB_SERVICE_PROVIDER in
inwx* | INWX* ) inwx* | INWX*)
dyndns_update_url=$INWX_DYNDNS_UPDATE_URL dyndns_update_url=$INWX_DYNDNS_UPDATE_URL
;; ;;
deSEC* | desec* | dedyn* ) deSEC* | desec* | dedyn*)
dyndns_update_url="${DESEC_DYNDNS_UPDATE_URL}" dyndns_update_url="${DESEC_DYNDNS_UPDATE_URL}"
;; ;;
dynv6* ) dynv6*)
dyndns_update_url="${DYNV6_DYNDNS_UPDATE_URL}" dyndns_update_url="${DYNV6_DYNDNS_UPDATE_URL}"
myip_str=ipv4 myip_str=ipv4
myipv6_str=ipv6 myipv6_str=ipv6
;; ;;
DuckDNS* | duckdns* ) DuckDNS* | duckdns*)
dyndns_update_url="${DUCKDNS_DYNDNS_UPDATE_URL}" dyndns_update_url="${DUCKDNS_DYNDNS_UPDATE_URL}"
myip_str=ipv4 myip_str=ipv4
myipv6_str=ipv6 myipv6_str=ipv6
;; ;;
* ) *)
errorMessage "$DYNB_SERVICE_PROVIDER is not supported" errorMessage "$DYNB_SERVICE_PROVIDER is not supported"
exit 1 exit 1
;; ;;
esac esac
# pre encode ip parameters # pre encode ip parameters
@@ -255,29 +261,30 @@ function dynupdate() {
## request ## ## request ##
case $DYNB_SERVICE_PROVIDER in case $DYNB_SERVICE_PROVIDER in
inwx* | INWX* ) inwx* | INWX*)
_response=$(curl --silent "$_interface_str" \
--user-agent "$_userAgent" \
--user "$DYNB_USERNAME":"$DYNB_PASSWORD" \
"${dyndns_update_url}" )
;;
deSEC* | desec* | dedyn* )
_response=$(curl --silent "$_interface_str" \
--user-agent "$_userAgent" \
--header "Authorization: Token $DYNB_TOKEN" \
--get --data-urlencode "hostname=$DYNB_DYN_DOMAIN" \
"${dyndns_update_url}" )
;;
dynv6* | duckDNS* | duckdns* )
_response=$(curl --silent "$_interface_str" \ _response=$(curl --silent "$_interface_str" \
--user-agent "$_userAgent" \ --user-agent "$_userAgent" \
"${dyndns_update_url}" --user "$DYNB_USERNAME":"$DYNB_PASSWORD" \
"${dyndns_update_url}")
;;
deSEC* | desec* | dedyn*)
_response=$(curl --silent "$_interface_str" \
--user-agent "$_userAgent" \
--header "Authorization: Token $DYNB_TOKEN" \
--get --data-urlencode "hostname=$DYNB_DYN_DOMAIN" \
"${dyndns_update_url}")
;;
dynv6* | duckDNS* | duckdns*)
_response=$(
curl --silent "$_interface_str" \
--user-agent "$_userAgent" \
"${dyndns_update_url}"
) )
;; ;;
esac esac
case $_response in case $_response in
good* | OK* | "addresses updated" ) good* | OK* | "addresses updated")
if [[ $_response == "good 127.0.0.1" ]]; then if [[ $_response == "good 127.0.0.1" ]]; then
errorMessage "$_response: Request ignored." errorMessage "$_response: Request ignored."
return 1 return 1
@@ -286,52 +293,52 @@ function dynupdate() {
_errorCounter=0 _errorCounter=0
return 0 return 0
fi fi
;; ;;
nochg* ) nochg*)
infoMessage "$_response: Nothing has changed, IP addresses are still up to date." infoMessage "$_response: Nothing has changed, IP addresses are still up to date."
return 1 return 1
;; ;;
abuse ) abuse)
errorMessage "$_response: Username is blocked due to abuse." errorMessage "$_response: Username is blocked due to abuse."
return 1 return 1
;; ;;
badauth | 401 ) badauth | 401)
errorMessage "$_response: Invalid username password combination." errorMessage "$_response: Invalid username password combination."
return 1 return 1
;; ;;
badagent ) badagent)
errorMessage "$_response: Client disabled. Something is very wrong!" errorMessage "$_response: Client disabled. Something is very wrong!"
return 1 return 1
;; ;;
!donator ) !donator)
errorMessage "$_response: An update request was sent, including a feature that is not available to that particular user such as offline options." errorMessage "$_response: An update request was sent, including a feature that is not available to that particular user such as offline options."
return 1 return 1
;; ;;
!yours ) !yours)
errorMessage "$_response: The domain does not belong to your user account" errorMessage "$_response: The domain does not belong to your user account"
return 1 return 1
;; ;;
notfqdn ) notfqdn)
errorMessage "$_response: Hostname $DYNB_DYN_DOMAIN is invalid" errorMessage "$_response: Hostname $DYNB_DYN_DOMAIN is invalid"
return 1 return 1
;; ;;
nohost ) nohost)
errorMessage "$_response: Hostname supplied does not exist under specified account, enter new login credentials before performing an additional request." errorMessage "$_response: Hostname supplied does not exist under specified account, enter new login credentials before performing an additional request."
return 1 return 1
;; ;;
numhost ) numhost)
errorMessage "$_response: Too many hostnames have been specified for this update" errorMessage "$_response: Too many hostnames have been specified for this update"
return 1 return 1
;; ;;
dnserr ) dnserr)
errorMessage "$_response: There is an internal error in the dyndns update system. Retry update no sooner than 30 minutes." errorMessage "$_response: There is an internal error in the dyndns update system. Retry update no sooner than 30 minutes."
return 1 return 1
;; ;;
911 | 5* ) 911 | 5*)
errorMessage "$_response: A fatal error on provider side such as a database outage. Retry update no sooner than 30 minutes." errorMessage "$_response: A fatal error on provider side such as a database outage. Retry update no sooner than 30 minutes."
return 1 return 1
;; ;;
* ) *)
if [[ "$_response" == "$_status" ]]; then if [[ "$_response" == "$_status" ]]; then
errorMessage "An unknown response code has been received. $_response" errorMessage "An unknown response code has been received. $_response"
return 1 return 1
@@ -339,34 +346,34 @@ function dynupdate() {
errorMessage "unknown respnse code: $_response" errorMessage "unknown respnse code: $_response"
return 0 return 0
fi fi
;; ;;
esac esac
} }
function setStatus() { function setStatus() {
echo "_status=$1; _eventTime=$2; _errorCounter=$3; _statusHostname=$4; _statusUsername=$5; _statusPassword=$6" > /tmp/dynb.status echo "_status=$1; _eventTime=$2; _errorCounter=$3; _statusHostname=$4; _statusUsername=$5; _statusPassword=$6" >/tmp/dynb.status
} }
# handle errors from past update requests # handle errors from past update requests
function checkStatus() { function checkStatus() {
case $_status in case $_status in
nochg* ) nochg*)
if [[ _errorCounter -gt 1 ]]; then if [[ _errorCounter -gt 1 ]]; then
errorMessage "The update client was spamming unnecessary update requests, something might be wrong with your IP-Check site." errorMessage "The update client was spamming unnecessary update requests, something might be wrong with your IP-Check site."
errorMessage "Fix your config an then delete $_statusFile or restart your docker container" errorMessage "Fix your config an then delete $_statusFile or restart your docker container"
return 1 return 1
fi fi
;; ;;
nohost | !yours ) nohost | !yours)
if [[ "$_statusHostname" == "$DYNB_DYN_DOMAIN" && ( "$_statusUsername" == "$DYNB_USERNAME" || $_statusUsername == "$DYNB_TOKEN" ) ]]; then if [[ "$_statusHostname" == "$DYNB_DYN_DOMAIN" && ("$_statusUsername" == "$DYNB_USERNAME" || $_statusUsername == "$DYNB_TOKEN") ]]; then
errorMessage "Hostname supplied does not exist under specified account, enter new login credentials before performing an additional request." errorMessage "Hostname supplied does not exist under specified account, enter new login credentials before performing an additional request."
return 1 return 1
else else
rm "$_statusFile" rm "$_statusFile"
fi fi
return 0 return 0
;; ;;
badauth | 401 ) badauth | 401)
if [[ "$_statusUsername" == "$DYNB_USERNAME" && "$_statusPassword" == "$DYNB_PASSWORD" ]]; then if [[ "$_statusUsername" == "$DYNB_USERNAME" && "$_statusPassword" == "$DYNB_PASSWORD" ]]; then
errorMessage "Invalid username password combination." errorMessage "Invalid username password combination."
return 1 return 1
@@ -374,27 +381,27 @@ function checkStatus() {
rm "$_statusFile" rm "$_statusFile"
fi fi
return 0 return 0
;; ;;
badagent ) badagent)
errorMessage "Client is deactivated by provider." errorMessage "Client is deactivated by provider."
echo "Fix your config and then manually remove $_statusFile to reset the client blockade." echo "Fix your config and then manually remove $_statusFile to reset the client blockade."
echo "If it still fails file an issue at github or try another client :)" echo "If it still fails file an issue at github or try another client :)"
return 1 return 1
;; ;;
!donator ) !donator)
errorMessage "An update request was sent, including a feature that is not available to that particular user such as offline options." errorMessage "An update request was sent, including a feature that is not available to that particular user such as offline options."
echo "Fix your config and then manually remove $_statusFile to reset the client blockade" echo "Fix your config and then manually remove $_statusFile to reset the client blockade"
echo "If it still fails file an issue at github or try another client :)" echo "If it still fails file an issue at github or try another client :)"
return 1 return 1
;; ;;
abuse ) abuse)
errorMessage "Username is blocked due to abuse." errorMessage "Username is blocked due to abuse."
echo "Fix your config and then manually remove $_statusFile to reset the client blockade" echo "Fix your config and then manually remove $_statusFile to reset the client blockade"
echo "If it still fails file an issue at github or try another client :)" echo "If it still fails file an issue at github or try another client :)"
return 1 return 1
;; ;;
911 | 5* ) 911 | 5*)
delta=$(( $(date +%s) - _eventTime )) delta=$(($(date +%s) - _eventTime))
if [[ $delta -lt 1800 ]]; then if [[ $delta -lt 1800 ]]; then
errorMessage "$_status: The provider currently has an fatal error. DynB will wait for next update until 30 minutes have passed since last request, $(date --date=@$delta -u +%M) minutes already passed." errorMessage "$_status: The provider currently has an fatal error. DynB will wait for next update until 30 minutes have passed since last request, $(date --date=@$delta -u +%M) minutes already passed."
return 1 return 1
@@ -402,69 +409,69 @@ function checkStatus() {
rm "$_statusFile" rm "$_statusFile"
fi fi
return 0 return 0
;; ;;
* ) *)
if [[ _errorCounter -gt 1 ]]; then if [[ _errorCounter -gt 1 ]]; then
errorMessage "An unknown response code has repeatedly been received. $_response" errorMessage "An unknown response code has repeatedly been received. $_response"
return 1 return 1
else else
return 0 return 0
fi fi
;; ;;
esac esac
} }
# requires parameter # requires parameter
# 1. param: 4 or 6 for IP version # 1. param: 4 or 6 for IP version
function ipHasChanged() { function ipHasChanged() {
case ${1} in case ${1} in
4) 4)
remote_ip=$(getRemoteIP 4 $_ipv4_checker) remote_ip=$(getRemoteIP 4 $_ipv4_checker)
if [[ $DYNB_UPDATE_METHOD == domrobot ]]; then if [[ $DYNB_UPDATE_METHOD == domrobot ]]; then
dns_ip=$(getDNSIP A) dns_ip=$(getDNSIP A)
else else
if [[ -n $_DNS_checkServer ]]; then if [[ -n $_DNS_checkServer ]]; then
dig_response=$(dig @"${_DNS_checkServer}" in a +short "$DYNB_DYN_DOMAIN") dig_response=$(dig @"${_DNS_checkServer}" in a +short "$DYNB_DYN_DOMAIN")
else else
dig_response=$(dig in a +short "$DYNB_DYN_DOMAIN") dig_response=$(dig in a +short "$DYNB_DYN_DOMAIN")
fi fi
if [[ $dig_response == ";; connection timed out; no servers could be reached" ]]; then if [[ $dig_response == ";; connection timed out; no servers could be reached" ]]; then
errorMessage "DNS request failed $dig_response" errorMessage "DNS request failed $dig_response"
return 0 return 0
fi fi
dns_ip=$dig_response dns_ip=$dig_response
fi fi
_new_IPv4=$remote_ip _new_IPv4=$remote_ip
debugMessage "New IPv4: $_new_IPv4 old was: $dns_ip" debugMessage "New IPv4: $_new_IPv4 old was: $dns_ip"
;; ;;
6) 6)
remote_ip=$(getRemoteIP 6 $_ipv6_checker) remote_ip=$(getRemoteIP 6 $_ipv6_checker)
if [[ $DYNB_UPDATE_METHOD == domrobot ]]; then if [[ $DYNB_UPDATE_METHOD == domrobot ]]; then
dns_ip=$(getDNSIP AAAA) dns_ip=$(getDNSIP AAAA)
else else
if [[ -n $_DNS_checkServer ]]; then if [[ -n $_DNS_checkServer ]]; then
dig_response=$(dig @"${_DNS_checkServer}" in aaaa +short "$DYNB_DYN_DOMAIN") dig_response=$(dig @"${_DNS_checkServer}" in aaaa +short "$DYNB_DYN_DOMAIN")
else else
dig_response=$(dig in aaaa +short "$DYNB_DYN_DOMAIN") dig_response=$(dig in aaaa +short "$DYNB_DYN_DOMAIN")
fi fi
if [[ $dig_response == ";; connection timed out; no servers could be reached" ]]; then if [[ $dig_response == ";; connection timed out; no servers could be reached" ]]; then
errorMessage "DNS request failed $dig_response" errorMessage "DNS request failed $dig_response"
return 0 return 0
fi fi
dns_ip=$dig_response dns_ip=$dig_response
fi fi
_new_IPv6=$remote_ip _new_IPv6=$remote_ip
debugMessage "New IPv6: $_new_IPv6 old was: $dns_ip" debugMessage "New IPv6: $_new_IPv6 old was: $dns_ip"
;; ;;
*) ;; *) ;;
esac esac
if [[ "$remote_ip" == "$dns_ip" ]]; then if [[ "$remote_ip" == "$dns_ip" ]]; then
return 0 return 0
else else
return 1 return 1
fi fi
} }
################ ################
@@ -488,7 +495,7 @@ function handleParameters() {
exit 0 exit 0
fi fi
# shellcheck disable=SC2154 # shellcheck disable=SC2154
if [[ $_arg_debug == "on" ]]; then if [[ $_arg_debug == "on" ]]; then
_debug=1 _debug=1
fi fi
# shellcheck disable=SC2154 # shellcheck disable=SC2154
@@ -532,7 +539,7 @@ function handleParameters() {
else else
_loopMode=1 _loopMode=1
fi fi
if [[ $_network_interface != "" ]]; then if [[ $_network_interface != "" ]]; then
_interface_str="--interface $_network_interface" _interface_str="--interface $_network_interface"
fi fi
@@ -573,13 +580,13 @@ function checkDependencies() {
for i in curl dig; do for i in curl dig; do
if ! command -v $i >/dev/null 2>&1; then if ! command -v $i >/dev/null 2>&1; then
errorMessage "could not find \"$i\", DynB depends on it. " errorMessage "could not find \"$i\", DynB depends on it. "
(( failCounter++ )) ((failCounter++))
fi fi
done done
[[ -x $(command -v jq 2> /dev/null) ]] || { [[ -x $(command -v jq 2>/dev/null) ]] || {
if [[ $DYNB_UPDATE_METHOD != dyndns* ]]; then if [[ $DYNB_UPDATE_METHOD != dyndns* ]]; then
echo "This script depends on jq and it is not available." >&2 echo "This script depends on jq and it is not available." >&2
(( failCounter++ )) ((failCounter++))
fi fi
} }
if [[ failCounter -gt 0 ]]; then if [[ failCounter -gt 0 ]]; then
@@ -640,11 +647,11 @@ function doDynDNS2Updates() {
changed=0 changed=0
if [[ $_is_IPv4_enabled == true ]]; then if [[ $_is_IPv4_enabled == true ]]; then
ipHasChanged 4 ipHasChanged 4
(( changed += $? )) ((changed += $?))
fi fi
if [[ $_is_IPv6_enabled == true ]]; then if [[ $_is_IPv6_enabled == true ]]; then
ipHasChanged 6 ipHasChanged 6
(( changed += $? )) ((changed += $?))
fi fi
if [[ $changed -gt 0 ]]; then if [[ $changed -gt 0 ]]; then
if checkStatus; then if checkStatus; then
@@ -653,7 +660,7 @@ function doDynDNS2Updates() {
debugMessage "DynDNS2 update success" debugMessage "DynDNS2 update success"
else else
debugMessage "Save new status after dynupdate has failed" debugMessage "Save new status after dynupdate has failed"
setStatus "$_response" "$(date +%s)" $(( _errorCounter += 1 )) "$DYNB_DYN_DOMAIN" "${DYNB_USERNAME}" "${DYNB_PASSWORD}${DYNB_TOKEN}" setStatus "$_response" "$(date +%s)" $((_errorCounter += 1)) "$DYNB_DYN_DOMAIN" "${DYNB_USERNAME}" "${DYNB_PASSWORD}${DYNB_TOKEN}"
fi fi
else else
debugMessage "Skip DynDNS2 update, checkStatus fetched previous error." debugMessage "Skip DynDNS2 update, checkStatus fetched previous error."
@@ -677,7 +684,7 @@ function doUpdates() {
## MAIN method ## ## MAIN method ##
################# #################
function dynb() { function dynb() {
# shellcheck disable=SC1091 # shellcheck disable=SC1091,SC1090
source "$(dirname "$(realpath "$0")")/dynb-parsing.sh" source "$(dirname "$(realpath "$0")")/dynb-parsing.sh"
# shellcheck source=.env # shellcheck source=.env
@@ -702,8 +709,7 @@ function dynb() {
checkDependencies checkDependencies
if loopMode; then if loopMode; then
while : while :; do
do
doUpdates doUpdates
sleep $DYNB_INTERVAL sleep $DYNB_INTERVAL
done done
@@ -718,7 +724,7 @@ function dynb() {
## END MAIN section ## ## END MAIN section ##
###################### ######################
dynb "${@}" dynb "${@}"
exit $? exit $?
# ] <-- needed because of Argbash # ] <-- needed because of Argbash