我有一个小的 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 我假设该进程具有执行该文件所需的权限。