87

In the following script I get an error:

syntax error: unexpected end of file

What is this error how can I resove it? It is pointing at the line whee the function is called.

#!/bin/sh

expected_diskusage="264"
expected_dbconn="25"
expected_httpdconn="20"
expected_cpuusage="95"
#expected_fd="100"

httpdconn=`ps -ef|grep -i httpd|grep -v grep|wc -l` #httpd connections
cpu_usage=`ps aux|awk 'NR > 0 { s +=$3 }; END {print s}'`
disk_usage=`df -h|awk {'print $2'}|head -n3|awk 'NF{s=$0}END{print s}'`
#db_connections=`mysql -uroot -pexxxxxx -s -N -e "show processlist"|wc -l`

db_connections=6
cld_alert()
{
    nwconn=$1
    cpu_usage=$2
    disk_usage=$3
    db_connections=$4
    message=$5
    `touch /tmp/alert.txt && > /tmp/alert.txt`
    date=`date`
    echo -e "$date\n" > /tmp/alert.txt
    echo -e "$message" >> /tmp/alert.txt
    path="/proc/$httpd/fd/";
    cd $path
    tfd=`ls -l|wc -l`;
    sfd=`ls -ltr|grep sock|wc -l`;
    echo "Total fds: $tfd" >> /tmp/alert.txt
    echo "Socket fds: $sfd" >> /tmp/alert.txt
    echo "Other fds: $[$tfd - $sfd]" >> /tmp/alert.txt


    freememory=`vmstat | awk '{if (NR == 3) print "Free Memory:"\$4}'`;
    echo "Free memory :$freememory" >> /tmp/alert.txt
    Bufferedmemory=`vmstat | awk '{if (NR == 3) print "Buffered Memory:"\$5}'`;
    echo "Buffered memory $Bufferedmemory" >> /tmp/alert.txt
    CacheMemory=`vmstat | awk '{if (NR == 3) print "Cache Memory:"\$6}'`;
    echo "Cache memory : $CacheMemory" >> /tmp/alert.txt
    sshconn=`netstat -an|grep 22|wc -l`  #ssh connections
    httpsconn=`netstat -an|grep 443|wc -l`  #https connections
    wwwconn=`netstat -an|grep 80|wc -l`  #www connections
    echo "Disk usage is $disk_usage" >> /tmp/alert.txt
    echo "DB connections $db_connections" >> /tmp/alert.txt
    echo "Network connections $nwconn" >> /tmp/alert.txt
    echo "CPU Usage: $cpu_usage" >> /tmp/alert.txt
    topsnapshot=`top -n 1 -b`
    echo "===========================TOP COMMAND    SNAPSHOT====================================================";
    echo "$topsnapshot" >> /tmp/alert.txt
    echo"==================PS COMMAND SNAPSHOT=============================================================="
    entireprocesslist=`ps -ef`
    echo "$entireprocesslist" >> /tmp/alert.txt


    echo Hello hi"";

}



message=""
if [ ${disk_usage%?} -le $expected_diskusage ]    ##{x%?} Removes last character
then
    echo "disk usage exceeded";
    message="Disk usage limit exceeded \nCurrent disk usage is $disk_usage\nConfigured disk usage is    $expected_diskusage\n\n\n\n\n";
    #Checking for CPU usage
    if [ $cpu_usage -ge $expected_cpuusage]    ##{x%?}
    then
        echo "CPU usage exceeded";
        if [ $message -ne "" ]
        then
            message="$message\n\nCPU usage exceeded configured usage limit \nCurrent CPU usage is $cpu_usage\nConfigured CPU usage is $expected_cpuusage\n\n\n\n\n";
        else
            message="CPU usage exceeded configured usage limit \nCurrent CPU usage is   $cpu_usage\nConfigured CPU usage is $expected_cpuusage\n\n\n\n\n";
        fi ;
    fi
    #Checking for httpd connections
    if [ $httpdconn -ge $expected_httpdconn]    ##{x%?}
    then
        echo "HTTPD connections exceeded";
        if [ $message -ne "" ]
        then
            message="$message\n\nHTTPD connections exceeded configured usage limit \nCurrent HTTPD connections is $httpdconn\nConfigured HTTPD connection is $expected_httpdconn";
        else
            message="HTTPD connections exceeded configured usage limit \nCurrent HTTPD connections is $httpdconn\nConfigured HTTPD connection is $expected_httpdconn";
        fi ;
    fi ;
    message="$message\n\n\n\n\n";
    value=$(cld_alert $message $httpdconn $cpu_usage $disk_usage $db_connections)
7
  • 1
    please copy the whole script (well, we would like to see a minimal code that reproduces the problem, but you already failed to post that...) Commented Mar 27, 2012 at 9:01
  • The error is most likely before that. Commented Mar 27, 2012 at 9:03
  • yes i have given the full code Commented Mar 27, 2012 at 9:11
  • 3
    Indent the code according to nesting level. And at least 4 spaces per indentation level at that, so you can really see the structure. It's most probably missing fi or } somewhere, but without indentation you won't ever see where. Commented Mar 27, 2012 at 9:17
  • What is the assignment to value in the last line used for - the value is never used. Commented Mar 27, 2012 at 9:23

12 Answers 12

151

Edit: Note that the original post has been edited since this answer was written and has been reformatted. You should look at the history to see the original formatting to understand the context for this answer.

This error occurs often when you have mismatched structure - that is, you do not have matching double quotes, matching single quotes, have not closed a control structure such as a missing fi with an if, or a missing done with a for.

The best way to spot these is to use correct indentation, which will show you where you have a broken control structure, and syntax highlighting, which will show you where quotes are not matched.

In this particular case, I can see you are missing a fi. In the latter part of your code, you have 5 ifs and 4 fis. However you also have a number of other problems - your backquoted touch /tmp/alert.txt... command is syntactically invalid, and you need a space before the closing bracket of an if test.

Clean up your code, and errors start to stand out.

Sign up to request clarification or add additional context in comments.

3 Comments

Awesome! This was really helpful. These are the common things which just slip. Keep adding :)
ShellCheck is great for finding out the exact error locations and maybe even further errors or warnings.
shfmt is another tool that has also been released since I answered this question that does the code clean-up for you. shellcheck and shfmt are essential tools for writing shell scripts.
61

in my case the issue was in the EOL Conversion. (End Of Line).

i created the file on windows and only after i converted the EOL from windows(CR LF) to unix(LF), everything went well.

I did the conversion with Notepad++ very easily from: Edit -> EOL Conversion -> Unix(LF)

3 Comments

This answer helped me. Using vscode , at bottom right of the editor change CRLF to LF
this helped me, I was running my file in wsl, and file was created in windows notepad++.
This one helped, exact same approach as @cjmling said
21

Unrelated to the OP's problem, but my issue was that I'm a noob shell scripter. All the other languages I've used require parentheses to invoke methods, whereas shell doesn't seem to like that.

function do_something() {
  # do stuff here
}

# bad
do_something()

# works
do_something

2 Comments

yes, forgot that
ah ! This is it ! Thanks :)
11

In my case, I found that placing a here document (like sqplus ... << EOF) statements indented also raise the same error as shown below:

./dbuser_case.ksh: line 25: syntax error: unexpected end of file

So after removing the indentation for this, then it went fine.

Hope it helps...

1 Comment

This! I used heredoc inside an if block. It felt so wrong to have un-indented code in the block, but it's absolutely necessary.
11

Indentation when using a block can cause this error and is very hard to find.

if [ ! -d /var/lib/mysql/mysql ]; then
   /usr/bin/mysql --protocol=socket --user root << EOSQL
        SET @@SESSION.SQL_LOG_BIN=0;
        CREATE USER 'root'@'%';
   EOSQL
fi

=> Example above will cause an error because EOSQL is indented. Remove indentation as shown below. Posting this because it took me over an hour to figure out the error.

if [ ! -d /var/lib/mysql/mysql ]; then
   /usr/bin/mysql --protocol=socket --user root << EOSQL
        SET @@SESSION.SQL_LOG_BIN=0;
        CREATE USER 'root'@'%';
EOSQL
fi

2 Comments

You are not joking when you said this error is VERY HARD to find
If only I could give you a medal for this answer. Thanks. This indentation just took my half day!!
6

I have found that this is sometimes caused by running a MS Dos version of a file. If that's the case dos2ux should fix that.

dos2ux file1 > file2

Comments

4

Helpful post, I found that my error was using else if instead of elif like so:

if [ -z "$VARIABLE1" ]; then
    # do stuff
else if [ -z "$VARIABLE2" ]; then
    # do other stuff
fi

Fixed it by changing to this:

if [ -z "$VARIABLE1" ]; then
    # do stuff
elif [ -z "$VARIABLE2" ]; then
    # do other stuff
fi

Comments

4

I had this problem when running some script in cygwin. Fixed by running dos2unix on the script, with proper description of problem and solution given in that answer

Comments

3

You've got an unclosed quote, brace, bracket, if, loop, or something.

If you can't see it just by looking (I'd recommend a syntax colouring editor and a neat indentation style), take a copy of the script, and delete half of it, cutting it of somewhere that ought to be valid. If the script runs, as far as it can, then the problem is in the other half. Repeat until you've narrowed down the problem.

Comments

2
echo"==================PS COMMAND SNAPSHOT=============================================================="

needs to be

echo "==================PS COMMAND SNAPSHOT=============================================================="

Else, a program or command named echo"===... is searched.

more problems:

If you do a grep (-A1: + 1 line context)

grep -A1 "if " cldtest.sh 

you find some embedded ifs, and 4 if/then blocks.

grep "fi " cldtest.sh 

only reveals 3 matching fi statements. So you forgot one fi too.

I agree with camh, that correct indentation from the beginning helps to avoid such errors. Finding the desired way later means double work in such spaghetti code.

Comments

1

It can also be caused by piping out of a pair of curly braces on a line.

This fails:

{ /usr/local/bin/mycommand ; outputstatus=$? } >> /var/log/mycommand.log 2>&1h
do_something
#Get NOW that saved output status for the following $? invocation
sh -c "exit $outputstatus"
do_something_more

while this is allowed:

{
   /usr/local/bin/mycommand
   outputstatus=$?
} >> /var/log/mycommand.log 2>&1h
do_something
#Get NOW that saved output status for the following $? invocation
sh -c "exit $outputstatus"
do_something_more

Comments

0

I have encountered the same error while trying to execute a script file created in windows OS using textpad. so that one can select proper file format like unix/mac etc.. or recreate the script in linux iteself.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.