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

Ste*_*iak 6 bash scripts 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$ 
Run Code Online (Sandbox Code Playgroud)

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

无关紧要的是,在最后一行中,脚本运行时无法建立连接。服务器现已关闭。

这是脚本:

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

Run Code Online (Sandbox Code Playgroud)

slm*_*slm 10

我不能肯定,但看起来你在第一行有一个错字,*右边有一个流浪。

#!/bin/sh                                                                                     *
Run Code Online (Sandbox Code Playgroud)

^^^ 向右滚动查看。

例子

$ cat script.bash
#!/bin/sh                    *
echo hi
Run Code Online (Sandbox Code Playgroud)

直接运行:

$ ./script.bash
/bin/sh: *: No such file or directory
Run Code Online (Sandbox Code Playgroud)

运行通过sh

$ sh script.bash
hi
Run Code Online (Sandbox Code Playgroud)

一般建议

通常建议使用您期望的与您的 shebang 完全相同的 shell。如果您怀疑自己遇到了您怀疑dash或正在使用其他 shell 的问题,您始终可以通过将 shebang 更改#!/bin/sh为您的 shebang来使您的 shebang 显式#!/bin/bash

以上是基于您在下面的评论:

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


G-M*_*ca' 5

该错误can't open *阻止脚本在由run-parts.?运行时正确运行。 为什么会发生此错误?

当你执行一个文件1,是不是一个二进制可执行文件,但有家当的文本文件(该文件的第一行开始#!),内核(没有任何程序帮助)建立了一个命令,它的家当线(部分#!),然后原始的,用户级的命令行。例如,如果doc-script开始

#!/bin/sh -x
Run Code Online (Sandbox Code Playgroud)

它被调用

./doc-script bashful dopey
Run Code Online (Sandbox Code Playgroud)

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

/bin/sh -x ./doc-script bashful dopey
Run Code Online (Sandbox Code Playgroud)

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

./doc-script b* ??p* [ghs]*
Run Code Online (Sandbox Code Playgroud)

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

./doc-script bashful dopey grumpy happy sleepy sneezy
Run Code Online (Sandbox Code Playgroud)

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

/bin/sh -x ./doc-script bashful dopey grumpy happy sleepy sneezy
Run Code Online (Sandbox Code Playgroud)

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

#!/bin/sh *
Run Code Online (Sandbox Code Playgroud)

那么最终的构造命令是

/bin/sh * ./doc-script bashful dopey grumpy happy sleepy sneezy
Run Code Online (Sandbox Code Playgroud)

因为 glob 扩展不会在这里发生。就外壳而言,这看起来像用户输入的

/bin/sh '*' ./doc-script bashful dopey grumpy happy sleepy sneezy
Run Code Online (Sandbox Code Playgroud)

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