Shell 脚本只能使用 sh 命令运行

Shell 脚本只能使用 sh 命令运行

我有一个小的 sh 脚本,用于备份到远程服务器。它在 Ubuntu 16.04 上运行了好几年,但现在在 18.04 上失败了。起初我以为是 anacron 的问题,但现在我认为这是脚本本身或 dash 的问题。以下是发生的情况:

stefan@stefan-Aspire-F5-573T:/etc/cron.daily$ sudo chmod +x rsync-doc-script 
[sudo] Mot de passe de stefan : 
stefan@stefan-Aspire-F5-573T:/etc/cron.daily$ ./rsync-doc-script 
/bin/sh: 0: Can't open *
stefan@stefan-Aspire-F5-573T:/etc/cron.daily$ sh rsync-doc-script
opening connection using: ssh -i /home/stefan/.ssh/id_rsa -l totem MouseHouse rsync --server -vvlogDtprze.iLsfxC . /totembackup/totemdoc  (11 args)
ssh: connect to host mousehouse port 22: Connection refused
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: unexplained error (code 255) at io.c(235) [sender=3.1.2]
stefan@stefan-Aspire-F5-573T:/etc/cron.daily$ 

该错误can't open *导致脚本在由 运行时无法正确运行run-parts。为什么会出现此错误?

最后一行中,脚本运行时无法建立连接,这并不重要。服务器现在已关闭。

脚本如下:

#!/bin/sh                                                                                     *
rsync -azvv -e "ssh -i /home/stefan/.ssh/id_rsa" /home/stefan/Documents/ totem@MouseHouse:/totembackup/totemdoc

答案1

我不能确定,但​​看起来你在第一行有一个拼写错误,*右边有一个偏离的符号。

#!/bin/sh                                                                                     *

^^^ 滚动到右侧即可看到。

例子

$ cat script.bash
#!/bin/sh                    *
echo hi

直接运行:

$ ./script.bash
/bin/sh: *: No such file or directory

运行方式sh

$ sh script.bash
hi

一般建议

通常建议使用与你的 shebang 完全相同的 shell。如果你怀疑遇到了你怀疑dash或正在使用其他 shell 的问题,你始终可以通过将其从#!/bin/sh作为你的 shebang进行更改来使你的 shebang 明确化#!/bin/bash

以上内容基于您以下的评论:

但现在我认为这是脚本本身或 dash 的问题。

答案2

该错误can't open *导致脚本无法在运行时正确运行run-parts。  为什么会发生此错误?

当你执行一个文件1时,它不是二进制可执行文件,而是一个带有 shebang 的文本文件(文件的第一行以#!),内核(无需任何 shell 的帮助)会构建一个命令,该命令是 shebang 行(部分)#!后跟原始的用户级命令行。例如,如果doc-script

#!/bin/sh -x

并被调用

./doc-script bashful dopey

然后内核构建并执行以下命令:

/bin/sh -x ./doc-script bashful dopey

这导致 shell 读取并解释doc-script脚本,追踪( -x) 选项集,并且$1 = bashful$2 =  dopey。(自然$0./doc-script。)如果原始用户提供的命令是

./doc-script b* ??p* [ghs]*

那么处理该命令的 shell(为简单起见,我们假设这是在用户终端上运行的交互式 shell)可能会将其扩展为

./doc-script bashful dopey grumpy happy sleepy sneezy

因此内核构建并执行以下命令:

/bin/sh -x ./doc-script bashful dopey grumpy happy sleepy sneezy

但请记住:shebang 行的处理是由内核完成的, 不是通过 shell  因此,如果事情是

#!/bin/sh *

那么最终构造的命令是

/bin/sh * ./doc-script bashful dopey grumpy happy sleepy sneezy

因为这里没有发生全局扩展。就 shell 而言,这看起来像是用户输入的

/bin/sh '*' ./doc-script bashful dopey grumpy happy sleepy sneezy

并且,因为*不是以-,shell 将其解释为文件名,因此它会尝试运行名为 = 、 = 、 = 、 = 等的脚本。* 但是$0 , *由于  $1 没有 ./doc-script名为 $2 的 bashful脚本 $3 , dopey因此 失败*。__________ 1 我假设该进程具有执行该文件所需的权限。

相关内容