我已经摆弄这个代码几天了。请注意,我是个初学者。我只想让我的脚本能够下载远程文件并扫描 MineCraft 插件。我让扫描插件工作了,但我遇到了另外两个问题。第一,我无法让 mc_addplugin 正常工作,并且在运行除 mc_scanplugins 或 mc_start 之外的任何其他命令时,我都会收到意外的 EOF 和意外的文档结束
bash: -c: line 0: unexpected EOF while looking for matching `"'
bash: -c: line 1: syntax error: unexpected end of file
非常感谢您的帮助!提前致谢。
#!/bin/bash
# /etc/init.d/craftbukkit
# version 0.9.1 2012-07-06 (YYYY-MM-DD)
### BEGIN INIT INFO
# Provides: craftbukkit
# Required-Start: $local_fs $remote_fs
# Required-Stop: $local_fs $remote_fs
# Should-Start: $network
# Should-Stop: $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Starts craftbukkit server
# Description: Starts and controls the craftbukkit server
### END INIT INFO
# SETTINGS
SERVICE='craftbukkit-1.2.5-R1.0.jar'
OPTIONS='nogui'
USERNAME='smith'
# LIST ALL THE WORLDS IN YOUR CRAFTBUKKIT SERVER FOLDER
WORLDS[1]='world'
WORLDS[2]='world_nether'
WORLDS[3]='world_the_end'
WORLDS[4]='flat_world'
MCPATH='/var/www/servers/Foundation'
PLUGINSPATH='/var/www/servers/Foundation/plugins'
TEMPPLUGINS='/var/www/servers/Foundationplugins/temp_plugins'
BACKUPPATH='/var/www/servers/Foundation/backup'
CPU_COUNT=2
INVOCATION="java -Xmx2024M -Xms2024M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=$CPU_COUNT -XX:+AggressiveOpts -jar $SERVICE $OPTIONS"
ME=`whoami`
as_user() {
if [ $ME == $USERNAME ] ; then
bash -c "$1"
else
su - $USERNAME -c "$1"
fi
}
mc_start() {
if pgrep -u $USERNAME -f $SERVICE > /dev/null
then
echo "$SERVICE is already running!"
else
echo "Starting $SERVICE..."
cd $MCPATH
as_user "cd $MCPATH && screen -dmS craftbukkit $INVOCATION"
sleep 7
if pgrep -u $USERNAME -f $SERVICE > /dev/null
then
echo "$SERVICE is now running."
else
echo "Error! Could not start $SERVICE!"
fi
fi
}
mc_saveoff() {
if pgrep -u $USERNAME -f $SERVICE > /dev/null
then
echo "$SERVICE is running... suspending saves"
as_user "screen -p 0 -S craftbukkit -X eval 'stuff \"say The server is preforming a backup. Server going to read-only mode. Do not build...\"\015'"
as_user "screen -p 0 -S craftbukkit -X eval 'stuff \"save-off\"\015'"
as_user "screen -p 0 -S craftbukkit -X eval 'stuff \"save-all\"\015'"
sync
sleep 10
else
echo "$SERVICE is not running. Not suspending saves."
fi
}
mc_save() {
if pgrep -u $USERNAME -f $SERVICE > /dev/null
then
echo "$SERVICE is running... Saving worlds..."
as_user "screen -p 0 -S craftbukkit -X eval 'stuff \"save-all\"\015'"
sync
sleep 10
echo "Save complete!"
else
echo "$SERVICE is not running. Cannot save!"
fi
}
mc_saveon() {
if pgrep -u $USERNAME -f $SERVICE > /dev/null
then
echo "$SERVICE is running... re-enabling saves"
as_user "screen -p 0 -S craftbukkit -X eval 'stuff \"save-on\"\015'"
as_user "screen -p 0 -S craftbukkit -X eval 'stuff \"say Server backup has completed. Server going to read-write mode. You can now continue building...\"\015'"
else
echo "$SERVICE is not running. Not resuming saves."
fi
}
mc_stop() {
if pgrep -u $USERNAME -f $SERVICE > /dev/null
then
echo "Stopping $SERVICE"
as_user "screen -p 0 -S craftbukkit -X eval 'stuff \"say $SERVERNAME is shutting down in 30 seconds! Please stop what you are doing. Check back later, we'll be back!\"\015'"
as_user "screen -p 0 -S craftbukkit -X eval 'stuff \"save-all\"\015'"
sleep 30
as_user "screen -p 0 -S craftbukkit -X eval 'stuff \"stop\"\015'"
sleep 7
else
echo "$SERVICE was not running."
fi
if pgrep -u $USERNAME -f $SERVICE > /dev/null
then
echo "Error! $SERVICE could not be stopped."
else
echo "$SERVICE is stopped."
fi
}
mc_update() {
if pgrep -u $USERNAME -f $SERVICE > /dev/null
then
echo "$SERVICE is running! Will not start update."
else
MC_SERVER_URL=http://dl.bukkit.org/latest-rb/craftbukkit.jar
as_user "cd $MCPATH && wget -q -O $MCPATH/craftbukkit_server.jar.update $MC_SERVER_URL"
if [ -f $MCPATH/craftbukkit_server.jar.update ]
then
if `diff $MCPATH/$SERVICE $MCPATH/craftbukkit_server.jar.update >/dev/null`
then
echo "You are already running the latest version of $SERVICE. Update anyway? [Y/n]"
select yn in "Yes" "No"; do
case $yn in
Yes ) as_user "mv $MCPATH/$SERVICE $MCPATH/${SERVICE}_old.jar"
as_user "mv $MCPATH/craftbukkit_server.jar.update $MCPATH/$SERVICE"
echo "$SERVICE updated successfully!"; break;;
No ) echo "The update was not installed! Removing temporary files and exiting..."
as_user "rm $MCPATH/craftbukkit_server.jar.update" exit;;
esac
done
else
as_user "mv $MCPATH/$SERVICE $MCPATH/${SERVICE}_old.jar"
as_user "mv $MCPATH/craftbukkit_server.jar.update $MCPATH/$SERVICE"
echo "$SERVICE updated successfully!"
fi
else
echo "$SERVICE update could not be downloaded."
fi
fi
}
mc_addplugin() {
if pgrep -u $USERNAME -f $SERVICE > /dev/null
then
echo "$SERVICE is running! Please stop the service before adding a plugin."
else
echo "Paste the URL to the .JAR Plugin..."
read JARURL
JARNAME=$(basename "$JARURL")
if [ -d "$TEMPPLUGINS" ]
then
as_user "cd $PLUGINSPATH && wget -r -A.jar $JARURL -o temp_plugins/$JARNAME"
else
as_user "cd $PLUGINSPATH && mkdir $TEMPPLUGINS && wget -r -A.jar $JARURL -o temp_plugins/$JARNAME"
fi
if [ -f "$TMPDIR/$JARNAME" ]
then
if [ -f "$PLUGINSPATH/$JARNAME" ]
then
if `diff $PLUGINSPATH/$JARNAME $TMPDIR/$JARNAME >/dev/null`
then
echo "You are already running the latest version of $JARNAME."
else
NOW=`date "+%Y-%m-%d_%Hh%M"`
echo "Are you sure you want to overwrite this plugin? [Y/n]"
echo "Note: Your old plugin will be moved to the "$TEMPPLUGINS" folder with todays date."
select yn in "Yes" "No"; do
case $yn in
Yes ) as_user "mv $PLUGINSPATH/$JARNAME $TEMPPLUGINS/${JARNAME}_${NOW} && mv $TEMPPLUGINS/$JARNAME $PLUGINSPATH/$JARNAME"; break;;
No ) echo "The plugin has not been installed! Removing temporary plugin and exiting..."
as_user "rm $TEMPPLUGINS/$JARNAME"; exit;;
esac
done
echo "Would you like to start the $SERVICE now? [Y/n]"
select yn in "Yes" "No"; do
case $yn in
Yes ) mc_start; break;;
No ) "$SERVICE not running! To start the service run: /etc/init.d/craftbukkit start"; exit;;
esac
done
fi
else
echo "Are you sure you want to add this new plugin? [Y/n]"
select yn in "Yes" "No"; do
case $yn in
Yes ) as_user "mv $PLUGINSPATH/$JARNAME $TEMPPLUGINS/${JARNAME}_${NOW} && mv $TEMPPLUGINS/$JARNAME $PLUGINSPATH/$JARNAME"; break;;
No ) echo "The plugin has not been installed! Removing temporary plugin and exiting..."
as_user "rm $TEMPPLUGINS/$JARNAME"; exit;;
esac
done
echo "Would you like to start the $SERVICE now? [Y/n]?"
select yn in "Yes" "No"; do
case $yn in
Yes ) mc_start; break;;
No ) "$SERVICE not running! To start the service run: /etc/init.d/craftbukkit start"; exit;;
esac
done
fi
else
echo "Failed to download the plugin from the URL you specified!"
exit;
fi
fi
}
mc_scanplugins() {
if [ "$(ls -A $PLUGINSPATH)" ]
then
shopt -s nullglob
PLUGINS=($PLUGINSPATH/*.jar)
i=1
for f in "${PLUGINS[@]}"
do
echo "${i}: $f"
PLUGIN[$i]=$f
i=$(( $i + 1 ))
done
echo "Enter the ID of a plugin you want removed, or any other key to cancel."
read INPUT
if [ ! -z "${INPUT##*[!0-9]*}" ]
then
if [ -f "${PLUGIN[INPUT]}" ]
then
echo "Removing plugin..."
JAR=$(basename ${PLUGIN[INPUT]})
JARNAME=${JAR%.jar}
as_user "rm -f ${PLUGIN[INPUT]}"
sleep 2
as_user "cd $PLUGINSPATH && rm -rf ./${JARNAME}"
if [ -f "${PLUGINSPATH}/${JARNAME}" ]
then
echo "Plugin folder could not be removed..."
fi
echo "Plugin removed."
else
echo "${PLUGIN[INPUT]}"
echo "Invalid plugin! Does not exist! Canceling..."
exit;
fi
else
echo "Canceling..."
exit;
fi
else
echo "You have no plugins installed."
exit;
fi
}
mc_backup() {
mc_saveoff
for i in "${WORLDS[@]}"; do
NOW=`date "+%Y-%m-%d_%Hh%M"`
BACKUP_FILE="$BACKUPPATH/${i}_${NOW}.tar"
echo "Backing up world: $i..."
#as_user "cd $MCPATH && cp -r $i $BACKUPPATH/${i}_`date "+%Y.%m.%d_%H.%M""`
as_user "tar -C \"$MCPATH\" -cf \"$BACKUP_FILE\" $i"
done
echo "Backing up $SERVICE"
as_user "tar -C \"$MCPATH\" -rf \"$BACKUP_FILE\" $SERVICE"
#as_user "cp \"$MCPATH/$SERVICE\" \"$BACKUPPATH/craftbukkit_server_${NOW}.jar\""
mc_saveon
echo "Compressing backup..."
as_user "tar -cvzf $BACKUPPATH/server_backup_${NOW}.tar.gz $MCPATH"
echo "Backup has completed successfully."
}
mc_command() {
command="$1";
if pgrep -u $USERNAME -f $SERVICE > /dev/null
then
pre_log_len=`wc -l "$MCPATH/server.log" | awk '{print $1}'`
echo "$SERVICE is running... executing command"
as_user "screen -p 0 -S craftbukkit -X eval 'stuff \"$command\"\015'"
sleep .1 # assumes that the command will run and print to the log file in less than .1 seconds
# print output
tail -n $[`wc -l "$MCPATH/server.log" | awk '{print $1}'`-$pre_log_len] "$MCPATH/server.log"
fi
}
#Start-Stop here
case "$1" in
start)
mc_start
;;
stop)
mc_stop
;;
restart)
mc_stop
mc_start
;;
save)
mc_save
;;
update)
mc_stop
mc_backup
mc_update
mc_start
;;
scanplugins)
mc_scanplugins
;;
addplugin)
mc_addplugin
;;
backup)
mc_backup
;;
status)
if pgrep -u $USERNAME -f $SERVICE > /dev/null
then
echo "$SERVICE is running."
else
echo "$SERVICE is not running."
fi
;;
command)
if [ $# -gt 1 ]; then
shift
mc_command "$*"
else
echo "Must specify server command (try 'help'?)"
fi
;;
*)
echo "Usage: $0 {start|stop|update|backup|status|restart|command \"server command\"}"
exit 1
;;
esac
exit 0
答案1
授人以鱼不如授人以渔:
仔细阅读错误信息并尝试找出错误来源
在这种情况下,我们有:
bash: -c: line 0: unexpected EOF while looking for matching `"'
bash: -c: line 1: syntax error: unexpected end of file
问:看一下脚本。我们在哪里使用 -c(命令)选项调用“bash”?
答:在 as_user() 函数内部,我们有一个调用:
bash -c "$1"
现在,这里的 $1 是传递给 as_user() 函数的第一个参数,因此我们再次查看脚本并找到调用 as_user() 的位置以及使用哪个参数。
其中一些参数非常复杂,有 3 个级别的转义/引用,因此值得怀疑。
您可以在执行任何其他操作之前在“as_user”内添加一个简单的调试语句作为第一行:
echo '$1 is:' $1
它将在失败之前打印命令,并清楚地表明错误的参数是什么。
更一般地:您可以通过添加跟踪(又名“echo”)来方便地调试 shell 脚本。只需将脚本的第一行更改为:
#!/bin/bash -x
并且每个命令都会在执行之前打印出来,使得调用和错误之间的联系显而易见。还有-v(详细)将打印每一行按照解析方式,在所有历史/命令/参数/文件扩展之前,但我发现-v在调试时用处不大-X。在极少数情况下,我会同时使用两者:-vx详细跟踪执行之前发生的扩展。
高血压
答案2
在计算了脚本 (SMOP) 中的字符数后,我注意到“ '
”字符的数量为奇数 (49)。在第 105 行左右,有一个未转义的“ '
”:
as_user "screen -p 0 -S craftbukkit -X eval 'stuff \"say $SERVERNAME is shutting down in 30 seconds! Please stop what you are doing. Check back later, we'll be back!\"\015'"
尝试更加正式一点:“......我们会回来的......”
认真地说,一个未转义的“ '
”会混淆脚本其余部分的解析(新的“匹配的” 在哪里'
?)。
修复此问题,然后使用-x
和-v
,并阅读man bash
。