在Ubuntu作为新用户运行脚本时遇到的Shell问题

2 投票
3 回答
2911 浏览
提问于 2025-04-16 06:27

当我通过SSH登录到一台特定的Ubuntu Linux(10.04 64位)主机时,我会进入一个bash命令行。在这里,我可以运行一个特定的Python脚本,这个脚本的第一行是这样的:

#!/usr/bin/env python

但是如果另一个(新)用户通过SSH登录到同一台主机,并尝试运行这个脚本(或者它的副本),他们会遇到这个错误:

$ ./script.py
: No such file or directory

结果发现,这个文件实际上是一个DOS格式的换行文件,而我可以在我的登录下正常运行。如果我把它转换成UNIX格式,那么其他人也可以正常运行它。

无论是DOS格式还是UNIX格式,只要我们在脚本前加上'python',这个脚本对我们俩来说都能正常运行:

$ python ./script.py
blah blah blah...

此外,一旦脚本转换为UNIX格式并且其他用户可以运行,它仍然无法通过Makefile运行——make显示的错误和上面一样。

我了解到,在Ubuntu中,/bin/sh是'dash'(而不是'bash')的命令行,这让我想知道这是否与此有关,因为它的行为和bash不同。如果是这样的话,我想知道我这个登录(多年来一直正常)和这个新用户的登录之间有什么区别,为什么会出现各种奇怪的行为。我该从哪里开始查找呢?

还有一个可能相关的情况——这个新用户是通过Likewise服务(一个Active Directory集成客户端)自动创建的,可能这个服务在某种程度上错误地配置了新用户。

我也尝试将第一行改为#!/usr/bin/python,但没有任何变化。

两个用户的登录shell都是bash

3 个回答

3

这个问题的关键在于,你为什么可以直接运行它而不需要转换。其他的行为是可以理解的,因为你的 shebang(脚本开头的那行)告诉 env 去执行 python^M,但这个文件并不存在。或者说,它真的不存在吗? 如果你的 $PATH 中有一个叫 python^M 的符号链接或者脚本,而其他用户的环境中没有,那就能解释这种奇怪的行为。你可以试试输入 type -a python^M(按 Ctrl-V 然后 Ctrl-M 来输入 ^M)。

如果你把 shebang 改成 #!/usr/bin/python,那么应该会有不同的结果。你应该会看到 -bash: ./script.py: /usr/bin/python^M: bad interpreter: No such file or directory,而不是 : No such file or directory

6

我之前也遇到过同样的问题,看到上面的回答时,没能立刻搞清楚问题出在哪里,或者解决办法是什么,不过现在我觉得我明白了。

原来,Windows的换行符编码方式和其他系统稍微有点不同。虽然cygwin可以用Unix格式来编码,但我在写脚本时使用的是Windows的文本编辑器(Notepad++),它的默认格式是Windows的CRLF编码。Notepad++可以重新设置为Unix格式作为默认格式。我同事在Linux或Mac机器上生成的所有脚本都能正常运行,但我在Windows上编辑后,没想到会出现问题,直到我尝试在Linux机器上运行其中一个脚本时才发现。

首先,你可以在cygwin或bash中用以下命令来诊断这个问题:

cat -v file.py

如果文件是DOS格式的,每一行的末尾会有一个^M。

其次,cygwin有一个简单的转换工具:

d2u file.py

你可以像第一步那样检查一下转换是否成功。这样,我的所有脚本就可以正常运行了。

2

我自己解决了这个问题,所以我来回答一下,方便大家参考。

问题出在我们在Cygwin/Windows上使用git,并且设置了core.autocrlf=true。我们这样做是出于各种原因,改变这个设置并不简单。

最开始的那个新用户登录到Linux机器时,把他们的Cygwin .gitconfig文件也复制到了新账户里,这个文件里也包含了core.autocrlf=true。然后他们克隆了一个包含相关python脚本的git仓库。我在最开始的问题中没有提到这些信息,因为我当时没有想到这些是相关的。我不想通过解释那些看似无关的事情来让问题变得更复杂。 hindsight eh?

总之,这导致克隆下来的所有脚本都是DOS格式的,这就是为什么这个用户的东西都无法正常工作。也解释了为什么错误信息没有用,因为^M这个回车符把光标移回了行首,但没有换行,然后“No such file or directory”这个信息又覆盖了有用的部分。我是在把PATH设置为一个没有权限的目录时发现这个问题的,得到了一个奇怪的错误信息“Permission deniedn”——那个多出来的'n'让我开始思考。

所以我最开始以为我们都在运行同一个脚本(因为它们都是从同一个git仓库来的)其实是错的——我们根本没有在运行同一个脚本。对我们大多数人来说,那是一个UNIX格式的python脚本,但对这个用户来说却是DOS格式的。最后发现这个问题其实很简单,但又一次我们被Windows相关的问题困扰了。这不会是最后一次。

谢谢大家的回复。

撰写回答