1

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.

Vituvo
  • 1,008
  • 1
  • 9
  • 29

2 Answers2

1

Running the script via 'bash -n' will indicate the 'real' error:

bash -n x.sh
x.sh: line 15: syntax error near unexpected token `then'
x.sh: line 15: `   < /dev/null if ssh -p 34499 root@"${fqdn}" '[ -d /etc/nginx ]' ; then'

You can not place redirection before on the 'if' statement. Move the redirection to the 'ssh' (condition part of the if) command, for example:

# USE:
if ssh < /dev/null -p 34499 root@"${fqdn}" '[ -d /etc/nginx ]' ; then'

# AND NOT:
< /dev/null if ssh -p 34499 root@"${fqdn}" '[ -d /etc/nginx ]' ; then'

dash-o
  • 13,723
  • 1
  • 10
  • 37
  • Your answer was extremely valuable to me. I knew ```sh -x x.sh``` for shell scripts printed line by line but was not aware of the error checking in bash with ```bash -n x.sh```. Hats off to you mate. – Vituvo Oct 03 '19 at 22:33
1

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}"
Tom Fenech
  • 72,334
  • 12
  • 107
  • 141
KamilCuk
  • 120,984
  • 8
  • 59
  • 111