I'm getting a syntax error unexpected token fi and Permission denied in the following script:

cd /home/NorthStar/Dhruva/server-specific-scripts/crons/ResetETA

su postgres -c "psql -d "Dhruva" -f /home/NorthStar/Dhruva/server-specific-scripts/crons/db-connection/query.sql" >> reset.log 2> reset.log

if su postgres -c "psql -d "Dhruva" -f /home/NorthStar/Dhruva/server-specific-scripts/crons/db-connection/query.sql; then 
    printf su postgres -c "psql -d "Dhruva" -f /home/NorthStar/Dhruva/server-specific-scripts/crons/db-connection/query.sql\n' >> resset.log
    printf su postgres -c "psql -d "Dhruva" -f /home/NorthStar/Dhruva/server-specific-scripts/crons/db-connection/query.sql\n' >> reset_error.log
  • why must the lines be so long? also, consider if :; then :; fi >>log
    – mikeserv
    Commented Dec 5, 2015 at 4:53
  • or use the character \ for breaking lines so it would be easier to read.
    – VaTo
    Commented Dec 5, 2015 at 6:40
  • The hint is in the red then and else there. Commented Dec 14, 2015 at 11:32
  • You realize you've placed your admin password on the Internet for everyone to see, right? I could edit it out, but the damage has been done. Might want to change it to something else... Commented Dec 15, 2015 at 7:36

1 Answer 1


Unbalanced quotes

What you have is a messy example of unbalanced quotation marks.

Every pair of single and double quotes must be balanced, meaning, whenever you have an opening quote, you have to have a closing quote later on in the same statement, and they must be properly nested. (So, for example, echo "foo 'bar' baz" is valid, but echo "foo 'bar baz"' is not.

So, in your case, sh (or whatever Bourne shell you appear to be using), interprets the quotes as if they're balanced, which results in parts of your script being "quoted" which you didn't intend, namely, much of the if .. else .. fi construct.

Another (abbreviated) example from your script: su "psql -d "Dhruva" blah.sql". In that example, the string Dhruva is actually outside the quotes, which is probably not what you intended.

Essentially, your problem is the unbalanced quotes. I will analyze your script a bit more to see if I can't figure out what you're trying to do, and suggest a fixed version, but I confess I don't quite understand your intentions with the script.

"Fixed" script

I've put "fixed" in scare-quotes because even though I can tell you how to repair the syntax of your script, I still have concerns, which I will enumerate at the end of this answer.

A bit of refactoring, and fixing the quotes

First, you have some very long lines containing repeated elements that can easily be refactored, which already makes our job of "fixing" much easier:


cd /home/NorthStar/Dhruva/server-specific-scripts/crons/ResetETA

cmd="psql -d $db -f $file"

su postgres -c "$cmd" >> reset.log 2> reset.log

if su postgres -c "$cmd"; then 
    printf su postgres -c "$cmd" >> resset.log
    printf su postgres -c "$cmd" >> reset_error.log

While the above is now valid syntax, I do have a few remaining concerns:

  • Is there a need to run $cmd so many times? Does the output change (i.e., does the query have side effects?) Or can you save the results and append to your log files separately?
  • Is resset.log a typo, or do you really have three different logs?
  • printf ... will not do what you (probably) want, here. printfs first argument is the format string (in this case, "su"), hence, it will print su.
  • Alternatively, run the sql query just once (instead of 3 times), capture the output in a variable with $(), and printf the output to different files depending on exit status.
    – cas
    Commented Dec 5, 2015 at 5:33
  • What is the reason to use #!/bin/bash instead of #!/bin/sh for this script?
    – RobertL
    Commented Dec 5, 2015 at 5:38
  • @cas Agreed! I questioned the multiple running in my first bullet point (but you were probably typing your comment while I submitted my edit). I hesitated on suggesting a specific solution for that because of the loose relationship between log files and output streams in the given script. Commented Dec 5, 2015 at 5:39
  • @RobertL None in particular. /bin/sh would do just as well in this case. I picked bash out of a hat as the question didn't specify. I could have mentioned that in my answer, though. Commented Dec 5, 2015 at 5:41
  • I think #!/bin/sh would be preferred in this case. bash is 9 times larger than sh and some systems don't have bash. So why restrict the script to bash when it will run with either? From the bash man page: "BUGS It's too big and too slow."
    – RobertL
    Commented Dec 5, 2015 at 6:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .