./和sh运行脚本有什么区别?


71

我写了一个简单的脚本。当我运行时sh <myscriptname.sh>,我得到了正确的输出,但是当我运行时./<myscriptname.sh>,我得到了一个错误。

sh和做什么时有什么区别./


15
不仅仅是说“我收到错误”,如果您粘贴错误中所说的内容也将有所帮助。
SpashHit 2011年

Answers:


67

通过将文件名传递给脚本解释器程序来运行任何脚本时,正在运行解释器程序,并将脚本作为传递给它的参数。例如,这看起来像带有参数“ filename.sh”的进程“ sh”。该sh解释器打开该文件。

另一方面,如果您运行脚本本身,则系统会调出指定的解释器程序并输入脚本内容。在这种情况下,该过程看起来像没有参数的“ filename.sh”。

您应该确保有一个爆炸行:

#!/bin/bash
# bash script here

爆炸行是脚本中的第一行,并以相同的两个字符开头#!,这是系统在尝试执行脚本时读取的内容,然后系统将脚本立即传递给程序。请注意,该行与bash无关,即使它们是非常不同的语言,它们也适用于python和perl。您将使用#!/usr/bin/python例如,然后使用python代码。

拥有脚本后,请确保已设置执行权限:

chmod a+x filename.sh

然后,您可以将脚本作为自己的进程运行:

./filename.sh

或将文件放入一个具有良好程序名称的已知位置,例如,/usr/sbin并可以在任何地方运行:

sudo cp filename.sh /usr/sbin/program-name
program-name

实际上是使用具有正确权限的爆炸句的实际好处-全部与部署有关。如果用户必须记住运行脚本的程序,那么很难使用户运行脚本。请记住,每次他们要运行脚本时,都要为其提供完整路径。/usr/local/bin例如,将其放到哪里并使其可执行,可以为尝试使用您的脚本的人们节省很多麻烦。然后,这些程序将对计算机上的所有用户可用。

这也有利于识别。如果你进入的top程序,没有爆炸线脚本运行将只具有的解释,即名称bashperlpython。但是,如果以正确的权限运行脚本,则会显示脚本的名称。

注意:如果要分发每个人都可以访问的脚本,请创建一个手册页和一个deb软件包以进行安装。我们需要减少在线随机脚本的数量,并增加可以卸载的deb的数量。


1
您还可以使用个人bin文件夹:在您的主文件夹中创建一个bin文件夹,然后注销并重新登录,然后您应该能够在该文件夹中运行任何脚本,而无需sh或./。
papukaija 2011年

当然,但是将您的主文件夹添加到PATH中可能会让人有些头疼。更好地安装东西。尽管有人谈论默认情况下将〜/ .local / bin添加到路径以允许本地用户安装软件包。
Martin Owens -doctormo-

请注意,默认解释器bash不是sh
内森·奥斯曼

1
不要在脚本上添加扩展名,尤其是放在扩展名中时PATH
geirha

1
/usr/local/bin可能会更好/usr/sbin-它表明该程序在此计算机上本地而不是在发行版中。
glenn jackman 2011年

41

简短版本:

  • sh是命令行解释器(破折号)。
    运行sh my_script使破折号解释脚本。

  • ./尝试通过查看第一行来找出要使用的解释器。例如#!/bin/bash,甚至#!/bin/ruby(相对于运行ruby my_script)。


7
并不是真正./找到任何东西,而是系统执行方法查看文件的前两个字节。
Martin Owens -doctormo- 2011年

9
绝对。这是一个很长的解释。我很务实:)
Stefano Palazzo

当您使用sh并且文件中包含有爆炸声时,是否意味着该爆炸声将被忽略,还是会在sh链接也打开外壳的地方打开外壳,然后打开其他外壳?
伊尼

5

您要做的是,

  • 使用sh,您正在运行一个程序,该程序将解释脚本中的行,就像您在终端的交互式提示上键入它们一样,

  • ./你正在做一个快捷方式假设脚本只是这里在当前目录下你坐在这将是可执行文件(因为比如你发出chmod +x myscript.sh),节省您的宝贵时间,将来时间:-)


3
+1是唯一明确声明该文件必须可执行的文件。
Mikel

2
请注意,sh该文件不一定必须是可执行文件。
燕丽

3

您可能会收到错误的三个主要原因:

  • 该文件是不可执行的
    运行chmod +x <myscriptname.sh>来修复
  • 分区不允许正在运行的脚本(已安装“ noexec”)
    将脚本复制到/usr/local/bin
  • #!行有错误,请
    确保第一行是#!/bin/sh#!/bin/bash

如果您的第一行看起来正确,但仍然无法正常工作,请确保该文件没有DOS行尾。

该错误看起来像这样:

$ ./myscript.sh
bash: ./myscript.sh: /bin/bash^M: bad interpreter: No such file or directory

您可以通过运行来解决它dos2unix <myscriptname.sh>,或者如果没有的话可以解决它
perl -p -i -e 's/\r\n$/\n/' <myscriptname.sh>


0

答案是sh是非常流行的shell的名称。但是过时了,被别人取代了。如今,sh已链接到机器上安装的其他外壳。例如我在那儿放了b子。从sh运行任何shell通常会触发具有原始“ shell”行为的“兼容”模式。

因此解决方案非常简单。查看sh命令(ls -al / bin / sh)后面的内容,然后将#!/ bin / whatever_you_find_there作为第一行(或者如果脚本中有类似内容,请对其进行编辑)。

另外,脚本本身也可能存在一些错误。类似于sh满足的依赖关系,但不是实际使用的解释器。


0
mkdir ~/bin ; cp myscript.sh ~/bin/

echo "export PATH="$PATH:/home/$USER/bin" >> ~/.profile ; source ~/.profile ; 

/usr/sbin,那是不必要的行政手段,/usr/local/bin是一个更好的选择,如果你不希望有一个~/bin/,但避免sudo尽可能多的建议。


在Ubuntu上,默认值~/.profile已经具有用于添加的代码~/bin(如果存在)PATH。另外,请不要在脚本上添加扩展名。
geirha 2011年

1
我正在引用<myscriptname.sh>,但是不对脚本进行扩展的理由是什么?我之所以这样做,是因为让这样的纯文本文件可见,使我无法尝试编辑也保存在〜/ bin /中的二进制文件。(ls ~/bin/|wc -l = 428)我在里面放了很多东西;)
Joey1978

假设您编写了一个脚本来完成特定任务。然后,您意识到用python编写此特定脚本将使其效率更高,因此您可以用python重写它。现在,您有两个选择。1)保留现在非常令人误解的.sh扩展名,或2)重命名脚本并搜索并替换脚本的所有使用以使用新名称。如果你看一下在脚本/bin/usr/bin你会看到他们不使用扩展。
geirha
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.