与 shell 脚本文件相关的奇怪问题

Strange issue relating to shell script files

我在名为 restart_server.sh:

的文件中有这个 shell 脚本
echo "KILLING SERVER SESSION"
kill $(cat serverlastpid.txt)
sleep 20
echo "STARTING SERVER..."
java -jar eu.greensmartcampus-0.0.1-SNAPSHOT-jar-with-dependencies.jar </dev/null>/dev/null 2>&1 &
echo $! > serverlastpid.txt
echo "SERVER STARTED! PID:" $(cat serverlastpid.txt)

如果我单独执行每一行,我会得到:

root@production:/opt/AppServer# echo "KILLING SERVER SESSION"
KILLING SERVER SESSION
root@production:/opt/AppServer# kill $(cat serverlastpid.txt)
root@production:/opt/AppServer# sleep 20
root@production:/opt/AppServer# echo "STARTING SERVER..."
STARTING SERVER...
root@production:/opt/AppServer# java -jar eu.greensmartcampus-0.0.1-SNAPSHOT-jar-with-dependencies.jar </dev/null>/dev/null 2>&1 &
[1] 14620
root@production:/opt/AppServer# echo $! > serverlastpid.txt
root@production:/opt/AppServer# echo "SERVER STARTED! PID:" $(cat serverlastpid.txt)
SERVER STARTED! PID: 14620
root@production:/opt/AppServer#

现在,如果我只是 运行 一个 shell 脚本文件中的所有这些行,我将得到以下输出:

root@production:/opt/AppServer# sh restart_server.sh
restart_server.sh: 1: restart_server.sh: echo: not found
STARTING SERVER...
SERVER STARTED! PID: 14777
[1]+  Exit 143                java -jar eu.greensmartcampus-0.0.1-SNAPSHOT-jar-with-dependencies.jar < /dev/null > /dev/null 2>&1
root@production:/opt/AppServer#

部分 echo 消息丢失,屏幕上出现一些错误。

为什么会这样?与 运行 逐行单独设置或 运行 在 .sh 文件中设置有什么不同?

编辑: 添加 #!/bin/bash 作为第一行输出:

root@production:/opt/AppServer# sh restart_server.sh
restart_server.sh: 1: restart_server.sh: #!/bin/bash: not found
KILLING SERVER SESSION
STARTING SERVER...
SERVER STARTED! PID: 15366
root@production:/opt/AppServer#

您需要调用 bash 才能执行 bash 脚本,为此请使用

whereis bash

那么你应该在 bash 脚本的 第一行 中输入给定的路径

#!/bin/bash

有时是#!/bin/sh

这取决于您的发行版

请参阅 chat 中的讨论。

问题出在以 UTF-8 编码为字节 0xEF 0xBB 0xBF 的 Unicode 字节顺序标记 (BOM),shell 不喜欢。删除它,并确保 shell 代码将与 dash 而不是 bash 一起工作,让事情正常工作。

诊断的关键步骤是:

  • 确定 shell 是 dash 而不是 bash
  • 使用十六进制转储工具检查文件的前几行,以便 BOM 可见。
  • 知道如何去掉 BOM(后面跟着一个换行符很方便,所以 sed 可以很容易地使用)。
  • 使用 sh -x restart_server.sh 查看正在执行的内容。