2

I am trying to setup the script below to take multiple argument input on the command line. I am using the script to request ssl certs from letsencrypt. The script currently takes one domain at a time but I would like to be able to set it to accept multiple command line arguments so that I will be able to use it to request for certs for domains that have multiple alternate names(example: domain.com and www.domain.com) I have tried changing CERTNAME="${2}" to CERTNAME="$@" and CERTNAME=$(echo "${2}" | sed -n "s/.*'\([^']\+\)'.*/\1/p") to CERTNAME=$(echo "$@" | sed -n "s/.*'\([^']\+\)'.*/\1/p") but it keeps getting stuck at echo "error: wrong CERTTYPE". I run the script like so ./<script name> --issue c_domain.com_rsa and it works but as soon as I add another argument like so ./<script name> --issue c_domain.com_rsa c_www.domain.com_rsa it doesn't work. What I'm I doing wrong? Script is below:

#!/bin/bash

if [ "$1" = "--issue" ]; then
  CERTNAME="${2}"

else
  CERTNAME=$(echo "${2}" | sed -n "s/.*'\([^']\+\)'.*/\1/p")

fi
  CERTFILE=$(echo "${CERTNAME}" | cut -d'_' -f 2)
  CERTTYPE=$(echo "${CERTNAME}" | cut -d'_' -f 3)

if [ -z "$CERTNAME" ] || [ -z "$CERTFILE" ] || [ -z "$CERTTYPE" ]; then
  echo "error, can't figure out CERTNAME or CERTFILE or CERTTYPE"
  exit 1
fi

ZCLI=$(locate zcli 2>/dev/null | egrep "test/bin/zcli$")
[ -z "$ZCLI" ] && ZCLI=$(which zcli)
[ -z "$ZCLI" ] && ZCLI=$(find / -name zcli | egrep "test/bin/zcli$")

if [ -z "$ZCLI" ]; then
  echo "Can't find zcli command"
  exit 1
fi


ACMEHOME="/root/certs/"
ACMEOPTIONS="--standalone --httpport 88"
TEST="--test --days 0"

case "$CERTTYPE" in
  ecc)
    ACMEKEY="--keylength ec-256"
    CERTDIR=$ACMEHOME/${CERTFILE}_${CERTTYPE}
    ;;
  rsa)
    ACMEKEY="--keylength 2048"
    CERTDIR=$ACMEHOME/${CERTFILE}
    ;;
  *)
   echo "error: wrong CERTTYPE"
   exit 1
esac

 if [ -d $CERTDIR ]; then
   # certificate renewal
   ACMEACTION="--renew"
   if [ "$CERTTYPE" = "ecc" ]; then
     ACMEKEY="--ecc"
   fi
else
  # certificate issuance
  ACMEACTION="--issue"
fi

$ACMEHOME/acme.sh $TEST $ACMEOPTIONS $ACMEACTION -d ${CERTFILE} $ACMEKEY

# key
key=$(cat $CERTDIR/${CERTFILE}.key)
key=${key//$'\n'/\\n}

# crt
crt=$(cat $CERTDIR/fullchain.cer)
crt=${crt//$'\n'/\\n}

echo "Catalog.SSL.Certificates.setRawCertificate ${CERTNAME} \"$crt\" " > 
$CERTDIR/zcli_${CERTFILE}.script 
$ZCLI $CERTDIR/zcli_${CERTFILE}.script
if [ $? -ne 0 ]; then
echo "Catalog.SSL.Certificates.importCertificate ${CERTNAME} { private_key: 
\"$key\", public_cert: \"$crt\" }" > $CERTDIR/zcli_${CERTFILE}.script
$ZCLI $CERTDIR/zcli_${CERTFILE}.script
fi

echo "Done!"
0

I'm not sure what's going on in the rest of your script, but you're not handling positional parameters correctly. Setting CERTNAME to $@ will set it to a string containing all of the parameters, including --include. Then you're running cut on this string, which I'm not sure what you expect to do. If you want to loop over parameters, you can do something like this:

#!/bin/bash

if [[ "$1" = "--issue" ]]; then
   certs=("${@:2}")
else
   :
   # something else here
fi

for cert in "${certs[@]}"; do
   echo "$cert"
   # process each cert here
done

exit

Given your last example this will print:

c_domain.com_rsa
c_www.domain.com_rsa

This puts all of your positional parameters excluding $1 into an array and loops over it. If you want to put the rest of the parameters into a string, just remove the parentheses like this: certs="${@:2}"

Using $@ this way is a bit confusing: when you say "$@" it expands positional parameters into words, i.e. $1..$n. However, using it in an array context like I'm doing will include $0, which is the name of the script. That's why I'm starting the slice at element 2.

Like I said there's a lot of other things going on here, but this should answer the question about parameters.

  • Thanks for the example. I don't want it to loop over the arguments. I am trying to request a cert and what I am trying to achieve is request one cert for a domain but that domain has multiple alternate names so for example, instead of requesting a cert for domain.com and www.domain.com(two seperate certs), I can just request a cert for domain.com(with www.domain.com as alternate name), thus one cert but serves two domains. – TeNaJ Systems Nov 21 '17 at 21:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.