Синтаксическая ошибка сценария оболочки: неожиданный конец файла

В следующем скрипте я получаю ошибку:

синтаксическая ошибка: неожиданный конец файла

Что это за ошибка, как я могу ее исправить? Он указывает на строку, где вызывается функция.

#!/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)

10 ответов

Решение

Изменить: Обратите внимание, что оригинальное сообщение было отредактировано с момента написания этого ответа и было переформатировано. Вы должны посмотреть историю, чтобы увидеть оригинальное форматирование, чтобы понять контекст этого ответа.

Эта ошибка часто возникает, когда у вас несоответствующая структура, то есть у вас нет совпадающих двойных кавычек, совпадающих одинарных кавычек, не закрыта управляющая структура, такая как отсутствующая fi с ifили пропавший done с for,

Лучший способ определить это - использовать правильный отступ, который покажет вам, где у вас нарушена структура управления, и подсветку синтаксиса, которая покажет, где кавычки не совпадают.

В этом конкретном случае, я вижу, что вам не хватает fi, В последней части вашего кода у вас есть 5 ifс и 4 fis. Однако у вас также есть ряд других проблем - ваши кавычки touch /tmp/alert.txt... Команда синтаксически неверна, и вам нужно пробел перед закрывающей скобкой if тестовое задание.

Очистите свой код, и ошибки начинают выделяться.

В моем случае проблема была в преобразовании EOL. (Конец линии).

Я создал файл в Windows, и только после того, как я преобразовал EOL из Windows(CR LF) в Unix(LF), все прошло хорошо.

Я сделал преобразование с Notepad++ очень легко из: Edit -> EOL Conversion -> Unix (LF)

Не имеет отношения к проблеме ОП, но моя проблема заключалась в том, что я являюсь сценаристом оболочки noob. Все остальные языки, которые я использовал, требуют скобок для вызова методов, тогда как shell, похоже, не такой.

function do_something() {
  # do stuff here
}

# bad
do_something()

# works
do_something

В моем случае я обнаружил, что размещение отступов здесь (например, sqplus ... << EOF) операторов также вызывает ту же ошибку, как показано ниже:

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

Так что после удаления отступа для этого все прошло нормально.

Надеюсь, поможет...

Отступ при использовании блока может вызвать эту ошибку, и его очень трудно найти.

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

=> Пример выше приведет к ошибке, потому что EOSQL имеет отступ. Удалите отступы, как показано ниже. Размещая это, потому что мне потребовалось больше часа, чтобы выяснить ошибку.

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

Я обнаружил, что это иногда вызвано запуском версии файла MS Dos. Если это так, то dos2ux должен это исправить.

dos2ux file1 > file2

У меня была эта проблема при запуске какого-то скрипта в cygwin. Исправлено при запуске dos2unix на сценарии, с надлежащим описанием проблемы и решения, указанного в этом ответе

Полезный пост, я обнаружил, что моя ошибка использовала else if вместо elif вот так:

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

Исправлено, изменив это:

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

У вас есть открытая цитата, скобка, скобка, если, цикл или что-то еще.

Если вы не можете увидеть его, просто посмотрев (я бы порекомендовал редактор окраски синтаксиса и аккуратный стиль отступов), возьмите копию сценария и удалите половину, вырезав ее где-то, что должно быть допустимым. Если скрипт выполняется настолько далеко, насколько это возможно, то проблема в другой половине. Повторяйте, пока не сузите проблему.

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

должно быть

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

Иначе, программа или команда с именем echo"===... ищется.

больше проблем:

Если вы делаете grep (-A1: + 1 строчный контекст)

grep -A1 "if " cldtest.sh 

Вы найдете несколько встроенных ifs и 4 блока if/then.

grep "fi " cldtest.sh 

показывает только 3 соответствующих фантастических высказывания. Таким образом, вы забыли один файл тоже.

Я согласен с Camh, что правильный отступ с самого начала помогает избежать таких ошибок. Поиск нужного пути позже означает двойную работу в таком коде спагетти.

Это также может быть вызвано выпуском пары фигурных скобок на линии.

Это не удается:

{ /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

пока это разрешено:

{
   /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

Я столкнулся с той же ошибкой при попытке выполнить файл сценария, созданный в ОС Windows, с помощью textpad. чтобы можно было выбрать подходящий формат файла, например, unix/mac и т. д., или пересоздать скрипт в linux.

Другие вопросы по тегам