我有一个小的 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。
以上是基于您在下面的评论:
但现在我认为这是脚本本身或破折号的问题。
该错误
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 ?我假设该进程具有执行该文件所需的权限。