次のスクリプトでは、エラーが発生します。
構文エラー:予期しないファイルの終わり
このエラーはどのように再保存できますか?関数が呼び出される行を指しています。
#!/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)
編集:この回答が書かれて再フォーマットされてから、元の投稿が編集されていることに注意してください。この回答のコンテキストを理解するには、履歴を見て元のフォーマットを確認する必要があります。
このエラーは、構造の不一致がある場合によく発生します。つまり、一致する二重引用符がなく、単一引用符に一致せず、fi
がif
であるなどの制御構造を閉じていない場合、またはdone
でfor
が欠落しています。
これらを見つける最良の方法は、正しいインデントを使用することです。これにより、制御構造が壊れている場所が表示され、構文の強調表示により、引用符が一致しない場所が表示されます。
この特定のケースでは、fi
が欠落していることがわかります。コードの後半には、5つのif
sと4つのfi
sがあります。ただし、他にも多くの問題があります。逆引用符で囲まれたtouch /tmp/alert.txt...
コマンドは構文的に無効であり、if
テストの閉じ括弧の前にスペースが必要です。
コードをクリーンアップすると、エラーが目立ち始めます。
私の場合、問題はEOL変換にありました。 (行末)。
私はWindows上でファイルを作成し、EOLをwindows(CR LF)からunix(LF)に変換した後にのみ、すべてがうまくいきました。
Notepad ++を使用した変換は非常に簡単でした。編集-> EOL変換-> Unix(LF)
私の場合、インデントされたhere文書(sqplus ... << EOFなど)ステートメントを配置すると、次のように同じエラーが発生することがわかりました。
./dbuser_case.ksh: line 25: syntax error: unexpected end of file
このため、インデントを削除した後、それはうまくいきました。
それが役に立てば幸い...
Cygwinでスクリプトを実行すると、この問題が発生しました。スクリプトでdos2unix
を実行し、問題と解決策の適切な説明を その答え
これは、MS DOSバージョンのファイルを実行していることが原因であることがわかっています。その場合、dos2uxで修正する必要があります。
dos2ux file1 > file2
ブロック使用時のインデントはこのエラーの原因になる可能性があり、見つけるのは非常に困難です。
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がインデントされているため、上記の例ではエラーが発生します。以下に示すように、インデントを削除します。エラーを把握するのに1時間以上かかったため、これを投稿しました。
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
echo"==================PS COMMAND SNAPSHOT=============================================================="
する必要があります
echo "==================PS COMMAND SNAPSHOT=============================================================="
そうでない場合は、echo"===...
という名前のプログラムまたはコマンドが検索されます。
Grepを実行する場合(-A1:+ 1行コンテキスト)
grep -A1 "if " cldtest.sh
いくつかの埋め込みifと4つのif/thenブロックがあります。
grep "fi " cldtest.sh
3つの一致するfiステートメントのみが明らかになります。だから、あなたも1つのfiを忘れました。
私はcamhに同意します。最初からの正しいインデントはそのようなエラーを避けるのに役立ちます。後で目的の方法を見つけることは、そのようなスパゲッティコードで二重に作業することを意味します。
OPの問題とは関係ありませんが、私の問題は、私がnoob Shellスクリプト作成者であることです。私が使用した他のすべての言語では、メソッドを呼び出すために括弧が必要ですが、シェルはそれを好まないようです。
function do_something() {
# do stuff here
}
# bad
do_something()
# works
do_something
閉じていない引用符、中括弧、括弧、if、ループ、または何かがあります。
見ただけでは表示されない場合(構文の色付けエディターときちんとしたインデントスタイルをお勧めします)、スクリプトのコピーを取り、その半分を削除して、有効なはずの場所を切り取ります。スクリプトが可能な限り実行される場合、問題は残りの半分にあります。問題を絞り込むまで繰り返します。
参考になった投稿では、私のエラーがElif
の代わりにelse if
を使用していることがわかりました。
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
テキストパッドを使用して、Windows OSで作成されたスクリプトファイルを実行しようとしたときに、同じエラーが発生しました。そのため、unix/macなどの適切なファイル形式を選択したり、Linux自体でスクリプトを再作成したりできます。
また、ライン上の中括弧のペアから配管することによっても発生する可能性があります。
これは失敗します:
{ /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