bashformattingshellcheck

How to properly format an 'if' statement being passed to a remote server in a when using 'while read'?


Ubuntu 18
Bash 4.4.0

I am wanting to pass an if statement to see whether or not a directory exist. If it does, I want to some commands and then a file. I have read through the similar posts but shellcheck complains about my formatting.

Script:

#!/bin/bash

testing="yes"
scriptDir="/root/.work"
wDir="${scriptDir}/.nginx-fix"
if [ "$testing" = "no" ]; then
  hostfile="${scriptDir}/.zzz-hostnames"
else
  hostfile="${scriptDir}/.zzz-hostnames-tester"
fi

cd "$wDir"
while read fqdn; do
  { clear; echo ""; echo ""; echo "$hostname"; echo ""; }
  < /dev/null if ssh -p 34499 root@"${fqdn}" '[ -d /etc/nginx ]'; then
    < /dev/null ssh -p 34499 root@"${fqdn}" 'mv /etc/nginx/nginx.conf /etc/nginx/.nginx-sept-30'
    < /dev/null scp -P 34499 nginx.conf root@"${fqdn}":/etc/nginx
    < /dev/null ssh -p 34499 root@"${fqdn}" 'sed -i "/honeypot/d" /etc/nginx/conf.d/*.conf'
    < /dev/null ssh -p 34499 root@"${fqdn}" 'nginx -t'
  else
    exit 1;
  fi
done<"${hostfile}"

Shellcheck complaint:

root@me ~/.work/.nginx-fix # shellcheck .nginx-fixer.sh

In .nginx-fixer.sh line 13:
while read fqdn; do
^-- SC1073: Couldn't parse this while loop.
                 ^-- SC1061: Couldn't find 'done' for this 'do'.


In .nginx-fixer.sh line 15:
        < /dev/null if ssh -p 33899 root@"${fqdn}" '[ -d /etc/nginx ]'; then
                                                                        ^-- SC1062: Expected 'done' matching previously mentioned 'do'.
                                                                            ^-- SC1072: Expected "#". Fix any mentioned problems and try again.

I'd appreciate your thoughts.


Solution

  • You can refactor the script to a clearer version and remove all the </dev/null:

    while read -r fqdn; do {
      { clear; echo ""; echo ""; echo "$hostname"; echo ""; }
      if ssh -p 34499 root@"${fqdn}" '[ -d /etc/nginx ]'; then
        ssh -p 34499 root@"${fqdn}" 'mv /etc/nginx/nginx.conf /etc/nginx/.nginx-sept-30'
        scp -P 34499 nginx.conf root@"${fqdn}":/etc/nginx
        ssh -p 34499 root@"${fqdn}" 'sed -i "/honeypot/d" /etc/nginx/conf.d/*.conf'
        ssh -p 34499 root@"${fqdn}" 'nginx -t'
      else
        exit 1;
      fi
    } </dev/null; done < "${hostfile}"
    

    Almost invisible to the eye, I have put all the commands inside do ... done inside { .. } </dev/null. That way any command won't read from ${hostfile} and won't mess with while read.

    Another option is to use a dedicated file descriptor and pass its number to read:

    while read -r -u 10 fqdn; do
      { clear; echo ""; echo ""; echo "$hostname"; echo ""; }
      if ssh -p 34499 root@"${fqdn}" '[ -d /etc/nginx ]'; then
        ssh -p 34499 root@"${fqdn}" 'mv /etc/nginx/nginx.conf /etc/nginx/.nginx-sept-30'
        scp -P 34499 nginx.conf root@"${fqdn}":/etc/nginx
        ssh -p 34499 root@"${fqdn}" 'sed -i "/honeypot/d" /etc/nginx/conf.d/*.conf'
        ssh -p 34499 root@"${fqdn}" 'nginx -t'
      else
        exit 1;
      fi
    done 10<"${hostfile}"