为什么通过“sh *.sh”运行的脚本与“./*.sh”运行的功能不同?

为什么通过“sh *.sh”运行的脚本与“./*.sh”运行的功能不同?

我正在使用 Ubuntu 15.10。我注意到一个奇怪的问题。

当我以 root 身份运行rsync嵌入在 shell 脚本中的命令时,如果带有--exclude={}选项,rsync它会正常工作并排除路径,就像我通过 root 身份启动它时一样

./rBackup.sh

但是,当我以 root 身份通过

sh rBackup.sh

排除目录选项不会延续,并且在备份其要备份到的驱动器时会无限循环/media/。为什么?

编辑 - 这不是 sh / bash 的区别 - 或者不应该是。我有 #!/bin/bash 作为第一行,因此当通过“sh *.sh”运行时,它应该使用 bash 解释器 - 至少理论上如此。

脚本如下:

#!/bin/bash

StandbyMount="/media/astump/sdb2"
mount /dev/sdb2 $StandbyMount
rsync -aAXv --exclude={/dev/*,/proc/*,/sys/*,/tmp/*,/run/*,/mnt/*,/media/*,/lost+found,/etc/fstab,/boot/grub/grub.cfg} --delete-before / $StandbyMount
umount $StandbyMount
rm -fr $StandbyMount

答案1

当你跑步时

sh rBackup.sh

该脚本由( )rBackup.sh运行,但不支持括号扩展。shdash

另一方面,当你这样做

./rBackup.sh

然后#!/bin/bash第一行指定要使用的确切解释器。恰好bash支持括号扩展。

如果您没有在 shebang 行中包含有效的可执行文件,那么您只是在当前所在的 shell 下运行脚本(或sh取决于 shell 实现)。

例子:bash

$ cat scr.sh 
echo {bar,spam}

$ sh scr.sh 
{bar,spam}

$ ./scr.sh 
bar spam

我的登录shell是zsh。以下是一些需要注意的事项:

  • 当 时zsh./scr.sh正在被发送到shdash

  • 正在发送bash./scr.shbash

  • 正在发送ksh./scr.shksh

  • 当 时dash./scr.sh正在被发送到shdash


为了安全起见,请始终尝试使用 shebang(脚本的第一行)提及所需的解释器,例如:

#!/usr/bin/env bash

答案2

请记住,sh实际上调用dash,与 Bash 相比,它是有限的。

正如所观察到的@Serg对这个问题的评论,花括号可能被解释为 dash 的输入,这就是它无法工作的原因。这就是它失败的原因——Dash 不进行括号扩展。

您可能希望系统使用 Bash 样式解释。如果您使用默认 shell,bash那么使用 执行脚本./rBackup.sh,我相信,它将在该正在运行的 shell 中执行。


我认为您期望该脚本将由 Bash 处理,但当您这样做时它将无法工作sh

因此,让我们在这里做一些不同的事情:

(1)#!/bin/bash在开头定义,使其直接执行时使用 Bash。

(2)chmod +x rBackup.sh- 这将设置可执行位

(3)执行命令仅有的使用./rBackup.shbash ./rBackup.sh或。这将确保在所有情况下都使用 Bash 来解释该函数;因为它在文件开头bash rBackup.sh定义了使用(如果您执行了步骤 1),它将在执行脚本时尝试使用 Bash。#!/bin/bash

相关内容